diff --git a/client/src/App.scss b/client/src/App.scss index 0e92c0b..2e0cd20 100644 --- a/client/src/App.scss +++ b/client/src/App.scss @@ -100,11 +100,19 @@ body, margin-bottom: 0; } -.table> :not(caption) .action-icon { - color: rgb(0, 89, 255); - cursor: pointer; - margin-left: 10px; - padding: 0; +.table> :not(caption) { + .action-icon { + color: rgb(0, 89, 255); + cursor: pointer; + margin-left: 10px; + padding: 0; + } + + .buyer-icon { + color: #dbba00; + margin-left: 10px; + padding: 0; + } } .table ul { diff --git a/client/src/App.tsx b/client/src/App.tsx index 80aa80d..d69a1fb 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -141,16 +141,6 @@ function App() { if (!auth?.login) { return } - // TODO tohle občas náhodně nezafunguje, nutno přepsat, viz https://medium.com/@teh_builder/ref-objects-inside-useeffect-hooks-eb7c15198780 - // TODO nutno opravit - // if (data?.choices && choiceRef.current) { - // for (let entry of Object.entries(data.choices)) { - // if (entry[1].includes(auth.login)) { - // const value = entry[0] as any as number; // TODO tohle je absurdní - // choiceRef.current.value = Object.values(Locations)[value]; - // } - // } - // } }, [auth, auth?.login, data?.choices]) // Reference na mojí objednávku @@ -310,7 +300,7 @@ function App() { const handlePizzaChange = async (value: SelectedOptionValue | SelectedOptionValue[]) => { if (auth?.login && data?.pizzaList) { if (typeof value !== 'string') { - throw Error('Nepodporovaný typ hodnoty'); + throw new TypeError('Nepodporovaný typ hodnoty: ' + typeof value); } const s = value.split('|'); const pizzaIndex = Number.parseInt(s[0]); @@ -331,30 +321,6 @@ function App() { updatePizzaDayNote({ body: { note: pizzaPoznamkaRef.current?.value } }); } - // const addToCart = async () => { - // TODO aktuálně nefunkční - nedokážeme poslat PHPSESSIONID cookie - // if (data?.pizzaDay?.orders) { - // for (const order of data?.pizzaDay?.orders) { - // for (const pizzaOrder of order.pizzaList) { - // const url = 'https://www.pizzachefie.cz/pridat.html'; - // const payload = new URLSearchParams(); - // payload.append('varId', pizzaOrder.varId.toString()); - // await fetch(url, { - // method: "POST", - // mode: "no-cors", - // cache: "no-cache", - // credentials: "same-origin", - // headers: { - // 'Content-Type': 'application/x-www-form-urlencoded', - // }, - // body: payload, - // }) - // } - // } - // // TODO otevřít košík v nové záložce - // } - // } - const handleChangeDepartureTime = async (event: React.ChangeEvent) => { if (foodChoiceList?.length && choiceRef.current?.value) { await changeDepartureTime({ body: { time: event.target.value as DepartureTime, dayIndex } }); @@ -477,11 +443,10 @@ function App() { } - {/* TODO zjednodušit, stačí iterovat klíče typu Restaurant */} - {food['SLADOVNICKA'] && renderFoodTable('SLADOVNICKA', food['SLADOVNICKA'])} - {food['TECHTOWER'] && renderFoodTable('TECHTOWER', food['TECHTOWER'])} - {food['ZASTAVKAUMICHALA'] && renderFoodTable('ZASTAVKAUMICHALA', food['ZASTAVKAUMICHALA'])} - {food['SENKSERIKOVA'] && renderFoodTable('SENKSERIKOVA', food['SENKSERIKOVA'])} + {Object.keys(Restaurant).map(key => { + const locationKey = key as Restaurant; + return food[locationKey] && renderFoodTable(locationKey, food[locationKey]); + })}
@@ -543,22 +508,22 @@ function App() { const isBuyer = userPayload?.isBuyer || false; return + {/* TODO zrefaktorovat, oddělit řádek do samostatné komponenty (a akce možná zvlášť) */} {trusted && } {login} {userPayload.departureTime && ({userPayload.departureTime})} {userPayload.note && ({userPayload.note})} - {/* TODO narovnat styly pomocí class */} {login === auth.login && canChangeChoice && locationKey === LunchChoice.OBJEDNAVAM && { markAsBuyer(); - }} icon={faBasketShopping} color={isBuyer ? '#dbba00' : 'rgb(0, 89, 255)'} style={{marginLeft: '10px', padding: 0, cursor: 'pointer'}} /> + }} icon={faBasketShopping} className={isBuyer ? 'buyer-icon' : 'action-icon'} style={{cursor: 'pointer'}} /> } {login !== auth.login && locationKey === LunchChoice.OBJEDNAVAM && isBuyer && { copyNote(userPayload.note!); - }} icon={faBasketShopping} color='#dbba00' style={{marginLeft: '10px', padding: 0}} /> + }} icon={faBasketShopping} className='buyer-icon' /> } {login !== auth.login && canChangeChoice && userPayload?.note?.length && { @@ -686,7 +651,10 @@ function App() { { data.pizzaDay.state === PizzaDayState.DELIVERED &&
-

{`Pizzy byly doručeny.${myOrder?.hasQr ? ` Objednávku můžete uživateli ${data.pizzaDay.creator} uhradit pomocí QR kódu níže.` : ''}`}

+

+ Pizzy byly doručeny. + {myOrder?.hasQr ? ` Objednávku můžete uživateli ${data.pizzaDay.creator} uhradit pomocí QR kódu níže.` : ''} +

}
diff --git a/client/src/Login.tsx b/client/src/Login.tsx index 39d23e1..650d764 100644 --- a/client/src/Login.tsx +++ b/client/src/Login.tsx @@ -26,7 +26,7 @@ export default function Login() { }, [auth]); const doLogin = useCallback(async () => { - const length = loginRef?.current?.value.length && loginRef.current.value.replace(/\s/g, '').length + const length = loginRef?.current?.value.length && loginRef.current.value.replaceAll(/\s/g, '').length if (length) { const response = await login({ body: { login: loginRef.current?.value } }); if (response.data) { diff --git a/client/src/Utils.tsx b/client/src/Utils.tsx index 4d081dc..1c89fb3 100644 --- a/client/src/Utils.tsx +++ b/client/src/Utils.tsx @@ -75,14 +75,14 @@ export const getDayOfWeekIndex = (date: Date) => { /** Vrátí první pracovní den v týdnu předaného data. */ export function getFirstWorkDayOfWeek(date: Date) { - const firstDay = new Date(date.getTime()); + const firstDay = new Date(date); firstDay.setDate(date.getDate() - getDayOfWeekIndex(date)); return firstDay; } /** Vrátí poslední pracovní den v týdnu předaného data. */ export function getLastWorkDayOfWeek(date: Date) { - const lastDay = new Date(date.getTime()); + const lastDay = new Date(date); lastDay.setDate(date.getDate() + (4 - getDayOfWeekIndex(date))); return lastDay; } diff --git a/client/src/components/Header.tsx b/client/src/components/Header.tsx index adbb2d7..c88f602 100644 --- a/client/src/components/Header.tsx +++ b/client/src/components/Header.tsx @@ -58,15 +58,15 @@ export default function Header() { if (bankAccountNumber) { try { // Validace kódu banky - if (bankAccountNumber.indexOf('/') < 0) { - throw Error("Číslo účtu neobsahuje lomítko/kód banky") + if (!bankAccountNumber.includes('/')) { + throw new Error("Číslo účtu neobsahuje lomítko/kód banky") } const split = bankAccountNumber.split("/"); if (split[1].length !== 4) { - throw Error("Kód banky musí být 4 číslice") + throw new Error("Kód banky musí být 4 číslice") } if (!isValidInteger(split[1])) { - throw Error("Kód banky není číslo") + throw new Error("Kód banky není číslo") } // Validace čísla a předčíslí @@ -76,7 +76,7 @@ export default function Header() { cislo = cislo.replace('-', ''); } if (!isValidInteger(cislo)) { - throw Error("Předčíslí nebo číslo účtu neobsahuje pouze číslice") + throw new Error("Předčíslí nebo číslo účtu neobsahuje pouze číslice") } if (cislo.length < 16) { cislo = cislo.padStart(16, '0'); @@ -89,7 +89,7 @@ export default function Header() { sum += Number.parseInt(char) * weight } if (sum % 11 !== 0) { - throw Error("Číslo účtu je neplatné") + throw new Error("Číslo účtu je neplatné") } } catch (e: any) { alert(e.message) diff --git a/client/src/components/modals/PizzaAdditionalFeeModal.tsx b/client/src/components/modals/PizzaAdditionalFeeModal.tsx index 2483cd2..5deac0d 100644 --- a/client/src/components/modals/PizzaAdditionalFeeModal.tsx +++ b/client/src/components/modals/PizzaAdditionalFeeModal.tsx @@ -15,12 +15,12 @@ export default function PizzaAdditionalFeeModal({ customerName, isOpen, onClose, const priceRef = useRef(null); const doSubmit = () => { - onSave(customerName, textRef.current?.value, parseInt(priceRef.current?.value ?? "0")); + onSave(customerName, textRef.current?.value, Number.parseInt(priceRef.current?.value ?? "0")); } const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { - onSave(customerName, textRef.current?.value, parseInt(priceRef.current?.value ?? "0")); + onSave(customerName, textRef.current?.value, Number.parseInt(priceRef.current?.value ?? "0")); } } diff --git a/client/src/components/modals/PizzaCalculatorModal.tsx b/client/src/components/modals/PizzaCalculatorModal.tsx index e199a7a..02e5bae 100644 --- a/client/src/components/modals/PizzaCalculatorModal.tsx +++ b/client/src/components/modals/PizzaCalculatorModal.tsx @@ -36,13 +36,13 @@ export default function PizzaCalculatorModal({ isOpen, onClose }: Readonly 0) { r.pizza1.diameter = diameter1; r.pizza1.area = Math.PI * Math.pow(diameter1 / 2, 2); if (price1Ref.current?.value) { - const price1 = parseInt(price1Ref.current?.value); + const price1 = Number.parseInt(price1Ref.current?.value); if (price1) { r.pizza1.pricePerM = price1 / r.pizza1.area; } else { @@ -56,13 +56,13 @@ export default function PizzaCalculatorModal({ isOpen, onClose }: Readonly 0) { r.pizza2.diameter = diameter2; r.pizza2.area = Math.PI * Math.pow(diameter2 / 2, 2); if (price2Ref.current?.value) { - const price2 = parseInt(price2Ref.current?.value); + const price2 = Number.parseInt(price2Ref.current?.value); if (price2) { r.pizza2.pricePerM = price2 / r.pizza2.area; } else { @@ -77,8 +77,8 @@ export default function PizzaCalculatorModal({ isOpen, onClose }: Readonly r.pizza2.pricePerM ? r.pizza1.pricePerM : r.pizza2.pricePerM; - const smaller = r.pizza1.pricePerM < r.pizza2.pricePerM ? r.pizza1.pricePerM : r.pizza2.pricePerM; + const bigger = Math.max(r.pizza1.pricePerM, r.pizza2.pricePerM); + const smaller = Math.min(r.pizza1.pricePerM, r.pizza2.pricePerM); r.ratio = (bigger / smaller) - 1; r.diameterDiff = Math.abs(r.pizza1.diameter - r.pizza2.diameter); } else { diff --git a/client/src/context/auth.tsx b/client/src/context/auth.tsx index a2cb3d3..00a6818 100644 --- a/client/src/context/auth.tsx +++ b/client/src/context/auth.tsx @@ -55,7 +55,7 @@ function useProvideAuth(): AuthContextProps { setLoginName(undefined); setTrusted(undefined); if (trusted && logoutUrl?.length) { - window.location.replace(logoutUrl); + globalThis.location.replace(logoutUrl); } } diff --git a/client/src/context/socket.js b/client/src/context/socket.js index ed2e2ea..1ed652e 100644 --- a/client/src/context/socket.js +++ b/client/src/context/socket.js @@ -7,8 +7,8 @@ if (process.env.NODE_ENV === 'development') { socketUrl = `http://localhost:3001`; socketPath = undefined; } else { - socketUrl = `${window.location.host}`; - socketPath = `${window.location.pathname}socket.io`; + socketUrl = `${globalThis.location.host}`; + socketPath = `${globalThis.location.pathname}socket.io`; } export const socket = socketio.connect(socketUrl, { path: socketPath, transports: ["websocket"] }); diff --git a/client/src/index.tsx b/client/src/index.tsx index 3f8e9d7..291f77c 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -17,7 +17,7 @@ client.setConfig({ // Interceptor na vyhození toasteru při chybě client.interceptors.response.use(async response => { // TODO opravit - login je zatím výjimka, voláme ho "naprázdno" abychom zjistili, zda nás nepřihlásily trusted headers - if (!response.ok && response.url.indexOf("/login") == -1) { + if (!response.ok && !response.url.includes("/login")) { const json = await response.json(); toast.error(json.error, { theme: "colored" }); } diff --git a/client/src/pages/StatsPage.tsx b/client/src/pages/StatsPage.tsx index 33f83de..cc79bb1 100644 --- a/client/src/pages/StatsPage.tsx +++ b/client/src/pages/StatsPage.tsx @@ -17,16 +17,15 @@ const CHART_HEIGHT = 700; const STROKE_WIDTH = 2.5; const COLORS = [ - // Komentáře jsou kvůli vizualizaci barev ve VS Code - '#ff1493', // #ff1493 - '#1e90ff', // #1e90ff - '#c5a700', // #c5a700 - '#006400', // #006400 - '#b300ff', // #b300ff - '#ff4500', // #ff4500 - '#bc8f8f', // #bc8f8f - '#00ff00', // #00ff00 - '#7c7c7c', // #7c7c7c + '#ff1493', + '#1e90ff', + '#c5a700', + '#006400', + '#b300ff', + '#ff4500', + '#bc8f8f', + '#00ff00', + '#7c7c7c', ] export default function StatsPage() {