Compare commits

...

1 Commits

Author SHA1 Message Date
0179afca75
feat: část refaktoru databáze 2025-11-25 13:42:06 +01:00
4 changed files with 27 additions and 32 deletions

View File

@ -15,7 +15,7 @@ import { useSettings } from './context/settings';
import Footer from './components/Footer'; import Footer from './components/Footer';
import { faChainBroken, faChevronLeft, faChevronRight, faGear, faSatelliteDish, faSearch } from '@fortawesome/free-solid-svg-icons'; import { faChainBroken, faChevronLeft, faChevronRight, faGear, faSatelliteDish, faSearch } from '@fortawesome/free-solid-svg-icons';
import Loader from './components/Loader'; import Loader from './components/Loader';
import { getHumanDateTime, isInTheFuture } from './Utils'; import { getDayOfWeekIndex, getHumanDate, getHumanDateTime, getIsWeekend, isInTheFuture } from './Utils';
import NoteModal from './components/modals/NoteModal'; import NoteModal from './components/modals/NoteModal';
import { useEasterEgg } from './context/eggs'; import { useEasterEgg } from './context/eggs';
import { ClientData, Food, PizzaOrder, DepartureTime, PizzaDayState, Restaurant, RestaurantDayMenu, RestaurantDayMenuMap, LunchChoice, UserLunchChoice, PizzaVariant, getData, getEasterEggImage, addPizza, removePizza, updatePizzaDayNote, createPizzaDay, deletePizzaDay, lockPizzaDay, unlockPizzaDay, finishOrder, finishDelivery, addChoice, jdemeObed, removeChoices, removeChoice, updateNote, changeDepartureTime } from '../../types'; import { ClientData, Food, PizzaOrder, DepartureTime, PizzaDayState, Restaurant, RestaurantDayMenu, RestaurantDayMenuMap, LunchChoice, UserLunchChoice, PizzaVariant, getData, getEasterEggImage, addPizza, removePizza, updatePizzaDayNote, createPizzaDay, deletePizzaDay, lockPizzaDay, unlockPizzaDay, finishOrder, finishDelivery, addChoice, jdemeObed, removeChoices, removeChoice, updateNote, changeDepartureTime } from '../../types';
@ -71,7 +71,10 @@ function App() {
const departureChoiceRef = useRef<HTMLSelectElement>(null); const departureChoiceRef = useRef<HTMLSelectElement>(null);
const pizzaPoznamkaRef = useRef<HTMLInputElement>(null); const pizzaPoznamkaRef = useRef<HTMLInputElement>(null);
const [failure, setFailure] = useState<boolean>(false); const [failure, setFailure] = useState<boolean>(false);
const [dayIndex, setDayIndex] = useState<number>(); const [dayIndex, setDayIndex] = useState<number>(); // Index zobrazovaného dne
// TODO berka zde je nutné dořešit mocking pro testování
const [todayDayIndex, setTodayDayIndex] = useState<number>(getDayOfWeekIndex(new Date())); // Index dnešního dne
const [isTodayWeekend, setIsTodayWeekend] = useState<boolean>(getIsWeekend(new Date()));
const [loadingPizzaDay, setLoadingPizzaDay] = useState<boolean>(false); const [loadingPizzaDay, setLoadingPizzaDay] = useState<boolean>(false);
const [noteModalOpen, setNoteModalOpen] = useState<boolean>(false); const [noteModalOpen, setNoteModalOpen] = useState<boolean>(false);
const [eggImage, setEggImage] = useState<Blob>(); const [eggImage, setEggImage] = useState<Blob>();
@ -89,8 +92,9 @@ function App() {
const data = response.data const data = response.data
if (data) { if (data) {
setData(data); setData(data);
setDayIndex(data.dayIndex); const dayIndex = getDayOfWeekIndex(new Date(data.date));
dayIndexRef.current = data.dayIndex; setDayIndex(dayIndex);
dayIndexRef.current = dayIndex;
setFood(data.menus); setFood(data.menus);
} }
}).catch(e => { }).catch(e => {
@ -103,6 +107,8 @@ function App() {
if (!auth?.login) { if (!auth?.login) {
return return
} }
setTodayDayIndex(getDayOfWeekIndex(new Date()));
setIsTodayWeekend(getIsWeekend(new Date()));
getData({ query: { dayIndex: dayIndex } }).then(response => { getData({ query: { dayIndex: dayIndex } }).then(response => {
const data = response.data; const data = response.data;
setData(data); setData(data);
@ -125,7 +131,7 @@ function App() {
socket.on(EVENT_MESSAGE, (newData: ClientData) => { socket.on(EVENT_MESSAGE, (newData: ClientData) => {
// console.log("Přijata nová data ze socketu", newData); // console.log("Přijata nová data ze socketu", newData);
// Aktualizujeme pouze, pokud jsme dostali data pro den, který máme aktuálně zobrazený // Aktualizujeme pouze, pokud jsme dostali data pro den, který máme aktuálně zobrazený
if (dayIndexRef.current == null || newData.dayIndex === dayIndexRef.current) { if (dayIndexRef.current == null || getDayOfWeekIndex(new Date(newData.date)) === dayIndexRef.current) {
setData(newData); setData(newData);
} }
}); });
@ -439,7 +445,7 @@ function App() {
} }
const noOrders = data?.pizzaDay?.orders?.length === 0; const noOrders = data?.pizzaDay?.orders?.length === 0;
const canChangeChoice = dayIndex == null || data.todayDayIndex == null || dayIndex >= data.todayDayIndex; const canChangeChoice = dayIndex == null || dayIndex >= todayDayIndex;
const { path, url, startOffset, endOffset, duration, ...style } = easterEgg || {}; const { path, url, startOffset, endOffset, duration, ...style } = easterEgg || {};
@ -448,7 +454,7 @@ function App() {
{easterEgg && eggImage && <img ref={eggRef} alt='' src={URL.createObjectURL(eggImage)} style={{ position: 'absolute', ...EASTER_EGG_STYLE, ...style, animationDuration: `${duration ?? EASTER_EGG_DEFAULT_DURATION}s` }} />} {easterEgg && eggImage && <img ref={eggRef} alt='' src={URL.createObjectURL(eggImage)} style={{ position: 'absolute', ...EASTER_EGG_STYLE, ...style, animationDuration: `${duration ?? EASTER_EGG_DEFAULT_DURATION}s` }} />}
<Header /> <Header />
<div className='wrapper'> <div className='wrapper'>
{data.isWeekend ? <h4>Užívejte víkend :)</h4> : <> {isTodayWeekend ? <h4>Užívejte víkend :)</h4> : <>
<Alert variant={'primary'}> <Alert variant={'primary'}>
{/* <img alt="" src='hat.png' style={{ position: "absolute", width: "70px", rotate: "-45deg", left: -40, top: -58 }} /> {/* <img alt="" src='hat.png' style={{ position: "absolute", width: "70px", rotate: "-45deg", left: -40, top: -58 }} />
<img alt="" src='snowman.png' style={{ position: "absolute", height: "110px", right: 10, top: 5 }} /> */} <img alt="" src='snowman.png' style={{ position: "absolute", height: "110px", right: 10, top: 5 }} /> */}
@ -464,7 +470,7 @@ function App() {
<span title='Předchozí den'> <span title='Předchozí den'>
<FontAwesomeIcon icon={faChevronLeft} style={{ cursor: "pointer", visibility: dayIndex > 0 ? "initial" : "hidden" }} onClick={() => handleDayChange(dayIndex - 1)} /> <FontAwesomeIcon icon={faChevronLeft} style={{ cursor: "pointer", visibility: dayIndex > 0 ? "initial" : "hidden" }} onClick={() => handleDayChange(dayIndex - 1)} />
</span> </span>
<h1 className='title' style={{ color: dayIndex === data.todayDayIndex ? 'black' : 'gray' }}>{data.date}</h1> <h1 className='title' style={{ color: dayIndex === todayDayIndex ? 'black' : 'gray' }}>{getHumanDate(new Date(data.date))}</h1>
<span title="Následující den"> <span title="Následující den">
<FontAwesomeIcon icon={faChevronRight} style={{ cursor: "pointer", visibility: dayIndex < 4 ? "initial" : "hidden" }} onClick={() => handleDayChange(dayIndex + 1)} /> <FontAwesomeIcon icon={faChevronRight} style={{ cursor: "pointer", visibility: dayIndex < 4 ? "initial" : "hidden" }} onClick={() => handleDayChange(dayIndex + 1)} />
</span> </span>
@ -480,7 +486,7 @@ function App() {
<div className='content-wrapper'> <div className='content-wrapper'>
<div className='content'> <div className='content'>
{canChangeChoice && <> {canChangeChoice && <>
<p>{`Jak to ${dayIndex == null || dayIndex === data.todayDayIndex ? 'dnes' : 'tento den'} vidíš s obědem?`}</p> <p>{`Jak to ${dayIndex == null || dayIndex === todayDayIndex ? 'dnes' : 'tento den'} vidíš s obědem?`}</p>
<Form.Select ref={choiceRef} onChange={doAddChoice}> <Form.Select ref={choiceRef} onChange={doAddChoice}>
<option></option> <option></option>
{Object.entries(LunchChoice) {Object.entries(LunchChoice)
@ -589,7 +595,7 @@ function App() {
: <div className='mt-5'><i>Zatím nikdo nehlasoval...</i></div> : <div className='mt-5'><i>Zatím nikdo nehlasoval...</i></div>
} }
</div> </div>
{dayIndex === data.todayDayIndex && {dayIndex === todayDayIndex &&
<div className='mt-5'> <div className='mt-5'>
{!data.pizzaDay && {!data.pizzaDay &&
<div style={{ textAlign: 'center' }}> <div style={{ textAlign: 'center' }}>

View File

@ -73,6 +73,12 @@ export const getDayOfWeekIndex = (date: Date) => {
return (((date.getDay() - 1) % 7) + 7) % 7; return (((date.getDay() - 1) % 7) + 7) % 7;
} }
/** Vrátí true, pokud je předané datum o víkendu. */
export function getIsWeekend(date: Date) {
const index = getDayOfWeekIndex(date);
return index == 5 || index == 6;
}
/** Vrátí první pracovní den v týdnu předaného data. */ /** Vrátí první pracovní den v týdnu předaného data. */
export function getFirstWorkDayOfWeek(date: Date) { export function getFirstWorkDayOfWeek(date: Date) {
const firstDay = new Date(date.getTime()); const firstDay = new Date(date.getTime());

View File

@ -1,4 +1,4 @@
import { InsufficientPermissions, formatDate, getDayOfWeekIndex, getFirstWorkDayOfWeek, getHumanDate, getIsWeekend, getWeekNumber } from "./utils"; import { InsufficientPermissions, formatDate, getDayOfWeekIndex, getFirstWorkDayOfWeek, getIsWeekend, getWeekNumber } from "./utils";
import getStorage from "./storage"; import getStorage from "./storage";
import { getMenuSladovnicka, getMenuTechTower, getMenuZastavkaUmichala, getMenuSenkSerikova } from "./restaurants"; import { getMenuSladovnicka, getMenuTechTower, getMenuZastavkaUmichala, getMenuSenkSerikova } from "./restaurants";
import { getTodayMock } from "./mock"; import { getTodayMock } from "./mock";
@ -31,10 +31,7 @@ export const getDateForWeekIndex = (index: number) => {
function getEmptyData(date?: Date): ClientData { function getEmptyData(date?: Date): ClientData {
const usedDate = date || getToday(); const usedDate = date || getToday();
return { return {
todayDayIndex: getDayOfWeekIndex(getToday()), date: usedDate.toISOString().split('T')[0],
date: getHumanDate(usedDate),
isWeekend: getIsWeekend(usedDate),
dayIndex: getDayOfWeekIndex(usedDate),
choices: {}, choices: {},
}; };
} }
@ -486,9 +483,5 @@ export async function updateDepartureTime(login: string, time?: string, date?: D
export async function getClientData(date?: Date): Promise<ClientData> { export async function getClientData(date?: Date): Promise<ClientData> {
const targetDate = date ?? getToday(); const targetDate = date ?? getToday();
const dateString = formatDate(targetDate); const dateString = formatDate(targetDate);
const clientData = await storage.getData<ClientData>(dateString) || getEmptyData(date); return await storage.getData<ClientData>(dateString) || getEmptyData(date);
return {
...clientData,
todayDayIndex: getDayOfWeekIndex(getToday()),
}
} }

View File

@ -21,23 +21,13 @@ ClientData:
type: object type: object
additionalProperties: false additionalProperties: false
required: required:
- todayDayIndex
- date - date
- isWeekend
- choices - choices
properties: properties:
todayDayIndex:
description: Index dnešního dne v týdnu
$ref: "#/DayIndex"
date: date:
description: Human-readable datum dne description: Datum konkrétního dne
type: string type: string
isWeekend: format: date
description: Příznak, zda je tento den víkend
type: boolean
dayIndex:
description: Index dne v týdnu, ke kterému se vztahují tato data
$ref: "#/DayIndex"
choices: choices:
$ref: "#/LunchChoices" $ref: "#/LunchChoices"
menus: menus: