diff --git a/client/src/App.tsx b/client/src/App.tsx index ed8df66..1bb8b7f 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -24,7 +24,7 @@ import { useEasterEgg } from './context/eggs'; import { getImage } from './api/EasterEggApi'; import { Link } from 'react-router'; import { STATS_URL } from './AppRoutes'; -import { ClientData, Food, PizzaOrder, DepartureTime, PizzaDayState, Restaurant, RestaurantDayMenu, RestaurantDayMenuMap, LunchChoice, LunchChoices, UserLunchChoice, PizzaVariant } from '../../types'; +import { ClientData, Food, PizzaOrder, DepartureTime, PizzaDayState, Restaurant, RestaurantDayMenu, RestaurantDayMenuMap, LunchChoice, UserLunchChoice, PizzaVariant } from '../../types'; const EVENT_CONNECT = "connect" @@ -41,7 +41,7 @@ const EASTER_EGG_DEFAULT_DURATION = 0.75; function App() { const auth = useAuth(); const settings = useSettings(); - const [easterEgg, easterEggLoading] = useEasterEgg(auth); + const [easterEgg, _] = useEasterEgg(auth); const [isConnected, setIsConnected] = useState(false); const [data, setData] = useState(); const [food, setFood] = useState(); @@ -65,7 +65,7 @@ function App() { // Načtení dat po přihlášení useEffect(() => { - if (!auth || !auth.login) { + if (!auth?.login) { return } getData().then(({ data }) => { @@ -82,7 +82,7 @@ function App() { // Přenačtení pro zvolený den useEffect(() => { - if (!auth || !auth.login) { + if (!auth?.login) { return } getData(dayIndex).then((data: ClientData) => { @@ -96,11 +96,9 @@ function App() { // Registrace socket eventů useEffect(() => { socket.on(EVENT_CONNECT, () => { - // console.log("Connected!"); setIsConnected(true); }); socket.on(EVENT_DISCONNECT, () => { - // console.log("Disconnected!"); setIsConnected(false); }); socket.on(EVENT_MESSAGE, (newData: ClientData) => { @@ -119,7 +117,7 @@ function App() { }, [socket]); useEffect(() => { - if (!auth || !auth.login) { + 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 @@ -277,7 +275,7 @@ function App() { const handlePizzaChange = async (value: SelectedOptionValue | SelectedOptionValue[]) => { if (auth?.login && data?.pizzaList) { - if (!(typeof value === 'string')) { + if (typeof value !== 'string') { throw Error('Nepodporovaný typ hodnoty'); } const s = value.split('|'); @@ -365,13 +363,13 @@ function App() { content =

Chyba načtení dat

} return -

doAddClickFoodChoice(location, undefined)}>{location}

+

doAddClickFoodChoice(location)}>{location}

{menu?.lastUpdate && Poslední aktualizace: {getHumanDateTime(new Date(menu.lastUpdate))}} {content} } - if (!auth || !auth.login) { + if (!auth?.login) { return ; } @@ -411,8 +409,8 @@ function App() {
{data.isWeekend ?

Užívejte víkend :)

: <> - - + + Poslední změny:
  • Možnost výběru restaurace a jídel kliknutím v tabulce
  • @@ -429,7 +427,6 @@ function App() { {/* TODO zjednodušit, stačí iterovat klíče typu Restaurant */} {food['SLADOVNICKA'] && renderFoodTable('SLADOVNICKA', food['SLADOVNICKA'])} - {/* {food['UMOTLIKU'] && renderFoodTable('UMOTLIKU', food['UMOTLIKU'])} */} {food['TECHTOWER'] && renderFoodTable('TECHTOWER', food['TECHTOWER'])} {food['ZASTAVKAUMICHALA'] && renderFoodTable('ZASTAVKAUMICHALA', food['ZASTAVKAUMICHALA'])} {food['SENKSERIKOVA'] && renderFoodTable('SENKSERIKOVA', food['SENKSERIKOVA'])} @@ -452,7 +449,7 @@ function App() {

    Na co dobrého? (nepovinné)

    - {foodChoiceList.map((food, index) => )} + {foodChoiceList.map((food, index) => )} } {foodChoiceList && !closed && <> @@ -491,7 +488,7 @@ function App() { const userPayload = entry[1]; const userChoices = userPayload?.selectedFoods; const trusted = userPayload?.trusted || false; - return + return {trusted && @@ -587,9 +584,6 @@ function App() { - {/* */} diff --git a/client/src/Login.tsx b/client/src/Login.tsx index 8b178bf..af769a4 100644 --- a/client/src/Login.tsx +++ b/client/src/Login.tsx @@ -25,9 +25,8 @@ export default function Login() { }, [auth]); const doLogin = useCallback(async () => { - const length = loginRef?.current?.value && loginRef?.current?.value.length && loginRef.current.value.replace(/\s/g, '').length + const length = loginRef?.current?.value.length && loginRef.current.value.replace(/\s/g, '').length if (length) { - // TODO odchytávat cokoliv mimo 200 const token = await login(loginRef.current?.value); if (token) { auth?.setToken(token); @@ -35,7 +34,7 @@ export default function Login() { } }, [auth]); - if (!auth || !auth.login) { + if (!auth?.login) { return

    Luncher

    Aplikace pro profesionální management obědů

    diff --git a/client/src/Utils.tsx b/client/src/Utils.tsx index 524e8e0..4d081dc 100644 --- a/client/src/Utils.tsx +++ b/client/src/Utils.tsx @@ -93,7 +93,7 @@ export function formatDate(date: Date, format?: string) { let month = String(date.getMonth() + 1).padStart(2, "0"); let year = String(date.getFullYear()); - const f = (format === undefined) ? 'YYYY-MM-DD' : format; + const f = format ?? 'YYYY-MM-DD'; return f.replace('DD', day).replace('MM', month).replace('YYYY', year); } diff --git a/client/src/api/FoodApi.ts b/client/src/api/FoodApi.ts index aa74827..d80bf8c 100644 --- a/client/src/api/FoodApi.ts +++ b/client/src/api/FoodApi.ts @@ -1,5 +1,4 @@ -import { AddChoiceRequest, ChangeDepartureTimeRequest, RemoveChoiceRequest, RemoveChoicesRequest, UpdateNoteRequest } from "../../../types"; -import { LunchChoice } from "../../../types"; +import { AddChoiceRequest, ChangeDepartureTimeRequest, LunchChoice, RemoveChoiceRequest, RemoveChoicesRequest, UpdateNoteRequest } from "../../../types"; import { api } from "./Api"; const FOOD_API_PREFIX = '/api/food'; diff --git a/client/src/api/PizzaDayApi.ts b/client/src/api/PizzaDayApi.ts index 46f4564..3a39ea6 100644 --- a/client/src/api/PizzaDayApi.ts +++ b/client/src/api/PizzaDayApi.ts @@ -1,5 +1,4 @@ -import { AddPizzaRequest, FinishDeliveryRequest, RemovePizzaRequest, UpdatePizzaDayNoteRequest, UpdatePizzaFeeRequest } from "../../../types"; -import { PizzaVariant } from "../../../types"; +import { AddPizzaRequest, FinishDeliveryRequest, PizzaVariant, RemovePizzaRequest, UpdatePizzaDayNoteRequest, UpdatePizzaFeeRequest } from "../../../types"; import { api } from "./Api"; const PIZZADAY_API_PREFIX = '/api/pizzaDay'; diff --git a/client/src/api/VotingApi.ts b/client/src/api/VotingApi.ts index a424736..a1f7341 100644 --- a/client/src/api/VotingApi.ts +++ b/client/src/api/VotingApi.ts @@ -1,5 +1,4 @@ -import { UpdateFeatureVoteRequest } from "../../../types"; -import { FeatureRequest } from "../../../types"; +import { FeatureRequest, UpdateFeatureVoteRequest } from "../../../types"; import { api } from "./Api"; const VOTING_API_PREFIX = '/api/voting'; diff --git a/client/src/components/Header.tsx b/client/src/components/Header.tsx index d5ba480..4fcbbbb 100644 --- a/client/src/components/Header.tsx +++ b/client/src/components/Header.tsx @@ -78,7 +78,7 @@ export default function Header() { cislo = cislo.padStart(16, '0'); } let sum = 0; - for (var i = 0; i < cislo.length; i++) { + for (let i = 0; i < cislo.length; i++) { const char = cislo.charAt(i); const order = (cislo.length - 1) - i; const weight = (2 ** order) % 11; diff --git a/client/src/components/Loader.tsx b/client/src/components/Loader.tsx index 608b12c..f898705 100644 --- a/client/src/components/Loader.tsx +++ b/client/src/components/Loader.tsx @@ -2,15 +2,15 @@ import { IconDefinition } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' type Props = { - title?: String, + title?: string, icon: IconDefinition, - description: String, - animation?: String, + description: string, + animation?: string, } -function Loader(props: Props) { +function Loader(props: Readonly) { return
    -

    {props.title || 'Prosím čekejte...'}

    +

    {props.title ?? 'Prosím čekejte...'}

    {props.description}

    diff --git a/client/src/components/PizzaOrderList.tsx b/client/src/components/PizzaOrderList.tsx index 3c67eef..3d313e2 100644 --- a/client/src/components/PizzaOrderList.tsx +++ b/client/src/components/PizzaOrderList.tsx @@ -10,7 +10,7 @@ type Props = { creator: string, } -export default function PizzaOrderList({ state, orders, onDelete, creator }: Props) { +export default function PizzaOrderList({ state, orders, onDelete, creator }: Readonly) { const saveFees = async (customer: string, text?: string, price?: number) => { await updatePizzaFee(customer, text, price); } @@ -21,26 +21,24 @@ export default function PizzaOrderList({ state, orders, onDelete, creator }: Pro const total = orders.reduce((total, order) => total + order.totalPrice, 0); - return <> - - - - - - - - - - - - {orders.map(order => - - )} - - - - - -
    JménoObjednávkaPoznámkaPříplatekCena
    Celkem{`${total} Kč`}
    - + return + + + + + + + + + + + {orders.map(order => + + )} + + + + + +
    JménoObjednávkaPoznámkaPříplatekCena
    Celkem{`${total} Kč`}
    } \ No newline at end of file diff --git a/client/src/components/PizzaOrderRow.tsx b/client/src/components/PizzaOrderRow.tsx index 07493aa..896e65a 100644 --- a/client/src/components/PizzaOrderRow.tsx +++ b/client/src/components/PizzaOrderRow.tsx @@ -13,19 +13,19 @@ type Props = { onFeeModalSave: (customer: string, name?: string, price?: number) => void, } -export default function PizzaOrderRow({ creator, order, state, onDelete, onFeeModalSave }: Props) { +export default function PizzaOrderRow({ creator, order, state, onDelete, onFeeModalSave }: Readonly) { const auth = useAuth(); - const [isFeeModalOpen, setFeeModalOpen] = useState(false); + const [isFeeModalOpen, setIsFeeModalOpen] = useState(false); const saveFees = (customer: string, text?: string, price?: number) => { onFeeModalSave(customer, text, price); - setFeeModalOpen(false); + setIsFeeModalOpen(false); } return <> {order.customer} - {order.pizzaList!.map((pizzaOrder, index) => - + {order.pizzaList!.map(pizzaOrder => + {`${pizzaOrder.name}, ${pizzaOrder.size} (${pizzaOrder.price} Kč)`} {auth?.login === order.customer && state === PizzaDayState.CREATED && { @@ -35,11 +35,11 @@ export default function PizzaOrderRow({ creator, order, state, onDelete, onFeeMo ) .reduce((prev, curr, index) => [prev,
    , curr])} - {order.note || '-'} + {order.note ?? '-'} {order.fee?.price ? `${order.fee.price} Kč${order.fee.text ? ` (${order.fee.text})` : ''}` : '-'} - {order.totalPrice} Kč{auth?.login === creator && state === PizzaDayState.CREATED && { setFeeModalOpen(true) }} title='Nastavit příplatek' className='action-icon' icon={faMoneyBill1} />} + {order.totalPrice} Kč{auth?.login === creator && state === PizzaDayState.CREATED && { setIsFeeModalOpen(true) }} title='Nastavit příplatek' className='action-icon' icon={faMoneyBill1} />} - setFeeModalOpen(false)} onSave={saveFees} initialValues={{ text: order.fee?.text, price: order.fee?.price?.toString() }} /> + setIsFeeModalOpen(false)} onSave={saveFees} initialValues={{ text: order.fee?.text, price: order.fee?.price?.toString() }} /> } \ No newline at end of file diff --git a/client/src/components/modals/FeaturesVotingModal.tsx b/client/src/components/modals/FeaturesVotingModal.tsx index 8674614..a265500 100644 --- a/client/src/components/modals/FeaturesVotingModal.tsx +++ b/client/src/components/modals/FeaturesVotingModal.tsx @@ -9,7 +9,7 @@ type Props = { } /** Modální dialog pro hlasování o nových funkcích. */ -export default function FeaturesVotingModal({ isOpen, onClose, onChange, initialValues }: Props) { +export default function FeaturesVotingModal({ isOpen, onClose, onChange, initialValues }: Readonly) { const handleChange = (e: React.ChangeEvent) => { onChange(e.currentTarget.value as FeatureRequest, e.currentTarget.checked); @@ -31,7 +31,7 @@ export default function FeaturesVotingModal({ isOpen, onClose, onChange, initial label={FeatureRequest[key]} onChange={handleChange} value={key} - defaultChecked={initialValues && initialValues.includes(key as FeatureRequest)} + defaultChecked={initialValues?.includes(key as FeatureRequest)} /> })}

    Něco jiného? Dejte vědět.

    diff --git a/client/src/components/modals/NoteModal.tsx b/client/src/components/modals/NoteModal.tsx index 4928f50..b458844 100644 --- a/client/src/components/modals/NoteModal.tsx +++ b/client/src/components/modals/NoteModal.tsx @@ -8,7 +8,7 @@ type Props = { } /** Modální dialog pro úpravu obecné poznámky. */ -export default function NoteModal({ isOpen, onClose, onSave }: Props) { +export default function NoteModal({ isOpen, onClose, onSave }: Readonly) { const note = useRef(null); const save = () => { diff --git a/client/src/components/modals/PizzaAdditionalFeeModal.tsx b/client/src/components/modals/PizzaAdditionalFeeModal.tsx index f843f57..2483cd2 100644 --- a/client/src/components/modals/PizzaAdditionalFeeModal.tsx +++ b/client/src/components/modals/PizzaAdditionalFeeModal.tsx @@ -10,17 +10,17 @@ type Props = { } /** Modální dialog pro nastavení příplatků za pizzu. */ -export default function PizzaAdditionalFeeModal({ customerName, isOpen, onClose, onSave, initialValues }: Props) { +export default function PizzaAdditionalFeeModal({ customerName, isOpen, onClose, onSave, initialValues }: Readonly) { const textRef = useRef(null); const priceRef = useRef(null); const doSubmit = () => { - onSave(customerName, textRef.current?.value, parseInt(priceRef.current?.value || "0")); + onSave(customerName, textRef.current?.value, 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, parseInt(priceRef.current?.value ?? "0")); } } diff --git a/client/src/components/modals/PizzaCalculatorModal.tsx b/client/src/components/modals/PizzaCalculatorModal.tsx index 1520882..774426b 100644 --- a/client/src/components/modals/PizzaCalculatorModal.tsx +++ b/client/src/components/modals/PizzaCalculatorModal.tsx @@ -23,7 +23,7 @@ type Result = { } /** Modální dialog pro výpočet výhodnosti pizzy. */ -export default function PizzaCalculatorModal({ isOpen, onClose }: Props) { +export default function PizzaCalculatorModal({ isOpen, onClose }: Readonly) { const diameter1Ref = useRef(null); const price1Ref = useRef(null); const diameter2Ref = useRef(null); diff --git a/client/src/components/modals/SettingsModal.tsx b/client/src/components/modals/SettingsModal.tsx index b83b341..4c4ba07 100644 --- a/client/src/components/modals/SettingsModal.tsx +++ b/client/src/components/modals/SettingsModal.tsx @@ -9,7 +9,7 @@ type Props = { } /** Modální dialog pro uživatelská nastavení. */ -export default function SettingsModal({ isOpen, onClose, onSave }: Props) { +export default function SettingsModal({ isOpen, onClose, onSave }: Readonly) { const settings = useSettings(); const bankAccountRef = useRef(null); const nameRef = useRef(null); diff --git a/client/src/context/auth.tsx b/client/src/context/auth.tsx index a22afd5..a2cb3d3 100644 --- a/client/src/context/auth.tsx +++ b/client/src/context/auth.tsx @@ -1,5 +1,4 @@ -import React, { ReactNode, useContext, useState } from "react" -import { useEffect } from "react" +import React, { ReactNode, useContext, useEffect, useState } from "react" import { useJwt } from "react-jwt"; import { deleteToken, getToken, storeToken } from "../Utils"; @@ -16,7 +15,7 @@ type ContextProps = { const authContext = React.createContext(null); -export function ProvideAuth(props: ContextProps) { +export function ProvideAuth(props: Readonly) { const auth = useProvideAuth(); return {props.children} } @@ -29,7 +28,7 @@ function useProvideAuth(): AuthContextProps { const [loginName, setLoginName] = useState(); const [trusted, setTrusted] = useState(); const [token, setToken] = useState(getToken()); - const { decodedToken } = useJwt(token || ''); + const { decodedToken } = useJwt(token ?? ''); useEffect(() => { if (token && token.length > 0) { diff --git a/client/src/context/settings.tsx b/client/src/context/settings.tsx index 13ea93e..8bbdec4 100644 --- a/client/src/context/settings.tsx +++ b/client/src/context/settings.tsx @@ -1,5 +1,4 @@ -import React, { ReactNode, useContext, useState } from "react" -import { useEffect } from "react" +import React, { ReactNode, useContext, useEffect, useState } from "react" const BANK_ACCOUNT_NUMBER_KEY = 'bank_account_number'; const BANK_ACCOUNT_HOLDER_KEY = 'bank_account_holder_name'; @@ -20,7 +19,7 @@ type ContextProps = { const settingsContext = React.createContext(null); -export function ProvideSettings(props: ContextProps) { +export function ProvideSettings(props: Readonly) { const settings = useProvideSettings(); return {props.children} } @@ -45,7 +44,7 @@ function useProvideSettings(): SettingsContextProps { } const hideSoups = localStorage.getItem(HIDE_SOUPS_KEY); if (hideSoups !== null) { - setHideSoups(hideSoups === 'true' ? true : false); + setHideSoups(hideSoups === 'true'); } }, []) diff --git a/client/src/context/socket.js b/client/src/context/socket.js index fd70419..ed2e2ea 100644 --- a/client/src/context/socket.js +++ b/client/src/context/socket.js @@ -18,8 +18,3 @@ export const SocketContext = React.createContext(); export const EVENT_CONNECT = 'connect'; export const EVENT_DISCONNECT = 'disconnect'; export const EVENT_MESSAGE = 'message'; -// export const EVENT_CONFIG = 'config'; -// export const EVENT_TOASTER = 'toaster'; -// export const EVENT_VOTING = 'voting'; -// export const EVENT_VOTE_CONFIG = 'voteSettings'; -// export const EVENT_ADMIN = 'admin'; diff --git a/server/src/chefie.ts b/server/src/chefie.ts index b9afba8..fe41d40 100644 --- a/server/src/chefie.ts +++ b/server/src/chefie.ts @@ -49,16 +49,16 @@ export async function downloadPizzy(mock: boolean): Promise { const $ = load(html); const links = $('.vypisproduktu > div > h4 > a'); const urls = []; - for (let i = 0; i < links.length; i++) { - if (links[i].name === 'a' && links[i].attribs?.href) { - const pizzaUrl = links[i].attribs?.href; + for (const element of links) { + if (element.name === 'a' && element.attribs?.href) { + const pizzaUrl = element.attribs?.href; urls.push(buildPizzaUrl(pizzaUrl)); } } // Scrapneme jednotlivé pizzy const result: Pizza[] = []; - for (let i = 0; i < urls.length; i++) { - const pizzaUrl = urls[i]; + for (const element of urls) { + const pizzaUrl = element; const pizzaHtml = await axios.get(pizzaUrl).then(res => res.data); // Název const name = $('.produkt > h2', pizzaHtml).first().text() diff --git a/server/src/index.ts b/server/src/index.ts index 4d68368..db44e86 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -14,7 +14,7 @@ import votingRoutes from "./routes/votingRoutes"; import easterEggRoutes from "./routes/easterEggRoutes"; import statsRoutes from "./routes/statsRoutes"; -const ENVIRONMENT = process.env.NODE_ENV || 'production'; +const ENVIRONMENT = process.env.NODE_ENV ?? 'production'; dotenv.config({ path: path.resolve(__dirname, `./.env.${ENVIRONMENT}`) }); // Validace nastavení JWT tokenu - nemá bez něj smysl vůbec povolit server spustit @@ -35,7 +35,7 @@ app.use(cors({ // Zapínatelný login přes hlavičky - pokud je zapnutý nepovolí "basicauth" const HTTP_REMOTE_USER_ENABLED = process.env.HTTP_REMOTE_USER_ENABLED === 'true' || false; -const HTTP_REMOTE_USER_HEADER_NAME = process.env.HTTP_REMOTE_USER_HEADER_NAME || 'remote-user'; +const HTTP_REMOTE_USER_HEADER_NAME = process.env.HTTP_REMOTE_USER_HEADER_NAME ?? 'remote-user'; if (HTTP_REMOTE_USER_ENABLED) { if (!process.env.HTTP_REMOTE_TRUSTED_IPS) { throw new Error('Je zapnutý login z hlaviček, ale není nastaven rozsah adres ze kterých hlavička může přijít.'); @@ -79,7 +79,6 @@ app.post("/api/login", (req, res) => { // TODO dočasné řešení - QR se zobrazuje přes , nemáme sem jak dostat token app.get("/api/qr", (req, res) => { - // const login = getLogin(parseToken(req)); if (!req.query?.login) { throw Error("Nebyl předán login"); } @@ -148,8 +147,8 @@ app.use((err: any, req: any, res: any, next: any) => { next(); }); -const PORT = process.env.PORT || 3001; -const HOST = process.env.HOST || '0.0.0.0'; +const PORT = process.env.PORT ?? 3001; +const HOST = process.env.HOST ?? '0.0.0.0'; server.listen(PORT, () => { console.log(`Server listening on ${HOST}, port ${PORT}`); diff --git a/server/src/notifikace.ts b/server/src/notifikace.ts index c06181a..8e6ef83 100644 --- a/server/src/notifikace.ts +++ b/server/src/notifikace.ts @@ -1,14 +1,11 @@ -/** Notifikace */ import axios from 'axios'; import dotenv from 'dotenv'; import path from 'path'; import { getClientData, getToday } from "./service"; import { getUsersByLocation, getHumanTime } from "./utils"; -import getStorage from "./storage"; import { NotifikaceData, NotifikaceInput } from '../../types'; -const storage = getStorage(); -const ENVIRONMENT = process.env.NODE_ENV || 'production' +const ENVIRONMENT = process.env.NODE_ENV ?? 'production'; dotenv.config({ path: path.resolve(__dirname, `../.env.${ENVIRONMENT}`) }); // const gotifyDataRaw = process.env.GOTIFY_SERVERS_AND_KEYS || "{}"; diff --git a/server/src/pizza.ts b/server/src/pizza.ts index ada27b0..b7a9ff3 100644 --- a/server/src/pizza.ts +++ b/server/src/pizza.ts @@ -128,11 +128,11 @@ export async function removePizzaOrder(login: string, pizzaOrder: PizzaVariant) if (!clientData.pizzaDay) { throw Error("Pizza day pro dnešní den neexistuje"); } - const orderIndex = clientData.pizzaDay!.orders!.findIndex(o => o.customer === login); + 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 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"); @@ -308,7 +308,7 @@ export async function updatePizzaFee(login: string, targetLogin: string, text?: targetOrder.fee = { text, price }; } // Přepočet ceny - targetOrder.totalPrice = targetOrder.pizzaList.reduce((price, pizzaOrder) => price + pizzaOrder.price, 0) + (targetOrder.fee?.price || 0); + targetOrder.totalPrice = targetOrder.pizzaList.reduce((price, pizzaOrder) => price + pizzaOrder.price, 0) + (targetOrder.fee?.price ?? 0); await storage.setData(today, clientData); return clientData; } \ No newline at end of file diff --git a/server/src/restaurants.ts b/server/src/restaurants.ts index 580c819..3ea236c 100644 --- a/server/src/restaurants.ts +++ b/server/src/restaurants.ts @@ -92,7 +92,6 @@ export const getMenuSladovnicka = async (firstDayOfWeek: Date, mock: boolean = f const rowText = $(dayRow).first().text().trim(); if (rowText === searchedDayText) { index = i; - return; } }) if (index === undefined) { @@ -360,7 +359,6 @@ export const getMenuZastavkaUmichala = async (firstDayOfWeek: Date, mock: boolea price: "", isSoup: false, }]; - continue; } else { const url = (currentDate.getDate() === nowDate) ? ZASTAVKAUMICHALA_URL : ZASTAVKAUMICHALA_URL + '/?do=dailyMenu-changeDate&dailyMenu-dateString=' + formatDate(currentDate, 'DD.MM.YYYY'); diff --git a/server/src/routes/easterEggRoutes.ts b/server/src/routes/easterEggRoutes.ts index 46bcd5b..347736a 100644 --- a/server/src/routes/easterEggRoutes.ts +++ b/server/src/routes/easterEggRoutes.ts @@ -1,5 +1,5 @@ import express, { NextFunction } from "express"; -import { getLogin, getTrusted } from "../auth"; +import { getLogin } from "../auth"; import { parseToken } from "../utils"; import path from "path"; import fs from "fs"; @@ -34,16 +34,11 @@ function generateUrl() { */ function getEasterEggImage(req: any, res: any, next: NextFunction) { const login = getLogin(parseToken(req)); - const trusted = getTrusted(parseToken(req)); try { - // TODO vrátit! - // if (trusted) { - if (true) { - if (login in easterEggs) { - const imagePath = easterEggs[login][Math.floor(Math.random() * easterEggs[login].length)].path; - res.sendFile(path.join(__dirname, IMAGES_PATH, imagePath)); - return; - } + if (login in easterEggs) { + const imagePath = easterEggs[login][Math.floor(Math.random() * easterEggs[login].length)].path; + res.sendFile(path.join(__dirname, IMAGES_PATH, imagePath)); + return; } res.sendStatus(404); } catch (e: any) { next(e) } @@ -124,7 +119,7 @@ let easterEggs: EasterEggsJson; if (fs.existsSync(EASTER_EGGS_JSON_PATH)) { const content = fs.readFileSync(EASTER_EGGS_JSON_PATH, 'utf-8'); easterEggs = JSON.parse(content); - for (const [key, eggs] of Object.entries(easterEggs)) { + for (const [_, eggs] of Object.entries(easterEggs)) { for (const easterEgg of eggs) { const url = generateUrl(); easterEgg.url = url; @@ -138,16 +133,11 @@ if (fs.existsSync(EASTER_EGGS_JSON_PATH)) { // Získání náhodného easter eggu pro přihlášeného uživatele router.get("/", async (req, res, next) => { const login = getLogin(parseToken(req)); - const trusted = getTrusted(parseToken(req)); try { - // TODO vrátit! - // if (trusted) { - if (true) { - if (easterEggs && login in easterEggs) { - const randomEasterEgg = easterEggs[login][Math.floor(Math.random() * easterEggs[login].length)]; - const { path, startOffset, endOffset, ...strippedEasterEgg } = randomEasterEgg; // Path klient k ničemu nepotřebuje a nemá ho znát - return res.status(200).json({ ...strippedEasterEgg, ...getRandomPosition(startOffset, endOffset) }); - } + if (easterEggs && login in easterEggs) { + const randomEasterEgg = easterEggs[login][Math.floor(Math.random() * easterEggs[login].length)]; + const { path, startOffset, endOffset, ...strippedEasterEgg } = randomEasterEgg; // Path klient k ničemu nepotřebuje a nemá ho znát + return res.status(200).json({ ...strippedEasterEgg, ...getRandomPosition(startOffset, endOffset) }); } return res.status(200).send(); } catch (e: any) { next(e) } diff --git a/server/src/routes/foodRoutes.ts b/server/src/routes/foodRoutes.ts index bb0d20a..db4ff2c 100644 --- a/server/src/routes/foodRoutes.ts +++ b/server/src/routes/foodRoutes.ts @@ -4,8 +4,7 @@ import { addChoice, getDateForWeekIndex, getToday, removeChoice, removeChoices, import { getDayOfWeekIndex, parseToken } from "../utils"; import { getWebsocket } from "../websocket"; import { callNotifikace } from "../notifikace"; -import { AddChoiceRequest, ChangeDepartureTimeRequest, IDayIndex, RemoveChoiceRequest, RemoveChoicesRequest, UpdateNoteRequest } from "../../../types"; -import { UdalostEnum } from "../../../types"; +import { AddChoiceRequest, ChangeDepartureTimeRequest, IDayIndex, RemoveChoiceRequest, RemoveChoicesRequest, UdalostEnum, UpdateNoteRequest } from "../../../types"; /** * Ověří a vrátí index dne v týdnu z požadavku, za předpokladu, že byl předán, a je zároveň diff --git a/server/src/routes/votingRoutes.ts b/server/src/routes/votingRoutes.ts index 618b8b7..2aa6672 100644 --- a/server/src/routes/votingRoutes.ts +++ b/server/src/routes/votingRoutes.ts @@ -2,8 +2,7 @@ import express, { Request, Response } from "express"; import { getLogin } from "../auth"; import { parseToken } from "../utils"; import { getUserVotes, updateFeatureVote } from "../voting"; -import { UpdateFeatureVoteRequest } from "../../../types"; -import { FeatureRequest } from "../../../types"; +import { FeatureRequest, UpdateFeatureVoteRequest } from "../../../types"; const router = express.Router(); diff --git a/server/src/service.ts b/server/src/service.ts index 9a73e55..344d1ff 100644 --- a/server/src/service.ts +++ b/server/src/service.ts @@ -1,6 +1,6 @@ import { InsufficientPermissions, formatDate, getDayOfWeekIndex, getFirstWorkDayOfWeek, getHumanDate, getIsWeekend, getWeekNumber } from "./utils"; import getStorage from "./storage"; -import { getMenuSladovnicka, getMenuTechTower, getMenuUMotliku, getMenuZastavkaUmichala, getMenuSenkSerikova } from "./restaurants"; +import { getMenuSladovnicka, getMenuTechTower, getMenuZastavkaUmichala, getMenuSenkSerikova } from "./restaurants"; import { getTodayMock } from "./mock"; import { ClientData, DepartureTime, LunchChoice, Restaurant, RestaurantDayMenu, WeekMenu } from "../../types"; @@ -152,10 +152,10 @@ export async function getRestaurantMenu(restaurant: keyof typeof Restaurant, dat weekMenu[i][restaurant]!.closed = true; } } - break; } catch (e: any) { console.error("Selhalo načtení jídel pro podnik TechTower", e); } + break; case 'ZASTAVKAUMICHALA': try { const zastavkaUmichalaFood = await getMenuZastavkaUmichala(firstDay, mock); @@ -165,10 +165,10 @@ export async function getRestaurantMenu(restaurant: keyof typeof Restaurant, dat weekMenu[i][restaurant]!.closed = true; } } - break; } catch (e: any) { console.error("Selhalo načtení jídel pro podnik Zastávka u Michala", e); } + break; case 'SENKSERIKOVA': try { const senkSerikovaFood = await getMenuSenkSerikova(firstDay, mock); @@ -178,10 +178,10 @@ export async function getRestaurantMenu(restaurant: keyof typeof Restaurant, dat weekMenu[i][restaurant]!.closed = true; } } - break; } catch (e: any) { console.error("Selhalo načtení jídel pro podnik Pivovarský šenk Šeříková", e); } + break; } await storage.setData(getMenuKey(usedDate), weekMenu); } diff --git a/server/src/stats.ts b/server/src/stats.ts index 6f9d2df..34507f6 100644 --- a/server/src/stats.ts +++ b/server/src/stats.ts @@ -2,7 +2,6 @@ import { DailyStats, LunchChoice, WeeklyStats } from "../../types"; import { getStatsMock } from "./mock"; import { getClientData } from "./service"; import getStorage from "./storage"; -import { formatDate } from "./utils"; const storage = getStorage(); diff --git a/server/src/storage/index.ts b/server/src/storage/index.ts index 082d492..dea6802 100644 --- a/server/src/storage/index.ts +++ b/server/src/storage/index.ts @@ -4,7 +4,7 @@ import { StorageInterface } from "./StorageInterface"; import JsonStorage from "./json"; import RedisStorage from "./redis"; -const ENVIRONMENT = process.env.NODE_ENV || 'production'; +const ENVIRONMENT = process.env.NODE_ENV ?? 'production'; dotenv.config({ path: path.resolve(__dirname, `../.env.${ENVIRONMENT}`) }); const JSON_KEY = 'json'; diff --git a/server/src/storage/redis.ts b/server/src/storage/redis.ts index 4251223..966236a 100644 --- a/server/src/storage/redis.ts +++ b/server/src/storage/redis.ts @@ -8,15 +8,15 @@ let client: RedisClientType; */ export default class RedisStorage implements StorageInterface { constructor() { - const HOST = process.env.REDIS_HOST || 'localhost'; - const PORT = process.env.REDIS_PORT || 6379; + const HOST = process.env.REDIS_HOST ?? 'localhost'; + const PORT = process.env.REDIS_PORT ?? 6379; client = createClient({ url: `redis://${HOST}:${PORT}` }); client.connect(); } async hasData(key: string) { const data = await client.json.get(key); - return (data ? true : false); + return (!!data); } async getData(key: string) { diff --git a/server/src/utils.ts b/server/src/utils.ts index 3c29a90..fa4402d 100644 --- a/server/src/utils.ts +++ b/server/src/utils.ts @@ -8,7 +8,7 @@ export function formatDate(date: Date, format?: string) { let month = String(date.getMonth() + 1).padStart(2, "0"); let year = String(date.getFullYear()); - const f = (format === undefined) ? 'YYYY-MM-DD' : format; + const f = format ?? 'YYYY-MM-DD'; return f.replace('DD', day).replace('MM', month).replace('YYYY', year); } @@ -61,10 +61,10 @@ export function getLastWorkDayOfWeek(date: Date) { /** Vrátí pořadové číslo týdne předaného data v roce dle ISO 8601. */ export function getWeekNumber(inputDate: Date) { - var date = new Date(inputDate.getTime()); + const date = new Date(inputDate.getTime()); date.setHours(0, 0, 0, 0); date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7); - var week1 = new Date(date.getFullYear(), 0, 4); + const week1 = new Date(date.getFullYear(), 0, 4); return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7); }