diff --git a/README.md b/README.md index 9f13e75..dc705a7 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ Aplikace sestává ze tří (čtyř) modulů. - [x] https://qr-platba.cz/pro-vyvojare/restful-api/ - [ ] Zobrazovat celkovou cenu objednávky pod tabulkou objednávek - [ ] Zobrazit upozornění před smazáním/zamknutím/odemknutím pizza day - - [ ] Umožnit přidat k objednávce poznámku (např. "bez oliv") + - [x] Umožnit přidat k objednávce poznámku (např. "bez oliv") - [ ] Negenerovat QR kód pro objednávajícího - [ ] Pizzy se samy budou při naklikání přidávat do košíku - [ ] Nutno nejprve vyřešit předávání PHPSESSIONID cookie na pizzachefie.cz pomocí fetch() diff --git a/client/src/Api.ts b/client/src/Api.ts index e013d2a..219ae63 100644 --- a/client/src/Api.ts +++ b/client/src/Api.ts @@ -68,4 +68,8 @@ export const addPizza = async (login: string, pizzaIndex: number, pizzaSizeIndex export const removePizza = async (login: string, pizzaOrder: PizzaOrder) => { return await api.post('/api/removePizza', JSON.stringify({ login, pizzaOrder })); +} + +export const updateNote = async (login: string, note?: string) => { + return await api.post('/api/updateNote', JSON.stringify({ login, note })); } \ No newline at end of file diff --git a/client/src/App.css b/client/src/App.css index 2642021..af56180 100644 --- a/client/src/App.css +++ b/client/src/App.css @@ -75,4 +75,8 @@ .qr-code { text-align: center; +} + +.select-search-container { + margin: auto; } \ No newline at end of file diff --git a/client/src/App.tsx b/client/src/App.tsx index 0d9dbd7..dd795f0 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,7 +1,7 @@ import React, { useContext, useEffect, useMemo, useRef, useState } from 'react'; import 'bootstrap/dist/css/bootstrap.min.css'; import { EVENT_DISCONNECT, EVENT_MESSAGE, SocketContext } from './context/socket'; -import { addPizza, createPizzaDay, deletePizzaDay, finishDelivery, finishOrder, getData, getFood, getPizzy, getQrUrl, lockPizzaDay, removePizza, unlockPizzaDay, updateChoice } from './Api'; +import { addPizza, createPizzaDay, deletePizzaDay, finishDelivery, finishOrder, getData, getFood, getPizzy, getQrUrl, lockPizzaDay, removePizza, unlockPizzaDay, updateChoice, updateNote } from './Api'; import { useAuth } from './context/auth'; import Login from './Login'; import { Locations, ClientData, Pizza, PizzaOrder, State, Order } from './Types'; @@ -29,6 +29,7 @@ function App() { const [myOrder, setMyOrder] = useState(); const socket = useContext(SocketContext); const choiceRef = useRef(null); + const poznamkaRef = useRef(null); // Prvotní načtení aktuálního stavu useEffect(() => { @@ -83,9 +84,7 @@ function App() { useEffect(() => { if (data?.pizzaDay?.orders) { const myOrder = data.pizzaDay.orders.find(o => o.customer === auth?.login); - if (myOrder) { - setMyOrder(myOrder); - } + setMyOrder(myOrder); } }, [data?.pizzaDay?.orders]) @@ -131,9 +130,19 @@ function App() { } } - const handlePizzaDelete = (pizzaOrder: PizzaOrder) => { + const handlePizzaDelete = async (pizzaOrder: PizzaOrder) => { if (auth?.login) { - removePizza(auth?.login, pizzaOrder); + await removePizza(auth?.login, pizzaOrder); + } + } + + const handlePoznamkaChange = async () => { + if (auth?.login) { + if (poznamkaRef.current?.value && poznamkaRef.current.value.length > 100) { + alert("Poznámka může mít maximálně 100 znaků"); + return; + } + updateNote(auth.login, poznamkaRef.current?.value); } } @@ -198,6 +207,7 @@ function App() {
  • Nová žárovka zatím funguje
  • Funkční generování a zobrazení QR kódů pro Pizza day
  • +
  • Možnost zadat k Pizza day objednávce poznámku

Dnes je {data.date}

@@ -260,7 +270,10 @@ function App() { { data.pizzaDay.state === State.CREATED &&
-

Pizza Day je založen a spravován uživatelem {data.pizzaDay.creator}.
Můžete upravovat své objednávky.

+

+ Pizza Day je založen a spravován uživatelem {data.pizzaDay.creator}.
+ Můžete upravovat své objednávky. +

{ data.pizzaDay.creator === auth.login && <> @@ -275,18 +288,22 @@ function App() {
} { - data.pizzaDay.state === State.LOCKED && data.pizzaDay.creator === auth.login && + data.pizzaDay.state === State.LOCKED &&

Objednávky jsou uzamčeny uživatelem {data.pizzaDay.creator}

- - {/* + {/* */} - + + + }
} { @@ -312,13 +329,27 @@ function App() { } - + {data.pizzaDay.state === State.CREATED && +
+ + Poznámka: { + if (event.key === 'Enter') { + handlePoznamkaChange(); + } + }} /> + +
+ } { data.pizzaDay.state === State.DELIVERED && myOrder?.hasQr && diff --git a/client/src/Types.tsx b/client/src/Types.tsx index cbfe068..370a0a2 100644 --- a/client/src/Types.tsx +++ b/client/src/Types.tsx @@ -29,6 +29,7 @@ export interface Order { pizzaList: PizzaOrder[], // seznam objednaných pizz totalPrice: number, // celková cena všech objednaných pizz a krabic hasQr?: boolean, // zda je pro objednávku vygenerován QR kód pro platbu + note?: string, // volitelná poznámka uživatele k objednávce } export interface Choices { diff --git a/client/src/components/PizzaOrderList.tsx b/client/src/components/PizzaOrderList.tsx index e9b3ce0..73c09c8 100644 --- a/client/src/components/PizzaOrderList.tsx +++ b/client/src/components/PizzaOrderList.tsx @@ -17,6 +17,7 @@ export default function PizzaOrderList({ state, orders, onDelete }: { state: Sta Jméno Objednávka + Poznámka Cena @@ -34,6 +35,7 @@ export default function PizzaOrderList({ state, orders, onDelete }: { state: Sta ) .reduce((prev, curr, index) => [prev,
, curr])} + {order.note || '-'} {order.totalPrice} Kč )} diff --git a/server/src/index.ts b/server/src/index.ts index 03ef1cb..dde5add 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -3,7 +3,7 @@ import { Server } from "socket.io"; import bodyParser from "body-parser"; import { fetchPizzy } from "./chefie"; import cors from 'cors'; -import { addPizzaOrder, createPizzaDay, deletePizzaDay, finishPizzaDelivery, finishPizzaOrder, getData, lockPizzaDay, removePizzaOrder, unlockPizzaDay, updateChoice } from "./service"; +import { addPizzaOrder, createPizzaDay, deletePizzaDay, finishPizzaDelivery, finishPizzaOrder, getData, lockPizzaDay, removePizzaOrder, unlockPizzaDay, updateChoice, updateNote } from "./service"; import dotenv from 'dotenv'; import path from 'path'; import { fetchMenus } from "./restaurants"; @@ -161,6 +161,18 @@ app.get("/api/qr", (req, res) => { res.end(img); }); +app.post("/api/updateNote", (req, res) => { + if (!req.body.login) { + throw Error("Nebyl předán login"); + } + if (req.body.note && req.body.note.length > 100) { + throw Error("Poznámka může mít maximálně 100 znaků"); + } + const data = updateNote(req.body.login, req.body.note); + io.emit("message", data); + res.status(200).json(data); +}); + io.on("connection", (socket) => { console.log(`New client connected: ${socket.id}`); diff --git a/server/src/service.ts b/server/src/service.ts index 88ed6b3..6fd84c9 100644 --- a/server/src/service.ts +++ b/server/src/service.ts @@ -262,4 +262,22 @@ export function updateChoice(login: string, choice: Locations | null) { } db.set(today, data); return data; +} + +export function updateNote(login: string, note?: string) { + const today = formatDate(getToday()); + let clientData: ClientData = db.get(today); + if (!clientData.pizzaDay) { + throw Error("Pizza day pro dnešní den neexistuje"); + } + if (clientData.pizzaDay.state !== PizzaDayState.CREATED) { + throw Error("Pizza day není ve stavu " + PizzaDayState.CREATED); + } + const myOrder = clientData.pizzaDay.orders.find(o => o.customer === login); + if (!myOrder || !myOrder.pizzaList.length) { + throw Error("Pizza day neobsahuje žádné objednávky uživatele " + login); + } + myOrder.note = note; + db.set(today, clientData); + return clientData; } \ No newline at end of file diff --git a/server/src/types.ts b/server/src/types.ts index 2bbc844..3604ce7 100644 --- a/server/src/types.ts +++ b/server/src/types.ts @@ -34,6 +34,7 @@ export interface Order { pizzaList: PizzaOrder[], // seznam objednaných pizz totalPrice: number, // celková cena všech objednaných pizz a krabic hasQr?: boolean, // true, pokud je k objednávce vygenerován QR kód pro platbu + note?: string, // volitelná uživatelská poznámka k objednávce } /** Stav pizza dne */