diff --git a/.DS_Store b/.DS_Store
index 729469a..f14dec1 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/myapp/package-lock.json b/myapp/package-lock.json
index 0c13121..321aab5 100644
--- a/myapp/package-lock.json
+++ b/myapp/package-lock.json
@@ -1320,6 +1320,11 @@
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz",
"integrity": "sha512-MsAhsUW1GxCdgYSO6tAfZrNapmUKk7mWx/k5mFY/A1gBtkaCaNapTg+FExCw1r9yeaZhqx/xPg43xgTFH6KL5w=="
},
+ "base64url": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz",
+ "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs="
+ },
"batch": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
@@ -4984,6 +4989,57 @@
"assert-plus": "1.0.0"
}
},
+ "gh-pages": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-1.1.0.tgz",
+ "integrity": "sha512-ZpDkeOVmIrN5mz+sBWDz5zmTqcbNJzI/updCwEv/7rrSdpTNlj1B5GhBqG7f4Q8p5sJOdnBV0SIqxJrxtZQ9FA==",
+ "requires": {
+ "async": "2.6.0",
+ "base64url": "2.0.0",
+ "commander": "2.11.0",
+ "fs-extra": "4.0.3",
+ "globby": "6.1.0",
+ "graceful-fs": "4.1.11",
+ "rimraf": "2.6.2"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
+ "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ=="
+ },
+ "fs-extra": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz",
+ "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==",
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "jsonfile": "4.0.0",
+ "universalify": "0.1.1"
+ }
+ },
+ "globby": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
+ "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
+ "requires": {
+ "array-union": "1.0.2",
+ "glob": "7.1.2",
+ "object-assign": "4.1.1",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "requires": {
+ "graceful-fs": "4.1.11"
+ }
+ }
+ }
+ },
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
diff --git a/myapp/package.json b/myapp/package.json
index 2d24d5c..bc1b8f5 100644
--- a/myapp/package.json
+++ b/myapp/package.json
@@ -4,16 +4,20 @@
"private": true,
"dependencies": {
"firebase": "^4.10.1",
+ "gh-pages": "^1.1.0",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-router-dom": "^4.2.2",
"react-scripts": "1.1.1",
"recharts": "^1.0.0-beta.10"
},
+ "homepage": "https://students.washington.edu/evanzhao/info343/p4-climbingApp/",
"scripts": {
+ "predeploy": "npm run build",
+ "deploy": "gh-pages -d build",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
-}
+}
\ No newline at end of file
diff --git a/myapp/src/App.css b/myapp/src/App.css
index 5660ac2..71cef39 100644
--- a/myapp/src/App.css
+++ b/myapp/src/App.css
@@ -55,7 +55,7 @@ nav {
text-align: center;
}
-h1, footer {
+h1 {
margin: 0;
padding: 1.5vh;
padding-left: 1.5vw;
@@ -147,10 +147,18 @@ button {
}
button:after {
- content: '\00bb';
+ /* content: '\00bb'; */
position: absolute;
opacity: 0;
top: 0;
- right: -20px;
+ /* right: -20px; */
transition: 0.5s;
+}
+
+footer {
+ bottom: 0;
+ position: fixed;
+ padding-left: 1rem;
+ padding-bottom: 0;
+ margin-bottom: 0;
}
\ No newline at end of file
diff --git a/myapp/src/App.js b/myapp/src/App.js
index eb7324d..c15d1ce 100644
--- a/myapp/src/App.js
+++ b/myapp/src/App.js
@@ -5,36 +5,84 @@ import firebase from 'firebase';
import 'firebase/auth';
import 'firebase/database';
import { PieChart, Pie, Cell } from 'recharts';
-import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
+import { BrowserRouter as Router, Route } from 'react-router-dom';
import { NavLink } from 'react-router-dom';
+
+//Renders the website
class App extends Component {
- constructor(props) {
- super(props);
+ constructor() {
+ super();
+ this.handleLogout = this.handleLogout.bind(this);
+ this.handleUser = this.handleUser.bind(this);
+ this.state = {
+ user: ''
+ };
}
+ //Handles Logout
+ handleLogout() {
+ this.setState({
+ user: ''
+ });
+ firebase.auth().signOut()
+ .catch((err) => {
+ console.log(err)
+ })
+ }
+
+ handleUser(data) {
+ this.setState({
+ user: data
+ });
+ }
+
+ //Renders Header and Nav Links to other parts of the website
render() {
return (
- {/* Find your Climb! */}
+
Find your Climb!
+ {this.state.user !== '' &&
+
+ Profile
+
+ }
+
Routes
Types
-
- Login
-
+ {this.state.user === '' ?
+
+ Login
+
+ :
+
Logout
+ }
-
-
+ {this.state.user === '' ?
+
(
+
+ )} />
+ :
+ (
+
+ )} />
+ }
+ (
+
+ )} />
+ (
+
+ )} />
@@ -43,6 +91,7 @@ class App extends Component {
}
}
+//Renders the homepage
class WelcomePage extends Component {
render() {
return (
@@ -56,6 +105,7 @@ class WelcomePage extends Component {
}
}
+//Renders the login page
class LoginPage extends Component {
constructor(props) {
super(props);
@@ -68,6 +118,7 @@ class LoginPage extends Component {
componentDidMount() {
this.stopWatchingAuth = firebase.auth().onAuthStateChanged(firebaseUser => {
if (firebaseUser) {
+ // this.props.history.push("/routes");
this.setState({
user: firebaseUser,
errorMessage: '',
@@ -75,12 +126,18 @@ class LoginPage extends Component {
password: '',
username: ''
});
+ this.props.handlerFromParent(this.state.user);
}
else {
this.setState({ user: null }); //null out the saved state
}
})
}
+ componentWillUnmount() {
+ this.stopWatchingAuth();
+ }
+
+ //Function that signs user up and stores their data in firebase
handleSignUp() {
/* Create a new user and save their information */
@@ -103,31 +160,22 @@ class LoginPage extends Component {
this.setState({ errorMessage: err.message })
})
}
+
+
handleSignIn() {
//A callback function for logging in existing users
-
/* Sign in the user */
firebase.auth().signInWithEmailAndPassword(this.state.email, this.state.password)
- .catch((err) => {
- console.log(err)
- this.setState({ errorMessage: err.message })
- });
-
- }
-
- handleSignOut() {
- this.setState({ errorMessage: null }); //clear old error
-
- /* Sign out the user, and update the state */
- firebase.auth().signOut()
- .then(() => {
- this.setState({ user: null }); //null out the saved state
+ .then(user => {
+ this.setState({
+ user: user
+ })
})
.catch((err) => {
- console.log(err)
+ console.log(err.message)
this.setState({ errorMessage: err.message })
- })
+ });
}
handleChange(event) {
@@ -185,9 +233,9 @@ class LoginPage extends Component {
this.handleSignIn()}>
Sign In
-
this.handleSignOut()}>
+ {/* this.handleSignOut()}>
Sign Out
-
+ */}
);
@@ -195,6 +243,7 @@ class LoginPage extends Component {
}
//skykomish valley
+//Default numbers for when website is first rendered
const DEFAULTS = {
lat: '47.8207',
lon: '-121.5551',
@@ -202,6 +251,7 @@ const DEFAULTS = {
maxDist: 10
};
+//Renders the page that shows routes
class RoutesPage extends Component {
constructor(props) {
@@ -209,6 +259,7 @@ class RoutesPage extends Component {
this.loadData(DEFAULTS.lat, DEFAULTS.lon, DEFAULTS.numRoutes, DEFAULTS.maxDist)
}
+ //Brings the data from the mountain project.com using an api call
loadData(lat, lon, numRoutes, maxDist) {
let url = "https://www.mountainproject.com/data/get-routes-for-lat-lon?key=200219054-5692fe76fab0e0f8dbdddb64cba1f33b&lat=" + lat + "&lon=" + lon + "&maxDistance=" + maxDist + "&maxResults=" + numRoutes;
fetch(url)
@@ -237,7 +288,7 @@ class RoutesPage extends Component {
this.handleSubmit(latLongParams)} />
-
+
@@ -249,11 +300,13 @@ class RoutesPage extends Component {
}
}
+//The card that shows the data of the rock climbing areas
class ClimbCard extends React.Component {
- constructor() {
- super()
+ constructor(props) {
+ super(props)
this.state = {
- isHidden: true
+ isHidden: true,
+ likes: ''
}
}
toggleHidden() {
@@ -261,7 +314,76 @@ class ClimbCard extends React.Component {
isHidden: !this.state.isHidden
})
}
+
+
+ //Counts the number of likes per location and stores it on firebase
+ countLikesToFireBase() {
+
+ firebase.database().ref('Post/' + this.props.id + "/Likes").transaction(function (Likes) {
+ console.log("likes", Likes);
+ if (Likes) {
+
+ Likes = Likes + 1;
+ } else {
+ Likes = 1;
+ }
+ return Likes;
+ });
+
+ }
+
+
+ //Saves a location that the user chose on firebase so that it can be viewed on their profile later
+ pushLikeToFireBase() {
+ let UserRef = firebase.database().ref('Users');
+ let dataName = this.props.name;
+ let foundKey = false;
+ Object.keys(UserRef).forEach((key) => {
+ if (key === this.props.uid) {
+ foundKey = true;
+ UserRef.child(key).child('Climbs').push({
+ Name: this.props.name,
+ Type: this.props.type,
+ Rating: this.props.rating,
+ Stars: this.props.stars,
+ Pitches: this.props.pitches,
+ Location: this.props.location,
+ Image: this.props.img,
+ Id: this.props.id
+
+ }).catch(err => console.log(err));
+ }
+ }
+ )
+ if (!foundKey) {
+ firebase.database().ref('Users/' + this.props.uid + '/Climbs/' + this.props.id + "/").set(
+ {
+ Name: this.props.name,
+ Type: this.props.type,
+ Rating: this.props.rating,
+ Stars: this.props.stars,
+ Pitches: this.props.pitches,
+ Location: this.props.location,
+ Image: this.props.img,
+ Id: this.props.id
+ }
+ ).catch(err => console.log(err));
+ }
+
+ foundKey = false;
+ }
+
+
+ componentDidMount() {
+ firebase.database().ref('Post/' + this.props.id + "/Likes").on('value', (snapshot) => {
+ this.setState({
+ likes: snapshot.val()
+ });
+ })
+ }
+
render() {
+ console.log(this.props.uid)
let pitches = this.props.pitches;
if (pitches === '') {
pitches = "N/A";
@@ -279,25 +401,39 @@ class ClimbCard extends React.Component {
Stars: {this.props.stars}
Pitches: {pitches}
Location: {this.props.location}
+ Likes: {this.state.likes === '' ? "0" : this.state.likes}
+ {this.props.uid === '' &&
+
+ Login to Add to your profile!
+ }
+ {this.props.uid !== '' &&
+ { event.cancelBubble = true; this.pushLikeToFireBase() }}> Add To Profile
+
+ }
+ {this.props.uid !== '' &&
+ { event.cancelBubble = true; this.countLikesToFireBase() }}> I LIKED THIS
+
+ }
+
}
+
)
}
}
+//Generates a list of card climbing routes and the pie chart
class ClimbList extends React.Component {
render() {
let dict = _(this.props.routes)
.countBy('type')
.value()
-
let arr = [];
let combined = 0;
Object.keys(dict).forEach((key) => {
- console.log(key, dict[key]);
if (!key.includes(',')) {
arr.push({ name: key, value: dict[key] })
} else {
@@ -317,6 +453,7 @@ class ClimbList extends React.Component {
return color;
}
+
let colorArray = [];
for (let i = 0; i < 5; i++) {
colorArray[i] = getRandomColor();
@@ -329,19 +466,11 @@ class ClimbList extends React.Component {
outerRadius={200} innerRadius={180} label={(something) => something.name} >
|
-
-
-
|
-
|
-
-
|
|
-
-
@@ -351,7 +480,7 @@ class ClimbList extends React.Component {
{
this.props.routes.map((climb) =>
- )
}
@@ -360,6 +489,8 @@ class ClimbList extends React.Component {
}
}
+
+// Takes in the user entered parameters and renders the form to submit them in
class ClimbParam extends React.Component {
constructor(props) {
super(props);
@@ -405,7 +536,7 @@ class ClimbParam extends React.Component {
onChange={this.handleChange} />
-
+
Notable Locations:
@@ -428,11 +559,18 @@ class ClimbParam extends React.Component {
Lat: 46.9454
Lon: -119.9873
+
+
SmithRock
+
Lat: 44.3682
+
Lon: -121.1406
+
);
}
}
+
+//Renders the about page containing information on types of bouldering
class AboutPage extends Component {
render() {
@@ -489,4 +627,50 @@ class AboutPage extends Component {
}
+//Redners the profile page which holds the user's saved climbing routes
+class ProfilePage extends Component {
+ constructor(props) {
+ super(props)
+ this.state = {
+ climbs: ''
+ }
+ }
+
+ componentDidMount() {
+ if (this.props.uid !== undefined) {
+ let ref = firebase.database().ref('Users').child(this.props.uid).child('Climbs');
+ ref.on('value', (snapshot) => {
+ this.setState({
+ climbs: snapshot.val()
+ });
+ console.log(this.state.climbs);
+
+ console.log(snapshot.val())
+ })
+
+ }
+ }
+
+ render() {
+ return (
+
+ < div >
+ Welcome to your Profile!
+ Here are your saved climbs!
+
+
+
+ {this.state.climbs !== null &&
+ Object.keys(this.state.climbs).map((climb) =>
+ // console.log(this.state.climbs[climb]))
+ < ClimbCard uid={this.props.uid} key={this.state.climbs[climb].Id} id={this.state.climbs[climb].Id} img={this.state.climbs[climb].Image} name={this.state.climbs[climb].Name} type={this.state.climbs[climb].Type}
+ rating={this.state.climbs[climb].Rating} stars={this.state.climbs[climb].Stars} pitches={this.state.climbs[climb].Pitches} location={this.state.climbs[climb].Location} />)
+ }
+
+
+
+
+ );
+ }
+}
export default App;