v1.3.1: Smart Cache Strategy + REQUIREMENTS.md überarbeitet
- Feature: isCacheFresh() – initialer API-Refresh nur wenn Cache >1h alt oder <5 Arbeitstage abgedeckt (FR-024) - REQUIREMENTS.md komplett überarbeitet: lösungsneutral, alle Features dokumentiert, Versions-Spalte - Build-Script: Git-Tag wird bei Rebuild auf aktuellen Commit verschoben (git tag -f) - Neue Regel 7: Requirements-Konsistenz im Implementation Plan - test_logic.js: statischer Check für isCacheFresh
This commit is contained in:
2
dist/bookmarklet-payload.js
vendored
2
dist/bookmarklet-payload.js
vendored
File diff suppressed because one or more lines are too long
2
dist/bookmarklet.txt
vendored
2
dist/bookmarklet.txt
vendored
File diff suppressed because one or more lines are too long
16
dist/install.html
vendored
16
dist/install.html
vendored
File diff suppressed because one or more lines are too long
48
dist/kantine-standalone.html
vendored
48
dist/kantine-standalone.html
vendored
@@ -1807,7 +1807,7 @@ body {
|
||||
<div class="brand">
|
||||
<span class="material-icons-round logo-icon">restaurant_menu</span>
|
||||
<div class="header-left">
|
||||
<h1>Kantinen Übersicht <small class="version-tag" style="font-size: 0.6em; opacity: 0.7; font-weight: 400; cursor: pointer;" title="Klick für Versionsmenü">v1.3.0</small></h1>
|
||||
<h1>Kantinen Übersicht <small class="version-tag" style="font-size: 0.6em; opacity: 0.7; font-weight: 400; cursor: pointer;" title="Klick für Versionsmenü">v1.3.1</small></h1>
|
||||
<div id="last-updated-subtitle" class="subtitle"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1919,7 +1919,7 @@ body {
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div style="margin-bottom: 1rem;">
|
||||
<strong>Aktuell:</strong> <span id="version-current">v1.3.0</span>
|
||||
<strong>Aktuell:</strong> <span id="version-current">v1.3.1</span>
|
||||
</div>
|
||||
<div class="dev-toggle">
|
||||
<label style="display:flex;align-items:center;gap:8px;cursor:pointer;">
|
||||
@@ -2532,6 +2532,34 @@ body {
|
||||
return false;
|
||||
}
|
||||
|
||||
// FR-024: Check if cache is fresh enough to skip API refresh
|
||||
function isCacheFresh() {
|
||||
const cachedTs = localStorage.getItem(CACHE_TS_KEY);
|
||||
if (!cachedTs) return false;
|
||||
|
||||
// Condition 1: Cache < 1 hour old
|
||||
const ageMs = Date.now() - new Date(cachedTs).getTime();
|
||||
if (ageMs > 60 * 60 * 1000) return false;
|
||||
|
||||
// Condition 2: Data covers next 5 working days
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
const cachedDates = new Set();
|
||||
allWeeks.forEach(w => (w.days || []).forEach(d => cachedDates.add(d.date)));
|
||||
|
||||
let coveredDays = 0;
|
||||
for (let i = 0; i < 7 && coveredDays < 5; i++) {
|
||||
const check = new Date(today);
|
||||
check.setDate(check.getDate() + i);
|
||||
const dow = check.getDay();
|
||||
if (dow === 0 || dow === 6) continue; // Skip weekends
|
||||
const dateStr = check.toISOString().split('T')[0];
|
||||
if (cachedDates.has(dateStr)) coveredDays++;
|
||||
}
|
||||
|
||||
return coveredDays >= 5;
|
||||
}
|
||||
|
||||
// === Menu Data Fetching (Direct from Bessa API) ===
|
||||
async function loadMenuDataFromAPI() {
|
||||
const loading = document.getElementById('loading');
|
||||
@@ -3243,7 +3271,7 @@ body {
|
||||
|
||||
// Periodic update check (runs on init + every hour)
|
||||
async function checkForUpdates() {
|
||||
const currentVersion = 'v1.3.0';
|
||||
const currentVersion = 'v1.3.1';
|
||||
const devMode = localStorage.getItem('kantine_dev_mode') === 'true';
|
||||
|
||||
try {
|
||||
@@ -3284,7 +3312,7 @@ body {
|
||||
const modal = document.getElementById('version-modal');
|
||||
const container = document.getElementById('version-list-container');
|
||||
const devToggle = document.getElementById('dev-mode-toggle');
|
||||
const currentVersion = 'v1.3.0';
|
||||
const currentVersion = 'v1.3.1';
|
||||
|
||||
if (!modal) return;
|
||||
modal.classList.remove('hidden');
|
||||
@@ -3487,13 +3515,19 @@ body {
|
||||
updateAuthUI();
|
||||
cleanupExpiredFlags();
|
||||
|
||||
// Load cached data first for instant UI, then refresh from API
|
||||
// Load cached data first for instant UI, refresh only if stale (FR-024)
|
||||
const hadCache = loadMenuCache();
|
||||
if (hadCache) {
|
||||
// Hide loading spinner since cache is shown
|
||||
document.getElementById('loading').classList.add('hidden');
|
||||
if (!isCacheFresh()) {
|
||||
console.log('Cache stale or incomplete – refreshing from API');
|
||||
loadMenuDataFromAPI();
|
||||
} else {
|
||||
console.log('Cache fresh & complete – skipping API refresh');
|
||||
}
|
||||
} else {
|
||||
loadMenuDataFromAPI();
|
||||
}
|
||||
loadMenuDataFromAPI();
|
||||
|
||||
// Auto-start polling if already logged in
|
||||
if (authToken) {
|
||||
|
||||
Reference in New Issue
Block a user