-
Notifications
You must be signed in to change notification settings - Fork 16
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
Metelev: HT6 #78
base: master
Are you sure you want to change the base?
Metelev: HT6 #78
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 ( | ||
<div className={styles.basketItem}> | ||
<div className={styles.name}> | ||
<span>{product.name}</span> | ||
<Link to={`/restaurants/${restaurantIdByProduct}`}> | ||
<span>{product.name}</span> | ||
</Link> | ||
</div> | ||
<div className={styles.info}> | ||
<div className={styles.counter}> | ||
|
@@ -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), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. селекторы лучше писать от всего стейта и всех пропов |
||
}); | ||
|
||
export default connect(mapStateToProps, mapDispatchToProps)(BasketItem); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ( | ||
<div> | ||
<Banner heading={name}> | ||
<Rate value={averageRating} /> | ||
</Banner> | ||
<Tabs tabs={tabs} activeId={activeTab} onChange={setActiveTab} /> | ||
{activeTab === 'menu' && <Menu menu={menu} key={id} restId={id} />} | ||
{activeTab === 'reviews' && <Reviews reviews={reviews} restId={id} />} | ||
|
||
<Route path="/restaurants/:restId/:activeId" component={Tabs} /> | ||
|
||
<Switch> | ||
<Route | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Как-то все слишком переусложнено. Поему нельзя было оставить Menu и Reviews в том же формате с теме же пропами, только переместить внутрь Route. Так бы не пришлось их переписывать. |
||
path="/restaurants/:restId/menu" | ||
component={({ match }) => { | ||
/* Сохраняем поведение с ререндером*/ | ||
const restId = match.params.restId; | ||
return <Menu key={restId} restId={restId} />; | ||
}} | ||
/> | ||
<Route path="/restaurants/:restId/reviews" component={Reviews} /> | ||
<Redirect to={`/restaurants/${id}/menu`} /> | ||
</Switch> | ||
</div> | ||
); | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 }) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tabs - это просто компонент, чтобы рисовать табы. Он не должен быть привязан к меню, ресторанам или еще к чему-то другому. |
||
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 ( | ||
<div className={styles.tabs}> | ||
{tabs.map(({ id, label }) => ( | ||
<span | ||
key={id} | ||
className={cn(styles.tab, { [styles.active]: id === activeId })} | ||
onClick={() => onChange(id)} | ||
> | ||
{label} | ||
</span> | ||
<Link to={`/restaurants/${restId}/${id}`} key={id}> | ||
<span | ||
className={cn(styles.tab, { [styles.active]: id === activeId })} | ||
> | ||
{label} | ||
</span> | ||
</Link> | ||
))} | ||
</div> | ||
); | ||
} | ||
|
||
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; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Из данных, которые у нас лежат в редьюсере ресторанов мы можем однозначно сказать какой продукт из какого ресторана. Теперь эта информация у нас есть в двух местах, тут и в ресторанах. Так делать не стоит. |
||
draft.toRestaurantMap[product.id] = restId; | ||
}); | ||
|
||
break; | ||
} | ||
case LOAD_PRODUCTS + FAILURE: { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
тут должен быть Redirect, а не Route