Files
menui_web/src/components/Dialogs/NewDish.js

420 lines
12 KiB
JavaScript

import React, { useState } from "react";
import { makeStyles } from "@material-ui/core/styles";
import DialogTitle from "@material-ui/core/DialogTitle";
import DialogContent from "@material-ui/core/DialogContent";
import Dialog from "@material-ui/core/Dialog";
import Divider from "@material-ui/core/Divider";
import ButtonSecondary from "../Input/ButtonSecondary";
import IconButton from "@material-ui/core/IconButton";
import TextField from "@material-ui/core/TextField";
import CloseIcon from "@material-ui/icons/Close";
import Paper from "@material-ui/core/Paper";
import MenuItem from "@material-ui/core/MenuItem";
import FormControl from "@material-ui/core/FormControl";
import Select from "@material-ui/core/Select";
import ImageUpload from "../Input/ImageUpload";
import validator from "validator";
import { useHistory, useParams } from "react-router-dom";
import axios from "axios";
import { useSelector, useDispatch } from "react-redux";
import { notification, refreshUserData } from "../../actions";
import { showBackdrop, hideBackdrop } from "../../actions/toggles.js";
import InputLabel from "@material-ui/core/InputLabel";
import InputAdornment from "@material-ui/core/InputAdornment";
import Checkboxes from "../Input/Checkboxes";
// ICONS
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";
// SETUP
const useStyles = makeStyles((theme) => ({
root: {
margin: "auto",
textAlign: "center",
maxHeight: "90vh",
"& .MuiPaper-root": {
width: "auto",
backgroundColor: "#262626",
color: "#bbbbbb",
overflow: "visible",
},
},
closeButton: {
color: "#bbbbbb",
position: "absolute",
right: theme.spacing(1),
top: theme.spacing(1),
},
textInput: {
margin: theme.spacing(2),
"& .MuiInputBase-root": {
color: "#bbbbbb",
},
"& .MuiInputLabel-root": {
color: "#bbbbbb",
},
},
textInputFullWidth: {
marginTop: theme.spacing(2),
marginBottom: theme.spacing(2),
color: "#bbbbbb",
"& .MuiInputBase-root": {
color: "#bbbbbb",
},
"& .MuiInputLabel-root": {
color: "#bbbbbb",
},
"$ .MuiFormHelperText-root": {
color: "#bbbbbb",
},
},
formControl: {
margin: theme.spacing(2),
minWidth: 100,
"& .MuiInputBase-root": {
color: "#bbbbbb",
},
"$ .MuiSelect-root": {
color: "#bbbbbb",
},
"& .MuiInputLabel-root": {
color: "#bbbbbb",
},
},
selectEmpty: {
marginTop: theme.spacing(2),
},
}));
export default function NewRestaurant() {
const dispatch = useDispatch();
const { restaurantID } = useParams();
const initialState = {
restaurantId: restaurantID,
name: "",
category: "",
price: "",
notes: "",
imgUrl: "",
hidden: false,
weight: "",
allergens: {
gluten: false,
lactose: false,
soy: false,
eggs: false,
seaFood: false,
peanuts: false,
sesame: false,
},
ingredients: "",
glicemicIndex: "",
kCal: "",
vegan: false,
vegetarian: false,
charLeft: 200,
nameError: false,
categoryError: false,
priceError: false,
};
const [state, setState] = useState(initialState);
const styles = useStyles();
const history = useHistory();
const token = useSelector((state) => state.data.userData.jwt);
const restaurants = useSelector((state) => state.data.userData.restaurants);
function matchId(element) {
return element._id === restaurantID;
}
const restaurant = restaurants.find(matchId);
if (restaurant === undefined) history.push("/");
const Categories = restaurant.categories.map((category) => {
return (
<MenuItem key={category} value={category}>
{category}
</MenuItem>
);
});
// HANDLERS
const handleCategoryChange = (event) => {
setState({ ...state, category: event.target.value });
};
const handleAdd = () => {
if (validateForm()) {
sendForm();
} else {
dispatch(notification("Popraw dane", "error"));
}
};
const validateForm = () => {
const validation = {
name: validator.isLength(state.name, { max: 50, min: 1 }),
category: restaurant.categories.includes(state.category),
price: validator.isAlphanumeric(state.price),
};
setState({
...state,
nameError: !validation.name,
categoryError: !validation.category,
priceError: !validation.price,
});
return validation.name && validation.category && validation.price;
};
const sendForm = () => {
const data = {
restaurantId: restaurantID,
name: state.name,
category: state.category,
price: state.price,
notes: state.notes,
imgUrl: state.imgUrl,
hidden: false,
weight: state.weight,
allergens: state.allergens,
ingredients: state.ingredients,
glicemicIndex: state.glicemicIndex,
kCal: state.kCal,
vegan: state.vegan,
vegetarian: state.vegetarian,
};
dispatch(showBackdrop());
axios({
url: "http://localhost:4000/dish",
method: "POST",
data: data,
headers: {
"x-auth-token": token,
},
})
.then((response) => {
dispatch(hideBackdrop());
dispatch(notification("Danie dodane pomyślnie.", "success"));
dispatch(refreshUserData(token));
history.push(`/editRestaurant/${restaurantID}`);
})
.catch((error) => {
dispatch(hideBackdrop());
dispatch(
notification(
"Wystąpił nieoczekiwany błąd, przepraszamy za utrudnienia. Spróbuj ponownie za chwilę.",
"error"
)
);
});
};
const handleImageUploaded = (link) => {
setState({ ...state, imgUrl: link });
};
const handleDescriptionChange = (event) => {
let stringLength = event.target.value.length;
let charleft = 200 - stringLength;
setState({ ...state, notes: event.target.value, charLeft: charleft });
};
// COMPONENTS
return (
<div>
<Dialog
className={styles.root}
open={true}
aria-labelledby="newRestaurant-title"
>
<DialogTitle id="newRestaurant-title">Dodaj danie</DialogTitle>
<IconButton
className={styles.closeButton}
onClick={() => history.goBack()}
aria-label="close"
>
<CloseIcon />
</IconButton>
<Divider />
<DialogContent>
<p>Danie zostanie dodane do: {restaurant.name}</p>
<Paper variant="outlined">
<div className="newRestaurant-content">
<TextField
className={styles.textInput}
required
value={state.name}
error={state.nameError}
label="Nazwa"
variant="outlined"
placeholder="np. Schabowy"
onChange={(event) =>
setState({ ...state, name: event.target.value })
}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<TextFieldsIcon color="primary" />
</InputAdornment>
),
}}
/>
<FormControl
variant="outlined"
required
className={styles.formControl}
>
<InputLabel id="category-select">Kategoria</InputLabel>
<Select
labelId="category-select"
id="category"
value={state.category}
error={state.categoryError}
required
onChange={handleCategoryChange}
>
{Categories}
</Select>
</FormControl>
<TextField
className={styles.textInput}
required
label="Cena"
placeholder="np. 18,50"
type="number"
error={state.priceError}
value={state.price}
variant="outlined"
onChange={(event) =>
setState({ ...state, price: event.target.value })
}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<AttachMoneyIcon color="primary" />
</InputAdornment>
),
}}
/>
<TextField
className={styles.textInput}
label="Waga (g)"
type="number"
placeholder="np. 150"
value={state.weight}
variant="outlined"
onChange={(event) =>
setState({ ...state, weight: event.target.value })
}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<FitnessCenterIcon color="primary" />
</InputAdornment>
),
}}
/>
<TextField
className={styles.textInput}
label="Indeks glikemiczny"
placeholder="np. 70"
type="number"
value={state.glicemicIndex}
variant="outlined"
onChange={(event) =>
setState({ ...state, glicemicIndex: event.target.value })
}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<LocalHospitalIcon color="primary" />
</InputAdornment>
),
}}
/>
<TextField
className={styles.textInput}
label="Kaloryczność (kcal)"
value={state.kCal}
placeholder="np. 1000"
variant="outlined"
onChange={(event) =>
setState({ ...state, kCal: event.target.value })
}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<FavoriteBorderIcon color="primary" />
</InputAdornment>
),
}}
/>
</div>
<div className="newRestaurant-content-fullwidth">
<TextField
className={styles.textInputFullWidth}
fullWidth
multiline
rows={2}
rowsMax={4}
value={state.ingredients}
placeholder="np. ziemniaki, mąka, filet z dorsza, pieprz, sól..."
label="Składniki"
variant="outlined"
onChange={(event) =>
setState({ ...state, ingredients: event.target.value })
}
/>
<TextField
className={styles.textInputFullWidth}
fullWidth
multiline
rows={2}
rowsMax={4}
value={state.note}
label="Uwagi"
variant="outlined"
onChange={handleDescriptionChange}
helperText={"Pozostałe znaki: " + state.charLeft}
FormHelperTextProps={{
style: { color: "#bbbbbb" },
}}
/>
<Checkboxes
allergens={state.allergens}
vegan={state.vegan}
vegetarian={state.vegetarian}
onVegan={() => setState({ ...state, vegan: !state.vegan })}
onVegetarian={() =>
setState({ ...state, vegetarian: !state.vegetarian })
}
onUpdate={(updated) =>
setState({ ...state, allergens: updated })
}
/>
</div>
</Paper>
<Paper>
<h4>Dodaj zdjęcie.</h4>
<ImageUpload
img={state.imgUrl}
onUpload={(link) => handleImageUploaded(link)}
/>
</Paper>
<div className="newRestaurant-bottom">
<ButtonSecondary onClick={handleAdd} text="Dodaj" />
</div>
</DialogContent>
</Dialog>
</div>
);
}