From dd9501e3ccf1fe79bc8c1e674bd10864e887d4f9 Mon Sep 17 00:00:00 2001 From: Jonasz Bigda Date: Sun, 8 Nov 2020 19:07:52 +0100 Subject: [PATCH] price -> prices (unfinished) --- src/components/Dialogs/Dish.js | 13 +- src/components/Dialogs/EditDish.js | 178 +++++++++++++++++++++------- src/components/Dialogs/NewDish.js | 102 +++++++++++++++- src/components/Input/InputPrices.js | 112 ++++++++++++++--- src/components/Input/SearchPanel.js | 6 +- src/components/Output/CardDish.js | 2 +- src/components/Output/DishPrices.js | 10 ++ src/styles/Dish.scss | 8 +- src/styles/DishList.scss | 4 +- src/styles/Pictograms.scss | 1 + src/styles/SearchResults.scss | 10 ++ 11 files changed, 364 insertions(+), 82 deletions(-) create mode 100644 src/components/Output/DishPrices.js diff --git a/src/components/Dialogs/Dish.js b/src/components/Dialogs/Dish.js index e91d594..bd0a3ff 100644 --- a/src/components/Dialogs/Dish.js +++ b/src/components/Dialogs/Dish.js @@ -7,6 +7,7 @@ import { backend } from "../../config.js"; import IconButton from "@material-ui/core/IconButton"; import ArrowBackIcon from "@material-ui/icons/ArrowBack"; import { makeStyles } from "@material-ui/core/styles"; +import DishPrices from "../Output/DishPrices"; const loginStyles = makeStyles((theme) => ({ closeButton: { @@ -72,28 +73,28 @@ export default function Dish(props) {
-
+
Cena
-

{dish.price}zł

+

-
+
Porcja

{dish.weight}


-
+
Wartość energrtyczna

{dish.kCal}kcal


-
+
Indeks glikemiczny

{dish.glicemicIndex}

{dish.notes !== "" &&
} {dish.notes !== "" && ( -
+
Uwagi

{dish.notes}

diff --git a/src/components/Dialogs/EditDish.js b/src/components/Dialogs/EditDish.js index a8a8a6c..eab126a 100644 --- a/src/components/Dialogs/EditDish.js +++ b/src/components/Dialogs/EditDish.js @@ -7,7 +7,6 @@ import ButtonPrimary from "../Input/ButtonPrimary"; import TextField from "@material-ui/core/TextField"; import { makeStyles } from "@material-ui/core/styles"; import TextFieldsIcon from "@material-ui/icons/TextFields"; -import AttachMoneyIcon from "@material-ui/icons/AttachMoney"; import FitnessCenterIcon from "@material-ui/icons/FitnessCenter"; import LocalHospitalIcon from "@material-ui/icons/LocalHospital"; import FavoriteBorderIcon from "@material-ui/icons/FavoriteBorder"; @@ -27,6 +26,7 @@ import validator from "validator"; import DialogTitle from "@material-ui/core/DialogTitle"; import DialogContent from "@material-ui/core/DialogContent"; import Dialog from "@material-ui/core/Dialog"; +import InputPrices from "../Input/InputPrices"; const useStyles = makeStyles((theme) => ({ root: { @@ -88,6 +88,7 @@ const useStyles = makeStyles((theme) => ({ })); export default function EditDish() { + useEffect(() => { document.title = "Menui - Edytuj danie"; }); @@ -98,12 +99,17 @@ export default function EditDish() { const history = useHistory(); const dispatch = useDispatch(); const dish = dishes.find((element) => element._id === id); + + const isMultiplePrices = () => { + return dish.prices.price1.priceName !== "" + } + if (dish === undefined) history.push("/"); const initialState = { restaurantId: dish.restaurantId, name: dish.name, category: dish.category, - price: dish.price, + prices: dish.prices, notes: dish.notes, imgUrl: dish.imgUrl, hidden: false, @@ -125,7 +131,21 @@ export default function EditDish() { charLeft: 200 - dish.notes.length, nameError: false, categoryError: false, - priceError: false, + priceErrors: { + price1: { + name: false, + price: false + }, + price2: { + name: false, + price: false + }, + price3: { + name: false, + price: false + }, + }, + multiplePrices: isMultiplePrices() }; const [state, setState] = useState(initialState); @@ -146,6 +166,70 @@ export default function EditDish() { // HANDLERS + const handlePricesChange = (value) => { + setState({ ...state, prices: value }); + } + + const setMulti = (value) => { + const cleanPrices = { + price1: { + priceName: "", + price: state.prices.price1.price + }, + price2: { + priceName: "", + price: "" + }, + price3: { + priceName: "", + price: "" + }, + } + setState({ ...state, multiplePrices: value, prices: cleanPrices }); + } + + const validatePrice = (value, secondValue) => { + if (!validator.isEmpty(secondValue)) { + return !validator.isEmpty(value); + } else { + return true; + } + } + + const validatePrices = () => { + if (state.multiplePrices) { + return { + price1: { + name: validatePrice(state.prices.price1.priceName, state.prices.price1.price), + price: validatePrice(state.prices.price1.price, state.prices.price1.priceName), + }, + price2: { + name: validatePrice(state.prices.price2.priceName, state.prices.price2.price), + price: validatePrice(state.prices.price2.price, state.prices.price2.priceName), + }, + price3: { + name: validatePrice(state.prices.price3.priceName, state.prices.price3.price), + price: validatePrice(state.prices.price3.price, state.prices.price3.priceName), + }, + } + } else { + return { + price1: { + name: true, + price: !validator.isEmpty(state.prices.price1.price) + }, + price2: { + name: true, + price: true + }, + price3: { + name: true, + price: true + }, + } + } + } + const handleCategoryChange = (event) => { setState({ ...state, category: event.target.value }); }; @@ -172,17 +256,34 @@ export default function EditDish() { const validation = { name: validator.isLength(state.name, { max: 50, min: 1 }), category: restaurant.categories.includes(state.category), - price: validator.isLength(state.price, { max: 10, min: 1 }), + prices: validatePrices() + }; + + const priceErrors = { + price1: { + name: !validation.prices.price1.name, + price: !validation.prices.price1.price + }, + price2: { + name: !validation.prices.price2.name, + price: !validation.prices.price2.price + }, + price3: { + name: !validation.prices.price3.name, + price: !validation.prices.price3.price + }, }; setState({ ...state, nameError: !validation.name, categoryError: !validation.category, - priceError: !validation.price, + priceErrors: priceErrors, }); - return validation.name && validation.category && validation.price; + const allPricesValid = validation.prices.price1.name && validation.prices.price1.price && validation.prices.price2.name && validation.prices.price2.price && validation.prices.price3.name && validation.prices.price3.price; + + return validation.name && validation.category && allPricesValid; }; const sendForm = () => { @@ -191,7 +292,7 @@ export default function EditDish() { restaurantId: state.restaurantId, name: state.name, category: state.category, - price: state.price, + prices: state.prices, notes: state.notes, imgUrl: state.imgUrl, hidden: false, @@ -238,26 +339,32 @@ export default function EditDish() {
-
+
- setState({ ...state, name: event.target.value }) - } - InputProps={{ - startAdornment: ( - - - - ), - }} - /> + className={styles.textInputFullWidth} + fullWidth + required + value={state.name} + error={state.nameError} + label="Nazwa" + variant="outlined" + placeholder="np. Schabowy" + onChange={(event) => + setState({ ...state, name: event.target.value }) + } + InputProps={{ + startAdornment: ( + + + + ), + }} + /> +
+
+ +
+
- - setState({ ...state, price: event.target.value }) - } - InputProps={{ - startAdornment: ( - - - - ), - }} - /> { + const cleanPrices = { + price1: { + priceName: "", + price: state.prices.price1.price + }, + price2: { + priceName: "", + price: "" + }, + price3: { + priceName: "", + price: "" + }, + } + setState({ ...state, multiplePrices: value, prices: cleanPrices }); + } + const handleAdd = () => { if (validateForm()) { sendForm(); @@ -182,21 +214,79 @@ export default function NewRestaurant() { } }; + const validatePrice = (value, secondValue) => { + if (!validator.isEmpty(secondValue)) { + return !validator.isEmpty(value); + } else { + return true; + } + } + + const validatePrices = () => { + if (state.multiplePrices) { + return { + price1: { + name: validatePrice(state.prices.price1.priceName, state.prices.price1.price), + price: validatePrice(state.prices.price1.price, state.prices.price1.priceName), + }, + price2: { + name: validatePrice(state.prices.price2.priceName, state.prices.price2.price), + price: validatePrice(state.prices.price2.price, state.prices.price2.priceName), + }, + price3: { + name: validatePrice(state.prices.price3.priceName, state.prices.price3.price), + price: validatePrice(state.prices.price3.price, state.prices.price3.priceName), + }, + } + } else { + return { + price1: { + name: true, + price: !validator.isEmpty(state.prices.price1.price) + }, + price2: { + name: true, + price: true + }, + price3: { + name: true, + price: true + }, + } + } + } + const validateForm = () => { const validation = { name: validator.isLength(state.name, { max: 50, min: 1 }), category: restaurant.categories.includes(state.category), - prices: validator.isLength(state.prices.price1.priceName, { max: 18, min: 1 }) && validator.isLength(state.prices.price1.price, { max: 18, min: 1 }), + prices: validatePrices() + }; + const priceErrors = { + price1: { + name: !validation.prices.price1.name, + price: !validation.prices.price1.price + }, + price2: { + name: !validation.prices.price2.name, + price: !validation.prices.price2.price + }, + price3: { + name: !validation.prices.price3.name, + price: !validation.prices.price3.price + }, }; setState({ ...state, nameError: !validation.name, categoryError: !validation.category, - priceError: !validation.prices, + priceErrors: priceErrors, }); - return validation.name && validation.category && validation.price; + const allPricesValid = validation.prices.price1.name && validation.prices.price1.price && validation.prices.price2.name && validation.prices.price2.price && validation.prices.price3.name && validation.prices.price3.price; + + return validation.name && validation.category && allPricesValid; }; const sendForm = () => { @@ -296,7 +386,7 @@ export default function NewRestaurant() { />
- +
- +
diff --git a/src/components/Input/InputPrices.js b/src/components/Input/InputPrices.js index 90c3556..327c818 100644 --- a/src/components/Input/InputPrices.js +++ b/src/components/Input/InputPrices.js @@ -1,7 +1,11 @@ -import React, { useState } from 'react' +import React from 'react' import { makeStyles } from '@material-ui/core/styles'; import Paper from '@material-ui/core/Paper'; import TextField from '@material-ui/core/TextField'; +import InputAdornment from "@material-ui/core/InputAdornment"; +import LocalOfferIcon from '@material-ui/icons/LocalOffer'; +import TextFieldsIcon from "@material-ui/icons/TextFields"; +import ButtonSecondary from "../Input/ButtonSecondary"; const useStyles = makeStyles((theme) => ({ root: { @@ -21,7 +25,8 @@ const useStyles = makeStyles((theme) => ({ }, header: { color: "#d68000", - fontSize: "16px" + fontSize: "16px", + fontWeight: "500" }, paragraph: { color: "#bbbbbb", @@ -55,77 +60,152 @@ const useStyles = makeStyles((theme) => ({ optionContainer: { display: "flex", alignItems: "center", + justifyContent: "center", margin: theme.spacing(1) } })); export default function InputPrices(props) { const classes = useStyles(); - const [multi, setMulti] = useState("initial"); + + const getDisplay = (index) => { + switch (index) { + case 0: + if (props.multi === false) { + return "initial"; + } else { + return "none"; + } + case 1: + if (props.multi === false) { + return "none"; + } else { + return "initial"; + } + default: + return "none"; + } + } return

Podaj ceny

Jeżeli ta pozycja w menu ma kilka opcji cenowych (np. Mała/Średnia/Duża porcja) - możesz dodać do trzech cen wraz z nazwami poszczególnych opcji.

-
+
+
+ { + props.setPrices({ + ...props.prices, price1: { + priceName: props.prices.price1.priceName, + price: event.target.value + } + })}} + InputProps={{ + startAdornment: ( + + + + ), + }}/> +
+
+

Cena 1

- { + { props.setPrices({ ...props.prices, price1: { priceName: event.target.value, price: props.prices.price1.price }}) - }} className={classes.textField} label="Nazwa" variant="outlined" required placeholder="np. Mała"/> - { + }} className={classes.textField} label="Nazwa" variant="outlined" required placeholder="np. Mała" InputProps={{ + startAdornment: ( + + + + ), + }}/> + { props.setPrices({ ...props.prices, price1: { priceName: props.prices.price1.priceName, price: event.target.value }}) - }} value={props.prices.price1.price} className={classes.textField} label="Cena" variant="outlined" required placeholder="np. 14zł"/> + }} value={props.prices.price1.price} className={classes.textField} label="Cena" variant="outlined" required placeholder="np. 14" InputProps={{ + startAdornment: ( + + + + ), + }}/>

Cena 2

(opcjonalna)

- { + { props.setPrices({ ...props.prices, price2: { priceName: event.target.value, price: props.prices.price2.price }}) - }} value={props.prices.price2.priceName} className={classes.textField} label="Nazwa" variant="outlined" placeholder="np. Średnia"/> - { + }} value={props.prices.price2.priceName} className={classes.textField} label="Nazwa" variant="outlined" placeholder="np. Średnia" InputProps={{ + startAdornment: ( + + + + ), + }}/> + { props.setPrices({ ...props.prices, price2: { priceName: props.prices.price2.priceName, price: event.target.value }}) - }} value={props.prices.price2.price} className={classes.textField} label="Cena" variant="outlined" placeholder="np. 18zł"/> + }} value={props.prices.price2.price} className={classes.textField} label="Cena" variant="outlined" placeholder="np. 18" InputProps={{ + startAdornment: ( + + + + ), + }}/>

Cena 3

(opcjonalna)

- { + { props.setPrices({ ...props.prices, price3: { priceName: event.target.value, price: props.prices.price3.price }}) - }} value={props.prices.price3.priceName} className={classes.textField} label="Nazwa" variant="outlined" placeholder="np. Duża"/> - { + }} value={props.prices.price3.priceName} className={classes.textField} label="Nazwa" variant="outlined" placeholder="np. Duża" InputProps={{ + startAdornment: ( + + + + ), + }}/> + { props.setPrices({ ...props.prices, price3: { priceName: props.prices.price3.priceName, price: event.target.value }}) - }} value={props.prices.price3.price} className={classes.textField} label="Cena" variant="outlined" placeholder="np. 22zł"/> + }} value={props.prices.price3.price} className={classes.textField} label="Cena" variant="outlined" placeholder="np. 22" InputProps={{ + startAdornment: ( + + + + ), + }}/>
+ props.setMulti(!props.multi)} text={ props.multi ? "Jedna cena" : "Kilka opcji cenowych" }/>
} \ No newline at end of file diff --git a/src/components/Input/SearchPanel.js b/src/components/Input/SearchPanel.js index 2838bce..1a84caf 100644 --- a/src/components/Input/SearchPanel.js +++ b/src/components/Input/SearchPanel.js @@ -10,14 +10,14 @@ const useStyles = makeStyles((theme) => ({ root: { "& .MuiOutlinedInput-root": { "& fieldset": { - borderColor: "#01c3a9", + borderColor: "#bbbbbb", }, }, "& .MuiInputBase-root": { - color: "#01c3a9", + color: "#bbbbbb", }, "& .MuiInputLabel-root": { - color: "#01c3a9", + color: "#bbbbbb", }, }, })); diff --git a/src/components/Output/CardDish.js b/src/components/Output/CardDish.js index 0769c79..4a4eccc 100644 --- a/src/components/Output/CardDish.js +++ b/src/components/Output/CardDish.js @@ -32,7 +32,7 @@ export default function CardDish(props) {

{name}

Porcja: {weight}

- {vegan && "Danie wegańskie "} + {vegan && "Danie wegańskie | "} {vegetarian && "Danie wegetariańskie"}

diff --git a/src/components/Output/DishPrices.js b/src/components/Output/DishPrices.js new file mode 100644 index 0000000..91a407f --- /dev/null +++ b/src/components/Output/DishPrices.js @@ -0,0 +1,10 @@ +import React from 'react' + +export default function DishPrices(props) { + const { prices } = props; + + const display2 = prices.price2.price !== ""; + const display3 = prices.price3.price !== ""; + + return

{display2 || display3 && prices.price1.priceName}{" " + prices.price1.price}zł{ display2 && " / " + prices.price2.priceName + " " + prices.price2.price + "zł"}{ display3 && " / " + prices.price3.priceName + " " + prices.price3.price + "zł"}

+} \ No newline at end of file diff --git a/src/styles/Dish.scss b/src/styles/Dish.scss index a69ac3d..d9fd7cf 100644 --- a/src/styles/Dish.scss +++ b/src/styles/Dish.scss @@ -48,7 +48,7 @@ h5 { font-size: 1rem; font-weight: 300; - margin: 0 8px 0 auto; + margin: 0 0 0 auto; } p { color: $gray; @@ -71,9 +71,9 @@ } .dish-row-column { - margin-top: 18px; - margin-bottom: 18px; + margin-top: 12px; + margin-bottom: 12px; h5 { - margin-bottom: 8px; + margin-bottom: 4px; } } diff --git a/src/styles/DishList.scss b/src/styles/DishList.scss index 9bde03d..87526be 100644 --- a/src/styles/DishList.scss +++ b/src/styles/DishList.scss @@ -40,10 +40,12 @@ h4 { .carddish-left { display: flex; h2 { - font-size: 1rem; + font-size: 1.1rem; + font-weight: 500; margin: auto; } p { + font-size: 13px; margin-left: auto; color: $gray; } diff --git a/src/styles/Pictograms.scss b/src/styles/Pictograms.scss index 8165493..7cc983b 100644 --- a/src/styles/Pictograms.scss +++ b/src/styles/Pictograms.scss @@ -24,6 +24,7 @@ padding: 2px; margin: 4px; h4 { + color: #c0c0c0; margin: 8px 4px 8px 8px; } .pictogram { diff --git a/src/styles/SearchResults.scss b/src/styles/SearchResults.scss index 49844ce..d92bf6c 100644 --- a/src/styles/SearchResults.scss +++ b/src/styles/SearchResults.scss @@ -79,3 +79,13 @@ font-size: 0.9rem; } } + +.card-description { + overflow: hidden; + line-height: 1.2em; + max-height: 3.5em; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 2; /* number of lines to show */ + -webkit-box-orient: vertical; +}