Možnost zadání preferovaného času odchodu
This commit is contained in:
parent
37542499a9
commit
3f303ea5ea
@ -87,3 +87,7 @@ export const updateNote = async (note?: string) => {
|
|||||||
export const login = async (login: string) => {
|
export const login = async (login: string) => {
|
||||||
return await api.post<any, any>('/api/login', JSON.stringify({ login }));
|
return await api.post<any, any>('/api/login', JSON.stringify({ login }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const changeDepartureTime = async (login: string, time: string) => {
|
||||||
|
return await api.post<any, any>('/api/changeDepartureTime', JSON.stringify({ login, time }));
|
||||||
|
}
|
@ -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 { addChoice, addPizza, 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, getPizzy, getQrUrl, lockPizzaDay, removeChoice, removeChoices, removePizza, unlockPizzaDay, updateNote } from './Api';
|
||||||
import { useAuth } from './context/auth';
|
import { useAuth } from './context/auth';
|
||||||
import Login from './Login';
|
import Login from './Login';
|
||||||
import { Alert, Button, Col, Form, Row, Table } from 'react-bootstrap';
|
import { Alert, Button, Col, Form, Row, Table } from 'react-bootstrap';
|
||||||
@ -17,9 +17,25 @@ import { useBank } from './context/bank';
|
|||||||
import { ClientData, Restaurants, Food, Pizza, Order, Locations, PizzaOrder, PizzaDayState, FoodChoices } from './types';
|
import { ClientData, Restaurants, Food, Pizza, Order, Locations, PizzaOrder, PizzaDayState, FoodChoices } from './types';
|
||||||
import Footer from './components/Footer';
|
import Footer from './components/Footer';
|
||||||
|
|
||||||
|
|
||||||
const EVENT_CONNECT = "connect"
|
const EVENT_CONNECT = "connect"
|
||||||
|
|
||||||
|
// TODO tohle má být kvůli bezpečnosti na serveru
|
||||||
|
const DEPARTURE_TIMES = [
|
||||||
|
"10:00",
|
||||||
|
"10:15",
|
||||||
|
"10:30",
|
||||||
|
"10:45",
|
||||||
|
"11:00",
|
||||||
|
"11:15",
|
||||||
|
"11:30",
|
||||||
|
"11:45",
|
||||||
|
"12:00",
|
||||||
|
"12:15",
|
||||||
|
"12:30",
|
||||||
|
"12:45",
|
||||||
|
"13:00",
|
||||||
|
]
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const auth = useAuth();
|
const auth = useAuth();
|
||||||
const bank = useBank();
|
const bank = useBank();
|
||||||
@ -222,6 +238,14 @@ function App() {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
const handleChangeDepartureTime = async (event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||||
|
if (foodChoiceList?.length && choiceRef.current?.value) {
|
||||||
|
if (auth?.login) {
|
||||||
|
await changeDepartureTime(auth.login, event.target.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const renderFoodTable = (name: string, food: Food[]) => {
|
const renderFoodTable = (name: string, food: Food[]) => {
|
||||||
return <Col md={12} lg={4}>
|
return <Col md={12} lg={4}>
|
||||||
<h3>{name}</h3>
|
<h3>{name}</h3>
|
||||||
@ -257,13 +281,8 @@ function App() {
|
|||||||
<Alert variant={'primary'}>
|
<Alert variant={'primary'}>
|
||||||
Poslední změny:
|
Poslední změny:
|
||||||
<ul>
|
<ul>
|
||||||
<li>(Trochu) přehlednější zobrazení tabulky
|
<li>Podpora <a href="https://redis.io">Redis</a></li>
|
||||||
<ul>
|
<li>Možnost výběru preferovaného času odchodu</li>
|
||||||
<li>Je to pořád ošklivý :(</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>(Opět) možnost vybrat jen jednu variantu</li>
|
|
||||||
<li>"Blue checkmark" pro uživatele přihlášené přes AD</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</Alert>
|
</Alert>
|
||||||
<h1 className='title'>Dnes je {data.date}</h1>
|
<h1 className='title'>Dnes je {data.date}</h1>
|
||||||
@ -293,6 +312,13 @@ function App() {
|
|||||||
{foodChoiceList.map((food, index) => <option key={index} value={index}>{food.name}</option>)}
|
{foodChoiceList.map((food, index) => <option key={index} value={index}>{food.name}</option>)}
|
||||||
</Form.Select>
|
</Form.Select>
|
||||||
</>}
|
</>}
|
||||||
|
{foodChoiceList && <>
|
||||||
|
<p style={{ marginTop: "10px" }}>V kolik hodin preferuješ odchod?</p>
|
||||||
|
<Form.Select ref={foodChoiceRef} onChange={handleChangeDepartureTime}>
|
||||||
|
<option></option>
|
||||||
|
{DEPARTURE_TIMES.map(time => <option key={time} value={time}>{time}</option>)}
|
||||||
|
</Form.Select>
|
||||||
|
</>}
|
||||||
{Object.keys(data.choices).length > 0 ?
|
{Object.keys(data.choices).length > 0 ?
|
||||||
<Table bordered className='mt-5'>
|
<Table bordered className='mt-5'>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -316,6 +342,7 @@ function App() {
|
|||||||
<FontAwesomeIcon title='Uživatel ověřený doménovým přihlášením' icon={faCircleCheck} style={{ cursor: "help" }} />
|
<FontAwesomeIcon title='Uživatel ověřený doménovým přihlášením' icon={faCircleCheck} style={{ cursor: "help" }} />
|
||||||
</span>}
|
</span>}
|
||||||
{login}
|
{login}
|
||||||
|
{userPayload.departureTime && <small> ({userPayload.departureTime})</small>}
|
||||||
{login === auth.login && <FontAwesomeIcon onClick={() => {
|
{login === auth.login && <FontAwesomeIcon onClick={() => {
|
||||||
doRemoveChoices(locationKey);
|
doRemoveChoices(locationKey);
|
||||||
}} title={`Odstranit volbu ${locationName}, včetně případných zvolených jídel`} className='trash-icon' icon={faTrashCan} />}
|
}} title={`Odstranit volbu ${locationName}, včetně případných zvolených jídel`} className='trash-icon' icon={faTrashCan} />}
|
||||||
|
@ -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 { addChoice, addPizzaOrder, createPizzaDay, deletePizzaDay, finishPizzaDelivery, finishPizzaOrder, getData, lockPizzaDay, removeChoice, removeChoices, removePizzaOrder, unlockPizzaDay, updateNote } from "./service";
|
import { addChoice, addPizzaOrder, createPizzaDay, deletePizzaDay, finishPizzaDelivery, finishPizzaOrder, getData, lockPizzaDay, removeChoice, removeChoices, removePizzaOrder, unlockPizzaDay, updateDepartureTime, updateNote } from "./service";
|
||||||
import dotenv from 'dotenv';
|
import dotenv from 'dotenv';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { getMenuSladovnicka, getMenuTechTower, getMenuUMotliku } from "./restaurants";
|
import { getMenuSladovnicka, getMenuTechTower, getMenuUMotliku } from "./restaurants";
|
||||||
@ -238,6 +238,13 @@ app.post("/api/updateNote", async (req, res) => {
|
|||||||
res.status(200).json(data);
|
res.status(200).json(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.post("/api/changeDepartureTime", async (req, res) => {
|
||||||
|
const login = getLogin(parseToken(req));
|
||||||
|
const data = await updateDepartureTime(login, req.body?.time);
|
||||||
|
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}`);
|
||||||
|
|
||||||
|
@ -372,4 +372,26 @@ export async function updateNote(login: string, note?: string) {
|
|||||||
myOrder.note = note;
|
myOrder.note = note;
|
||||||
await storage.setData(today, clientData);
|
await storage.setData(today, clientData);
|
||||||
return clientData;
|
return clientData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aktualizuje preferovaný čas odchodu strávníka.
|
||||||
|
*
|
||||||
|
* @param login login uživatele
|
||||||
|
* @param time preferovaný čas odchodu
|
||||||
|
*/
|
||||||
|
export async function updateDepartureTime(login: string, time?: string) {
|
||||||
|
const today = formatDate(getToday());
|
||||||
|
let clientData: ClientData = await storage.getData(today);
|
||||||
|
const found = Object.values(clientData.choices).find(location => login in location);
|
||||||
|
// TODO validace, že se jedná o restauraci
|
||||||
|
if (found) {
|
||||||
|
if (!time?.length) {
|
||||||
|
delete found[login].departureTime;
|
||||||
|
} else {
|
||||||
|
found[login].departureTime = time;
|
||||||
|
}
|
||||||
|
await storage.setData(today, clientData);
|
||||||
|
}
|
||||||
|
return clientData;
|
||||||
}
|
}
|
@ -7,7 +7,8 @@ export enum Restaurants {
|
|||||||
|
|
||||||
export interface FoodChoices {
|
export interface FoodChoices {
|
||||||
trusted: boolean,
|
trusted: boolean,
|
||||||
options: number[]
|
options: number[],
|
||||||
|
departureTime?: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Choices {
|
export interface Choices {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user