Created
July 6, 2020 23:11
-
-
Save Sammykhaleel/1751ef87dd482fec514e8d1d9c9b53a3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import axios from "axios"; | |
import { BrowserRouter as Router, Route } from "react-router-dom"; | |
import { LoginView } from "../login-view/login-view"; | |
import { RegistrationView } from "../registration-view/registration-view"; | |
import { MovieCard } from "../movie-card/movie-card"; | |
import { MovieView } from "../movie-view/movie-view"; | |
import { ProfileView } from "../profile-view/profile-view"; | |
import { DirectorView } from "../director-view/director-view"; | |
import { GenreView } from "../genre-view/genre-view"; | |
import { UpdateView } from "../update-view/update-view"; | |
import Button from "react-bootstrap/Button"; | |
import Navbar from "react-bootstrap/Navbar"; | |
import { Link } from "react-router-dom"; | |
import "./main-view.scss"; | |
import Row from "react-bootstrap/Row"; | |
import Container from "react-bootstrap/Container"; | |
import Col from "react-bootstrap/Col"; | |
export class MainView extends React.Component { | |
constructor() { | |
// Call the superclass constructor | |
// so React can initialize it | |
super(); | |
// Initialize the state to an empty object so we can destructure it later | |
this.state = { | |
movies: [], | |
user: null, | |
profileInfo: null, | |
}; | |
} | |
getMovies(token) { | |
axios | |
.get("https://vfa.herokuapp.com/movies", { | |
headers: { Authorization: "Bearer " + token }, | |
}) | |
.then((response) => { | |
// Assign result to a state | |
this.setState({ | |
movies: response.data, | |
}); | |
}) | |
.catch((error) => { | |
console.log(error); | |
}); | |
} | |
getAccount(accessToken) { | |
const url = | |
"https://vfa.herokuapp.com/users/" + localStorage.getItem("user"); | |
console.log(url); | |
axios | |
.get(url, { | |
headers: { Authorization: "Bearer " + accessToken }, | |
}) | |
.then((response) => { | |
// console.log(response.data); | |
// Assign result to a state | |
this.setState({ | |
profileInfo: response.data, | |
}); | |
}) | |
.catch(function (error) { | |
console.log(error); | |
}); | |
} | |
componentDidMount() { | |
// Get value of token from localStorage if present | |
let accessToken = localStorage.getItem("token"); | |
if (accessToken !== null) { | |
this.setState({ | |
user: localStorage.getItem("user"), | |
}); | |
this.getMovies(accessToken); | |
this.getAccount(accessToken); | |
} | |
} | |
logOut() { | |
localStorage.removeItem("token"); | |
localStorage.removeItem("user"); | |
localStorage.removeItem("id"); | |
this.setState({ | |
user: null, | |
}); | |
} | |
onLoggedIn(authData) { | |
this.setState({ | |
user: authData.user.Username, | |
}); | |
// Add authData to browser's cache (that we got from props.logInFunc(data) in the profile.view) | |
localStorage.setItem("token", authData.token); | |
localStorage.setItem("user", authData.user.Username); | |
localStorage.setItem("id", authData.user._id); | |
// Calls endpoint once user is logged in | |
this.getMovies(authData.token); | |
this.getAccount(authData.token); | |
} | |
render() { | |
// If the state isn't initialized, this will throw on runtime | |
// before the data is initially loaded | |
const { movies, user, profileInfo } = this.state; | |
// Logging to check states | |
// console.log('M = ' + movies); | |
// console.log('U = ' + user); | |
// console.log('pi =' + profileInfo); | |
// Before the movies have been loaded | |
if (!movies && !profileInfo) return <div className="main-view" />; | |
return ( | |
<Router> | |
<div className="main-view text-center container-fluid main-view-styles "> | |
{/* Nav start */} | |
<Navbar | |
sticky="top" | |
bg="light" | |
expand="lg" | |
className="mb-3 shadow-sm p-3 mb-5" | |
> | |
<Navbar.Brand | |
href="http://localhost:1234/" | |
className="navbar-brand" | |
> | |
VFA | |
</Navbar.Brand> | |
<Navbar.Toggle aria-controls="basic-navbar-nav" /> | |
<Navbar.Collapse | |
className="justify-content-end" | |
id="basic-navbar-nav" | |
> | |
{!user ? ( | |
<ul> | |
<Link to={`/`}> | |
<Button variant="link">login</Button> | |
</Link> | |
<Link to={`/register`}> | |
<Button variant="link">Register</Button> | |
</Link> | |
</ul> | |
) : ( | |
<ul> | |
<Link to={`/`}> | |
<Button variant="link" onClick={() => this.logOut()}> | |
Log out | |
</Button> | |
</Link> | |
<Link to={`/users/`}> | |
<Button variant="link">Account</Button> | |
</Link> | |
<Link to={`/`}> | |
<Button variant="link">Movies</Button> | |
</Link> | |
<Link to={`/about`}> | |
<Button variant="link">About</Button> | |
</Link> | |
<Link to={`/contact`}> | |
<Button variant="link">Contact</Button> | |
</Link> | |
</ul> | |
)} | |
</Navbar.Collapse> | |
</Navbar> | |
{/* Nav end */} | |
{/* If this.user === null don't show Link */} | |
<Route | |
exact | |
path="/" | |
render={() => { | |
if (!user) | |
return ( | |
<LoginView logInFunc={(user) => this.onLoggedIn(user)} /> | |
); | |
return ( | |
<div className="row d-flex mt-4 ml-2"> | |
{movies.map((m) => ( | |
<MovieCard key={m._id} movie={m} /> | |
))} | |
</div> | |
); | |
}} | |
/> | |
<Route | |
path="/movies/:movieId" | |
render={({ match }) => ( | |
<MovieView | |
movie={movies.find((m) => m._id === match.params.movieId)} | |
/> | |
)} | |
/> | |
<Route | |
path="/users/" | |
render={() => ( | |
<ProfileView | |
user={user} | |
profileInfo={this.state.profileInfo} | |
movies={movies} | |
logOutFunc={() => this.logOut()} | |
/> | |
)} | |
/> | |
<Route | |
path="/Update/:name" | |
render={() => ( | |
<UpdateView user={user} profileInfo={this.state.profileInfo} /> | |
)} | |
/> | |
<Route | |
path="/directors/:name" | |
render={({ match }) => ( | |
<DirectorView | |
director={movies.find( | |
(m) => m.Director.Name === match.params.name | |
)} | |
movies={movies} | |
/> | |
)} | |
/> | |
<Route | |
path="/genres/:name" | |
render={({ match }) => ( | |
<GenreView | |
genre={movies.find((m) => m.Genre.Name === match.params.name)} | |
movies={movies} | |
/> | |
)} | |
/> | |
<Route path="/register" render={() => <RegistrationView />} /> | |
</div> | |
</Router> | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import axios from 'axios'; | |
import Button from 'react-bootstrap/Button'; | |
import PropTypes from 'prop-types'; | |
import { Link } from 'react-router-dom'; | |
import Row from 'react-bootstrap/Row'; | |
import Container from 'react-bootstrap/Container'; | |
import Col from 'react-bootstrap/Col'; | |
import Card from 'react-bootstrap/Card'; | |
import './profile-view.scss'; | |
export class ProfileView extends React.Component { | |
constructor() { | |
super(); | |
this.state = {}; | |
} | |
removeFavourite(movie) { | |
/* Send a request to the server for authentication */ | |
const url = | |
'https://vfa.herokuapp.com/users/' + | |
localStorage.getItem('id') + | |
'/favourites/' + | |
movie; // 'https://vfa.herokuapp.com/users/localStorage.getItem('user')}/favourites/${movie}'; | |
axios | |
.delete(url, { | |
headers: { Authorization: 'Bearer ' + localStorage.getItem('token') }, // `Bearer ${localStorage.getItem('token')}` | |
}) | |
// reload page | |
.then(() => { | |
document.location.reload(true); | |
}) | |
.then(() => { | |
alert('Movie removed from favourites'); | |
}) | |
.catch((error) => { | |
console.log('Issue deleting movie from favourites... >' + error); | |
}); | |
} | |
unregisterAccount() { | |
if (!confirm('Are you sure?')) { | |
return; | |
} | |
const url = 'https://vfa.herokuapp.com/users/' + localStorage.getItem('id'); | |
console.log(url); | |
axios | |
.delete(url, { | |
headers: { Authorization: 'Bearer ' + localStorage.getItem('token') }, | |
}) | |
.then((response) => { | |
console.log(response.data); | |
// Set profile info to null | |
this.setState({ | |
profileInfo: null, | |
user: null, | |
}); | |
this.props.logOutFunc(); | |
window.open('/', '_self'); | |
alert('Your account was successfully deleted'); | |
}) | |
.catch(function (error) { | |
console.log(error); | |
}); | |
} | |
render() { | |
const { user, profileInfo, movies } = this.props; | |
if (!profileInfo || !user) return <div>Loading</div>; | |
console.log(profileInfo.FavouriteMovies); | |
const favouritesList = movies.filter((movie) => | |
profileInfo.FavouriteMovies.includes(movie._id) | |
); | |
console.log('FL =' + favouritesList); | |
return ( | |
<Container className="profile-view wrapper container-fluid"> | |
<Row> | |
<Col className="col-3" /> | |
<Col className="container-fluid align-items-center col-6"> | |
<img | |
className="profile-avatar " | |
src="https://via.placeholder.com/150" | |
/> | |
<div className="account-username "> | |
<span className="label">Username: </span> | |
<span className="value">{profileInfo.Username}</span> | |
</div> | |
<div className="account-email "> | |
<span className="label">Email: </span> | |
<span className="value">{profileInfo.Email}</span> | |
</div> | |
<div className="account-birthday "> | |
<span className="label">Birthday: </span> | |
<span className="value">{profileInfo.Birthday}</span> | |
</div> | |
<div className="account-password "> | |
<span className="label">Password: </span> | |
<span className="value">***********</span> | |
</div> | |
</Col> | |
<Col className="col-3" /> | |
</Row> | |
<Container> | |
<h4>Favourites List</h4> | |
<div className="d-flex row mt-3 ml-1"> | |
{favouritesList.map((movie) => { | |
return ( | |
<div key={movie._id}> | |
<Card className="mb-3 mr-2 h-100" style={{ width: '16rem' }}> | |
<Card.Img variant="top" src={movie.ImagePath} /> | |
<Card.Body> | |
<Link className="text-muted" to={`/movies/${movie._id}`}> | |
<Card.Title>{movie.Title}</Card.Title> | |
</Link> | |
<Card.Text> | |
{movie.Description.substring(0, 90)}... | |
</Card.Text> | |
</Card.Body> | |
<Card.Footer className="bg-white border-top-0"> | |
<span className="d-flex align-items-center"> | |
<Button | |
variant="primary" | |
size="sm" | |
className="mr-2" | |
onClick={() => this.removeFavourite(movie._id)} | |
> | |
<i className="material-icons bin">Remove</i> | |
</Button> | |
</span> | |
</Card.Footer> | |
</Card> | |
</div> | |
); | |
})} | |
</div> | |
</Container> | |
<Row> | |
<Col> | |
<Link to={`/update/${profileInfo.Username}`}> | |
<Button variant="primary" className="update-button"> | |
Update my profile | |
</Button> | |
</Link> | |
<div className=""> | |
<Button onClick={() => this.unregisterAccount()} variant="link"> | |
Delete Account | |
</Button> | |
</div> | |
<Link to={`/`}> | |
<Button variant="link">Home</Button> | |
</Link> | |
</Col> | |
</Row> | |
</Container> | |
); | |
} | |
} | |
ProfileView.propTypes = { | |
profileInfo: PropTypes.shape({ | |
Username: PropTypes.string.isRequired, | |
Email: PropTypes.string.isRequired, | |
// ImagePath: PropTypes.string.isRequired, | |
Birthday: PropTypes.string.isRequired, | |
}).isRequired, | |
logOutFunc: PropTypes.func.isRequired, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment