From ba2614b28c2126f31664afe5ecab87dca08d9b79 Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 25 Oct 2021 22:22:35 +0300 Subject: [PATCH 1/5] 4.1 - fixed restaurants and reviews reducers --- src/redux/reducer/restaurants.js | 7 ++++++- src/redux/reducer/reviews.js | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/redux/reducer/restaurants.js b/src/redux/reducer/restaurants.js index e7f30c6..226c7f2 100644 --- a/src/redux/reducer/restaurants.js +++ b/src/redux/reducer/restaurants.js @@ -1,4 +1,9 @@ -import { normalizedRestaurants as defaultRestaurants } from '../../fixtures'; +import { normalizedRestaurants } from '../../fixtures'; + +const defaultRestaurants = normalizedRestaurants.reduce( + (acc, restaurant) => ({ ...acc, [restaurant.id]: restaurant }), + {} +); export default (restaurants = defaultRestaurants, action) => { const { type } = action; diff --git a/src/redux/reducer/reviews.js b/src/redux/reducer/reviews.js index 494b5cd..fb5eba9 100644 --- a/src/redux/reducer/reviews.js +++ b/src/redux/reducer/reviews.js @@ -1,4 +1,9 @@ -import { normalizedReviews as defaultReviews } from '../../fixtures'; +import { normalizedReviews } from '../../fixtures'; + +const defaultReviews = normalizedReviews.reduce( + (acc, review) => ({ ...acc, [review.id]: review }), + {} +); export default (reviews = defaultReviews, action) => { const { type } = action; From 795dfc50adc4eaa7fcebdcfc47697bcb0f395a66 Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 25 Oct 2021 22:24:44 +0300 Subject: [PATCH 2/5] 4.2 added users reducer --- src/redux/reducer/users.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/redux/reducer/users.js diff --git a/src/redux/reducer/users.js b/src/redux/reducer/users.js new file mode 100644 index 0000000..a995cbe --- /dev/null +++ b/src/redux/reducer/users.js @@ -0,0 +1,15 @@ +import { normalizedUsers } from '../../fixtures'; + +const defaultUsers = normalizedUsers.reduce( + (acc, user) => ({ ...acc, [user.id]: user }), + {} +); + +export default (users = defaultUsers, action) => { + const { type } = action; + + switch (type) { + default: + return users; + } +}; From 1552d9d17c6ca305eda33f609c8a82ac64d56b87 Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 25 Oct 2021 23:46:29 +0300 Subject: [PATCH 3/5] 4.3 Fixed Review --- src/components/reviews/review/review.js | 11 +++++++++-- src/components/reviews/reviews.js | 7 ++++++- src/redux/reducer/index.js | 2 ++ src/redux/reducer/restaurants.js | 7 +------ src/redux/selectors.js | 3 +++ 5 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/components/reviews/review/review.js b/src/components/reviews/review/review.js index fe89ecb..8aba96c 100644 --- a/src/components/reviews/review/review.js +++ b/src/components/reviews/review/review.js @@ -1,5 +1,6 @@ import PropTypes from 'prop-types'; - +import { connect } from 'react-redux'; +import review from '.'; import Rate from '../../rate'; import styles from './review.module.css'; @@ -31,4 +32,10 @@ Review.defaultProps = { user: 'Anonymous', }; -export default Review; +const mapStateToProps = (state, props) => ({ + text: props.text, + rating: props.rating, + user: state.users[props.userId].name, +}); + +export default connect(mapStateToProps)(Review); diff --git a/src/components/reviews/reviews.js b/src/components/reviews/reviews.js index 66f6cf1..22a0aa2 100644 --- a/src/components/reviews/reviews.js +++ b/src/components/reviews/reviews.js @@ -1,4 +1,5 @@ import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; import Review from './review'; import ReviewForm from './review-form'; import styles from './reviews.module.css'; @@ -22,4 +23,8 @@ Reviews.propTypes = { ).isRequired, }; -export default Reviews; +const mapStateToProps = (state, props) => ({ + reviews: props.reviews.map((review) => state.reviews[review]), +}); + +export default connect(mapStateToProps)(Reviews); diff --git a/src/redux/reducer/index.js b/src/redux/reducer/index.js index f86f67d..3b5c632 100644 --- a/src/redux/reducer/index.js +++ b/src/redux/reducer/index.js @@ -3,10 +3,12 @@ import order from './order'; import restaurants from './restaurants'; import products from './products'; import reviews from './reviews'; +import users from './users'; export default combineReducers({ order, restaurants, products, reviews, + users, }); diff --git a/src/redux/reducer/restaurants.js b/src/redux/reducer/restaurants.js index 226c7f2..e7f30c6 100644 --- a/src/redux/reducer/restaurants.js +++ b/src/redux/reducer/restaurants.js @@ -1,9 +1,4 @@ -import { normalizedRestaurants } from '../../fixtures'; - -const defaultRestaurants = normalizedRestaurants.reduce( - (acc, restaurant) => ({ ...acc, [restaurant.id]: restaurant }), - {} -); +import { normalizedRestaurants as defaultRestaurants } from '../../fixtures'; export default (restaurants = defaultRestaurants, action) => { const { type } = action; diff --git a/src/redux/selectors.js b/src/redux/selectors.js index 887af3f..5465956 100644 --- a/src/redux/selectors.js +++ b/src/redux/selectors.js @@ -3,6 +3,9 @@ import { createSelector } from 'reselect'; // const restaurantsSelector = (state) => state.restaurants; const productsSelector = (state) => state.products; const orderSelector = (state) => state.order; +const restaurantsSelector = (state) => state.restaurants; +const reviewsSelector = (state) => state.reviews; +const usersSelector = (state) => state.users; export const orderProductsSelector = createSelector( orderSelector, From f58193bb408c652966750eae1e9e0d452f8cb6f6 Mon Sep 17 00:00:00 2001 From: Alexey Date: Tue, 26 Oct 2021 04:38:19 +0300 Subject: [PATCH 4/5] 4.4 selectors --- src/components/menu/menu.js | 14 ++-- src/components/product/product.js | 5 +- src/components/restaurant/restaurant.js | 50 ++++++++----- src/components/restaurants/restaurants.js | 44 +++++------- src/components/reviews/review/review.js | 59 +++++++-------- src/components/reviews/reviews.js | 11 ++- src/redux/constants.js | 1 + src/redux/reducer/restaurants.js | 7 +- src/redux/reducer/reviews.js | 8 ++- src/redux/selectors.js | 88 +++++++++++++++++++++-- 10 files changed, 190 insertions(+), 97 deletions(-) diff --git a/src/components/menu/menu.js b/src/components/menu/menu.js index aebcf81..e604a2a 100644 --- a/src/components/menu/menu.js +++ b/src/components/menu/menu.js @@ -7,13 +7,13 @@ import Basket from '../basket'; import styles from './menu.module.css'; class Menu extends Component { - static propTypes = { - menu: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - }).isRequired - ).isRequired, - }; + // static propTypes = { + // menu: PropTypes.arrayOf( + // PropTypes.shape({ + // id: PropTypes.string.isRequired, + // }).isRequired + // ).isRequired, + // }; state = { error: null }; diff --git a/src/components/product/product.js b/src/components/product/product.js index 71ce160..1f81ef2 100644 --- a/src/components/product/product.js +++ b/src/components/product/product.js @@ -4,6 +4,7 @@ import PropTypes from 'prop-types'; import styles from './product.module.css'; import Button from '../button'; import { decrement, increment } from '../../redux/actions'; +import { productAmountSelector, productSelector } from '../../redux/selectors'; function Product({ product, amount, decrement, increment, fetchData }) { useEffect(() => { @@ -56,8 +57,8 @@ Product.propTypes = { }; const mapStateToProps = (state, props) => ({ - amount: state.order[props.id] || 0, - product: state.products[props.id], + amount: productAmountSelector(state)(props.id), + product: productSelector(state)(props.id), }); // const mapDispatchToProps = { diff --git a/src/components/restaurant/restaurant.js b/src/components/restaurant/restaurant.js index 364e73c..3129e0c 100644 --- a/src/components/restaurant/restaurant.js +++ b/src/components/restaurant/restaurant.js @@ -5,16 +5,21 @@ import Reviews from '../reviews'; import Banner from '../banner'; import Rate from '../rate'; import Tabs from '../tabs'; +import { connect } from 'react-redux'; +import { + averageRatingSelector, + restaurantSelector, +} from '../../redux/selectors'; -const Restaurant = ({ restaurant }) => { +const Restaurant = ({ restaurant, averageRating }) => { const { id, name, menu, reviews } = restaurant; - + console.log('----- restaraunt.reviews: ', reviews); const [activeTab, setActiveTab] = useState('menu'); - const averageRating = useMemo(() => { - const total = reviews.reduce((acc, { rating }) => acc + rating, 0); - return Math.round(total / reviews.length); - }, [reviews]); + // const averageRating = useMemo(() => { + // const total = reviews.reduce((acc, { rating }) => acc + rating, 0); + // return Math.round(total / reviews.length); + // }, [reviews]); const tabs = [ { id: 'menu', label: 'Menu' }, @@ -33,17 +38,26 @@ const Restaurant = ({ restaurant }) => { ); }; -Restaurant.propTypes = { - restaurant: PropTypes.shape({ - id: PropTypes.string.isRequired, - name: PropTypes.string, - menu: PropTypes.array, - reviews: PropTypes.arrayOf( - PropTypes.shape({ - rating: PropTypes.number.isRequired, - }).isRequired - ).isRequired, - }).isRequired, +Restaurant.defaultProps = { + averageRating: 3, }; -export default Restaurant; +// Restaurant.propTypes = { +// restaurant: PropTypes.shape({ +// id: PropTypes.string.isRequired, +// name: PropTypes.string, +// menu: PropTypes.array, +// reviews: PropTypes.arrayOf( +// PropTypes.shape({ +// rating: PropTypes.number.isRequired, +// }).isRequired +// ).isRequired, +// }).isRequired, +// }; + +export default connect((state, props) => { + return { + restaurant: restaurantSelector(state)(props.id), + averageRating: averageRatingSelector(state)(props.id), + }; +})(Restaurant); diff --git a/src/components/restaurants/restaurants.js b/src/components/restaurants/restaurants.js index 2037758..bca9080 100644 --- a/src/components/restaurants/restaurants.js +++ b/src/components/restaurants/restaurants.js @@ -3,39 +3,31 @@ import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import Restaurant from '../restaurant'; import Tabs from '../tabs'; +import { tabsSelector, restaurantsSelector } from '../../redux/selectors'; -function Restaurants({ restaurants }) { - const [activeId, setActiveId] = useState(restaurants[0].id); - - const tabs = useMemo( - () => restaurants.map(({ id, name }) => ({ id, label: name })), - [restaurants] - ); - - const activeRestaurant = useMemo( - () => restaurants.find((restaurant) => restaurant.id === activeId), - [activeId, restaurants] - ); +function Restaurants({ restaurants, tabs }) { + const [activeId, setActiveId] = useState(restaurants[0]); return (
- +
); } -Restaurants.propTypes = { - restaurants: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - name: PropTypes.string, - }).isRequired - ).isRequired, -}; - -const mapStateToProps = (state) => ({ - restaurants: state.restaurants, -}); +// Restaurants.propTypes = { +// restaurants: PropTypes.arrayOf( +// PropTypes.shape({ +// id: PropTypes.string.isRequired, +// name: PropTypes.string, +// }).isRequired +// ).isRequired, +// }; -export default connect(mapStateToProps)(Restaurants); +export default connect((state) => { + return { + tabs: tabsSelector(state), + restaurants: restaurantsSelector(state), + }; +})(Restaurants); diff --git a/src/components/reviews/review/review.js b/src/components/reviews/review/review.js index 8aba96c..8ff9468 100644 --- a/src/components/reviews/review/review.js +++ b/src/components/reviews/review/review.js @@ -1,41 +1,44 @@ import PropTypes from 'prop-types'; import { connect } from 'react-redux'; -import review from '.'; +import { reviewsSelector, userSelector } from '../../../redux/selectors'; import Rate from '../../rate'; import styles from './review.module.css'; -const Review = ({ user, text, rating }) => ( -
-
-
-

- {user} -

-

- {text} -

-
-
- +const Review = ({ user, review }) => { + const { text, rating } = review; + console.log(review); + return ( +
+
+
+

+ {user} +

+

+ {text} +

+
+
+ +
-
-); - -Review.propTypes = { - user: PropTypes.string, - text: PropTypes.string, - rating: PropTypes.number.isRequired, + ); }; +// Review.propTypes = { +// user: PropTypes.string, +// text: PropTypes.string, +// rating: PropTypes.number.isRequired, +// }; + Review.defaultProps = { user: 'Anonymous', }; -const mapStateToProps = (state, props) => ({ - text: props.text, - rating: props.rating, - user: state.users[props.userId].name, -}); - -export default connect(mapStateToProps)(Review); +export default connect((state, props) => { + return { + review: reviewsSelector(state)(props.id), + user: userSelector(state)(props.id), + }; +})(Review); diff --git a/src/components/reviews/reviews.js b/src/components/reviews/reviews.js index 22a0aa2..e9d8e1b 100644 --- a/src/components/reviews/reviews.js +++ b/src/components/reviews/reviews.js @@ -1,5 +1,6 @@ import PropTypes from 'prop-types'; import { connect } from 'react-redux'; +import { reviewsSelector } from '../../redux/selectors'; import Review from './review'; import ReviewForm from './review-form'; import styles from './reviews.module.css'; @@ -7,8 +8,8 @@ import styles from './reviews.module.css'; const Reviews = ({ reviews }) => { return (
- {reviews.map((review) => ( - + {reviews.map((id) => ( + ))}
@@ -23,8 +24,4 @@ Reviews.propTypes = { ).isRequired, }; -const mapStateToProps = (state, props) => ({ - reviews: props.reviews.map((review) => state.reviews[review]), -}); - -export default connect(mapStateToProps)(Reviews); +export default connect()(Reviews); diff --git a/src/redux/constants.js b/src/redux/constants.js index 9cfa25d..715146f 100644 --- a/src/redux/constants.js +++ b/src/redux/constants.js @@ -1,3 +1,4 @@ export const INCREMENT = 'INCREMENT'; export const DECREMENT = 'DECREMENT'; export const REMOVE = 'REMOVE'; +export const SUBMIT = 'SUBMIT'; diff --git a/src/redux/reducer/restaurants.js b/src/redux/reducer/restaurants.js index e7f30c6..226c7f2 100644 --- a/src/redux/reducer/restaurants.js +++ b/src/redux/reducer/restaurants.js @@ -1,4 +1,9 @@ -import { normalizedRestaurants as defaultRestaurants } from '../../fixtures'; +import { normalizedRestaurants } from '../../fixtures'; + +const defaultRestaurants = normalizedRestaurants.reduce( + (acc, restaurant) => ({ ...acc, [restaurant.id]: restaurant }), + {} +); export default (restaurants = defaultRestaurants, action) => { const { type } = action; diff --git a/src/redux/reducer/reviews.js b/src/redux/reducer/reviews.js index fb5eba9..2ef5c0b 100644 --- a/src/redux/reducer/reviews.js +++ b/src/redux/reducer/reviews.js @@ -1,4 +1,5 @@ import { normalizedReviews } from '../../fixtures'; +import { SUBMIT } from '../constants'; const defaultReviews = normalizedReviews.reduce( (acc, review) => ({ ...acc, [review.id]: review }), @@ -6,9 +7,14 @@ const defaultReviews = normalizedReviews.reduce( ); export default (reviews = defaultReviews, action) => { - const { type } = action; + const { type, review } = action; switch (type) { + case SUBMIT: + return { + ...reviews, + [review.id]: review, + }; default: return reviews; } diff --git a/src/redux/selectors.js b/src/redux/selectors.js index 5465956..a4057d3 100644 --- a/src/redux/selectors.js +++ b/src/redux/selectors.js @@ -1,15 +1,15 @@ import { createSelector } from 'reselect'; // const restaurantsSelector = (state) => state.restaurants; -const productsSelector = (state) => state.products; -const orderSelector = (state) => state.order; -const restaurantsSelector = (state) => state.restaurants; -const reviewsSelector = (state) => state.reviews; -const usersSelector = (state) => state.users; +const productsListSelector = (state) => state.products; +const orderListSelector = (state) => state.order; +const restaurantsListSelector = (state) => state.restaurants; +const reviewsListSelector = (state) => state.reviews; +const usersListSelector = (state) => state.users; export const orderProductsSelector = createSelector( - orderSelector, - productsSelector, + orderListSelector, + productsListSelector, (order, products) => Object.keys(order) .filter((productId) => order[productId] > 0) @@ -26,3 +26,77 @@ export const totalSelector = createSelector( (orderProducts) => orderProducts.reduce((acc, { subtotal }) => acc + subtotal, 0) ); + +export const userSelector = createSelector( + usersListSelector, + reviewsListSelector, + (usersList, reviewsList) => { + return function (id) { + const review = reviewsList[id]; + const user = usersList[review.userId].name; + return user; + }; + } +); + +export const reviewsSelector = createSelector( + reviewsListSelector, + (reviewsList) => { + return function (id) { + return reviewsList[id]; + }; + } +); + +export const productSelector = createSelector( + productsListSelector, + (productList) => { + return function (id) { + return productList[id]; + }; + } +); + +export const productAmountSelector = createSelector( + orderListSelector, + (orderList) => { + return function (id) { + return orderList[id] || 0; + }; + } +); + +export const averageRatingSelector = createSelector( + restaurantsListSelector, + reviewsListSelector, + (restaurantList, reviewsList) => { + return function (restaurantId) { + const restaurant = restaurantList[restaurantId]; + const sum = restaurant.reviews + .map((reviewId) => reviewsList[reviewId]) + .reduce((acc, { rating }) => acc + rating, 0); + const averageRating = Math.round(sum / restaurant.reviews.length); + return averageRating; + }; + } +); + +export const tabsSelector = createSelector( + restaurantsListSelector, + (restaurants) => + Object.values(restaurants).map(({ id, name }) => ({ id, label: name })) +); + +export const restaurantsSelector = createSelector( + restaurantsListSelector, + (restaurantList) => Object.keys(restaurantList) +); + +export const restaurantSelector = createSelector( + restaurantsListSelector, + (restaurantList) => { + return function (restaurantId) { + return restaurantList[restaurantId]; + }; + } +); From 4079ef24ab1c9420fb6e1cc2e71a5440f52feac8 Mon Sep 17 00:00:00 2001 From: Alexey Date: Tue, 26 Oct 2021 07:27:07 +0300 Subject: [PATCH 5/5] 4.5 , 4.6 - added middleware and posibility to add a new review --- package.json | 3 ++- src/components/restaurant/restaurant.js | 5 +++-- .../reviews/review-form/review-form.js | 22 ++++++++++++------- src/components/reviews/review/review.js | 1 - src/components/reviews/reviews.js | 18 +++++++-------- src/redux/actions.js | 3 ++- src/redux/middleware/idCreator.js | 15 +++++++++++++ src/redux/reducer/restaurants.js | 15 ++++++++++++- src/redux/reducer/reviews.js | 5 +++-- src/redux/reducer/users.js | 9 +++++++- src/redux/store.js | 3 ++- yarn.lock | 2 +- 12 files changed, 73 insertions(+), 28 deletions(-) create mode 100644 src/redux/middleware/idCreator.js diff --git a/package.json b/package.json index ba1b4a1..21dae21 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "react-scripts": "4.0.3", "redux": "^4.1.1", "redux-devtools-extension": "^2.13.9", - "reselect": "^4.0.0" + "reselect": "^4.0.0", + "uuid": "^8.3.2" }, "scripts": { "start": "react-scripts start", diff --git a/src/components/restaurant/restaurant.js b/src/components/restaurant/restaurant.js index 3129e0c..0887cc1 100644 --- a/src/components/restaurant/restaurant.js +++ b/src/components/restaurant/restaurant.js @@ -13,7 +13,6 @@ import { const Restaurant = ({ restaurant, averageRating }) => { const { id, name, menu, reviews } = restaurant; - console.log('----- restaraunt.reviews: ', reviews); const [activeTab, setActiveTab] = useState('menu'); // const averageRating = useMemo(() => { @@ -33,7 +32,9 @@ const Restaurant = ({ restaurant, averageRating }) => { {activeTab === 'menu' && } - {activeTab === 'reviews' && } + {activeTab === 'reviews' && ( + + )}
); }; diff --git a/src/components/reviews/review-form/review-form.js b/src/components/reviews/review-form/review-form.js index 1267e77..cbb441c 100644 --- a/src/components/reviews/review-form/review-form.js +++ b/src/components/reviews/review-form/review-form.js @@ -1,19 +1,18 @@ import { connect } from 'react-redux'; - import useForm from '../../../hooks/use-form'; import Rate from '../../rate'; import Button from '../../button'; - import styles from './review-form.module.css'; +import { submit } from '../../../redux/actions'; +import { restaurantSelector } from '../../../redux/selectors'; const INITIAL_VALUES = { name: '', text: '', rating: 3 }; -const ReviewForm = ({ onSubmit }) => { +const ReviewForm = ({ onSubmit, restaurantId }) => { const { values, handlers, reset } = useForm(INITIAL_VALUES); - const handleSubmit = (ev) => { ev.preventDefault(); - onSubmit(values); + onSubmit({ ...values, restaurantId }); reset(); }; @@ -51,6 +50,13 @@ const ReviewForm = ({ onSubmit }) => { ); }; -export default connect(null, () => ({ - onSubmit: (values) => console.log(values), // TODO -}))(ReviewForm); +const mapStateToProps = (state, props) => { + return { + restaurantId: props.restaurantId, + }; +}; +const mapDispatchToProps = (dispatch) => ({ + onSubmit: (values) => dispatch(submit(values)), +}); + +export default connect(mapStateToProps, mapDispatchToProps)(ReviewForm); diff --git a/src/components/reviews/review/review.js b/src/components/reviews/review/review.js index 8ff9468..0fde169 100644 --- a/src/components/reviews/review/review.js +++ b/src/components/reviews/review/review.js @@ -6,7 +6,6 @@ import styles from './review.module.css'; const Review = ({ user, review }) => { const { text, rating } = review; - console.log(review); return (
diff --git a/src/components/reviews/reviews.js b/src/components/reviews/reviews.js index e9d8e1b..c76ff57 100644 --- a/src/components/reviews/reviews.js +++ b/src/components/reviews/reviews.js @@ -5,23 +5,23 @@ import Review from './review'; import ReviewForm from './review-form'; import styles from './reviews.module.css'; -const Reviews = ({ reviews }) => { +const Reviews = ({ reviews, restaurantId }) => { return (
{reviews.map((id) => ( ))} - +
); }; -Reviews.propTypes = { - reviews: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - }).isRequired - ).isRequired, -}; +// Reviews.propTypes = { +// reviews: PropTypes.arrayOf( +// PropTypes.shape({ +// id: PropTypes.string.isRequired, +// }).isRequired +// ).isRequired, +// }; export default connect()(Reviews); diff --git a/src/redux/actions.js b/src/redux/actions.js index ea78f99..44b6479 100644 --- a/src/redux/actions.js +++ b/src/redux/actions.js @@ -1,5 +1,6 @@ -import { DECREMENT, INCREMENT, REMOVE } from './constants'; +import { DECREMENT, INCREMENT, REMOVE, SUBMIT } from './constants'; export const increment = (id) => ({ type: INCREMENT, id }); export const decrement = (id) => ({ type: DECREMENT, id }); export const remove = (id) => ({ type: REMOVE, id }); +export const submit = (values) => ({ type: SUBMIT, values }); diff --git a/src/redux/middleware/idCreator.js b/src/redux/middleware/idCreator.js new file mode 100644 index 0000000..a9989d1 --- /dev/null +++ b/src/redux/middleware/idCreator.js @@ -0,0 +1,15 @@ +import { v4 as uuidv4 } from 'uuid'; +import { SUBMIT } from '../constants'; +export default (store) => (next) => (action) => { + if (action.type === SUBMIT) { + const reviewId = uuidv4(); + const userId = uuidv4(); + + action.values.userId = userId; + action.values.id = reviewId; + + next(action); + } + + return; +}; diff --git a/src/redux/reducer/restaurants.js b/src/redux/reducer/restaurants.js index 226c7f2..027808a 100644 --- a/src/redux/reducer/restaurants.js +++ b/src/redux/reducer/restaurants.js @@ -1,4 +1,5 @@ import { normalizedRestaurants } from '../../fixtures'; +import { SUBMIT } from '../constants'; const defaultRestaurants = normalizedRestaurants.reduce( (acc, restaurant) => ({ ...acc, [restaurant.id]: restaurant }), @@ -6,9 +7,21 @@ const defaultRestaurants = normalizedRestaurants.reduce( ); export default (restaurants = defaultRestaurants, action) => { - const { type } = action; + const { type, values } = action; switch (type) { + case SUBMIT: + const { values } = action; + const { restaurantId, id } = values; + const restaurant = restaurants[restaurantId]; + return { + ...restaurants, + [restaurantId]: { + ...restaurant, + reviews: [...restaurant.reviews, id], + }, + }; + default: return restaurants; } diff --git a/src/redux/reducer/reviews.js b/src/redux/reducer/reviews.js index 2ef5c0b..1969826 100644 --- a/src/redux/reducer/reviews.js +++ b/src/redux/reducer/reviews.js @@ -7,13 +7,14 @@ const defaultReviews = normalizedReviews.reduce( ); export default (reviews = defaultReviews, action) => { - const { type, review } = action; + const { type, values } = action; switch (type) { case SUBMIT: + const { id, rating, text, userId } = values; return { ...reviews, - [review.id]: review, + [values.id]: { id, rating, text, userId }, }; default: return reviews; diff --git a/src/redux/reducer/users.js b/src/redux/reducer/users.js index a995cbe..b3277c8 100644 --- a/src/redux/reducer/users.js +++ b/src/redux/reducer/users.js @@ -1,4 +1,5 @@ import { normalizedUsers } from '../../fixtures'; +import { SUBMIT } from '../constants'; const defaultUsers = normalizedUsers.reduce( (acc, user) => ({ ...acc, [user.id]: user }), @@ -6,9 +7,15 @@ const defaultUsers = normalizedUsers.reduce( ); export default (users = defaultUsers, action) => { - const { type } = action; + const { type, values } = action; switch (type) { + case SUBMIT: + const { name, userId } = values; + return { + ...users, + [userId]: { id: userId, name }, + }; default: return users; } diff --git a/src/redux/store.js b/src/redux/store.js index 7ac3e5a..8e9b5c8 100644 --- a/src/redux/store.js +++ b/src/redux/store.js @@ -1,5 +1,6 @@ import { applyMiddleware, createStore } from 'redux'; import { composeWithDevTools } from 'redux-devtools-extension'; +import idCreator from './middleware/idCreator'; import logger from './middleware/logger'; @@ -7,5 +8,5 @@ import reducer from './reducer'; export default createStore( reducer, - composeWithDevTools(applyMiddleware(logger)) + composeWithDevTools(applyMiddleware(logger, idCreator)) ); diff --git a/yarn.lock b/yarn.lock index 54e1f92..186009b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11069,7 +11069,7 @@ uuid@^3.3.2, uuid@^3.4.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -uuid@^8.3.0: +uuid@^8.3.0, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==