Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/ht6 #81

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
4 changes: 3 additions & 1 deletion src/components/basket/basket-item/basket-item.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { connect } from 'react-redux';
import cn from 'classnames';
import { NavLink } from 'react-router-dom';
import { increment, decrement, remove } from '../../../redux/actions';
import Button from '../../button';
import styles from './basket-item.module.css';
Expand All @@ -8,14 +9,15 @@ function BasketItem({
product,
amount,
subtotal,
restId,
increment,
decrement,
remove,
}) {
return (
<div className={styles.basketItem}>
<div className={styles.name}>
<span>{product.name}</span>
<NavLink to={`/restaurants/${restId}`}>{product.name}</NavLink>
</div>
<div className={styles.info}>
<div className={styles.counter}>
Expand Down
3 changes: 2 additions & 1 deletion src/components/basket/basket.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ function Basket({ title = 'Basket', total, orderProducts }) {
return (
<div className={styles.basket}>
<h4 className={styles.title}>{title}</h4>
{orderProducts.map(({ product, amount, subtotal }) => (
{orderProducts.map(({ product, amount, subtotal, restId }) => (
<BasketItem
product={product}
amount={amount}
key={product.id}
subtotal={subtotal}
restId={restId}
/>
))}
<hr className={styles.hr} />
Expand Down
4 changes: 2 additions & 2 deletions src/components/menu/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class Menu extends Component {
}

render() {
const { menu, loading, loaded } = this.props;
const { menu, loading, loaded, restId } = this.props;

if (loading) {
return <Loader />;
Expand All @@ -57,7 +57,7 @@ class Menu extends Component {
<div className={styles.menu}>
<div>
{menu.map((id) => (
<Product key={id} id={id} />
<Product key={id} id={id} restId={restId} />
))}
</div>
<div>
Expand Down
5 changes: 3 additions & 2 deletions src/components/product/product.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Product.propTypes = {
price: PropTypes.number,
ingredients: PropTypes.arrayOf(PropTypes.string.isRequired).isRequired,
}).isRequired,
restId: PropTypes.string.isRequired,

// from connect
amount: PropTypes.number,
Expand All @@ -57,8 +58,8 @@ const mapStateToProps = (state, props) => ({
});

const mapDispatchToProps = (dispatch, props) => ({
increment: () => dispatch(increment(props.id)),
decrement: () => dispatch(decrement(props.id)),
increment: () => dispatch(increment(props.id, props.restId)),
decrement: () => dispatch(decrement(props.id, props.restId)),
});

export default connect(mapStateToProps, mapDispatchToProps)(Product);
14 changes: 7 additions & 7 deletions src/components/restaurant/restaurant.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';

import Menu from '../menu';
import Reviews from '../reviews';
import Banner from '../banner';
Expand All @@ -11,22 +11,21 @@ import {
restaurantSelector,
} from '../../redux/selectors';

const Restaurant = ({ restaurant, averageRating }) => {
const Restaurant = ({ restaurant, averageRating, activeTab }) => {
const { id, name, menu, reviews } = restaurant;

const [activeTab, setActiveTab] = useState('menu');

const tabs = [
{ id: 'menu', label: 'Menu' },
{ id: 'reviews', label: 'Reviews' },
{ id: 'menu', label: 'Menu', route: `/restaurants/${id}/menu` },
{ id: 'reviews', label: 'Reviews', route: `/restaurants/${id}/reviews` },
];

return (
<div>
<Banner heading={name}>
<Rate value={averageRating} />
</Banner>
<Tabs tabs={tabs} activeId={activeTab} onChange={setActiveTab} />

<Tabs tabs={tabs} activeId={activeTab} />
{activeTab === 'menu' && <Menu menu={menu} key={id} restId={id} />}
{activeTab === 'reviews' && <Reviews reviews={reviews} restId={id} />}
</div>
Expand All @@ -41,6 +40,7 @@ Restaurant.propTypes = {
reviews: PropTypes.array,
}).isRequired,
averageRating: PropTypes.number,
activeTab: PropTypes.string.isRequired,
};

const mapStateToProps = (state, props) => ({
Expand Down
16 changes: 14 additions & 2 deletions src/components/restaurants/restaurants.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,22 @@ function Restaurants({ restaurants, loading, loaded, loadRestaurants }) {
))}
</div>
<Switch>
<Route path="/restaurants/:restId/menu">
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

этот роутинг проще описать на уровне одного ресторана, будет немного аккуратнее, покажу на своей домашке

{({ match }) => (
<Restaurant id={match.params.restId} activeTab={'menu'} />
)}
</Route>
<Route path="/restaurants/:restId/reviews">
{({ match }) => (
<Restaurant id={match.params.restId} activeTab={'reviews'} />
)}
</Route>
<Route path="/restaurants/:restId">
{({ match }) => <Restaurant id={match.params.restId} />}
{({ match }) => (
<Redirect to={`/restaurants/${match.params.restId}/menu`} />
)}
</Route>
<Redirect to={`/restaurants/${restaurants[0]?.id}`} />
<Redirect to={`/restaurants/${restaurants[0]?.id}/menu`} />
</Switch>
</div>
);
Expand Down
16 changes: 9 additions & 7 deletions src/components/tabs/tabs.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import PropTypes from 'prop-types';
import cn from 'classnames';
import { NavLink } from 'react-router-dom';

import styles from './tabs.module.css';

function Tabs({ tabs, activeId, onChange }) {
function Tabs({ tabs, activeId }) {
return (
<div className={styles.tabs}>
{tabs.map(({ id, label }) => (
<span
{tabs.map(({ id, label, route }) => (
<NavLink
key={id}
className={cn(styles.tab, { [styles.active]: id === activeId })}
onClick={() => onChange(id)}
to={route}
className={styles.tab}
activeClassName={cn(styles.tab, { [styles.active]: id === activeId })}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
activeClassName={cn(styles.tab, { [styles.active]: id === activeId })}
activeClassName={styles.active}

>
{label}
</span>
</NavLink>
))}
</div>
);
Expand All @@ -24,10 +26,10 @@ Tabs.propTypes = {
PropTypes.shape({
id: PropTypes.string.isRequired,
label: PropTypes.string,
route: PropTypes.string.isRequired,
}).isRequired
).isRequired,
activeId: PropTypes.string,
onChange: PropTypes.func.isRequired,
};

export default Tabs;
4 changes: 2 additions & 2 deletions src/redux/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import {
reviewsLoadedSelector,
} from './selectors';

export const increment = (id) => ({ type: INCREMENT, id });
export const decrement = (id) => ({ type: DECREMENT, id });
export const increment = (id, restId) => ({ type: INCREMENT, id, restId });
export const decrement = (id, restId) => ({ type: DECREMENT, id, restId });
export const remove = (id) => ({ type: REMOVE, id });

export const changeRestaurant = (activeId) => ({
Expand Down
22 changes: 17 additions & 5 deletions src/redux/reducer/order.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
import { DECREMENT, INCREMENT, REMOVE } from '../constants';

// { [productId]: amount }
// { [productId]: {amount, restId} }
export default function (state = {}, action) {
const { type, id } = action;
const { type, id, restId } = action;
switch (type) {
case INCREMENT:
return { ...state, [id]: (state[id] || 0) + 1 };
const item = state[id] || { restId, amount: 0 };
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Из данных, которые у нас лежат в редьюсере ресторанов мы можем однозначно сказать какой продукт из какого ресторана. Теперь эта информация у нас есть в двух местах, тут и в ресторанах. Так делать не стоит.

return {
...state,
[id]: { ...item, amount: item.amount + 1 },
};
case DECREMENT:
return { ...state, [id]: state[id] > 0 ? (state[id] || 0) - 1 : 0 };
return state[id]
? {
...state,
[id]: {
...state[id],
amount: state[id].amount > 0 ? (state[id].amount || 0) - 1 : 0,
},
}
: state;
case REMOVE:
return { ...state, [id]: 0 };
return { ...state, [id]: { ...state[id], amount: 0 } };
default:
return state;
}
Expand Down
10 changes: 6 additions & 4 deletions src/redux/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,20 @@ export const restaurantSelector = (state, { id }) =>
restaurantsSelector(state)[id];
export const productSelector = (state, { id }) => productsSelector(state)[id];
export const reviewSelector = (state, { id }) => reviewsSelector(state)[id];
export const amountSelector = (state, { id }) => orderSelector(state)[id] || 0;
export const amountSelector = (state, { id }) =>
orderSelector(state)[id] ? orderSelector(state)[id].amount : 0;
export const orderProductsSelector = createSelector(
orderSelector,
productsSelector,
(order, products) =>
Object.keys(order)
.filter((productId) => order[productId] > 0)
.filter((productId) => order[productId].amount > 0)
.map((productId) => products[productId])
.map((product) => ({
product,
amount: order[product.id],
subtotal: order[product.id] * product.price,
amount: order[product.id].amount,
subtotal: order[product.id].amount * product.price,
restId: order[product.id].restId,
}))
);

Expand Down