From 18cb172e06b6295ce77716912862a644b6a910ee Mon Sep 17 00:00:00 2001 From: Martin Berka Date: Sun, 6 Aug 2023 18:52:18 +0200 Subject: [PATCH] =?UTF-8?q?Ukl=C3=A1d=C3=A1n=C3=AD=20pizz=20do=20DB=20m?= =?UTF-8?q?=C3=ADsto=20do=C4=8Dasn=C3=A9ho=20souboru?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/Api.ts | 4 ---- client/src/App.tsx | 16 ++++++---------- server/src/chefie.ts | 28 +--------------------------- server/src/index.ts | 17 +++++++---------- server/src/service.ts | 25 +++++++++++++++++++++++++ types/Types.ts | 2 ++ 6 files changed, 41 insertions(+), 51 deletions(-) diff --git a/client/src/Api.ts b/client/src/Api.ts index f7fa61b..388fdf2 100644 --- a/client/src/Api.ts +++ b/client/src/Api.ts @@ -32,10 +32,6 @@ export const getFood = async () => { return await api.get('/api/food'); } -export const getPizzy = async () => { - return await api.get('/api/pizza'); -} - export const createPizzaDay = async () => { return await api.post('/api/createPizzaDay', undefined); } diff --git a/client/src/App.tsx b/client/src/App.tsx index f6de122..cc5a3d1 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 { addChoice, addPizza, changeDepartureTime, createPizzaDay, deletePizzaDay, finishDelivery, finishOrder, getData, getFood, getPizzy, getQrUrl, lockPizzaDay, removeChoice, removeChoices, removePizza, unlockPizzaDay, updateNote } from './Api'; +import { addChoice, addPizza, changeDepartureTime, createPizzaDay, deletePizzaDay, finishDelivery, finishOrder, getData, getFood, getQrUrl, lockPizzaDay, removeChoice, removeChoices, removePizza, unlockPizzaDay, updateNote } from './Api'; import { useAuth } from './context/auth'; import Login from './Login'; import { Alert, Button, Col, Form, Row, Table } from 'react-bootstrap'; @@ -14,7 +14,7 @@ import './App.css'; import { SelectSearchOption } from 'react-select-search'; import { faCircleCheck, faTrashCan } from '@fortawesome/free-regular-svg-icons'; import { useBank } from './context/bank'; -import { ClientData, Restaurants, Food, Pizza, Order, Locations, PizzaOrder, PizzaDayState, FoodChoices } from './types'; +import { ClientData, Restaurants, Food, Order, Locations, PizzaOrder, PizzaDayState, FoodChoices } from './types'; import Footer from './components/Footer'; const EVENT_CONNECT = "connect" @@ -42,7 +42,6 @@ function App() { const [isConnected, setIsConnected] = useState(false); const [data, setData] = useState(); const [food, setFood] = useState<{ [key in Restaurants]: Food[] }>(); - const [pizzy, setPizzy] = useState(); const [myOrder, setMyOrder] = useState(); const [foodChoiceList, setFoodChoiceList] = useState(); const socket = useContext(SocketContext); @@ -55,9 +54,6 @@ function App() { if (!auth || !auth.login) { return } - getPizzy().then(pizzy => { - setPizzy(pizzy); - }); getData().then(data => { setData(data); }) @@ -174,11 +170,11 @@ function App() { } const pizzaSuggestions = useMemo(() => { - if (!pizzy) { + if (!data?.pizzaList) { return []; } const suggestions: SelectSearchOption[] = []; - pizzy.forEach((pizza, index) => { + data.pizzaList.forEach((pizza, index) => { const group: SelectSearchOption = { name: pizza.name, type: "group", items: [] } pizza.sizes.forEach((size, sizeIndex) => { const name = `${size.size} (${size.price} Kč)`; @@ -188,10 +184,10 @@ function App() { suggestions.push(group); }) return suggestions; - }, [pizzy]); + }, [data?.pizzaList]); const handlePizzaChange = async (value: SelectedOptionValue | SelectedOptionValue[]) => { - if (auth?.login && pizzy) { + if (auth?.login && data?.pizzaList) { if (!(typeof value === 'string')) { throw Error('Nepodporovaný typ hodnoty'); } diff --git a/server/src/chefie.ts b/server/src/chefie.ts index fd9657e..2d3df80 100644 --- a/server/src/chefie.ts +++ b/server/src/chefie.ts @@ -1,9 +1,5 @@ -import os from 'os'; -import path from 'path'; -import fs from 'fs'; import axios from 'axios'; import { load } from 'cheerio'; -import { formatDate } from './utils'; // TODO přesunout do types type PizzaSize = { @@ -40,7 +36,7 @@ const boxPrices: { [key: string]: number } = { /** * Stáhne a scrapne aktuální pizzy ze stránek Pizza Chefie. */ -const downloadPizzy = async () => { +export async function downloadPizzy(): Promise { // Získáme seznam pizz const html = await axios.get(pizzyUrl).then(res => res.data); const $ = load(html); @@ -81,26 +77,4 @@ const downloadPizzy = async () => { }); } return result; -} - -/** - * Vrátí pizzy z tempu, nebo čerstvě stažené, pokud v tempu nejsou. - */ -export const fetchPizzy = async (): Promise => { - const tmpDir = os.tmpdir(); - const date_ob = new Date(); - const dateStr = formatDate(date_ob); - const dataPath = path.join(tmpDir, `chefie-${dateStr}.json`); - - if (fs.existsSync(dataPath)) { - console.log(`Soubor pro ${dataPath} již existuje, bude použit.`); - const rawdata = fs.readFileSync(dataPath); - return JSON.parse(rawdata.toString()); - } else { - console.log(`Soubor pro ${dataPath} neexistuje, stahuji...`); - const pizzy = await downloadPizzy(); - fs.writeFileSync(dataPath, JSON.stringify(pizzy)); - console.log(`Zapsán ${dataPath}`); - return pizzy; - } } \ No newline at end of file diff --git a/server/src/index.ts b/server/src/index.ts index d5c8412..8fe51d7 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -1,15 +1,15 @@ import express from "express"; import { Server } from "socket.io"; import bodyParser from "body-parser"; -import { fetchPizzy } from "./chefie"; import cors from 'cors'; -import { addChoice, addPizzaOrder, createPizzaDay, deletePizzaDay, finishPizzaDelivery, finishPizzaOrder, getData, lockPizzaDay, removeChoice, removeChoices, removePizzaOrder, unlockPizzaDay, updateDepartureTime, updateNote } from "./service"; +import { addChoice, addPizzaOrder, createPizzaDay, deletePizzaDay, finishPizzaDelivery, finishPizzaOrder, getData, getPizzaList, lockPizzaDay, removeChoice, removeChoices, removePizzaOrder, savePizzaList, unlockPizzaDay, updateDepartureTime, updateNote } from "./service"; import dotenv from 'dotenv'; import path from 'path'; import { getMenuSladovnicka, getMenuTechTower, getMenuUMotliku } from "./restaurants"; import { getQr } from "./qr"; import { generateToken, getLogin, getTrusted, verify } from "./auth"; import { Locations, Restaurants } from "../../types"; +import { downloadPizzy } from "./chefie"; const ENVIRONMENT = process.env.NODE_ENV || 'production'; dotenv.config({ path: path.resolve(__dirname, `./.env.${ENVIRONMENT}`) }); @@ -121,13 +121,6 @@ app.get("/api/food", async (req, res) => { res.status(200).json(data); }); -/** Vrátí seznam dostupných pizz. */ -app.get("/api/pizza", async (req, res) => { - const pizzaList = await fetchPizzy(); - // console.log("Výsledek", pizzaList); - res.status(200).json(pizzaList); -}); - /** Založí pizza day pro aktuální den, za předpokladu že dosud neexistuje. */ app.post("/api/createPizzaDay", async (req, res) => { const login = getLogin(parseToken(req)); @@ -153,7 +146,11 @@ app.post("/api/addPizza", async (req, res) => { throw Error("Nebyl předán index velikosti pizzy"); } const pizzaSizeIndex = req.body.pizzaSizeIndex; - const pizzy = await fetchPizzy(); + let pizzy = await getPizzaList(); + if (!pizzy) { + pizzy = await downloadPizzy(); + savePizzaList(pizzy); + } if (!pizzy[pizzaIndex]) { throw Error("Neplatný index pizzy: " + pizzaIndex); } diff --git a/server/src/service.ts b/server/src/service.ts index ed2750c..b9eaf41 100644 --- a/server/src/service.ts +++ b/server/src/service.ts @@ -26,6 +26,31 @@ export async function getData(): Promise { return await storage.getData(formatDate(getToday())) || getEmptyData(); } +/** + * Vrátí seznam dostupných pizz pro dnešní den. + */ +export async function getPizzaList(): Promise { + await initIfNeeded(); + const today = formatDate(getToday()); + const clientData: ClientData = await storage.getData(today); + return Promise.resolve(clientData.pizzaList); +} + +/** + * Uloží seznam dostupných pizz pro dnešní den. + * + * @param pizzaList seznam dostupných pizz + */ +export async function savePizzaList(pizzaList: Pizza[]): Promise { + await initIfNeeded(); + const today = formatDate(getToday()); + const clientData: ClientData = await storage.getData(today); + clientData.pizzaList = pizzaList; + clientData.pizzaListLastUpdate = new Date(); + await storage.setData(today, clientData); + return clientData; +} + /** * Vytvoří pizza day pro aktuální den a vrátí data pro klienta. */ diff --git a/types/Types.ts b/types/Types.ts index 6115bf5..2a33402 100644 --- a/types/Types.ts +++ b/types/Types.ts @@ -72,6 +72,8 @@ export interface ClientData { isWeekend: boolean, // příznak, zda je dnes víkend choices: Choices, // seznam voleb pizzaDay?: PizzaDay, // pizza day pro dnešní den, pokud existuje + pizzaList?: Pizza[], // seznam dostupných pizz pro dnešní den + pizzaListLastUpdate?: Date, // datum a čas poslední aktualizace pizz } /** Jídlo z obědového menu restaurace. */