- #21: Add missing await in removeChoiceIfPresent() to prevent user appearing in two restaurants - #15: Add 1-hour TTL for menu refetching to avoid scraping on every page load - #9: Block stats API and UI navigation for future dates - #14: Add restaurant warnings (missing soup/prices, stale data) with warning icon - #12: Pre-fill restaurant/departure dropdowns from existing choices on page refresh - #10: Add voting statistics endpoint and table on stats page
This commit is contained in:
@@ -198,7 +198,14 @@ export async function getRestaurantMenu(restaurant: Restaurant, date?: Date, for
|
||||
food: [],
|
||||
};
|
||||
}
|
||||
if (forceRefresh || (!weekMenu[dayOfWeekIndex][restaurant]?.food?.length && !weekMenu[dayOfWeekIndex][restaurant]?.closed)) {
|
||||
const MENU_REFETCH_TTL_MS = 60 * 60 * 1000; // 1 hour
|
||||
const existingMenu = weekMenu[dayOfWeekIndex][restaurant];
|
||||
const lastFetchExpired = !existingMenu?.lastUpdate ||
|
||||
existingMenu.lastUpdate === now || // freshly initialized, never fetched
|
||||
(now - existingMenu.lastUpdate) > MENU_REFETCH_TTL_MS;
|
||||
const shouldFetch = forceRefresh ||
|
||||
(!existingMenu?.food?.length && !existingMenu?.closed && lastFetchExpired);
|
||||
if (shouldFetch) {
|
||||
const firstDay = getFirstWorkDayOfWeek(usedDate);
|
||||
|
||||
try {
|
||||
@@ -240,7 +247,32 @@ export async function getRestaurantMenu(restaurant: Restaurant, date?: Date, for
|
||||
console.error(`Selhalo načtení jídel pro podnik ${restaurant}`, e);
|
||||
}
|
||||
}
|
||||
return weekMenu[dayOfWeekIndex][restaurant]!;
|
||||
const result = weekMenu[dayOfWeekIndex][restaurant]!;
|
||||
result.warnings = generateMenuWarnings(result, now);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generuje varování o kvalitě/úplnosti dat menu restaurace.
|
||||
*/
|
||||
function generateMenuWarnings(menu: RestaurantDayMenu, now: number): string[] {
|
||||
const warnings: string[] = [];
|
||||
if (!menu.food?.length || menu.closed) {
|
||||
return warnings;
|
||||
}
|
||||
const hasSoup = menu.food.some(f => f.isSoup);
|
||||
if (!hasSoup) {
|
||||
warnings.push('Chybí polévka');
|
||||
}
|
||||
const missingPrice = menu.food.some(f => !f.isSoup && (!f.price || f.price.trim() === ''));
|
||||
if (missingPrice) {
|
||||
warnings.push('U některých jídel chybí cena');
|
||||
}
|
||||
const STALE_THRESHOLD_MS = 24 * 60 * 60 * 1000;
|
||||
if (menu.lastUpdate && (now - menu.lastUpdate) > STALE_THRESHOLD_MS) {
|
||||
warnings.push('Data jsou starší než 24 hodin');
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -378,7 +410,7 @@ export async function addChoice(login: string, trusted: boolean, locationKey: Lu
|
||||
data = await removeChoiceIfPresent(login, usedDate);
|
||||
} else {
|
||||
// Mažeme případné ostatní volby (měla by být maximálně jedna)
|
||||
removeChoiceIfPresent(login, usedDate, locationKey);
|
||||
data = await removeChoiceIfPresent(login, usedDate, locationKey);
|
||||
}
|
||||
// TODO vytáhnout inicializaci "prázdné struktury" do vlastní funkce
|
||||
data.choices[locationKey] ??= {};
|
||||
|
||||
Reference in New Issue
Block a user