From d20b9ca9e5c1d4d9f74ff683ff9cfe573dc8ac2f Mon Sep 17 00:00:00 2001 From: Ivan Metelev Date: Mon, 1 Nov 2021 11:55:58 +0300 Subject: [PATCH] HT6 --- src/components/app/app.js | 2 +- .../basket/basket-item/basket-item.js | 13 ++++++- src/components/menu/menu.js | 2 + src/components/restaurant/restaurant.js | 29 +++++++++------ src/components/reviews/reviews.js | 17 ++++----- src/components/tabs/tabs.js | 37 +++++++++---------- src/redux/reducer/products.js | 6 +++ src/redux/selectors.js | 5 +++ 8 files changed, 67 insertions(+), 44 deletions(-) diff --git a/src/components/app/app.js b/src/components/app/app.js index eebabc8..1e4c909 100644 --- a/src/components/app/app.js +++ b/src/components/app/app.js @@ -10,7 +10,7 @@ export default class App extends PureComponent {
-

Home page

} /> +

404 - Not found :(

} /> diff --git a/src/components/basket/basket-item/basket-item.js b/src/components/basket/basket-item/basket-item.js index ad8be9e..4092ddd 100644 --- a/src/components/basket/basket-item/basket-item.js +++ b/src/components/basket/basket-item/basket-item.js @@ -3,6 +3,8 @@ import cn from 'classnames'; import { increment, decrement, remove } from '../../../redux/actions'; import Button from '../../button'; import styles from './basket-item.module.css'; +import { restaurantIdByProductSelector } from '../../../redux/selectors'; +import { Link } from 'react-router-dom'; function BasketItem({ product, @@ -11,11 +13,14 @@ function BasketItem({ increment, decrement, remove, + restaurantIdByProduct, }) { return (
- {product.name} + + {product.name} +
@@ -36,4 +41,8 @@ const mapDispatchToProps = (dispatch, ownProps) => ({ remove: () => dispatch(remove(ownProps.product.id)), }); -export default connect(null, mapDispatchToProps)(BasketItem); +const mapStateToProps = (state, props) => ({ + restaurantIdByProduct: restaurantIdByProductSelector(state, props.product), +}); + +export default connect(mapStateToProps, mapDispatchToProps)(BasketItem); diff --git a/src/components/menu/menu.js b/src/components/menu/menu.js index 4e19a21..fbe413a 100644 --- a/src/components/menu/menu.js +++ b/src/components/menu/menu.js @@ -6,6 +6,7 @@ import { loadProducts } from '../../redux/actions'; import { productsLoadingSelector, productsLoadedSelector, + menuSelector, } from '../../redux/selectors'; import Loader from '../loader'; @@ -71,6 +72,7 @@ class Menu extends Component { const mapStateToProps = (state, props) => ({ loading: productsLoadingSelector(state, props), loaded: productsLoadedSelector(state, props), + menu: menuSelector(state, props), }); const mapDispatchToProps = { loadProducts }; diff --git a/src/components/restaurant/restaurant.js b/src/components/restaurant/restaurant.js index 8cb7a7f..107dba9 100644 --- a/src/components/restaurant/restaurant.js +++ b/src/components/restaurant/restaurant.js @@ -1,4 +1,3 @@ -import { useState } from 'react'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import Menu from '../menu'; @@ -10,25 +9,31 @@ import { averageRatingSelector, restaurantSelector, } from '../../redux/selectors'; +import { Redirect, Route, Switch } from 'react-router-dom'; const Restaurant = ({ restaurant, averageRating }) => { - const { id, name, menu, reviews } = restaurant; - - const [activeTab, setActiveTab] = useState('menu'); - - const tabs = [ - { id: 'menu', label: 'Menu' }, - { id: 'reviews', label: 'Reviews' }, - ]; + const { id, name } = restaurant; return (
- - {activeTab === 'menu' && } - {activeTab === 'reviews' && } + + + + + { + /* Сохраняем поведение с ререндером*/ + const restId = match.params.restId; + return ; + }} + /> + + +
); }; diff --git a/src/components/reviews/reviews.js b/src/components/reviews/reviews.js index 2b09fda..4697389 100644 --- a/src/components/reviews/reviews.js +++ b/src/components/reviews/reviews.js @@ -1,6 +1,5 @@ import { useEffect } from 'react'; import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; import Review from './review'; import Loader from '../loader'; import ReviewForm from './review-form'; @@ -8,18 +7,22 @@ import styles from './reviews.module.css'; import { loadReviews, loadUsers } from '../../redux/actions'; import { + restaurantSelector, reviewsLoadedSelector, usersLoadedSelector, } from '../../redux/selectors'; const Reviews = ({ - reviews, - restId, + restaurant, loadReviews, loadUsers, usersLoaded, reviewsLoaded, + match, }) => { + const { reviews } = restaurant; + const restId = match.params.restId; + useEffect(() => { loadUsers(); loadReviews(restId); @@ -37,14 +40,10 @@ const Reviews = ({ ); }; -Reviews.propTypes = { - restId: PropTypes.string, - reviews: PropTypes.arrayOf(PropTypes.string.isRequired).isRequired, -}; - const mapStateToProps = (state, props) => ({ - reviewsLoaded: reviewsLoadedSelector(state, props), + reviewsLoaded: reviewsLoadedSelector(state, props.match.params), usersLoaded: usersLoadedSelector(state, props), + restaurant: restaurantSelector(state, { id: props.match.params.restId }), }); const mapDispatchToProps = { diff --git a/src/components/tabs/tabs.js b/src/components/tabs/tabs.js index aa6445c..bbd9ca2 100644 --- a/src/components/tabs/tabs.js +++ b/src/components/tabs/tabs.js @@ -1,33 +1,30 @@ -import PropTypes from 'prop-types'; import cn from 'classnames'; import styles from './tabs.module.css'; +import { Link } from 'react-router-dom'; + +function Tabs({ match }) { + const restId = match.params.restId; + const activeId = match.params.activeId; + + const tabs = [ + { id: 'menu', label: 'Menu' }, + { id: 'reviews', label: 'Reviews' }, + ]; -function Tabs({ tabs, activeId, onChange }) { return (
{tabs.map(({ id, label }) => ( - onChange(id)} - > - {label} - + + + {label} + + ))}
); } -Tabs.propTypes = { - tabs: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - label: PropTypes.string, - }).isRequired - ).isRequired, - activeId: PropTypes.string, - onChange: PropTypes.func.isRequired, -}; - export default Tabs; diff --git a/src/redux/reducer/products.js b/src/redux/reducer/products.js index 6332ef3..96b6965 100644 --- a/src/redux/reducer/products.js +++ b/src/redux/reducer/products.js @@ -7,6 +7,7 @@ const initialState = { loading: {}, loaded: {}, error: null, + toRestaurantMap: {}, }; export default (state = initialState, action) => @@ -23,6 +24,11 @@ export default (state = initialState, action) => draft.loaded[restId] = true; draft.error = null; Object.assign(draft.entities, arrToMap(data)); + + data.forEach((product) => { + draft.toRestaurantMap[product.id] = restId; + }); + break; } case LOAD_PRODUCTS + FAILURE: { diff --git a/src/redux/selectors.js b/src/redux/selectors.js index c3c8da8..f2ad1c9 100644 --- a/src/redux/selectors.js +++ b/src/redux/selectors.js @@ -46,6 +46,11 @@ export const orderProductsSelector = createSelector( subtotal: order[product.id] * product.price, })) ); +export const menuSelector = (state, { restId }) => + restaurantSelector(state, { id: restId }).menu; + +export const restaurantIdByProductSelector = (state, { id }) => + state.products.toRestaurantMap[id]; export const totalSelector = createSelector( [orderProductsSelector],