420 lines
12 KiB
JavaScript
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>
|
|
);
|
|
}
|