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

HT6 #49

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

HT6 #49

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,8 @@
5. При загрузках показывать лоадеры, все грузить максимально низко, там где эти данные нужны
6. Все данные грузить только один раз (не загружать повторно данные, которые уже есть)
7. (Опционально) переписать все на **immer**

# HT6

1. Сделать reviews/menu отдельными роутами (/restaurant/:id/reviews)
2. В корзине сделать продукты линками на их ресторан
10 changes: 9 additions & 1 deletion src/components/basket/basket-item/basket-item.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React from 'react';
import { connect } from 'react-redux';
import { NavLink } from 'react-router-dom';
import cn from 'classnames';
import { increment, decrement, remove } from '../../../redux/actions';
import Button from '../../button';
import styles from './basket-item.module.css';

function BasketItem({
product,
restaurant,
amount,
subtotal,
increment,
Expand All @@ -16,7 +18,13 @@ function BasketItem({
return (
<div className={styles.basketItem}>
<div className={styles.name}>
<span>{product.name}</span>
<NavLink
exact
to={`/restaurants/${restaurant}`}
activeClassName={styles.active}
>
{product.name}
</NavLink>
</div>
<div className={styles.info}>
<div className={styles.counter}>
Expand Down
9 changes: 9 additions & 0 deletions src/components/basket/basket-item/basket-item.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@
display: inline-block;
text-decoration: none;
color: var(--black);
transition: transform 150ms ease-out 0s;
}

.name > a:hover {
transform: translateY(-1px);
}

.active {
font-weight: bold;
}

.info {
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 @@ -21,9 +21,10 @@ 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, restaurant, amount, subtotal }) => (
<BasketItem
product={product}
restaurant={restaurant}
amount={amount}
key={product.id}
subtotal={subtotal}
Expand Down
26 changes: 24 additions & 2 deletions src/components/restaurant/restaurant.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { createStructuredSelector } from 'reselect';
import { Route, Switch } from 'react-router-dom';

import Menu from '../menu';
import Reviews from '../reviews';
Expand All @@ -13,10 +14,15 @@ import { averageRatingSelector } from '../../redux/selectors';
const Restaurant = ({ restaurant, averageRating }) => {
const { id, name, menu, reviews } = restaurant;
const tabs = [
{ title: 'Menu', content: <Menu menu={menu} restaurantId={id} /> },
{
title: 'Menu',
target: `/restaurants/${id}`,
exact: true,
},
{
title: 'Reviews',
content: <Reviews reviews={reviews} restaurantId={id} />,
target: `/restaurants/${id}/reviews`,
exact: true,
},
];

Expand All @@ -26,6 +32,22 @@ const Restaurant = ({ restaurant, averageRating }) => {
{!!averageRating && <Rate value={averageRating} />}
</Banner>
<Tabs tabs={tabs} />
<Switch>
<Route
exact
path={`/restaurants/${id}/reviews`}
render={(props) => (
<Reviews {...props} reviews={reviews} restaurantId={id} />
)}
/>
<Route
exact
path={`/restaurants/${id}`}
render={(props) => (
<Menu {...props} menu={menu} restaurantId={id} />
)}
/>
</Switch>
</div>
);
};
Expand Down
22 changes: 7 additions & 15 deletions src/components/restaurants/restaurants.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,23 @@
import React from 'react';
import { connect } from 'react-redux';
import { NavLink } from 'react-router-dom';
import { createStructuredSelector } from 'reselect';
import PropTypes from 'prop-types';
import Tabs from '../tabs';
import Restaurant from '../restaurant';
import { restaurantsListSelector } from '../../redux/selectors';

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

const Restaurants = ({ restaurants, match }) => {
const { restId } = match.params;
const restaurant = restaurants.find((restaurant) => restaurant.id === restId);

const tabs = restaurants.map(({ id, name }) => ({
title: name,
target: `/restaurants/${id}`,
}))

return (
<>
<div className={styles.tabs}>
{restaurants.map(({ id, name }, index) => (
<NavLink
key={id}
className={styles.tab}
to={`/restaurants/${id}`}
activeClassName={styles.active}
>
{name}
</NavLink>
))}
</div>
<Tabs tabs={tabs} />
<Restaurant restaurant={restaurant} />
</>
);
Expand Down
20 changes: 0 additions & 20 deletions src/components/restaurants/restaurants.module.css

This file was deleted.

26 changes: 13 additions & 13 deletions src/components/tabs/tabs.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
import React, { useState } from 'react';
import React from 'react';
import PropTypes from 'prop-types';
import cn from 'classnames';
import { NavLink } from 'react-router-dom';

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

const Tabs = ({ tabs }) => {
const [activeTab, setActiveTab] = useState(0);

const { content } = tabs[activeTab];

return (
<>
<div className={styles.tabs}>
{tabs.map(({ title }, index) => (
<span
key={title}
className={cn(styles.tab, { [styles.active]: index === activeTab })}
onClick={() => setActiveTab(index)}
{tabs.map(({ target, title, exact, ...props }, index) => (
<NavLink
exact={exact}
key={index}
to={target}
className={styles.tab}
activeClassName={styles.active}
>
{title}
</span>
</NavLink>
))}
</div>
{content}

</>
);
};
Expand All @@ -31,7 +30,8 @@ Tabs.propTypes = {
tabs: PropTypes.arrayOf(
PropTypes.shape({
title: PropTypes.string.isRequired,
content: PropTypes.element.isRequired,
target: PropTypes.string.isRequired,
exact: PropTypes.bool,
}).isRequired
).isRequired,
};
Expand Down
1 change: 1 addition & 0 deletions src/components/tabs/tabs.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

.tab {
padding: 4px 12px;
color: var(--black);
}

.tab.active {
Expand Down
18 changes: 17 additions & 1 deletion src/redux/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,31 @@ export const productAmountSelector = getById(orderSelector, 0);
export const productSelector = getById(productsSelector);
const reviewSelector = getById(reviewsSelector);

const productsWithRestaurantIdSelector = createSelector(
restaurantsListSelector,
(restaurants) =>
restaurants.reduce((acc, restaurant) =>
({
...acc,
...restaurant.menu.reduce((acc, product) =>
({
...acc,
[product]: restaurant.id
}), {})
}), {})
);

export const orderProductsSelector = createSelector(
productsSelector,
orderSelector,
(products, order) =>
productsWithRestaurantIdSelector,
(products, order, restaurants) =>
Object.keys(order)
.filter((productId) => order[productId] > 0)
.map((productId) => products[productId])
.map((product) => ({
product,
restaurant: restaurants[product.id],
amount: order[product.id],
subtotal: order[product.id] * product.price,
}))
Expand Down