From 47b51a6da6d9154a95c5b55a030ecd1d723c8cc8 Mon Sep 17 00:00:00 2001 From: tatiyanakryzhnyaya Date: Tue, 5 Jan 2021 01:38:46 +0300 Subject: [PATCH 1/4] add basket component --- src/components/app/app.js | 2 + src/components/basket/basket.js | 75 +++++++++++++++++++++++++ src/components/basket/basket.module.css | 31 ++++++++++ src/components/basket/icons/minus.svg | 1 + src/components/basket/icons/plus.svg | 1 + src/components/basket/index.js | 1 + src/redux/actions.js | 3 +- src/redux/constants.js | 1 + src/redux/reducers/order.js | 7 ++- 9 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 src/components/basket/basket.js create mode 100644 src/components/basket/basket.module.css create mode 100644 src/components/basket/icons/minus.svg create mode 100644 src/components/basket/icons/plus.svg create mode 100644 src/components/basket/index.js diff --git a/src/components/app/app.js b/src/components/app/app.js index 9d6eaf0..20b9341 100644 --- a/src/components/app/app.js +++ b/src/components/app/app.js @@ -2,12 +2,14 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import Restaurants from '../restaurants'; import Header from '../header'; +import Basket from '../basket'; export default class App extends PureComponent { render() { return (
+
); diff --git a/src/components/basket/basket.js b/src/components/basket/basket.js new file mode 100644 index 0000000..eaef294 --- /dev/null +++ b/src/components/basket/basket.js @@ -0,0 +1,75 @@ +import React, { useMemo } from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import { clear, increment, decrement } from '../../redux/actions'; +import MinusIcon from './icons/minus.svg'; +import PlusIcon from './icons/plus.svg'; + +import styles from './basket.module.css'; + +const Basket = ({ + order = {}, + restaurants, + clearBasket, + increment, + decrement, +}) => { + const products = useMemo(() => { + return restaurants.flatMap(({ menu }) => menu); + }, [restaurants]); + + return ( +
+ {products.map((product) => ( +
+ {product.name} +
Price {product.price} $
+
Count {order[product.id] || 0}
+
Total coast {order[product.id] * product.price || 0}
+
+ + +
+
+ ))} + +
+ ); +}; + +Basket.propTypes = { + order: PropTypes.object.isRequired, + clearBasket: PropTypes.func.isRequired, + increment: PropTypes.func.isRequired, + decrement: PropTypes.func.isRequired, +}; + +const mapStateToProps = (state) => ({ + order: state.order, +}); + +const mapDispatchToProps = (dispatch) => ({ + clearBasket: () => dispatch(clear()), + increment: (productId) => dispatch(increment(productId)), + decrement: (productId) => dispatch(decrement(productId)), +}); + +export default connect(mapStateToProps, mapDispatchToProps)(Basket); diff --git a/src/components/basket/basket.module.css b/src/components/basket/basket.module.css new file mode 100644 index 0000000..1deb250 --- /dev/null +++ b/src/components/basket/basket.module.css @@ -0,0 +1,31 @@ +.basket { + border: 1px solid var(--yellow); + margin: 5px; +} + +.buttons { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + width: 80px; +} + +.button { + color: var(--white); + background-color: var(--yellow); + border: 1px solid var(--yellow); + border-radius: 2px; + width: 36px; + height: 36px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 0; + font-weight: 700; + font-size: 24px; + outline: none; + box-shadow: none; + cursor: pointer; +} diff --git a/src/components/basket/icons/minus.svg b/src/components/basket/icons/minus.svg new file mode 100644 index 0000000..d038dac --- /dev/null +++ b/src/components/basket/icons/minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/basket/icons/plus.svg b/src/components/basket/icons/plus.svg new file mode 100644 index 0000000..36b641f --- /dev/null +++ b/src/components/basket/icons/plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/basket/index.js b/src/components/basket/index.js new file mode 100644 index 0000000..d9c6b0c --- /dev/null +++ b/src/components/basket/index.js @@ -0,0 +1 @@ +export { default } from './basket'; diff --git a/src/redux/actions.js b/src/redux/actions.js index 2807b77..d399b2d 100644 --- a/src/redux/actions.js +++ b/src/redux/actions.js @@ -1,4 +1,5 @@ -import { INCREMENT, DECREMENT } from './constants'; +import { INCREMENT, DECREMENT, CLEAR } from './constants'; export const increment = (id) => ({ type: INCREMENT, payload: { id } }); export const decrement = (id) => ({ type: DECREMENT, payload: { id } }); +export const clear = () => ({ type: CLEAR }); diff --git a/src/redux/constants.js b/src/redux/constants.js index 930d9ef..67a6d13 100644 --- a/src/redux/constants.js +++ b/src/redux/constants.js @@ -1,2 +1,3 @@ export const INCREMENT = 'INCREMENT'; export const DECREMENT = 'DECREMENT'; +export const CLEAR = 'CLEAR'; diff --git a/src/redux/reducers/order.js b/src/redux/reducers/order.js index 3d83bb4..38061bd 100644 --- a/src/redux/reducers/order.js +++ b/src/redux/reducers/order.js @@ -1,13 +1,16 @@ -import { DECREMENT, INCREMENT } from '../constants'; +import { DECREMENT, INCREMENT, CLEAR } from '../constants'; // { [productId]: amount } -export default (state = 0, action) => { +export default (state = {}, action) => { const { type, payload } = action; switch (type) { case INCREMENT: return { ...state, [payload.id]: (state[payload.id] || 0) + 1 }; case DECREMENT: return { ...state, [payload.id]: (state[payload.id] || 0) - 1 }; + case CLEAR: + console.log('clear'); + return {}; default: return state; } From 59ef1456882e30b08f46f697f673b0295d11f00c Mon Sep 17 00:00:00 2001 From: tatiyanakryzhnyaya Date: Tue, 5 Jan 2021 02:08:03 +0300 Subject: [PATCH 2/4] add minimal style --- src/components/basket/basket.js | 70 +++++++++++++++---------- src/components/basket/basket.module.css | 24 +++++++-- 2 files changed, 63 insertions(+), 31 deletions(-) diff --git a/src/components/basket/basket.js b/src/components/basket/basket.js index eaef294..689f76e 100644 --- a/src/components/basket/basket.js +++ b/src/components/basket/basket.js @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react'; +import React, { useMemo, useState } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { clear, increment, decrement } from '../../redux/actions'; @@ -14,43 +14,57 @@ const Basket = ({ increment, decrement, }) => { + const [isOpenBasket, toggleBasket] = useState(false); + const hideBasket = () => toggleBasket(false); + const openBasket = () => toggleBasket(true); const products = useMemo(() => { return restaurants.flatMap(({ menu }) => menu); }, [restaurants]); return ( -
- {products.map((product) => ( -
- {product.name} -
Price {product.price} $
-
Count {order[product.id] || 0}
-
Total coast {order[product.id] * product.price || 0}
-
- - -
-
- ))} +
+ {isOpenBasket && ( +
+ {products.map((product) => ( +
+ {product.name} +
Price {product.price} $
+
Count {order[product.id] || 0}
+
Total coast {order[product.id] * product.price || 0}
+
+ + +
+
+ ))} + +
+ )}
); }; diff --git a/src/components/basket/basket.module.css b/src/components/basket/basket.module.css index 1deb250..395c185 100644 --- a/src/components/basket/basket.module.css +++ b/src/components/basket/basket.module.css @@ -1,14 +1,32 @@ .basket { - border: 1px solid var(--yellow); - margin: 5px; + position: relative; + padding: 15px; +} + +.products { + position: absolute; + padding: 15px; + margin-top: 10px; + width: 50%; + height: 300px; + z-index: 5; + border: 1px solid var(--grey); + background: var(--white); + overflow-y: scroll; +} + +.product { + padding: 5px; + margin: 5px 0; + border: 1px solid var(--grey); } .buttons { + width: 80px; display: flex; flex-direction: row; justify-content: space-between; align-items: center; - width: 80px; } .button { From 75a90210d784fa7f4b3c2ceecbac5db7fcdc251e Mon Sep 17 00:00:00 2001 From: tatiyanakryzhnyaya Date: Tue, 5 Jan 2021 02:22:58 +0300 Subject: [PATCH 3/4] add hoc --- src/components/basket/basket.js | 22 ++++++++++++++++------ src/hocs/popup.js | 7 +++++++ src/hooks/use-popup.js | 9 +++++++++ src/redux/reducers/order.js | 1 - 4 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 src/hocs/popup.js create mode 100644 src/hooks/use-popup.js diff --git a/src/components/basket/basket.js b/src/components/basket/basket.js index 689f76e..db6aa4d 100644 --- a/src/components/basket/basket.js +++ b/src/components/basket/basket.js @@ -4,6 +4,7 @@ import { connect } from 'react-redux'; import { clear, increment, decrement } from '../../redux/actions'; import MinusIcon from './icons/minus.svg'; import PlusIcon from './icons/plus.svg'; +import popup from '../../hocs/popup'; import styles from './basket.module.css'; @@ -13,14 +14,18 @@ const Basket = ({ clearBasket, increment, decrement, + isOpenBasket, + hideBasket, + openBasket, }) => { - const [isOpenBasket, toggleBasket] = useState(false); - const hideBasket = () => toggleBasket(false); - const openBasket = () => toggleBasket(true); const products = useMemo(() => { return restaurants.flatMap(({ menu }) => menu); }, [restaurants]); + const getCountProduct = (productId) => { + return order[productId] || 0; + }; + return (
- {isOpenBasket && ( -
- {products.map((product) => ( -
- {product.name} -
Price {product.price} $
-
Count {getCountProduct(product.id)}
-
- Total coast {getCountProduct(product.id) * product.price} -
-
- - + {isOpenBasket && + (selectedProducts.length ? ( +
+ {selectedProducts.map((product) => ( +
+ {product.name} +
Price {product.price} $
+
Count {getCountProduct(product.id)}
+
+ Total coast {getCountProduct(product.id) * product.price} +
+
+ + +
-
- ))} - -
- )} + ))} + +
+ ) : ( +
Корзина пуста
+ ))}
); }; diff --git a/src/components/basket/basket.module.css b/src/components/basket/basket.module.css index 395c185..b2d2dcb 100644 --- a/src/components/basket/basket.module.css +++ b/src/components/basket/basket.module.css @@ -8,7 +8,7 @@ padding: 15px; margin-top: 10px; width: 50%; - height: 300px; + max-height: 300px; z-index: 5; border: 1px solid var(--grey); background: var(--white);