web client v1.0 (production)

This commit is contained in:
2020-10-08 21:29:06 +02:00
parent d0dab37649
commit 20c7dd18a7
22 changed files with 289 additions and 33 deletions

View File

@@ -23,6 +23,7 @@ import Settings from "./components/Dialogs/Settings";
import EditRestaurant from "./components/Dialogs/EditRestaurant";
import NewDish from "./components/Dialogs/NewDish";
import EditDish from "./components/Dialogs/EditDish";
import Dish from "./components/Dialogs/Dish";
const theme = createMuiTheme({
palette: {
@@ -75,7 +76,7 @@ function App(props) {
component={<NewDish />}
/>
<Route path="/dish/:id">
<LogoMain />
<Dish />
</Route>
<Route path="/login">
<LoginDialog />

View File

@@ -9,6 +9,7 @@
@import "./styles/Dialogs.scss";
@import "./styles/NewRestaurant.scss";
@import "./styles/EditRestaurant.scss";
@import "./styles/Dish.scss";
.App {
background-image: url("./public/bg_tile.jpg");

View File

@@ -92,6 +92,13 @@ const setDishes = (data) => {
};
};
const setDish = (data) => {
return {
type: "SET_DISH",
payload: data,
};
};
export const fetchAllDishes = (id) => {
return function (dispatch) {
axios
@@ -103,6 +110,20 @@ export const fetchAllDishes = (id) => {
};
};
export const fetchDish = (id) => {
return function (dispatch) {
axios
.get(backend + "dish/?dishId=" + id)
.then((response) => {
dispatch(setDish(response.data));
})
.catch((err) => {
dispatch(notification("Nie udało się pobrać :(", "error"));
dispatch(push("/"));
});
};
};
export const refreshUserData = (token) => {
return function (dispatch) {
axios({

View File

@@ -0,0 +1,105 @@
import React, { useState, useEffect } from "react";
import PictogramsSeparate from "../Output/PictogramsSeparate";
import axios from "axios";
import { useParams, useHistory } from "react-router-dom";
import { extractTags } from "../../Services";
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";
const loginStyles = makeStyles((theme) => ({
closeButton: {
color: "#868686",
position: "absolute",
right: theme.spacing(1),
top: theme.spacing(1),
},
}));
export default function Dish(props) {
const { id } = useParams();
const history = useHistory();
const initialState = {};
const [dish, setDish] = useState(initialState);
const styles = loginStyles();
useEffect(() => {
axios
.get(`${backend}dish?dishId=${id}`)
.then((response) => {
setDish(response.data);
})
.catch((err) => {
console.log(err);
});
}, [id]);
if (typeof dish === "undefined") {
return null;
} else {
return (
<div className="dish-container">
<div className="dish-left">
<div
className="dish-hero"
style={{ backgroundImage: "url(" + dish.imgUrl + ")" }}
>
<div className="button-container">
<IconButton
className={styles.back}
onClick={() => history.goBack()}
>
<ArrowBackIcon />
</IconButton>
</div>
</div>
</div>
<div className="dish-content">
<div className="dish-info">
<h1>{dish.name}</h1>
</div>
<hr />
<div className="dish-row-column">
<h5>Składniki</h5>
<p>{dish.ingredients}</p>
</div>
<hr />
<div className="dish-row-column">
<h5>Alergeny</h5>
<div className="dish-pictograms">
<PictogramsSeparate pictograms={extractTags(dish.allergens)} />
</div>
</div>
<hr />
<div className="dish-row">
<h5>Cena</h5>
<p>{dish.price}</p>
</div>
<hr />
<div className="dish-row">
<h5>Porcja</h5>
<p>{dish.weight}</p>
</div>
<hr />
<div className="dish-row">
<h5>Wartość energrtyczna</h5>
<p>{dish.kCal}kcal</p>
</div>
<hr />
<div className="dish-row">
<h5>Indeks glikemiczny</h5>
<p>{dish.glicemicIndex}</p>
</div>
{dish.notes !== "" && <hr />}
{dish.notes !== "" && (
<div className="dish-row">
<h5>Uwagi</h5>
<p>{dish.notes}</p>
</div>
)}
</div>
</div>
);
}
}

View File

@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { useParams, useHistory } from "react-router-dom";
import Divider from "@material-ui/core/Divider";
@@ -88,6 +88,9 @@ const useStyles = makeStyles((theme) => ({
}));
export default function EditDish() {
useEffect(() => {
document.title = "Menui - Edytuj danie";
});
const styles = useStyles();
const token = useSelector((state) => state.data.userData.jwt);
const { id } = useParams();

View File

@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { useParams, useHistory } from "react-router-dom";
import { makeStyles } from "@material-ui/core/styles";
@@ -46,6 +46,9 @@ const useStyles = makeStyles((theme) => ({
}));
export default function EditRestaurant(props) {
useEffect(() => {
document.title = "Menui - Edytuj lokal";
});
const dispatch = useDispatch();
const classes = useStyles();
const [tab, setTab] = useState(0);

View File

@@ -1,4 +1,4 @@
import React, { useState } from "react";
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";
@@ -17,6 +17,9 @@ import { remindPassword, notification } from "../../actions";
import { useHistory } from "react-router-dom";
export default function ForgotPassword(props) {
useEffect(() => {
document.title = "Menui - Odzyskiwanie hasła";
});
const initialData = {
email: "",
emailError: false,

View File

@@ -1,4 +1,4 @@
import React, { useState } from "react";
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";
@@ -18,6 +18,9 @@ import { tryLogin, notification } from "../../actions";
import { useHistory } from "react-router-dom";
export default function LoginDialog(props) {
useEffect(() => {
document.title = "Menui - Logowanie";
});
const initialData = {
email: "",
password: "",

View File

@@ -1,4 +1,4 @@
import React, { useState } from "react";
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";
@@ -94,6 +94,9 @@ const useStyles = makeStyles((theme) => ({
}));
export default function NewRestaurant() {
useEffect(() => {
document.title = "Menui - Dodaj danie";
});
const dispatch = useDispatch();
const { restaurantID } = useParams();
const initialState = {

View File

@@ -1,4 +1,4 @@
import React, { useState } from "react";
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";
@@ -86,6 +86,9 @@ const useStyles = makeStyles((theme) => ({
}));
export default function NewRestaurant() {
useEffect(() => {
document.title = "Menui - Dodaj lokal";
});
const dispatch = useDispatch();
const initialState = {
name: "",

View File

@@ -1,4 +1,4 @@
import React, { useState } from "react";
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";
@@ -42,6 +42,9 @@ export default function RegisterDialog(props) {
const [formData, setFormData] = useState(initialFormData);
const dispatch = useDispatch();
const history = useHistory();
useEffect(() => {
document.title = "Menui - Rejestracja";
});
// STYLES

View File

@@ -1,4 +1,4 @@
import React, { useState } from "react";
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";
@@ -20,6 +20,9 @@ function useQuery() {
}
export default function ResetPassword(props) {
useEffect(() => {
document.title = "Menui - Resetowanie hasła";
});
const initialData = {
email: "",
emailError: false,

View File

@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import DialogTitle from "@material-ui/core/DialogTitle";
import DialogContent from "@material-ui/core/DialogContent";
import Dialog from "@material-ui/core/Dialog";
@@ -69,6 +69,9 @@ const useStyles = makeStyles((theme) => ({
}));
export default function Settings() {
useEffect(() => {
document.title = "Menui - Moje konto";
});
const history = useHistory();
const style = useStyles();
const data = useSelector((state) => state.data.userData);

View File

@@ -3,7 +3,7 @@ import ImageUploadWide from "../Input/ImageUploadWide";
import ButtonSecondary from "../Input/ButtonSecondary";
import ButtonPrimary from "../Input/ButtonPrimary";
import { useDispatch, useSelector } from "react-redux";
import { notification } from "../../actions";
import { notification, refreshUserData } from "../../actions";
import { showBackdrop, hideBackdrop } from "../../actions/toggles.js";
import axios from "axios";
import { backend } from "../../config";
@@ -60,6 +60,7 @@ export default function EditRestaurantPhoto(props) {
.then((res) => {
dispatch(hideBackdrop());
dispatch(notification("Zmieniono zdjęcie.", "success"));
dispatch(refreshUserData(token));
})
.catch((e) => {
dispatch(hideBackdrop());

View File

@@ -1,4 +1,4 @@
import React from "react";
import React, { useEffect } from "react";
import { makeStyles } from "@material-ui/core/styles";
import ButtonSecondary from "./ButtonSecondary";
import TextField from "@material-ui/core/TextField";
@@ -28,6 +28,16 @@ export default function SearchPanel() {
const dispatch = useDispatch();
const classes = useStyles();
useEffect(() => {
document.title = "Menui - Food Guide";
});
const keyDown = (event) => {
if (event.keyCode === 13) {
dispatch(fetchSearch(searchQuery));
}
};
return (
<div className="searchPanel">
<Autocomplete
@@ -41,6 +51,7 @@ export default function SearchPanel() {
className={classes.root}
label="Miasto, Nazwa lokalu, ..."
variant="outlined"
onKeyDown={keyDown}
onChange={(event) => dispatch(setSearchQuery(event.target.value))}
onInput={(event) => dispatch(fetchAutocomplete(event.target.value))}
/>

View File

@@ -1,4 +1,4 @@
import React from "react";
import React, { useEffect } from "react";
import Paper from "@material-ui/core/Paper";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
@@ -21,6 +21,9 @@ const useStyles = makeStyles((theme) => ({
}));
export default function Contact() {
useEffect(() => {
document.title = "Menui - Kontakt";
});
const style = useStyles();
return (
<Paper style={{ backgroundColor: "#262626", color: "#bbbbbb" }}>

View File

@@ -8,6 +8,8 @@ function extractCategories(dishes) {
if (typeof dishes !== "undefined" && dishes.length > 0) {
dishes.map((dish) => categories.add(dish.category));
return Array.from(categories);
} else {
return [];
}
}
@@ -36,5 +38,10 @@ export default function DishList(props) {
);
});
return <div className="dishlist-container">{categories}</div>;
return (
<div className="dishlist-container">
{categories}
{categoriesArray.length === 0 && <h2>Menu jest puste :(</h2>}
</div>
);
}

View File

@@ -8,6 +8,7 @@ export default function LunchMenu(props) {
const lunchMenu = restaurant.lunchMenu;
function filterDishes(dishes, set) {
var result = [];
if (dishes.length !== 0) {
dishes.map((dish) => {
if (set.lunchSetDishes.includes(dish._id)) {
result.push(dish);
@@ -15,6 +16,9 @@ export default function LunchMenu(props) {
return true;
});
return result;
} else {
return [];
}
}
const sets = lunchMenu.map((set) => {
return (
@@ -28,5 +32,5 @@ export default function LunchMenu(props) {
);
});
return <div className="dishlist-container">{sets}</div>;
return <div className="dishlist-container">{sets && sets}</div>;
}

View File

@@ -19,13 +19,8 @@ import vegetarian from "../../public/i_vegetarian.svg";
export default function (props) {
const pictograms = props.pictograms.map((pictogram, index) => (
<Tooltip title={getTooltip(pictogram)}>
<img
key={index}
className="pictogram"
src={getImage(pictogram)}
alt={pictogram}
/>
<Tooltip key={index} title={getTooltip(pictogram)}>
<img className="pictogram" src={getImage(pictogram)} alt={pictogram} />
</Tooltip>
));

View File

@@ -73,11 +73,11 @@ export default function Restaurant(props) {
{restaurant.lunchHours && (
<h3>Lunch menu ({restaurant.lunchHours})</h3>
)}
{showDishList === false && <CircularProgress />}
{showDishList === true && <LunchMenu restaurant={restaurant} />}
{!showDishList && <CircularProgress />}
{showDishList && <LunchMenu restaurant={restaurant} />}
<h3>Menu</h3>
{showDishList === false && <CircularProgress />}
{showDishList === true && <DishList />}
{!showDishList && <CircularProgress />}
{showDishList && <DishList />}
</div>
</div>
</div>

View File

@@ -2,6 +2,8 @@ const dishes = (state = [], action) => {
switch (action.type) {
case "SET_DISHES":
return (state = action.payload);
case "SET_DISH":
return [action.payload];
case "ADD_DISH":
return [...state, action.payload];
case "CLEAR_DISHES":

78
src/styles/Dish.scss Normal file
View File

@@ -0,0 +1,78 @@
.dish-container {
min-width: 70%;
min-height: 600px;
max-height: 80vh;
max-width: 80%;
background-color: #1f1f1f;
border-radius: 15px;
display: grid;
grid-template-columns: 1fr 1fr;
hr {
border: solid 1px $dark-gray;
border-bottom: none;
}
}
.dish-left {
width: 100%;
height: 100%;
}
.dish-hero {
width: 100%;
height: 100%;
border-top-left-radius: 15px;
border-bottom-left-radius: 15px;
background-size: cover;
text-align: left;
}
.button-container {
position: relative;
top: 18px;
left: 18px;
background-color: #d68000;
width: fit-content;
border-radius: 30px;
}
.dish-info {
h1 {
font-weight: 200;
color: $gray;
}
}
.dish-content {
h5 {
font-size: 1rem;
font-weight: 300;
margin: 0 8px 0 auto;
}
p {
color: $gray;
margin: 0 auto 0 0;
font-weight: 500;
}
}
.dish-pictograms {
width: fit-content;
margin: auto;
}
.dish-row {
margin-top: 18px;
margin-bottom: 18px;
display: flex;
justify-content: center;
align-items: center;
}
.dish-row-column {
margin-top: 18px;
margin-bottom: 18px;
h5 {
margin-bottom: 8px;
}
}