From d09a55e92a055d7e223de997e82384bf0e81dc83 Mon Sep 17 00:00:00 2001 From: Alex Hoskins Date: Tue, 2 Nov 2021 16:28:00 -0700 Subject: [PATCH] MVP done --- README.md | 50 ++++++++++++++--------------- src/App.js | 11 +++++-- src/actions/movieActions.js | 21 +++++++++++- src/components/AddMovieForm.js | 13 ++++++-- src/components/FavoriteMovieList.js | 21 ++++++++---- src/components/Movie.js | 30 +++++++++++++---- src/components/MovieHeader.js | 21 +++++++++--- src/components/MovieList.js | 15 +++++---- src/index.js | 11 ++++--- src/reducers/favoritesReducer.js | 31 ++++++++++++++++++ src/reducers/index.js | 6 +++- src/reducers/movieReducer.js | 8 ++++- 12 files changed, 178 insertions(+), 60 deletions(-) create mode 100644 src/reducers/favoritesReducer.js diff --git a/README.md b/README.md index f8ae4e56..77f6010c 100755 --- a/README.md +++ b/README.md @@ -17,62 +17,62 @@ In this project, you take a fairly complex application used to search a movie da ## Instructions ### Task 1: Project Set Up -* [ ] Create a forked copy of this project. -* [ ] Clone your OWN version of the repository in your terminal -* [ ] cd into the project base directory `cd web-module-project-redux` -* [ ] Download project dependencies by running `npm install`` -* [ ] Start up the app using `npm start` +* [x] Create a forked copy of this project. +* [x] Clone your OWN version of the repository in your terminal +* [x] cd into the project base directory `cd web-module-project-redux` +* [x] Download project dependencies by running `npm install`` +* [x] Start up the app using `npm start` ### Task 2: Project Requirements #### Setup Redux > *The DOM and movie reducer has been provided for you, but it's up to to connect it to redux...* -* [ ] In index.js, make use of the createStore method and Provider component to link your App to redux. +* [x] In index.js, make use of the createStore method and Provider component to link your App to redux. #### Connecting the Movie reducer > *Within the reducers folder is the movieReducers file. We have the state already setup it up here with some initial data. Let's connect that state to our component.* -* [ ] **In movieReducer.js, make sure that we are setting our state by default to initialState.** Otherwise your state will not have the original structure it needs to function! +* [x] **In movieReducer.js, make sure that we are setting our state by default to initialState.** Otherwise your state will not have the original structure it needs to function! -* [ ] **The MovieList component prints all of our movies to the screen.** Use the connect method here to map the movies state value into props. Replace our static movie variable with that prop. +* [x] **The MovieList component prints all of our movies to the screen.** Use the connect method here to map the movies state value into props. Replace our static movie variable with that prop. -* [ ] **The Movie component needs to access our list of movies to function.** Map movies to props here as well. +* [x] **The Movie component needs to access our list of movies to function.** Map movies to props here as well. -* [ ] **Finally, MovieHeader uses appTitle to display the title text.** Connect this component to appTitle and test appTitle is correctly displayed in your app. +* [x] **Finally, MovieHeader uses appTitle to display the title text.** Connect this component to appTitle and test appTitle is correctly displayed in your app. #### Connecting the Delete and Add Movie actions > *Looks like you got a good handle on mapping stateToProps! Now let's connect some actions.* -* [ ] Note that the deleteMovie reducer case and action creator are already available. +* [x] Note that the deleteMovie reducer case and action creator are already available. -* [ ] **We can delete movies within the Movie Component.** Connect the deleteMovie action through the connect method. +* [x] **We can delete movies within the Movie Component.** Connect the deleteMovie action through the connect method. -* [ ] **Find the HTML element that should trigger a deletion in the movie component.** Create and connect the necessary event handlers to call deleteMovie on the current movie's id. After setting the state, redirect the user using the push('/movies') command. +* [x] **Find the HTML element that should trigger a deletion in the movie component.** Create and connect the necessary event handlers to call deleteMovie on the current movie's id. After setting the state, redirect the user using the push('/movies') command. -* [ ] Add in an ADD_MOVIE case to movieReducer.js. -* [ ] Make this new case return a version of state with new movie values passed in through the payload. -* [ ] Create an action creator for addMovie in movieActions.js. -* [ ] Find the component that triggers the adding of a movie and connect the addMovie action. -* [ ] Create and connect the necessary event handlers to call addMovie. -* [ ] Add in push('/movies/) after calling your action to trigger a redirect. +* [x] Add in an ADD_MOVIE case to movieReducer.js. +* [x] Make this new case return a version of state with new movie values passed in through the payload. +* [x] Create an action creator for addMovie in movieActions.js. +* [x] Find the component that triggers the adding of a movie and connect the addMovie action. +* [x] Create and connect the necessary event handlers to call addMovie. +* [x] Add in push('/movies/) after calling your action to trigger a redirect. #### Build out the favorites reducer > *Alright! Now that the movie reducer is complete, you have the chance to build a reducer from scratch to handle favorite movie functionality. We will also work on combining reducers.* -* [ ] Create a reducer file for handling business logic for favorites. Include the following state values in your initialState setup: +* [x] Create a reducer file for handling business logic for favorites. Include the following state values in your initialState setup: - favorites: an array of movie objects - displayFavorites: a boolean that holds if favorite elements should be displayed in app -* [ ] **Import your new reducer file into the ./reducers/index.js file.** As a start, only add a default case to the switch statement. +* [x] **Import your new reducer file into the ./reducers/index.js file.** As a start, only add a default case to the switch statement. -* [ ] **In reducers/index.js, use the combineReducers method to connect both movies and favorite movies to redux.** +* [x] **In reducers/index.js, use the combineReducers method to connect both movies and favorite movies to redux.** -* [ ] **Notice that your movie functions no longer work. Why?** Make changes necessary to get the component connected to the movie reducer working again. +* [x] **Notice that your movie functions no longer work. Why?** Make changes necessary to get the component connected to the movie reducer working again. -* [ ] Connect the favorites state to the FavoriteMovieList component and test. +* [x] Connect the favorites state to the FavoriteMovieList component and test. -* [ ] Connect the displayFavorites state to the Movie and MovieHeader component. +* [x] Connect the displayFavorites state to the Movie and MovieHeader component. #### Build out the favorites actions > *Now is your chance to build our all the rest of the app on your own. You can do this!* diff --git a/src/App.js b/src/App.js index cb66bfe6..89c3239e 100644 --- a/src/App.js +++ b/src/App.js @@ -13,6 +13,7 @@ import FavoriteMovieList from './components/FavoriteMovieList'; const App = props => { const displayFavorites = true; + console.log("props from App: ", props) return (
@@ -23,7 +24,7 @@ const App = props => {
- {displayFavorites && } + {props.favorites.displayFavorites && } @@ -48,4 +49,10 @@ const App = props => { ); }; -export default App; \ No newline at end of file +const mapStateToProps = (state)=>{ + return{ + favorites: state.favorites + } +} + +export default connect(mapStateToProps)(App); \ No newline at end of file diff --git a/src/actions/movieActions.js b/src/actions/movieActions.js index 3fb8c9dd..fa6c9b59 100644 --- a/src/actions/movieActions.js +++ b/src/actions/movieActions.js @@ -1,5 +1,24 @@ export const DELETE_MOVIE = "DELETE_MOVIE"; +export const ADD_MOVIE = "ADD_MOVIE"; +export const ADD_FAVORITE = "ADD_FAVORITE"; +export const DELETE_FAVORITE = "DELETE_FAVORITE"; +export const TOGGLE_FAVORITE = "TOGGLE_FAVORITE"; export const deleteMovie = (id)=>{ return({type: DELETE_MOVIE, payload:id}); -} \ No newline at end of file +} + +export const addMovie = (newMovie) =>{ + return({type: ADD_MOVIE, payload: newMovie}) +} + +export const addFavorite = (e) =>{ + return({type: ADD_FAVORITE, payload: e}) +} + +export const deleteFavorite = (e) =>{ + return({type: DELETE_FAVORITE, payload: e}) +} +export const toggleFavorite = (e) =>{ + return({type: TOGGLE_FAVORITE}) +} diff --git a/src/components/AddMovieForm.js b/src/components/AddMovieForm.js index d8a4d768..57558125 100644 --- a/src/components/AddMovieForm.js +++ b/src/components/AddMovieForm.js @@ -12,7 +12,8 @@ const AddMovieForm = (props) => { director: "", genre: "", metascore: 0, - description:"" + description:"", + id: Date.now() }); const handleChange = (e) => { @@ -23,6 +24,12 @@ const AddMovieForm = (props) => { } const handleSubmit = (e) => { + + } + + const oneMoreMovie=()=>{ + props.addMovie(movie) + push('/movies/'); } const { title, director, genre, metascore, description } = movie; @@ -58,7 +65,7 @@ const AddMovieForm = (props) => {
- +
@@ -67,4 +74,4 @@ const AddMovieForm = (props) => {
); } -export default AddMovieForm; \ No newline at end of file +export default connect(null,{addMovie})(AddMovieForm); \ No newline at end of file diff --git a/src/components/FavoriteMovieList.js b/src/components/FavoriteMovieList.js index 54f4383f..c28d27a6 100644 --- a/src/components/FavoriteMovieList.js +++ b/src/components/FavoriteMovieList.js @@ -1,19 +1,22 @@ import React from 'react'; - +import { connect } from 'react-redux'; import { Link } from 'react-router-dom'; +import { deleteFavorite } from '../actions/movieActions'; const FavoriteMovieList = (props) => { - const favorites = []; - + const dltFav = (id) =>{ + props.deleteFavorite(id); + } + return (
Favorite Movies
{ - favorites.map(movie=>{ + props.favorites.favorites.map(movie=>{ return
{movie.title} - remove_circle + remove_circle
}) @@ -21,5 +24,11 @@ const FavoriteMovieList = (props) => {
); } +const mapStateToProps = (state) =>{ + return{ + favorites: state.favorites + } + +} -export default FavoriteMovieList; \ No newline at end of file +export default connect(mapStateToProps,{ deleteFavorite })(FavoriteMovieList); \ No newline at end of file diff --git a/src/components/Movie.js b/src/components/Movie.js index 373201e5..f18da130 100644 --- a/src/components/Movie.js +++ b/src/components/Movie.js @@ -1,13 +1,24 @@ import React from 'react'; import { useParams, useHistory } from 'react-router-dom'; +import { connect } from 'react-redux'; +import { deleteMovie, addFavorite } from '../actions/movieActions'; const Movie = (props) => { const { id } = useParams(); const { push } = useHistory(); - - const movies = []; - const movie = movies.find(movie=>movie.id===Number(id)); + const movie = props.cinema.movies.find(movie=>movie.id===Number(id)); + + + const dltMovie = (id) =>{ + props.deleteMovie(id); + push('/movies') + } + + const addCinema = () =>{ + props.addFavorite(movie) + } + return(
@@ -37,8 +48,8 @@ const Movie = (props) => {
- Favorite - + Favorite +
@@ -47,4 +58,11 @@ const Movie = (props) => {
); } -export default Movie; \ No newline at end of file +const mapStateToProps = (state) =>{ + return{ + cinema: state.cinema, + favorites: state.favorites + } +} + +export default connect(mapStateToProps, { deleteMovie, addFavorite })(Movie); \ No newline at end of file diff --git a/src/components/MovieHeader.js b/src/components/MovieHeader.js index e3443e5f..d8f518b2 100644 --- a/src/components/MovieHeader.js +++ b/src/components/MovieHeader.js @@ -1,17 +1,21 @@ import React from 'react'; import { Link } from 'react-router-dom'; +import { connect } from 'react-redux'; +import { toggleFavorite } from '../actions/movieActions'; const MovieHeader = (props) => { - const appTitle = ""; - const displayFavorites = true; + + const disFav = () =>{ + props.toggleFavorite(); + } return(
-

{appTitle}

+

{props.appTitle}

-
{ displayFavorites ? "Hide" : "Show"} Favorites
+
{ props.favorites.displayFavorites ? "Hide" : "Show"} Favorites
View All Movies Add New Movie
@@ -19,4 +23,11 @@ const MovieHeader = (props) => {
); } -export default MovieHeader; \ No newline at end of file +const mapStateToProps = (state) =>{ + return{ + appTitle: state.cinema.appTitle, + favorites: state.favorites + } +} + +export default connect(mapStateToProps, {toggleFavorite})(MovieHeader); \ No newline at end of file diff --git a/src/components/MovieList.js b/src/components/MovieList.js index 268c7809..086525b5 100644 --- a/src/components/MovieList.js +++ b/src/components/MovieList.js @@ -1,11 +1,9 @@ import React from 'react'; - +import { connect } from 'react-redux'; import MovieListItem from './MovieListItem'; import MovieFooter from './MovieFooter'; const MovieList = (props)=> { - const movies = []; - return (
@@ -21,14 +19,19 @@ const MovieList = (props)=> { { - movies.map(movie=>) + props.cinema.movies.map(movie=>) }
- +
); } -export default MovieList; \ No newline at end of file +const mapStateToProps = (state) =>{ + return{ + cinema: state.cinema + } +} +export default connect(mapStateToProps)(MovieList); \ No newline at end of file diff --git a/src/index.js b/src/index.js index dfc70e99..f2ed6f1b 100644 --- a/src/index.js +++ b/src/index.js @@ -3,15 +3,18 @@ import ReactDOM from 'react-dom'; import { createStore } from 'redux'; import { Provider} from 'react-redux'; -import reducer from './reducers'; +import combineReducer from './reducers'; import App from './App' import { BrowserRouter as Router } from 'react-router-dom'; import './index.css'; +const store = createStore(combineReducer) ReactDOM.render( - - - , + + + + + , document.getElementById('root') ); diff --git a/src/reducers/favoritesReducer.js b/src/reducers/favoritesReducer.js new file mode 100644 index 00000000..19597838 --- /dev/null +++ b/src/reducers/favoritesReducer.js @@ -0,0 +1,31 @@ +import { ADD_FAVORITE, DELETE_FAVORITE, TOGGLE_FAVORITE } from '../actions/movieActions.js'; + +const initialState = { + favorites: [], + displayFavorites: true +} + + +const reducer = (state = initialState, action) => { + switch(action.type) { + case DELETE_FAVORITE: + return { + ...state, + favorites: state.favorites.filter(item=>(action.payload !== item.id)) + } + case ADD_FAVORITE: + return{ + ...state, + favorites: [...state.favorites, action.payload] + } + case TOGGLE_FAVORITE: + return{ + ...state, + displayFavorites: !state.displayFavorites + } + default: + return state; + } +} + +export default reducer; \ No newline at end of file diff --git a/src/reducers/index.js b/src/reducers/index.js index 6629609c..89c85827 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,5 +1,9 @@ import { combineReducers } from 'redux'; import movieReducer from './movieReducer'; +import favoriteReducer from './favoritesReducer' -export default movieReducer; \ No newline at end of file +export default combineReducers({ + cinema: movieReducer, + favorites: favoriteReducer +}); \ No newline at end of file diff --git a/src/reducers/movieReducer.js b/src/reducers/movieReducer.js index 16f33bcd..7b32475c 100644 --- a/src/reducers/movieReducer.js +++ b/src/reducers/movieReducer.js @@ -6,12 +6,18 @@ const initialState = { appTitle: "IMDB Movie Database" } -const reducer = (state, action) => { +const reducer = (state = initialState, action) => { switch(action.type) { case DELETE_MOVIE: return { + ...state, movies: state.movies.filter(item=>(action.payload !== item.id)) } + case ADD_MOVIE: + return{ + ...state, + movies: [...state.movies, action.payload] + } default: return state; }