563 lines
17 KiB
JavaScript
563 lines
17 KiB
JavaScript
import React, { useState, useEffect } 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 Stepper from "@material-ui/core/Stepper";
|
|
import Step from "@material-ui/core/Step";
|
|
import StepLabel from "@material-ui/core/StepLabel";
|
|
import Paper from "@material-ui/core/Paper";
|
|
import Autocomplete from "@material-ui/lab/Autocomplete";
|
|
import InputAdornment from "@material-ui/core/InputAdornment";
|
|
import ImageUpload from "../Input/ImageUpload";
|
|
import validator from "validator";
|
|
import { useHistory } from "react-router-dom";
|
|
import InputGoogleMaps from "../Input/InputGoogleMaps";
|
|
import { prepareTags } from "../../Services.js";
|
|
import axios from "axios";
|
|
import { useSelector, useDispatch } from "react-redux";
|
|
import { notification, refreshUserData } from "../../actions";
|
|
import { showBackdrop, hideBackdrop } from "../../actions/toggles.js";
|
|
import InputWorkingHours from "../Input/InputWorkingHours";
|
|
import InputLunchMenuHours from "../Input/InputLunchMenuHours";
|
|
import { backend, restaurantTypes } from "../../config";
|
|
import MenuItem from "@material-ui/core/MenuItem";
|
|
import FormControl from "@material-ui/core/FormControl";
|
|
import Select from "@material-ui/core/Select";
|
|
import InputLabel from "@material-ui/core/InputLabel";
|
|
// ICONS
|
|
import FastfoodIcon from "@material-ui/icons/Fastfood";
|
|
import LocationCityIcon from "@material-ui/icons/LocationCity";
|
|
import PhoneIcon from "@material-ui/icons/Phone";
|
|
import FacebookIcon from "@material-ui/icons/Facebook";
|
|
import InstagramIcon from "@material-ui/icons/Instagram";
|
|
import LanguageIcon from "@material-ui/icons/Language";
|
|
import ButtonPrimary from "../Input/ButtonPrimary";
|
|
|
|
// SETUP
|
|
|
|
const useStyles = makeStyles((theme) => ({
|
|
root: {
|
|
margin: "auto",
|
|
textAlign: "center",
|
|
maxHeight: "90vh",
|
|
"& .MuiPaper-root": {
|
|
width: "auto",
|
|
backgroundColor: "#262626",
|
|
color: "#bbbbbb",
|
|
},
|
|
},
|
|
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),
|
|
"& .MuiInputBase-root": {
|
|
color: "#bbbbbb",
|
|
},
|
|
"& .MuiInputLabel-root": {
|
|
color: "#bbbbbb",
|
|
},
|
|
"$ .MuiFormHelperText-root": {
|
|
color: "#bbbbbb",
|
|
},
|
|
},
|
|
stepLabel: {
|
|
"& .MuiStepLabel-label": {
|
|
color: "#bbbbbb",
|
|
},
|
|
"& .MuiStepLabel-active": {
|
|
color: "#bbbbbb",
|
|
},
|
|
},
|
|
formControl: {
|
|
marginTop: theme.spacing(2),
|
|
marginBottom: theme.spacing(2),
|
|
minWidth: 100,
|
|
maxHeight: 400,
|
|
"& .MuiInputBase-root": {
|
|
color: "#bbbbbb",
|
|
},
|
|
"$ .MuiSelect-root": {
|
|
color: "#bbbbbb",
|
|
},
|
|
"& .MuiInputLabel-root": {
|
|
color: "#bbbbbb",
|
|
},
|
|
},
|
|
selectEmpty: {
|
|
marginTop: theme.spacing(2),
|
|
},
|
|
}));
|
|
|
|
export default function NewRestaurant() {
|
|
useEffect(() => {
|
|
document.title = "Menui - Dodaj lokal";
|
|
});
|
|
const dispatch = useDispatch();
|
|
const initialState = {
|
|
name: "",
|
|
city: "",
|
|
adress: "",
|
|
coordinates: [52.354293, 19.42377],
|
|
placesId: "",
|
|
type: "polska",
|
|
imgUrl: "",
|
|
workingHours: {
|
|
pn: "8:00 - 22:00",
|
|
wt: "8:00 - 22:00",
|
|
sr: "8:00 - 22:00",
|
|
cz: "8:00 - 22:00",
|
|
pt: "8:00 - 22:00",
|
|
sb: "8:00 - 22:00",
|
|
nd: "8:00 - 22:00",
|
|
},
|
|
lunchHours: "12:30 - 13:30",
|
|
description: "",
|
|
tags: [],
|
|
phone: "",
|
|
links: {
|
|
facebook: "",
|
|
instagram: "",
|
|
www: "",
|
|
},
|
|
nameError: false,
|
|
cityError: false,
|
|
adressError: false,
|
|
descriptionError: false,
|
|
charLeft: 400,
|
|
};
|
|
const steps = ["Informacje", "Zdjęcie", "Lokalizacja"];
|
|
const [state, setState] = useState(initialState);
|
|
const [activeStep, setActiveStep] = React.useState(0);
|
|
const styles = useStyles();
|
|
const availableTags = [
|
|
"Płatność kartą",
|
|
"Lubimy zwierzaki",
|
|
"Bezglutenowe",
|
|
"Wegańskie",
|
|
"Wegetariańskie",
|
|
"Podajemy alkohol",
|
|
"Dowozimy",
|
|
];
|
|
const history = useHistory();
|
|
const token = useSelector((state) => state.data.userData.jwt);
|
|
|
|
const availableTypes = restaurantTypes.map((type) => {
|
|
return <MenuItem key={type} value={type}>{type}</MenuItem>
|
|
});
|
|
|
|
// HANDLERS
|
|
|
|
const sendForm = () => {
|
|
const formattedTags = prepareTags(state.tags);
|
|
const data = {
|
|
name: state.name,
|
|
city: state.city,
|
|
adress: state.adress,
|
|
coordinates: state.coordinates,
|
|
placesId: state.placesId,
|
|
lunchHours: state.lunchHours,
|
|
type: state.type,
|
|
imgUrl: state.imgUrl,
|
|
workingHours: state.workingHours,
|
|
description: state.description,
|
|
tags: formattedTags,
|
|
links: state.links,
|
|
phone: state.phone,
|
|
hidden: false,
|
|
};
|
|
dispatch(showBackdrop());
|
|
axios({
|
|
url: backend + "restaurant",
|
|
method: "POST",
|
|
data: data,
|
|
headers: {
|
|
"x-auth-token": token,
|
|
},
|
|
})
|
|
.then((response) => {
|
|
dispatch(hideBackdrop());
|
|
dispatch(
|
|
notification(
|
|
"Lokal został dodany, aktywuj subskrypcję, aby był widoczny w wynikach wyszukiwania.",
|
|
"success"
|
|
)
|
|
);
|
|
dispatch(refreshUserData(token));
|
|
history.push("/");
|
|
})
|
|
.catch((error) => {
|
|
dispatch(hideBackdrop());
|
|
console.log(error);
|
|
dispatch(
|
|
notification(
|
|
"Wystąpił nieoczekiwany błąd, przepraszamy za utrudnienia. Spróbuj ponownie za chwilę.",
|
|
"error"
|
|
)
|
|
);
|
|
history.push("/");
|
|
});
|
|
};
|
|
|
|
const setLunchHours = (hours) => {
|
|
setState({ ...state, lunchHours: hours });
|
|
}
|
|
|
|
const setCoordinatesAndPlacesID = (coordinates, placesID) => {
|
|
if (!placesID) {
|
|
setState({ ...state, coordinates: coordinates });
|
|
} else {
|
|
setState({ ...state, coordinates: coordinates, placesId: placesID });
|
|
}
|
|
};
|
|
|
|
const handleNextButton = () => {
|
|
switch (activeStep) {
|
|
case 0:
|
|
if (validateForm()) {
|
|
setActiveStep(1);
|
|
}
|
|
break;
|
|
case 1:
|
|
if (!validator.isEmpty(state.imgUrl)) {
|
|
setActiveStep(2);
|
|
}
|
|
break;
|
|
case 2:
|
|
sendForm();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
};
|
|
|
|
const handleImageUploaded = (link) => {
|
|
setState({ ...state, imgUrl: link });
|
|
};
|
|
|
|
const handleDescriptionChange = (event) => {
|
|
let stringLength = event.target.value.length;
|
|
let charleft = 400 - stringLength;
|
|
setState({ ...state, description: event.target.value, charLeft: charleft });
|
|
};
|
|
|
|
const handlePreviousButton = () => {
|
|
setActiveStep(activeStep - 1);
|
|
};
|
|
|
|
const validateForm = () => {
|
|
const validation = {
|
|
nameValid: validator.isLength(state.name, { min: 1, max: 40 }),
|
|
cityValid: validator.isLength(state.city, { min: 1, max: 40 }),
|
|
adressValid: validator.isLength(state.name, { min: 1, max: 40 }),
|
|
descriptionValid: validator.isLength(state.description, {
|
|
min: 1,
|
|
max: 400,
|
|
}),
|
|
};
|
|
setState({
|
|
...state,
|
|
nameError: !validation.nameValid,
|
|
cityError: !validation.cityValid,
|
|
adressError: !validation.adressValid,
|
|
descriptionError: !validation.descriptionValid,
|
|
});
|
|
|
|
return (
|
|
validation.nameValid &&
|
|
validation.cityValid &&
|
|
validation.adressValid &&
|
|
validation.descriptionValid
|
|
);
|
|
};
|
|
|
|
// COMPONENTS
|
|
|
|
return (
|
|
<div>
|
|
<Dialog
|
|
className={styles.root}
|
|
open={true}
|
|
aria-labelledby="newRestaurant-title"
|
|
>
|
|
<DialogTitle id="newRestaurant-title">Dodaj Lokal</DialogTitle>
|
|
<IconButton
|
|
className={styles.closeButton}
|
|
onClick={() => history.goBack()}
|
|
aria-label="close"
|
|
>
|
|
<CloseIcon />
|
|
</IconButton>
|
|
<Divider />
|
|
<DialogContent>
|
|
<Stepper activeStep={activeStep} alternativeLabel>
|
|
{steps.map((label) => (
|
|
<Step key={label}>
|
|
<StepLabel className={styles.stepLabel}>{label}</StepLabel>
|
|
</Step>
|
|
))}
|
|
</Stepper>
|
|
|
|
{activeStep === 0 && (
|
|
<Paper variant="outlined">
|
|
<div className="newRestaurant-content-fullwidth">
|
|
<TextField
|
|
className={styles.textInputFullWidth}
|
|
fullWidth
|
|
required
|
|
error={state.nameError}
|
|
value={state.name}
|
|
label="Nazwa lokalu"
|
|
placeholder="np. Pierożek"
|
|
variant="outlined"
|
|
onChange={(event) =>
|
|
setState({ ...state, name: event.target.value })
|
|
}
|
|
InputProps={{
|
|
startAdornment: (
|
|
<InputAdornment position="start">
|
|
<FastfoodIcon color="primary" />
|
|
</InputAdornment>
|
|
),
|
|
}}
|
|
/>
|
|
</div>
|
|
<div className="newRestaurant-content-fullwidth">
|
|
<FormControl
|
|
variant="outlined"
|
|
required
|
|
fullWidth
|
|
className={styles.formControl}
|
|
>
|
|
<InputLabel id="category-select">Kuchnia</InputLabel>
|
|
<Select
|
|
labelId="category-select"
|
|
id="category"
|
|
value={state.type}
|
|
required
|
|
onChange={(event) => setState({ ...state, type: event.target.value })}
|
|
>
|
|
{availableTypes}
|
|
</Select>
|
|
</FormControl>
|
|
</div>
|
|
<div className="newRestaurant-content">
|
|
<TextField
|
|
className={styles.textInput}
|
|
required
|
|
label="Miasto"
|
|
placeholder="np. Ciechanów"
|
|
error={state.cityError}
|
|
value={state.city}
|
|
variant="outlined"
|
|
onChange={(event) =>
|
|
setState({ ...state, city: event.target.value })
|
|
}
|
|
InputProps={{
|
|
startAdornment: (
|
|
<InputAdornment position="start">
|
|
<LocationCityIcon color="primary" />
|
|
</InputAdornment>
|
|
),
|
|
}}
|
|
/>
|
|
<TextField
|
|
className={styles.textInput}
|
|
required
|
|
label="Adres"
|
|
placeholder="np. Akacjowa 13"
|
|
variant="outlined"
|
|
error={state.adressError}
|
|
value={state.adress}
|
|
onChange={(event) =>
|
|
setState({ ...state, adress: event.target.value })
|
|
}
|
|
InputProps={{
|
|
startAdornment: (
|
|
<InputAdornment position="start">
|
|
<LocationCityIcon color="primary" />
|
|
</InputAdornment>
|
|
),
|
|
}}
|
|
/>
|
|
<InputWorkingHours
|
|
hours={state.workingHours}
|
|
setHours={(hours) =>
|
|
setState({ ...state, workingHours: hours })
|
|
}
|
|
/>
|
|
<div className="newRestaurant-content-fullwidth">
|
|
<div className="workingHours-container" style={{ marginTop: 14 }}>
|
|
<InputLunchMenuHours nieczynne={!state.lunchHours} hours={state.lunchHours} changeValue={(value) => setLunchHours(value)}/></div>
|
|
</div>
|
|
<div className="newRestaurant-content-fullwidth">
|
|
<TextField
|
|
className={styles.textInputFullWidth}
|
|
fullWidth
|
|
label="Opis"
|
|
value={state.description}
|
|
onChange={(event) => handleDescriptionChange(event)}
|
|
multiline
|
|
error={state.descriptionError}
|
|
rows={3}
|
|
rowsMax={8}
|
|
variant="outlined"
|
|
helperText={"Pozostałe znaki: " + state.charLeft}
|
|
FormHelperTextProps={{
|
|
style: { color: "#bbbbbb" },
|
|
}}
|
|
required
|
|
/>
|
|
<Autocomplete
|
|
multiple
|
|
options={availableTags}
|
|
value={state.tags}
|
|
onChange={(event, values) =>
|
|
setState({ ...state, tags: values })
|
|
}
|
|
renderInput={(params) => (
|
|
<TextField
|
|
{...params}
|
|
className={styles.textInputFullWidth}
|
|
variant="outlined"
|
|
label="Tagi"
|
|
placeholder="Wybierz tagi"
|
|
/>
|
|
)}
|
|
/>
|
|
</div>
|
|
<TextField
|
|
className={styles.textInput}
|
|
label="Telefon"
|
|
type="tel"
|
|
variant="outlined"
|
|
value={state.phone}
|
|
onChange={(event) =>
|
|
setState({ ...state, phone: event.target.value })
|
|
}
|
|
InputProps={{
|
|
startAdornment: (
|
|
<InputAdornment position="start">
|
|
<PhoneIcon color="primary" />
|
|
</InputAdornment>
|
|
),
|
|
}}
|
|
/>
|
|
<TextField
|
|
className={styles.textInput}
|
|
label="Facebook"
|
|
variant="outlined"
|
|
value={state.links.facebook}
|
|
onChange={(event) =>
|
|
setState({
|
|
...state,
|
|
links: { ...state.links, facebook: event.target.value },
|
|
})
|
|
}
|
|
InputProps={{
|
|
startAdornment: (
|
|
<InputAdornment position="start">
|
|
<FacebookIcon color="primary" />
|
|
</InputAdornment>
|
|
),
|
|
}}
|
|
/>
|
|
<TextField
|
|
className={styles.textInput}
|
|
label="Instagram"
|
|
variant="outlined"
|
|
value={state.links.instagram}
|
|
onChange={(event) =>
|
|
setState({
|
|
...state,
|
|
links: { ...state.links, instagram: event.target.value },
|
|
})
|
|
}
|
|
InputProps={{
|
|
startAdornment: (
|
|
<InputAdornment position="start">
|
|
<InstagramIcon color="primary" />
|
|
</InputAdornment>
|
|
),
|
|
}}
|
|
/>
|
|
<TextField
|
|
className={styles.textInput}
|
|
label="www"
|
|
variant="outlined"
|
|
value={state.links.www}
|
|
onChange={(event) =>
|
|
setState({
|
|
...state,
|
|
links: { ...state.links, www: event.target.value },
|
|
})
|
|
}
|
|
InputProps={{
|
|
startAdornment: (
|
|
<InputAdornment position="start">
|
|
<LanguageIcon color="primary" />
|
|
</InputAdornment>
|
|
),
|
|
}}
|
|
/>
|
|
</div>
|
|
</Paper>
|
|
)}
|
|
{activeStep === 1 && (
|
|
<Paper>
|
|
<h4>Dodaj zdjęcie lokalu.</h4>
|
|
<ImageUpload
|
|
img={state.imgUrl}
|
|
onUpload={(link) => handleImageUploaded(link)}
|
|
/>
|
|
</Paper>
|
|
)}
|
|
{activeStep === 2 && (
|
|
<Paper>
|
|
<p>
|
|
Kliknij w miejscu, w którym znajduje się Twoja restauracja, by
|
|
dodać marker. <br />
|
|
Jeżeli lokal znajduje się na mapie - kliknij jego ikonkę.
|
|
</p>
|
|
<InputGoogleMaps
|
|
setCoordinates={(coordinates, placesID) =>
|
|
setCoordinatesAndPlacesID(coordinates, placesID)
|
|
}
|
|
coordinates={state.coordinates}
|
|
/>
|
|
</Paper>
|
|
)}
|
|
<div className="newRestaurant-bottom">
|
|
{activeStep !== 0 && (
|
|
<ButtonPrimary onClick={handlePreviousButton} text="Cofnij" />
|
|
)}
|
|
<ButtonSecondary
|
|
onClick={handleNextButton}
|
|
text={activeStep === 2 ? "Dodaj lokal" : "Dalej"}
|
|
/>
|
|
</div>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</div>
|
|
);
|
|
}
|