Možnost přidat k objednávce poznámku
This commit is contained in:
parent
26337121de
commit
67242c48df
@ -48,7 +48,7 @@ Aplikace sestává ze tří (čtyř) modulů.
|
|||||||
- [x] https://qr-platba.cz/pro-vyvojare/restful-api/
|
- [x] https://qr-platba.cz/pro-vyvojare/restful-api/
|
||||||
- [ ] Zobrazovat celkovou cenu objednávky pod tabulkou objednávek
|
- [ ] Zobrazovat celkovou cenu objednávky pod tabulkou objednávek
|
||||||
- [ ] Zobrazit upozornění před smazáním/zamknutím/odemknutím pizza day
|
- [ ] 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
|
- [ ] Negenerovat QR kód pro objednávajícího
|
||||||
- [ ] Pizzy se samy budou při naklikání přidávat do košíku
|
- [ ] 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()
|
- [ ] Nutno nejprve vyřešit předávání PHPSESSIONID cookie na pizzachefie.cz pomocí fetch()
|
||||||
|
@ -68,4 +68,8 @@ export const addPizza = async (login: string, pizzaIndex: number, pizzaSizeIndex
|
|||||||
|
|
||||||
export const removePizza = async (login: string, pizzaOrder: PizzaOrder) => {
|
export const removePizza = async (login: string, pizzaOrder: PizzaOrder) => {
|
||||||
return await api.post<any, any>('/api/removePizza', JSON.stringify({ login, pizzaOrder }));
|
return await api.post<any, any>('/api/removePizza', JSON.stringify({ login, pizzaOrder }));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const updateNote = async (login: string, note?: string) => {
|
||||||
|
return await api.post<any, any>('/api/updateNote', JSON.stringify({ login, note }));
|
||||||
}
|
}
|
@ -75,4 +75,8 @@
|
|||||||
|
|
||||||
.qr-code {
|
.qr-code {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-search-container {
|
||||||
|
margin: auto;
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
|
import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||||
import { EVENT_DISCONNECT, EVENT_MESSAGE, SocketContext } from './context/socket';
|
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 { useAuth } from './context/auth';
|
||||||
import Login from './Login';
|
import Login from './Login';
|
||||||
import { Locations, ClientData, Pizza, PizzaOrder, State, Order } from './Types';
|
import { Locations, ClientData, Pizza, PizzaOrder, State, Order } from './Types';
|
||||||
@ -29,6 +29,7 @@ function App() {
|
|||||||
const [myOrder, setMyOrder] = useState<Order>();
|
const [myOrder, setMyOrder] = useState<Order>();
|
||||||
const socket = useContext(SocketContext);
|
const socket = useContext(SocketContext);
|
||||||
const choiceRef = useRef<HTMLSelectElement>(null);
|
const choiceRef = useRef<HTMLSelectElement>(null);
|
||||||
|
const poznamkaRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
// Prvotní načtení aktuálního stavu
|
// Prvotní načtení aktuálního stavu
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -83,9 +84,7 @@ function App() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data?.pizzaDay?.orders) {
|
if (data?.pizzaDay?.orders) {
|
||||||
const myOrder = data.pizzaDay.orders.find(o => o.customer === auth?.login);
|
const myOrder = data.pizzaDay.orders.find(o => o.customer === auth?.login);
|
||||||
if (myOrder) {
|
setMyOrder(myOrder);
|
||||||
setMyOrder(myOrder);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, [data?.pizzaDay?.orders])
|
}, [data?.pizzaDay?.orders])
|
||||||
|
|
||||||
@ -131,9 +130,19 @@ function App() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handlePizzaDelete = (pizzaOrder: PizzaOrder) => {
|
const handlePizzaDelete = async (pizzaOrder: PizzaOrder) => {
|
||||||
if (auth?.login) {
|
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() {
|
|||||||
<ul>
|
<ul>
|
||||||
<li>Nová žárovka zatím funguje</li>
|
<li>Nová žárovka zatím funguje</li>
|
||||||
<li>Funkční generování a zobrazení QR kódů pro Pizza day</li>
|
<li>Funkční generování a zobrazení QR kódů pro Pizza day</li>
|
||||||
|
<li>Možnost zadat k Pizza day objednávce poznámku</li>
|
||||||
</ul>
|
</ul>
|
||||||
</Alert>
|
</Alert>
|
||||||
<h1 className='title'>Dnes je {data.date}</h1>
|
<h1 className='title'>Dnes je {data.date}</h1>
|
||||||
@ -260,7 +270,10 @@ function App() {
|
|||||||
{
|
{
|
||||||
data.pizzaDay.state === State.CREATED &&
|
data.pizzaDay.state === State.CREATED &&
|
||||||
<div>
|
<div>
|
||||||
<p>Pizza Day je založen a spravován uživatelem {data.pizzaDay.creator}.<br />Můžete upravovat své objednávky.</p>
|
<p>
|
||||||
|
Pizza Day je založen a spravován uživatelem {data.pizzaDay.creator}.<br />
|
||||||
|
Můžete upravovat své objednávky.
|
||||||
|
</p>
|
||||||
{
|
{
|
||||||
data.pizzaDay.creator === auth.login &&
|
data.pizzaDay.creator === auth.login &&
|
||||||
<>
|
<>
|
||||||
@ -275,18 +288,22 @@ function App() {
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
data.pizzaDay.state === State.LOCKED && data.pizzaDay.creator === auth.login &&
|
data.pizzaDay.state === State.LOCKED &&
|
||||||
<div>
|
<div>
|
||||||
<p>Objednávky jsou uzamčeny uživatelem {data.pizzaDay.creator}</p>
|
<p>Objednávky jsou uzamčeny uživatelem {data.pizzaDay.creator}</p>
|
||||||
<Button className='danger mb-3' title="Umožní znovu editovat objednávky." onClick={async () => {
|
{data.pizzaDay.creator === auth.login &&
|
||||||
await unlockPizzaDay(auth.login);
|
<>
|
||||||
}}>Odemknout</Button>
|
<Button className='danger mb-3' title="Umožní znovu editovat objednávky." onClick={async () => {
|
||||||
{/* <Button className='danger mb-3' style={{ marginLeft: '20px' }} onClick={async () => {
|
await unlockPizzaDay(auth.login);
|
||||||
|
}}>Odemknout</Button>
|
||||||
|
{/* <Button className='danger mb-3' style={{ marginLeft: '20px' }} onClick={async () => {
|
||||||
await addToCart();
|
await addToCart();
|
||||||
}}>Přidat vše do košíku</Button> */}
|
}}>Přidat vše do košíku</Button> */}
|
||||||
<Button className='danger mb-3' style={{ marginLeft: '20px' }} title={noOrders ? "Nelze objednat - neexistuje žádná objednávka" : "Použij po objednání. Objednávky zůstanou zamčeny."} disabled={noOrders} onClick={async () => {
|
<Button className='danger mb-3' style={{ marginLeft: '20px' }} title={noOrders ? "Nelze objednat - neexistuje žádná objednávka" : "Použij po objednání. Objednávky zůstanou zamčeny."} disabled={noOrders} onClick={async () => {
|
||||||
await finishOrder(auth.login);
|
await finishOrder(auth.login);
|
||||||
}}>Objednáno</Button>
|
}}>Objednáno</Button>
|
||||||
|
</>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -312,13 +329,27 @@ function App() {
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<SelectSearch
|
{data.pizzaDay.state === State.CREATED &&
|
||||||
search={true}
|
<div style={{ textAlign: 'center' }}>
|
||||||
options={pizzaSuggestions}
|
<SelectSearch
|
||||||
placeholder='Vyhledat pizzu...'
|
search={true}
|
||||||
onChange={handlePizzaChange}
|
options={pizzaSuggestions}
|
||||||
disabled={data.pizzaDay.state !== State.CREATED}
|
placeholder='Vyhledat pizzu...'
|
||||||
/>
|
onChange={handlePizzaChange}
|
||||||
|
/>
|
||||||
|
Poznámka: <input ref={poznamkaRef} className='mt-3' type="text" onKeyDown={event => {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
handlePoznamkaChange();
|
||||||
|
}
|
||||||
|
}} />
|
||||||
|
<Button
|
||||||
|
style={{ marginLeft: '20px' }}
|
||||||
|
disabled={!myOrder?.pizzaList?.length}
|
||||||
|
onClick={handlePoznamkaChange}>
|
||||||
|
Uložit
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
<PizzaOrderList state={data.pizzaDay.state} orders={data.pizzaDay.orders} onDelete={handlePizzaDelete} />
|
<PizzaOrderList state={data.pizzaDay.state} orders={data.pizzaDay.orders} onDelete={handlePizzaDelete} />
|
||||||
{
|
{
|
||||||
data.pizzaDay.state === State.DELIVERED && myOrder?.hasQr &&
|
data.pizzaDay.state === State.DELIVERED && myOrder?.hasQr &&
|
||||||
|
@ -29,6 +29,7 @@ export interface Order {
|
|||||||
pizzaList: PizzaOrder[], // seznam objednaných pizz
|
pizzaList: PizzaOrder[], // seznam objednaných pizz
|
||||||
totalPrice: number, // celková cena všech objednaných pizz a krabic
|
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
|
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 {
|
export interface Choices {
|
||||||
|
@ -17,6 +17,7 @@ export default function PizzaOrderList({ state, orders, onDelete }: { state: Sta
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Jméno</th>
|
<th>Jméno</th>
|
||||||
<th>Objednávka</th>
|
<th>Objednávka</th>
|
||||||
|
<th>Poznámka</th>
|
||||||
<th>Cena</th>
|
<th>Cena</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -34,6 +35,7 @@ export default function PizzaOrderList({ state, orders, onDelete }: { state: Sta
|
|||||||
</span>)
|
</span>)
|
||||||
.reduce((prev, curr, index) => [prev, <br key={`br-${index}`} />, curr])}
|
.reduce((prev, curr, index) => [prev, <br key={`br-${index}`} />, curr])}
|
||||||
</td>
|
</td>
|
||||||
|
<td>{order.note || '-'}</td>
|
||||||
<td>{order.totalPrice} Kč</td>
|
<td>{order.totalPrice} Kč</td>
|
||||||
</tr>)}
|
</tr>)}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -3,7 +3,7 @@ import { Server } from "socket.io";
|
|||||||
import bodyParser from "body-parser";
|
import bodyParser from "body-parser";
|
||||||
import { fetchPizzy } from "./chefie";
|
import { fetchPizzy } from "./chefie";
|
||||||
import cors from 'cors';
|
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 dotenv from 'dotenv';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { fetchMenus } from "./restaurants";
|
import { fetchMenus } from "./restaurants";
|
||||||
@ -161,6 +161,18 @@ app.get("/api/qr", (req, res) => {
|
|||||||
res.end(img);
|
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) => {
|
io.on("connection", (socket) => {
|
||||||
console.log(`New client connected: ${socket.id}`);
|
console.log(`New client connected: ${socket.id}`);
|
||||||
|
|
||||||
|
@ -262,4 +262,22 @@ export function updateChoice(login: string, choice: Locations | null) {
|
|||||||
}
|
}
|
||||||
db.set(today, data);
|
db.set(today, data);
|
||||||
return 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;
|
||||||
}
|
}
|
@ -34,6 +34,7 @@ export interface Order {
|
|||||||
pizzaList: PizzaOrder[], // seznam objednaných pizz
|
pizzaList: PizzaOrder[], // seznam objednaných pizz
|
||||||
totalPrice: number, // celková cena všech objednaných pizz a krabic
|
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
|
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 */
|
/** Stav pizza dne */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user