Add Restaurant almost done
This commit is contained in:
20
package-lock.json
generated
20
package-lock.json
generated
@@ -1513,6 +1513,26 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz",
|
||||||
"integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw=="
|
"integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw=="
|
||||||
},
|
},
|
||||||
|
"@react-google-maps/api": {
|
||||||
|
"version": "1.10.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@react-google-maps/api/-/api-1.10.1.tgz",
|
||||||
|
"integrity": "sha512-hb8urUcwZw99Cu3yQnZWUbXjR1Ym/8C21kSX6B02I29l6DXNxDbJ5Jo/T5swhnizPKY7TNhR1oTctC/HY7SQWA==",
|
||||||
|
"requires": {
|
||||||
|
"@react-google-maps/infobox": "1.10.0",
|
||||||
|
"@react-google-maps/marker-clusterer": "1.10.0",
|
||||||
|
"invariant": "2.2.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@react-google-maps/infobox": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@react-google-maps/infobox/-/infobox-1.10.0.tgz",
|
||||||
|
"integrity": "sha512-MhT2nMmjeG7TCxRv/JdylDyNd/n66ggSQQhTWVjJJTtdB/xqd0T8BHCkBWDN9uF0i0yCZzMFl2P2Y1zJ+xppBg=="
|
||||||
|
},
|
||||||
|
"@react-google-maps/marker-clusterer": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@react-google-maps/marker-clusterer/-/marker-clusterer-1.10.0.tgz",
|
||||||
|
"integrity": "sha512-3GLVgeXNStVcdiLMxzi3cBjr32ctlexLPPGQguwcYd6yPLaCcnVCwyzhV68KvL00xqOAD1c3aABV9EGgY8u6Qw=="
|
||||||
|
},
|
||||||
"@sheerun/mutationobserver-shim": {
|
"@sheerun/mutationobserver-shim": {
|
||||||
"version": "0.3.3",
|
"version": "0.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
"@material-ui/icons": "^4.9.1",
|
"@material-ui/icons": "^4.9.1",
|
||||||
"@material-ui/lab": "^4.0.0-alpha.56",
|
"@material-ui/lab": "^4.0.0-alpha.56",
|
||||||
"@material-ui/pickers": "^3.2.10",
|
"@material-ui/pickers": "^3.2.10",
|
||||||
|
"@react-google-maps/api": "^1.10.1",
|
||||||
"@testing-library/jest-dom": "^4.2.4",
|
"@testing-library/jest-dom": "^4.2.4",
|
||||||
"@testing-library/react": "^9.5.0",
|
"@testing-library/react": "^9.5.0",
|
||||||
"@testing-library/user-event": "^7.2.1",
|
"@testing-library/user-event": "^7.2.1",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Router, Switch, Route } from "react-router-dom";
|
import { Router, Switch, Route } from "react-router-dom";
|
||||||
|
import PrivateRoute from "./components/PrivateRoute";
|
||||||
import "./App.scss";
|
import "./App.scss";
|
||||||
import TopBar from "./components/TopBar";
|
import TopBar from "./components/TopBar";
|
||||||
import LogoMain from "./components/Output/logoMain";
|
import LogoMain from "./components/Output/logoMain";
|
||||||
@@ -61,9 +62,11 @@ function App(props) {
|
|||||||
<Route path="/register">
|
<Route path="/register">
|
||||||
<RegisterDialog />
|
<RegisterDialog />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/newRestaurant">
|
<PrivateRoute
|
||||||
<NewRestaurant />
|
path="/newRestaurant"
|
||||||
</Route>
|
component={<NewRestaurant />}
|
||||||
|
/>
|
||||||
|
<PrivateRoute path="/newDish" component={<NewRestaurant />} />
|
||||||
<Route path="/forgotpassword">
|
<Route path="/forgotpassword">
|
||||||
<ForgotPassword />
|
<ForgotPassword />
|
||||||
</Route>
|
</Route>
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ import InputAdornment from "@material-ui/core/InputAdornment";
|
|||||||
import ImageUpload from "../Input/ImageUpload";
|
import ImageUpload from "../Input/ImageUpload";
|
||||||
import validator from "validator";
|
import validator from "validator";
|
||||||
import { useHistory } from "react-router-dom";
|
import { useHistory } from "react-router-dom";
|
||||||
|
import InputGoogleMaps from "../Input/InputGoogleMaps";
|
||||||
|
import InfoDialog from "../Output/InfoDialog";
|
||||||
// ICONS
|
// ICONS
|
||||||
import FastfoodIcon from "@material-ui/icons/Fastfood";
|
import FastfoodIcon from "@material-ui/icons/Fastfood";
|
||||||
import LocationCityIcon from "@material-ui/icons/LocationCity";
|
import LocationCityIcon from "@material-ui/icons/LocationCity";
|
||||||
@@ -89,6 +91,9 @@ export default function NewRestaurant() {
|
|||||||
name: "",
|
name: "",
|
||||||
city: "",
|
city: "",
|
||||||
adress: "",
|
adress: "",
|
||||||
|
coordinates: [52.354293, 19.42377],
|
||||||
|
placesId: "",
|
||||||
|
imgURL: "",
|
||||||
hoursFrom: "07:00",
|
hoursFrom: "07:00",
|
||||||
hoursTo: "23:00",
|
hoursTo: "23:00",
|
||||||
description: "",
|
description: "",
|
||||||
@@ -102,6 +107,8 @@ export default function NewRestaurant() {
|
|||||||
adressError: false,
|
adressError: false,
|
||||||
descriptionError: false,
|
descriptionError: false,
|
||||||
charLeft: 400,
|
charLeft: 400,
|
||||||
|
open: true,
|
||||||
|
response: "",
|
||||||
};
|
};
|
||||||
const steps = ["Informacje", "Zdjęcie", "Lokalizacja"];
|
const steps = ["Informacje", "Zdjęcie", "Lokalizacja"];
|
||||||
const [state, setState] = useState(initialState);
|
const [state, setState] = useState(initialState);
|
||||||
@@ -120,12 +127,56 @@ export default function NewRestaurant() {
|
|||||||
|
|
||||||
// HANDLERS
|
// HANDLERS
|
||||||
|
|
||||||
|
const sendForm = () => {
|
||||||
|
// format tags
|
||||||
|
const formattedTags;
|
||||||
|
const data = {
|
||||||
|
name: state.name,
|
||||||
|
city: state.city,
|
||||||
|
adress: state.adress,
|
||||||
|
coordinates: state.coordinates,
|
||||||
|
placesId: state.placesId,
|
||||||
|
imgURL: state.imgURL,
|
||||||
|
workingHours: `${state.hoursFrom} - ${state.hoursTo}`,
|
||||||
|
description: state.description,
|
||||||
|
tags: formattedTags,
|
||||||
|
links: {},
|
||||||
|
phone: request.phone,
|
||||||
|
hidden: request.hidden,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const setCoordinatesAndPlacesID = (coordinates, placesID) => {
|
||||||
|
if (!placesID) {
|
||||||
|
setState({ ...state, coordinates: coordinates });
|
||||||
|
} else {
|
||||||
|
setState({ ...state, coordinates: coordinates, placesId: placesID });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleNextButton = () => {
|
const handleNextButton = () => {
|
||||||
if (activeStep === 0) {
|
switch (activeStep) {
|
||||||
|
case 0:
|
||||||
if (validateForm()) {
|
if (validateForm()) {
|
||||||
setActiveStep(1);
|
setActiveStep(1);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (!validator.isEmpty(state.imgURL)) {
|
||||||
|
setActiveStep(2);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
setState({ ...state, open: false });
|
||||||
|
sendForm();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleImageUploaded = (link) => {
|
||||||
|
setState({ ...state, imgURL: link });
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDescriptionChange = (event) => {
|
const handleDescriptionChange = (event) => {
|
||||||
@@ -168,9 +219,16 @@ export default function NewRestaurant() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
{!state.open && (
|
||||||
|
<InfoDialog
|
||||||
|
title={"Dodawanie lokalu"}
|
||||||
|
text={"Dodawanie lokalu, prosimy o chwilę cierpliwości..."}
|
||||||
|
loading={true}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<Dialog
|
<Dialog
|
||||||
className={styles.root}
|
className={styles.root}
|
||||||
open={true}
|
open={state.open}
|
||||||
aria-labelledby="newRestaurant-title"
|
aria-labelledby="newRestaurant-title"
|
||||||
>
|
>
|
||||||
<DialogTitle id="newRestaurant-title">Dodaj Lokal</DialogTitle>
|
<DialogTitle id="newRestaurant-title">Dodaj Lokal</DialogTitle>
|
||||||
@@ -390,7 +448,20 @@ export default function NewRestaurant() {
|
|||||||
{activeStep === 1 && (
|
{activeStep === 1 && (
|
||||||
<Paper>
|
<Paper>
|
||||||
<h4>Dodaj zdjęcie lokalu.</h4>
|
<h4>Dodaj zdjęcie lokalu.</h4>
|
||||||
<ImageUpload />
|
<ImageUpload
|
||||||
|
img={state.imgURL}
|
||||||
|
onUpload={(link) => handleImageUploaded(link)}
|
||||||
|
/>
|
||||||
|
</Paper>
|
||||||
|
)}
|
||||||
|
{activeStep === 2 && (
|
||||||
|
<Paper>
|
||||||
|
<InputGoogleMaps
|
||||||
|
setCoordinates={(coordinates, placesID) =>
|
||||||
|
setCoordinatesAndPlacesID(coordinates, placesID)
|
||||||
|
}
|
||||||
|
coordinates={state.coordinates}
|
||||||
|
/>
|
||||||
</Paper>
|
</Paper>
|
||||||
)}
|
)}
|
||||||
{activeStep !== 0 && (
|
{activeStep !== 0 && (
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import CircularProgress from "@material-ui/core/CircularProgress";
|
import CircularProgress from "@material-ui/core/CircularProgress";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
export default function ImageUpload() {
|
export default function ImageUpload(props) {
|
||||||
const [imagePreviewURL, setPreviewURL] = useState("");
|
const [imagePreviewURL, setPreviewURL] = useState(props.img);
|
||||||
let showCircle = false;
|
let showCircle = false;
|
||||||
|
const token = useSelector((state) => state.data.jwt);
|
||||||
|
|
||||||
const handleInputChange = (event) => {
|
const handleInputChange = (event) => {
|
||||||
let data = new FormData();
|
let data = new FormData();
|
||||||
data.append("menuiImage", new Blob([event.target.files[0]]));
|
data.append("menuiImage", event.target.files[0]);
|
||||||
|
|
||||||
axios({
|
axios({
|
||||||
url: "http://localhost:4000/img",
|
url: "http://localhost:4000/img",
|
||||||
@@ -17,20 +19,16 @@ export default function ImageUpload() {
|
|||||||
headers: {
|
headers: {
|
||||||
Accept: "application/json",
|
Accept: "application/json",
|
||||||
"Content-Type": "multipart/form-data",
|
"Content-Type": "multipart/form-data",
|
||||||
|
"x-auth-token": token,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
console.log(response);
|
setPreviewURL(response.data.imgURL);
|
||||||
|
props.onUpload(response.data.imgURL);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.log(error);
|
console.log("Wystąpił błąd podczas wgrywania pliku.");
|
||||||
});
|
});
|
||||||
|
|
||||||
let reader = new FileReader();
|
|
||||||
reader.onloadend = () => {
|
|
||||||
setPreviewURL(reader.result);
|
|
||||||
};
|
|
||||||
reader.readAsDataURL(event.target.files[0]);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let imagePreview = (
|
let imagePreview = (
|
||||||
|
|||||||
47
src/components/Input/InputGoogleMaps.js
Normal file
47
src/components/Input/InputGoogleMaps.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { GoogleMap, LoadScript, Marker } from "@react-google-maps/api";
|
||||||
|
|
||||||
|
function InputGoogleMaps(props) {
|
||||||
|
const containerStyle = {
|
||||||
|
width: "500px",
|
||||||
|
height: "500px",
|
||||||
|
};
|
||||||
|
|
||||||
|
const center = {
|
||||||
|
lat: props.coordinates[0],
|
||||||
|
lng: props.coordinates[1],
|
||||||
|
};
|
||||||
|
const [visibility, setVisibility] = useState(true);
|
||||||
|
|
||||||
|
const handleMapClick = (event) => {
|
||||||
|
const location = {
|
||||||
|
lat: event.latLng.lat(),
|
||||||
|
lng: event.latLng.lng(),
|
||||||
|
};
|
||||||
|
if (event.placeId) {
|
||||||
|
setVisibility(false);
|
||||||
|
props.setCoordinates([location.lat, location.lng], event.placeId);
|
||||||
|
} else {
|
||||||
|
setVisibility(true);
|
||||||
|
props.setCoordinates([location.lat, location.lng]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LoadScript googleMapsApiKey="AIzaSyDAlZSiBanP52qpZ1kaH06XkuA2zndLUd8">
|
||||||
|
<GoogleMap
|
||||||
|
mapContainerStyle={containerStyle}
|
||||||
|
center={center}
|
||||||
|
zoom={7}
|
||||||
|
onClick={handleMapClick}
|
||||||
|
>
|
||||||
|
<Marker
|
||||||
|
position={{ lat: props.coordinates[0], lng: props.coordinates[1] }}
|
||||||
|
visible={visibility}
|
||||||
|
/>
|
||||||
|
</GoogleMap>
|
||||||
|
</LoadScript>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default React.memo(InputGoogleMaps);
|
||||||
57
src/components/Output/InfoDialog.js
Normal file
57
src/components/Output/InfoDialog.js
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import React from "react";
|
||||||
|
import CloseIcon from "@material-ui/icons/Close";
|
||||||
|
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 CircularProgress from "@material-ui/core/CircularProgress";
|
||||||
|
import { useHistory } from "react-router-dom";
|
||||||
|
|
||||||
|
export default function InfoDialog(props) {
|
||||||
|
const history = useHistory();
|
||||||
|
const loading = props.loading;
|
||||||
|
const loginStyles = makeStyles((theme) => ({
|
||||||
|
root: {
|
||||||
|
textAlign: "center",
|
||||||
|
"& .MuiPaper-root": {
|
||||||
|
backgroundColor: "#262626",
|
||||||
|
color: "#bbbbbb",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
closeButton: {
|
||||||
|
color: "#bbbbbb",
|
||||||
|
position: "absolute",
|
||||||
|
right: theme.spacing(1),
|
||||||
|
top: theme.spacing(1),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const styles = loginStyles();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
className={styles.root}
|
||||||
|
onClose={() => history.push("/")}
|
||||||
|
open={true}
|
||||||
|
aria-labelledby="title"
|
||||||
|
>
|
||||||
|
<DialogTitle id="title">{props.title}</DialogTitle>
|
||||||
|
<IconButton
|
||||||
|
className={styles.closeButton}
|
||||||
|
onClick={() => history.push("/")}
|
||||||
|
aria-label="close"
|
||||||
|
>
|
||||||
|
<CloseIcon />
|
||||||
|
</IconButton>
|
||||||
|
<Divider />
|
||||||
|
<DialogContent>
|
||||||
|
<p>{props.text}</p>
|
||||||
|
{loading && <CircularProgress />}
|
||||||
|
<ButtonSecondary onClick={history.push("/")} text="Ok" />
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
25
src/components/PrivateRoute.js
Normal file
25
src/components/PrivateRoute.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
import { Redirect, Route } from "react-router-dom";
|
||||||
|
|
||||||
|
export default function PrivateRoute({ component, ...rest }) {
|
||||||
|
const loggedIn = useSelector((state) => state.data.loggedIn);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Route
|
||||||
|
{...rest}
|
||||||
|
render={({ location }) =>
|
||||||
|
loggedIn ? (
|
||||||
|
component
|
||||||
|
) : (
|
||||||
|
<Redirect
|
||||||
|
to={{
|
||||||
|
pathname: "/login",
|
||||||
|
state: { from: location },
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user