Základní funkčnost Pizza Day
This commit is contained in:
parent
2e80faa6b8
commit
cdcd620ee5
19
README.md
19
README.md
@ -7,11 +7,20 @@ Server je v adresáři /server, client v adresáři /client obojí lze spustit p
|
||||
### `yarn start`
|
||||
|
||||
## TODO
|
||||
- Předvyplnění poslední vybrané hodnoty občas nefunguje, viz komentář
|
||||
- [x] Umožnit smazání aktuální volby "popelnicí", místo nutnosti vybrat prázdnou položku v selectu
|
||||
- Popsat Food API, nginx
|
||||
- Popsat spuštění pro vývoj
|
||||
- [x] Přívětivější možnost odhlašování
|
||||
- [x] Vyřešit responzivní design pro použití na mobilu
|
||||
- [x] Vyndat URL na Food API do .env
|
||||
- Neselhat při nedostupnosti nebo chybě z Food API
|
||||
- [x] Neselhat při nedostupnosti nebo chybě z Food API
|
||||
- [x] Dokončit docker-compose pro kompletní funkčnost
|
||||
- Implementovat pizza day
|
||||
- [x] Implementovat základ pro pizza day
|
||||
- [ ] Umožnit uzamčení objednávek zakladatelem
|
||||
- [ ] Možnost uložení čísla účtu
|
||||
- [ ] Automatické generování a zobrazení QR kódů
|
||||
- [ ] Zobrazovat celkovou cenu
|
||||
- [ ] Zobrazit upozornění před smazáním pizza day
|
||||
- [ ] Předvyplnění poslední vybrané hodnoty občas nefunguje, viz komentář
|
||||
- [ ] Nasazení nové verze v Docker smaže veškerá data (protože data.json není venku)
|
||||
- [ ] Popsat Food API, nginx
|
||||
- [ ] Popsat závislosti a postup spuštění pro vývoj
|
||||
- [ ] Popsat dostupné env
|
@ -1,12 +1,4 @@
|
||||
// type Pizza = {
|
||||
// name: string;
|
||||
// // TODO ingredience
|
||||
// sizes: [
|
||||
// size: number,
|
||||
// price: number,
|
||||
// ];
|
||||
// }
|
||||
|
||||
import { PizzaOrder } from "./Types";
|
||||
import { getBaseUrl } from "./Utils";
|
||||
|
||||
async function request<TResponse>(
|
||||
@ -53,3 +45,7 @@ export const updateChoice = async (name: string, choice: number | null) => {
|
||||
export const addPizza = async (login: string, pizzaIndex: number, pizzaSizeIndex: number) => {
|
||||
return await api.post<any, any>('/api/addPizza', JSON.stringify({ login, pizzaIndex, pizzaSizeIndex }));
|
||||
}
|
||||
|
||||
export const removePizza = async (login: string, pizzaOrder: PizzaOrder) => {
|
||||
return await api.post<any, any>('/api/removePizza', JSON.stringify({ login, pizzaOrder }));
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
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, getData, getFood, getPizzy, updateChoice } from './Api';
|
||||
import { addPizza, createPizzaDay, deletePizzaDay, getData, getFood, getPizzy, removePizza, updateChoice } from './Api';
|
||||
import { useAuth } from './context/auth';
|
||||
import Login from './Login';
|
||||
import { Locations, ClientData, Pizza } from './Types';
|
||||
import { Locations, ClientData, Pizza, PizzaOrder } from './Types';
|
||||
import { Alert, Button, Col, Form, Row, Table } from 'react-bootstrap';
|
||||
import Header from './components/Header';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
@ -99,29 +99,33 @@ function App() {
|
||||
}
|
||||
const suggestions: SelectSearchOption[] = [];
|
||||
pizzy.forEach((pizza, index) => {
|
||||
const group: SelectSearchOption = { name: pizza.name, type: "group", items: [] }
|
||||
pizza.sizes.forEach((size, sizeIndex) => {
|
||||
const name = `${pizza.name}, ${size.size} (${size.price} Kč)`;
|
||||
const name = `${size.size} (${size.price} Kč)`;
|
||||
const value = `${index}|${sizeIndex}`;
|
||||
suggestions.push({ name, value });
|
||||
group.items?.push({ name, value });
|
||||
})
|
||||
suggestions.push(group);
|
||||
})
|
||||
return suggestions;
|
||||
}, [pizzy]);
|
||||
|
||||
const handlePizzaChange = async (value) => {
|
||||
console.log("Pizza vybrána", value);
|
||||
if (auth?.login && pizzy) {
|
||||
const s = value.split('|');
|
||||
const pizzaIndex = Number.parseInt(s[0]);
|
||||
const pizzaSizeIndex = Number.parseInt(s[1]);
|
||||
const pizza = pizzy[pizzaIndex];
|
||||
const size = pizza.sizes[pizzaSizeIndex];
|
||||
// TODO smazat
|
||||
console.log("Vybraná pizza a velikost", pizza, size);
|
||||
await addPizza(auth.login, pizzaIndex, pizzaSizeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
const handlePizzaDelete = (pizzaOrder: PizzaOrder) => {
|
||||
if (auth?.login) {
|
||||
removePizza(auth?.login, pizzaOrder);
|
||||
}
|
||||
}
|
||||
|
||||
const renderFoodTable = (name, food) => {
|
||||
return <Col md={12} lg={4}>
|
||||
<h3>{name}</h3>
|
||||
@ -200,29 +204,35 @@ function App() {
|
||||
: <div className='mt-5'><i>Zatím nikdo nehlasoval...</i></div>
|
||||
}
|
||||
</div>
|
||||
<div className='mt-5'>
|
||||
{!data.pizzaDay &&
|
||||
<div>
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<p>Pro dnešní den není aktuálně založen Pizza day.</p>
|
||||
<Button onClick={async () => {
|
||||
await createPizzaDay(auth.login);
|
||||
}}>Založit Pizza day</Button>
|
||||
</div>
|
||||
}
|
||||
{data.pizzaDay && <div>
|
||||
{data.pizzaDay &&
|
||||
<div>
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<p>Pizza Day je založen uživatelem {data.pizzaDay.creator}</p>
|
||||
{
|
||||
data.pizzaDay.creator === auth.login && <Button className='danger mb-3' onClick={async () => {
|
||||
await deletePizzaDay(auth.login);
|
||||
}}>Smazat Pizza day</Button>
|
||||
}
|
||||
</div>
|
||||
<SelectSearch
|
||||
search={true}
|
||||
options={pizzaSuggestions}
|
||||
placeholder='Vyhledat pizzu...'
|
||||
onChange={handlePizzaChange}
|
||||
/>
|
||||
<PizzaOrderList orders={data.pizzaDay.orders} />
|
||||
</div>}
|
||||
<PizzaOrderList orders={data.pizzaDay.orders} onDelete={handlePizzaDelete} />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</>}
|
||||
</div>
|
||||
|
@ -14,10 +14,17 @@ export interface Pizza {
|
||||
sizes: PizzaSize[], // dostupné velikosti pizzy
|
||||
}
|
||||
|
||||
/** Jedna objednávka v rámci Pizza day */
|
||||
/** Objednávka jedné konkrétní pizzy */
|
||||
export interface PizzaOrder {
|
||||
name: string, // název pizzy
|
||||
size: string, // velikost pizzy jako string (30cm)
|
||||
price: number, // cena pizzy v Kč, včetně krabice
|
||||
}
|
||||
|
||||
/** Celková objednávka jednoho člověka */
|
||||
export interface Order {
|
||||
customer: string, // název člověka
|
||||
pizzaList: Pizza[], // seznam objednaných pizz
|
||||
customer: string, // jméno objednatele
|
||||
pizzaList: PizzaOrder[], // seznam objednaných pizz
|
||||
totalPrice: number, // celková cena všech objednaných pizz a krabic
|
||||
}
|
||||
|
||||
|
@ -1,21 +1,36 @@
|
||||
import React from "react";
|
||||
import { Table } from "react-bootstrap";
|
||||
import { Order } from "../Types";
|
||||
import { Order, PizzaOrder } from "../Types";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faTrashCan } from "@fortawesome/free-regular-svg-icons";
|
||||
import { useAuth } from "../context/auth";
|
||||
|
||||
export default function PizzaOrderList({ orders, onDelete }: { orders: Order[], onDelete: (pizzaOrder: PizzaOrder) => void }) {
|
||||
const auth = useAuth();
|
||||
|
||||
export default function PizzaOrderList({ orders }: { orders: Order[] }) {
|
||||
return <Table className="mt-3" striped bordered hover>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Pizza</th>
|
||||
<th>Jméno</th>
|
||||
<th>Cena (Kč)</th>
|
||||
<th>Objednávka</th>
|
||||
<th>Celkem</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{orders.map(order => <tr>
|
||||
<td>{order.pizzaList[0].name}</td>
|
||||
{orders.map(order => <tr key={order.customer}>
|
||||
<td>{order.customer}</td>
|
||||
<td>{order.totalPrice}</td>
|
||||
<td>{order.pizzaList.map<React.ReactNode>((pizzaOrder, index) =>
|
||||
<span key={index}>
|
||||
{`${pizzaOrder.name}, ${pizzaOrder.size} (${pizzaOrder.price} Kč)`}
|
||||
{auth?.login === order.customer &&
|
||||
<FontAwesomeIcon onClick={() => {
|
||||
onDelete(pizzaOrder);
|
||||
}} title='Odstranit' className='trash-icon' icon={faTrashCan} />
|
||||
}
|
||||
</span>)
|
||||
.reduce((prev, curr) => [prev, <br />, curr])}
|
||||
</td>
|
||||
<td>{order.totalPrice} Kč</td>
|
||||
</tr>)}
|
||||
</tbody>
|
||||
</Table>
|
||||
|
124
client/yarn.lock
124
client/yarn.lock
@ -2342,14 +2342,14 @@
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^5.5.0":
|
||||
version "5.59.8"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.8.tgz#1e7a3e5318ece22251dfbc5c9c6feeb4793cc509"
|
||||
integrity sha512-JDMOmhXteJ4WVKOiHXGCoB96ADWg9q7efPWHRViT/f09bA8XOMLAVHHju3l0MkZnG1izaWXYmgvQcUjTRcpShQ==
|
||||
version "5.59.9"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.9.tgz#2604cfaf2b306e120044f901e20c8ed926debf15"
|
||||
integrity sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA==
|
||||
dependencies:
|
||||
"@eslint-community/regexpp" "^4.4.0"
|
||||
"@typescript-eslint/scope-manager" "5.59.8"
|
||||
"@typescript-eslint/type-utils" "5.59.8"
|
||||
"@typescript-eslint/utils" "5.59.8"
|
||||
"@typescript-eslint/scope-manager" "5.59.9"
|
||||
"@typescript-eslint/type-utils" "5.59.9"
|
||||
"@typescript-eslint/utils" "5.59.9"
|
||||
debug "^4.3.4"
|
||||
grapheme-splitter "^1.0.4"
|
||||
ignore "^5.2.0"
|
||||
@ -2358,78 +2358,78 @@
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/experimental-utils@^5.0.0":
|
||||
version "5.59.8"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.59.8.tgz#21d20f3b657f8dbd237887d9bbb40bf1b5b38cd0"
|
||||
integrity sha512-jAf+hihtd0G2RLB9x796+3i8D0L5T5xjftuPpJ82RLsPNHdzGXmbZNNftQ558h90ogc45DD8/W3OrxmdSO5Nng==
|
||||
version "5.59.9"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.59.9.tgz#e77482a8b70f1a6aa3a1c6a128be4a5e0e6db940"
|
||||
integrity sha512-eZTK/Ci0QAqNc/q2MqMwI2+QI5ZI9HM12FcfGwbEvKif5ev/CIIYLmrlckvgPrC8XSbl39HtErR5NJiQkRkvWg==
|
||||
dependencies:
|
||||
"@typescript-eslint/utils" "5.59.8"
|
||||
"@typescript-eslint/utils" "5.59.9"
|
||||
|
||||
"@typescript-eslint/parser@^5.5.0":
|
||||
version "5.59.8"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.8.tgz#60cbb00671d86cf746044ab797900b1448188567"
|
||||
integrity sha512-AnR19RjJcpjoeGojmwZtCwBX/RidqDZtzcbG3xHrmz0aHHoOcbWnpDllenRDmDvsV0RQ6+tbb09/kyc+UT9Orw==
|
||||
version "5.59.9"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.9.tgz#a85c47ccdd7e285697463da15200f9a8561dd5fa"
|
||||
integrity sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "5.59.8"
|
||||
"@typescript-eslint/types" "5.59.8"
|
||||
"@typescript-eslint/typescript-estree" "5.59.8"
|
||||
"@typescript-eslint/scope-manager" "5.59.9"
|
||||
"@typescript-eslint/types" "5.59.9"
|
||||
"@typescript-eslint/typescript-estree" "5.59.9"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/scope-manager@5.59.8":
|
||||
version "5.59.8"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.8.tgz#ff4ad4fec6433647b817c4a7d4b4165d18ea2fa8"
|
||||
integrity sha512-/w08ndCYI8gxGf+9zKf1vtx/16y8MHrZs5/tnjHhMLNSixuNcJavSX4wAiPf4aS5x41Es9YPCn44MIe4cxIlig==
|
||||
"@typescript-eslint/scope-manager@5.59.9":
|
||||
version "5.59.9"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.9.tgz#eadce1f2733389cdb58c49770192c0f95470d2f4"
|
||||
integrity sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.59.8"
|
||||
"@typescript-eslint/visitor-keys" "5.59.8"
|
||||
"@typescript-eslint/types" "5.59.9"
|
||||
"@typescript-eslint/visitor-keys" "5.59.9"
|
||||
|
||||
"@typescript-eslint/type-utils@5.59.8":
|
||||
version "5.59.8"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.59.8.tgz#aa6c029a9d7706d26bbd25eb4666398781df6ea2"
|
||||
integrity sha512-+5M518uEIHFBy3FnyqZUF3BMP+AXnYn4oyH8RF012+e7/msMY98FhGL5SrN29NQ9xDgvqCgYnsOiKp1VjZ/fpA==
|
||||
"@typescript-eslint/type-utils@5.59.9":
|
||||
version "5.59.9"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.59.9.tgz#53bfaae2e901e6ac637ab0536d1754dfef4dafc2"
|
||||
integrity sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q==
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree" "5.59.8"
|
||||
"@typescript-eslint/utils" "5.59.8"
|
||||
"@typescript-eslint/typescript-estree" "5.59.9"
|
||||
"@typescript-eslint/utils" "5.59.9"
|
||||
debug "^4.3.4"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/types@5.59.8":
|
||||
version "5.59.8"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.8.tgz#212e54414733618f5d0fd50b2da2717f630aebf8"
|
||||
integrity sha512-+uWuOhBTj/L6awoWIg0BlWy0u9TyFpCHrAuQ5bNfxDaZ1Ppb3mx6tUigc74LHcbHpOHuOTOJrBoAnhdHdaea1w==
|
||||
"@typescript-eslint/types@5.59.9":
|
||||
version "5.59.9"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.9.tgz#3b4e7ae63718ce1b966e0ae620adc4099a6dcc52"
|
||||
integrity sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==
|
||||
|
||||
"@typescript-eslint/typescript-estree@5.59.8":
|
||||
version "5.59.8"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.8.tgz#801a7b1766481629481b3b0878148bd7a1f345d7"
|
||||
integrity sha512-Jy/lPSDJGNow14vYu6IrW790p7HIf/SOV1Bb6lZ7NUkLc2iB2Z9elESmsaUtLw8kVqogSbtLH9tut5GCX1RLDg==
|
||||
"@typescript-eslint/typescript-estree@5.59.9":
|
||||
version "5.59.9"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz#6bfea844e468427b5e72034d33c9fffc9557392b"
|
||||
integrity sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.59.8"
|
||||
"@typescript-eslint/visitor-keys" "5.59.8"
|
||||
"@typescript-eslint/types" "5.59.9"
|
||||
"@typescript-eslint/visitor-keys" "5.59.9"
|
||||
debug "^4.3.4"
|
||||
globby "^11.1.0"
|
||||
is-glob "^4.0.3"
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/utils@5.59.8", "@typescript-eslint/utils@^5.58.0":
|
||||
version "5.59.8"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.59.8.tgz#34d129f35a2134c67fdaf024941e8f96050dca2b"
|
||||
integrity sha512-Tr65630KysnNn9f9G7ROF3w1b5/7f6QVCJ+WK9nhIocWmx9F+TmCAcglF26Vm7z8KCTwoKcNEBZrhlklla3CKg==
|
||||
"@typescript-eslint/utils@5.59.9", "@typescript-eslint/utils@^5.58.0":
|
||||
version "5.59.9"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.59.9.tgz#adee890107b5ffe02cd46fdaa6c2125fb3c6c7c4"
|
||||
integrity sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.2.0"
|
||||
"@types/json-schema" "^7.0.9"
|
||||
"@types/semver" "^7.3.12"
|
||||
"@typescript-eslint/scope-manager" "5.59.8"
|
||||
"@typescript-eslint/types" "5.59.8"
|
||||
"@typescript-eslint/typescript-estree" "5.59.8"
|
||||
"@typescript-eslint/scope-manager" "5.59.9"
|
||||
"@typescript-eslint/types" "5.59.9"
|
||||
"@typescript-eslint/typescript-estree" "5.59.9"
|
||||
eslint-scope "^5.1.1"
|
||||
semver "^7.3.7"
|
||||
|
||||
"@typescript-eslint/visitor-keys@5.59.8":
|
||||
version "5.59.8"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.8.tgz#aa6a7ef862add919401470c09e1609392ef3cc40"
|
||||
integrity sha512-pJhi2ms0x0xgloT7xYabil3SGGlojNNKjK/q6dB3Ey0uJLMjK2UDGJvHieiyJVW/7C3KI+Z4Q3pEHkm4ejA+xQ==
|
||||
"@typescript-eslint/visitor-keys@5.59.9":
|
||||
version "5.59.9"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.9.tgz#9f86ef8e95aca30fb5a705bb7430f95fc58b146d"
|
||||
integrity sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.59.8"
|
||||
"@typescript-eslint/types" "5.59.9"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5":
|
||||
@ -4015,9 +4015,9 @@ ejs@^3.1.6:
|
||||
jake "^10.8.5"
|
||||
|
||||
electron-to-chromium@^1.4.411:
|
||||
version "1.4.419"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.419.tgz#6fbea1f3abb65bf46e8ad874b5c1f0816ce2f8ce"
|
||||
integrity sha512-jdie3RiEgygvDTyS2sgjq71B36q2cDSBfPlwzUyuOrfYTNoYWyBxxjGJV/HAu3A2hB0Y+HesvCVkVAFoCKwCSw==
|
||||
version "1.4.420"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.420.tgz#21d4b55e9deef16cdbf009557fb2fe8f96798248"
|
||||
integrity sha512-BpPy2KXZc+UPbI8NGo2QdHU1Mkq11pO/zaNDHY57L09K/0ytrPw+IiLOUvZ1NjI5BlAVF5DkNr1UBUS76Tc4ow==
|
||||
|
||||
emittery@^0.10.2:
|
||||
version "0.10.2"
|
||||
@ -5063,9 +5063,9 @@ html-encoding-sniffer@^2.0.1:
|
||||
whatwg-encoding "^1.0.5"
|
||||
|
||||
html-entities@^2.1.0, html-entities@^2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46"
|
||||
integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==
|
||||
version "2.3.4"
|
||||
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.4.tgz#c65db1302652a0a2986f216ef911df65015dc1ac"
|
||||
integrity sha512-TtiHkpRBqP40OzizVWjwBPBsiqchEZxAg/nys6D6lIpdoVLo7sWZ/5Sf/s4UaBHQ6pzUzEr3NiItvEoO46sPtQ==
|
||||
|
||||
html-escaper@^2.0.0:
|
||||
version "2.0.2"
|
||||
@ -8875,9 +8875,9 @@ toidentifier@1.0.1:
|
||||
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
|
||||
|
||||
tough-cookie@^4.0.0:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874"
|
||||
integrity sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==
|
||||
version "4.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf"
|
||||
integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==
|
||||
dependencies:
|
||||
psl "^1.1.33"
|
||||
punycode "^2.1.1"
|
||||
@ -9285,9 +9285,9 @@ webpack-sources@^3.2.3:
|
||||
integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
|
||||
|
||||
webpack@^5.64.4:
|
||||
version "5.85.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.85.0.tgz#c14a6a3a91f84d67c450225661fda8da36bc7f49"
|
||||
integrity sha512-7gazTiYqwo5OSqwH1tigLDL2r3qDeP2dOKYgd+LlXpsUMqDTklg6tOghexqky0/+6QY38kb/R/uRPUleuL43zg==
|
||||
version "5.85.1"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.85.1.tgz#d77406352f8f14ec847c54e4dcfb80b28c776b3f"
|
||||
integrity sha512-xTb7MRf4LY8Z5rzn7aIx4TDrwYJrjcHnIfU1TqtyZOoObyuGSpAUwIvVuqq5wPnv7WEgQr8UvO1q/dgoGG4HjA==
|
||||
dependencies:
|
||||
"@types/eslint-scope" "^3.7.3"
|
||||
"@types/estree" "^1.0.0"
|
||||
|
@ -3,7 +3,7 @@ import { Server } from "socket.io";
|
||||
import bodyParser from "body-parser";
|
||||
import { fetchPizzy } from "./chefie";
|
||||
import cors from 'cors';
|
||||
import { createPizzaDay, deletePizzaDay, getData, updateChoice } from "./service";
|
||||
import { addPizzaOrder, createPizzaDay, deletePizzaDay, getData, removePizzaOrder, updateChoice } from "./service";
|
||||
import dotenv from 'dotenv';
|
||||
import path from 'path';
|
||||
import { fetchMenus } from "./restaurants";
|
||||
@ -49,7 +49,6 @@ app.get("/api/pizza", (req, res) => {
|
||||
|
||||
/** Založí pizza day pro aktuální den, za předpokladu že dosud neexistuje. */
|
||||
app.post("/api/createPizzaDay", (req, res) => {
|
||||
console.log("Založení pizza day", req) // TODO smazat
|
||||
if (!req.body?.creator) {
|
||||
throw Error("Nebyl předán název zakládajícího");
|
||||
}
|
||||
@ -86,17 +85,25 @@ app.post("/api/addPizza", (req, res) => {
|
||||
if (!pizzy[pizzaIndex].sizes[pizzaSizeIndex]) {
|
||||
throw Error("Neplatný index velikosti pizzy: " + pizzaSizeIndex);
|
||||
}
|
||||
console.log("Vybraná pizza", pizzy[pizzaIndex], pizzy[pizzaIndex].sizes[pizzaSizeIndex]);
|
||||
// TODO implementovat přidání objednávky - nutno zjistit co vlastně chceme ukládat
|
||||
// pravděpodobně název, velikost, cenu
|
||||
const data = addPizzaOrder(req.body.login, pizzy[pizzaIndex], pizzy[pizzaIndex].sizes[pizzaSizeIndex]);
|
||||
io.emit("message", data);
|
||||
res.status(200).json({});
|
||||
// TODO odeslat aktuální data socketem
|
||||
// io.emit("message", data);
|
||||
})
|
||||
});
|
||||
|
||||
app.post("/api/removePizza", (req, res) => {
|
||||
if (!req.body?.login) {
|
||||
throw Error("Nebyl předán login");
|
||||
}
|
||||
if (!req.body?.pizzaOrder) {
|
||||
throw Error("Nebyla předána objednávka");
|
||||
}
|
||||
const data = removePizzaOrder(req.body.login, req.body?.pizzaOrder);
|
||||
io.emit("message", data);
|
||||
res.status(200).json({});
|
||||
});
|
||||
|
||||
app.post("/api/updateChoice", (req, res) => {
|
||||
console.log("Změna výběru", req.body);
|
||||
if (!req.body.hasOwnProperty('name')) {
|
||||
res.status(400).json({});
|
||||
}
|
||||
@ -105,23 +112,6 @@ app.post("/api/updateChoice", (req, res) => {
|
||||
res.status(200).json(data);
|
||||
});
|
||||
|
||||
// TODO smazat
|
||||
app.post("/api/zprava", (req, res) => {
|
||||
const { username, message } = req.body;
|
||||
|
||||
if (
|
||||
typeof username !== "string" ||
|
||||
typeof message !== "string" ||
|
||||
username.length > 500 ||
|
||||
message.length > 500
|
||||
) {
|
||||
return res.status(400).json({ error: "Invalid input" });
|
||||
}
|
||||
console.log(`posílám ${username} ${message} `);
|
||||
io.emit("externalMessage", `${username} -> ${message}`);
|
||||
res.status(200).json({ success: "Message sent" });
|
||||
});
|
||||
|
||||
io.on("connection", (socket) => {
|
||||
console.log(`New client connected: ${socket.id}`);
|
||||
|
||||
@ -129,12 +119,6 @@ io.on("connection", (socket) => {
|
||||
io.emit("message", message);
|
||||
});
|
||||
|
||||
// TODO smazat
|
||||
socket.on("jduKafe", ({ username, timeString }) => {
|
||||
console.log(`Received message: ${username}`);
|
||||
socket.broadcast.emit("jduKafe", `${timeString}: ${username} -> jdu Kafe`);
|
||||
});
|
||||
|
||||
socket.on("disconnect", () => {
|
||||
console.log(`Client disconnected: ${socket.id}`);
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ClientData, Locations, State } from "./types";
|
||||
import { ClientData, Locations, Order, Pizza, PizzaDayState, PizzaOrder, PizzaSize } from "./types";
|
||||
import { db } from "./database";
|
||||
import { getHumanDate, getIsWeekend } from "./utils";
|
||||
import { formatDate } from "./utils";
|
||||
@ -34,7 +34,7 @@ export function createPizzaDay(creator: string): ClientData {
|
||||
if (clientData.pizzaDay) {
|
||||
throw Error("Pizza day pro dnešní den již existuje");
|
||||
}
|
||||
const data: ClientData = { pizzaDay: { state: State.CREATED, creator, orders: [] }, ...clientData };
|
||||
const data: ClientData = { pizzaDay: { state: PizzaDayState.CREATED, creator, orders: [] }, ...clientData };
|
||||
db.set(today, data);
|
||||
return data;
|
||||
}
|
||||
@ -54,6 +54,70 @@ export function deletePizzaDay(login: string) {
|
||||
db.delete(today);
|
||||
}
|
||||
|
||||
/**
|
||||
* Přidá objednávku pizzy uživateli.
|
||||
*
|
||||
* @param login login uživatele
|
||||
* @param pizza zvolená pizza
|
||||
* @param size zvolená velikost pizzy
|
||||
*/
|
||||
export function addPizzaOrder(login: string, pizza: Pizza, size: PizzaSize) {
|
||||
const today = formatDate(getToday());
|
||||
const clientData: ClientData = db.get(today);
|
||||
if (!clientData.pizzaDay) {
|
||||
throw Error("Pizza day pro dnešní den neexistuje");
|
||||
}
|
||||
let order: Order | undefined = clientData.pizzaDay.orders.find(o => o.customer === login);
|
||||
if (!order) {
|
||||
order = {
|
||||
customer: login,
|
||||
pizzaList: [],
|
||||
totalPrice: 0,
|
||||
}
|
||||
clientData.pizzaDay.orders.push(order);
|
||||
}
|
||||
const pizzaOrder: PizzaOrder = {
|
||||
name: pizza.name,
|
||||
size: size.size,
|
||||
price: size.price,
|
||||
}
|
||||
order.pizzaList.push(pizzaOrder);
|
||||
order.totalPrice += pizzaOrder.price;
|
||||
db.set(today, clientData);
|
||||
return clientData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Odstraní danou objednávku pizzy.
|
||||
*
|
||||
* @param login login uživatele
|
||||
* @param pizzaOrder objednávka pizzy
|
||||
*/
|
||||
export function removePizzaOrder(login: string, pizzaOrder: PizzaOrder) {
|
||||
const today = formatDate(getToday());
|
||||
const clientData: ClientData = db.get(today);
|
||||
if (!clientData.pizzaDay) {
|
||||
throw Error("Pizza day pro dnešní den neexistuje");
|
||||
}
|
||||
const orderIndex = clientData.pizzaDay.orders.findIndex(o => o.customer === login);
|
||||
if (orderIndex < 0) {
|
||||
throw Error("Nebyly nalezeny žádné objednávky pro uživatele " + login);
|
||||
}
|
||||
const order = clientData.pizzaDay.orders[orderIndex];
|
||||
const index = order.pizzaList.findIndex(o => o.name === pizzaOrder.name && o.size === pizzaOrder.size);
|
||||
if (index < 0) {
|
||||
throw Error("Objednávka s danými parametry nebyla nalezena");
|
||||
}
|
||||
const price = order.pizzaList[index].price;
|
||||
order.pizzaList.splice(index, 1);
|
||||
order.totalPrice -= price;
|
||||
if (order.pizzaList.length == 0) {
|
||||
clientData.pizzaDay.orders.splice(orderIndex, 1);
|
||||
}
|
||||
db.set(today, clientData);
|
||||
return clientData;
|
||||
}
|
||||
|
||||
export function initIfNeeded() {
|
||||
const today = formatDate(getToday());
|
||||
if (!db.has(today)) {
|
||||
|
@ -2,34 +2,50 @@ export interface Choices {
|
||||
[location: string]: string[],
|
||||
}
|
||||
|
||||
// /** Jedna konkrétní pizza */
|
||||
interface Pizza {
|
||||
/** Velikost konkrétní pizzy */
|
||||
export interface PizzaSize {
|
||||
size: string, // velikost pizzy, např. "30cm"
|
||||
pizzaPrice: number, // cena samotné pizzy
|
||||
boxPrice: number, // cena krabice
|
||||
price: number, // celková cena (pizza + krabice)
|
||||
}
|
||||
|
||||
/** Jedna konkrétní pizza */
|
||||
export interface Pizza {
|
||||
name: string, // název pizzy
|
||||
size: number, // velikost pizzy v cm
|
||||
ingredients: string[], // seznam ingrediencí
|
||||
sizes: PizzaSize[], // dostupné velikosti pizzy
|
||||
}
|
||||
|
||||
/** Objednávka jedné konkrétní pizzy */
|
||||
export interface PizzaOrder {
|
||||
name: string, // název pizzy
|
||||
size: string, // velikost pizzy jako string (30cm)
|
||||
price: number, // cena pizzy v Kč, včetně krabice
|
||||
}
|
||||
|
||||
// /** Objednávka jednoho člověka */
|
||||
interface Order {
|
||||
customer: string, // název člověka
|
||||
pizzaList: Pizza[], // seznam objednaných pizz
|
||||
/** Celková objednávka jednoho člověka */
|
||||
export interface Order {
|
||||
customer: string, // jméno objednatele
|
||||
pizzaList: PizzaOrder[], // seznam objednaných pizz
|
||||
totalPrice: number, // celková cena všech objednaných pizz a krabic
|
||||
}
|
||||
|
||||
// /** Stav pizza dne. */
|
||||
export enum State {
|
||||
/** Stav pizza dne */
|
||||
export enum PizzaDayState {
|
||||
NOT_CREATED, // Pizza day nebyl založen
|
||||
CREATED, // Pizza day je založen
|
||||
LOCKED // Objednávky uzamčeny
|
||||
}
|
||||
|
||||
// /** Veškerá data pro zobrazení na klientovi */
|
||||
/** Informace o pizza day pro dnešní den */
|
||||
interface PizzaDay {
|
||||
state: State, // stav pizza dne
|
||||
state: PizzaDayState, // stav pizza dne
|
||||
creator: string, // jméno zakladatele
|
||||
orders: Order[], // seznam objednávek, pokud není vyplněno, není založen pizza day
|
||||
orders: Order[], // seznam objednávek jednotlivých lidí
|
||||
}
|
||||
|
||||
/** Veškerá data pro zobrazení na klientovi */
|
||||
export interface ClientData {
|
||||
date: string, // dnešní datum pro zobrazení
|
||||
isWeekend: boolean, // příznak, zda je dnes víkend
|
||||
|
Loading…
x
Reference in New Issue
Block a user