Compare commits
21 Commits
5f30696315
...
v1.5.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4cf3e4adc2 | ||
|
|
4fe7950697 | ||
|
|
e162a16550 | ||
|
|
b7c3aac921 | ||
|
|
a902732d4b | ||
|
|
eaab21151a | ||
|
|
5af1f86700 | ||
|
|
90b503ddb7 | ||
|
|
10ffbd8c68 | ||
|
|
0294db7976 | ||
|
|
5a2c23524d | ||
|
|
d4a9d39d67 | ||
|
|
3c8d946a1e | ||
|
|
f71bcf1ac7 | ||
|
|
b041e9f318 | ||
|
|
984a897f73 | ||
|
|
ae54d97d96 | ||
|
|
6ed0831f5d | ||
|
|
ba75544f68 | ||
|
|
7fdf7f6f3e | ||
|
|
614f498d11 |
@@ -24,6 +24,24 @@ echo "=== Kantine Bookmarklet Builder ($VERSION) ==="
|
|||||||
# Check files exist
|
# Check files exist
|
||||||
if [ ! -f "$CSS_FILE" ]; then echo "ERROR: $CSS_FILE not found"; exit 1; fi
|
if [ ! -f "$CSS_FILE" ]; then echo "ERROR: $CSS_FILE not found"; exit 1; fi
|
||||||
if [ ! -f "$JS_FILE" ]; then echo "ERROR: $JS_FILE not found"; exit 1; fi
|
if [ ! -f "$JS_FILE" ]; then echo "ERROR: $JS_FILE not found"; exit 1; fi
|
||||||
|
|
||||||
|
# Generate favicon.png from favicon_base.png if base exists
|
||||||
|
FAVICON_BASE="$SCRIPT_DIR/favicon_base.png"
|
||||||
|
if [ -f "$FAVICON_BASE" ]; then
|
||||||
|
echo "Generating 32x32 favicon.png from favicon_base.png..."
|
||||||
|
python3 -c "
|
||||||
|
import sys
|
||||||
|
from PIL import Image
|
||||||
|
try:
|
||||||
|
img = Image.open('$FAVICON_BASE')
|
||||||
|
img_resized = img.resize((32, 32), Image.Resampling.LANCZOS)
|
||||||
|
img_resized.save('$FAVICON_FILE')
|
||||||
|
except Exception as e:
|
||||||
|
print('Favicon generation error:', e)
|
||||||
|
sys.exit(1)
|
||||||
|
"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ ! -f "$FAVICON_FILE" ]; then echo "ERROR: $FAVICON_FILE not found"; exit 1; fi
|
if [ ! -f "$FAVICON_FILE" ]; then echo "ERROR: $FAVICON_FILE not found"; exit 1; fi
|
||||||
|
|
||||||
# Generate favicon Base64 data URI from PNG
|
# Generate favicon Base64 data URI from PNG
|
||||||
@@ -129,7 +147,11 @@ cat > "$DIST_DIR/install.html" << INSTALLEOF
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div style="text-align: center; margin-bottom: 30px;">
|
<div style="text-align: center; margin-bottom: 30px;">
|
||||||
<h1 style="margin-bottom: 5px;">🍽️ Kantine Wrapper <span style="font-size:0.5em; opacity:0.6; font-weight:400; vertical-align:middle; margin-left:10px;">$VERSION</span></h1>
|
<h1 style="margin-bottom: 5px; display: flex; align-items: center; justify-content: center; gap: 10px;">
|
||||||
|
<img src="$FAVICON_URL" alt="Logo" style="width: 38px; height: 38px;">
|
||||||
|
Kantine Wrapper
|
||||||
|
<span style="font-size:0.5em; opacity:0.6; font-weight:400; margin-left:5px;">$VERSION</span>
|
||||||
|
</h1>
|
||||||
<p style="font-size: 1.2rem; color: #a0aec0; margin-top: 0; font-style: italic;">"Mahlzeit! Jetzt bessa einfach."</p>
|
<p style="font-size: 1.2rem; color: #a0aec0; margin-top: 0; font-style: italic;">"Mahlzeit! Jetzt bessa einfach."</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -243,13 +265,16 @@ $CHANGELOG_HTML
|
|||||||
EOF
|
EOF
|
||||||
|
|
||||||
cat >> "$DIST_DIR/install.html" << INSTALLEOF
|
cat >> "$DIST_DIR/install.html" << INSTALLEOF
|
||||||
// Dynamic favicon injection (overrides proxy defaults like htmlpreview.github.io)
|
// Dynamic favicon injection — setTimeout ensures it runs AFTER
|
||||||
|
// htmlpreview.github.io's document.write() processing completes
|
||||||
|
setTimeout(function() {
|
||||||
document.querySelectorAll('link[rel*="icon"]').forEach(function(el) { el.remove(); });
|
document.querySelectorAll('link[rel*="icon"]').forEach(function(el) { el.remove(); });
|
||||||
var fi = document.createElement('link');
|
var fi = document.createElement('link');
|
||||||
fi.rel = 'icon';
|
fi.rel = 'icon';
|
||||||
fi.type = 'image/png';
|
fi.type = 'image/png';
|
||||||
fi.href = '$FAVICON_URL';
|
fi.href = '$FAVICON_URL';
|
||||||
document.head.appendChild(fi);
|
document.head.appendChild(fi);
|
||||||
|
}, 0);
|
||||||
document.getElementById('bookmarklet-link').textContent = 'Kantine $VERSION';
|
document.getElementById('bookmarklet-link').textContent = 'Kantine $VERSION';
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
97
changelog.md
97
changelog.md
@@ -1,91 +1,16 @@
|
|||||||
## v1.4.28
|
## v1.5.0 (2026-02-26)
|
||||||
- 🎨 **Favicon**: Eigenes Favicon-Design aus `favicon_base.png` (2048x2048) auf 32x32 skaliert. Wird beim Build automatisch als PNG-Data-URI in Bookmarklet und Installer injiziert.
|
Das große "Quality of Life"-Update! Zusammenfassung aller Features und Fixes seit v1.4.0:
|
||||||
|
|
||||||
## v1.4.27
|
- ✨ **Bestellhistorie**: Übersichtliche Historie direkt in der App – gruppiert nach Jahr/Monat, inklusive Summen, Stati (Offen/Abgeschlossen/Storniert) und Delta-Cache für rasantes Laden.
|
||||||
- 🔧 **Build**: Favicon wird jetzt sauber aus `favicon.png` per Build-Script als PNG-Base64-Data-URI generiert und über `{{FAVICON_DATA_URI}}` Platzhalter in `kantine.js` + `install.html` injiziert. Funktioniert auf allen Browsern und Proxy-Diensten.
|
- ⚡ **Smart Cache & Performance**: Massive Reduzierung von API-Calls und Ladezeiten durch intelligenten lokalen Cache. Das Bookmarklet startet nun praktisch verzögerungsfrei.
|
||||||
|
- 🔄 **GitHub Release Management**: In-App Versions-Menü mit Auto-Update Check (`🆕` Icon). Umschalten zwischen "Stable" und "Dev" Versionen sowie Downgrade-Möglichkeit direkt über die GitHub API.
|
||||||
|
- 🌟 **Smart Highlights & UX**: Speisen-Favoriten leuchten nun im Design-Violett und erhalten Feature-Badges. Der Bestell-Badge für nächste Woche filtert nun intelligent personalisierte Highlights voraus.
|
||||||
|
- 🔔 **Bestell-Warnung & Notifications**: Der System-Alarm berücksichtigt nun Sessions korrekt, zeigt dynamische Farbwechsel (gelb/grün/rot) und warnt verlässlich vor dem Bestellschluss (10:00 Uhr). Altlasten von Vortagen werden automatisch geputzt.
|
||||||
|
- 🎨 **Eigenes Favicon**: Das Bookmarklet und der Installer haben nun ein eigenes Icon (Dreieck mit Besteck), das beim Hineinziehen in die Lesezeichenleiste übernommen wird (dynamisch generiert als lokales PNG).
|
||||||
|
- 🧹 **Lokaler Cache-Clear**: Ein in das Versions-Menü eingebauter "Papierkorb", der ausschließlich fehlerhafte Kantinen-Caches putzt, ohne dabei versehentlich die aktive Bessa-Host-Session zu zerstören.
|
||||||
|
- 🔒 **Sitzungs-Persistenz**: Die Login-Session überdauert jetzt neue Tabs, Fenster und Version-Upgrades reibungslos durch den Wechsel auf `localStorage`.
|
||||||
|
- 🛡️ **Testing & Stabilität**: Vollautomatische DOM- und Logik-Testing-Suites in der Release-Pipeline integriert. Fehlerhafte UI-Buttons gehören der Vergangenheit an.
|
||||||
|
|
||||||
## v1.4.26
|
|
||||||
- 🎨 **Favicon**: Von SVG-Base64 auf PNG-Datei (`favicon.png`) umgestellt, verlinkt via raw.githubusercontent.com. Funktioniert zuverlässig auf allen Browsern und Proxy-Diensten (htmlpreview.github.io).
|
|
||||||
|
|
||||||
## v1.4.25
|
|
||||||
- 🐛 **Bugfix**: Favicon wird in `install.html` jetzt zusätzlich per JavaScript injiziert, um Proxy-Dienste wie htmlpreview.github.io zu überschreiben. Release-Script pusht nun auch `main` Branch zu GitHub.
|
|
||||||
|
|
||||||
## v1.4.24
|
|
||||||
- 🐛 **Bugfix**: Favicon-Encoding korrigiert – `encodeURIComponent` verursachte doppeltes Encoding der Farbcodes (`%23` → `%2523`). Auf Base64 umgestellt, funktioniert nun auch unter Chrome/Windows.
|
|
||||||
|
|
||||||
## v1.4.23
|
|
||||||
- 🐛 **Bugfix**: Favicon wird jetzt beim Ausführen des Bookmarklets in die Seite injiziert (ersetzt das Bessa-Favicon im Tab). Chrome cached das Icon und übernimmt es anschließend auch in die Lesezeichenleiste.
|
|
||||||
|
|
||||||
## v1.4.22
|
|
||||||
- 📝 **Docs**: Vollständiger Dokumentations-Audit: README.md um fehlende Dateien (favicon.svg, release.sh, Tests) und Features (Bestellhistorie, Version-Menü, Cache leeren, Favicon) ergänzt. REQUIREMENTS.md: Doppelte IDs (FR-090/091) behoben, FR-092 an dynamische Glow-Logik angepasst, FR-116 (Cache leeren) und FR-117 (Favicon) hinzugefügt, NFR-008 um DOM-Tests erweitert.
|
|
||||||
|
|
||||||
## v1.4.21
|
|
||||||
- ✨ **UX**: Der Glow-Effekt des „Nächste Woche"-Buttons bleibt nun aktiv, solange Menüdaten vorhanden aber noch keine Bestellungen getätigt wurden. Verschwindet automatisch nach der ersten Bestellung.
|
|
||||||
|
|
||||||
## v1.4.20
|
|
||||||
- 🐛 **Bugfix**: Der Badge-Counter im „Nächste Woche"-Tab wird jetzt sofort nach einer Bestellung oder Stornierung aktualisiert.
|
|
||||||
|
|
||||||
## v1.4.19
|
|
||||||
- 🎨 **Feature**: Eigenes Favicon für die Installer-Seite hinzugefügt (Dreieck + Gabel & Messer). Wird beim Drag & Drop in die Lesezeichenleiste als Icon übernommen.
|
|
||||||
|
|
||||||
## v1.4.18
|
|
||||||
- 🧪 **Testing**: Die automatische DOM-Testing Suite (`test_dom.js`) wurde massiv ausgebaut. Sie prüft nun neben der Alarmglocke und den Highlights auch systematisch alle anderen UI-Komponenten (Login-Modal, History-Modal, Versionen-Modal, Theme-Toggle, und Navigation Tabs) auf korrekte Event-Listener-Bindungen, um Regressionen (tote Buttons) endgültig auszuschließen.
|
|
||||||
|
|
||||||
## v1.4.17
|
|
||||||
- 🐛 **Bugfix**: Regression behoben: Der "Persönliche Highlights" (Stern-Button) Dialog öffnet sich nun wieder korrekt.
|
|
||||||
- 🧪 **Testing**: Es wurde ein initialer UI-Testing-Hook (`test_dom.js` mit `jsdom`) in die Build-Pipeline integriert, um kritische DOM Event-Listener Regressionen (wie den Highlights-Button und die Alarmglocke) automatisch zu preventen.
|
|
||||||
|
|
||||||
## v1.4.16
|
|
||||||
- ⚡ **Feature**: Ein Button "Lokalen Cache leeren" wurde zum Versionen-Menü hinzugefügt, um bei hartnäckigen lokalen Fehlern alle Caches und Sessions bereinigen zu können, ohne die Entwicklertools (F12) des Browsers bemühen zu müssen.
|
|
||||||
|
|
||||||
## v1.4.15
|
|
||||||
- 🧹 **Bugfix**: In der Vergangenheit gesetzte Alarme/Flags wurden nicht zuverlässig gelöscht. Dies ist nun behoben, sodass verfallene Menüs nach 10:00 Uhr bzw. an vergangenen Tagen automatisch aus dem Tracker verschwinden.
|
|
||||||
|
|
||||||
## v1.4.14
|
|
||||||
- 🐛 **Bugfix**: Alarmglocke versteckt sich jetzt zuverlässig auch auf Endgeräten mit CSS Konflikten
|
|
||||||
- 🚀 **Feature**: Sofortige API-Aktualisierung (Refresh) bei Aktivierung eines Menüalarms
|
|
||||||
- ⚡ **Optimierung**: "Unbekannt" im letzten Refresh-Zeitpunkt wird abgefangen und zeigt initial "gerade eben"
|
|
||||||
|
|
||||||
## v1.4.13 (2026-02-24)
|
|
||||||
- **Fix**: Die Farben der Glocke funktionieren nun verlässlich, da CSS-Variablen durch direkte Hex-Codes ersetzt wurden.
|
|
||||||
|
|
||||||
## v1.4.12 (2026-02-24)
|
|
||||||
- **Fix**: Das Glocken-Icon sollte nun endgültig versteckt bleiben, wenn keine Benachrichtigungen aktiv sind (CSS-Kollision mit `.hidden` behoben).
|
|
||||||
|
|
||||||
## v1.4.11 (2026-02-24)
|
|
||||||
- **Feature**: Das Versionsmenü prüft nun im Hintergrund direkt beim Öffnen nach neuen Versionen und aktualisiert die Liste automatisch, selbst wenn eine veraltete Liste noch im Cache liegt.
|
|
||||||
|
|
||||||
## v1.4.10 (2026-02-24)
|
|
||||||
- **Fix**: Die Farben der Benachrichtigungs-Glocke wurden korrigiert: Sie ist nun gelb, während man auf ein Menü wartet, und wird grün, sobald eines verfügbar ist.
|
|
||||||
|
|
||||||
## v1.4.9 (2026-02-24)
|
|
||||||
- **Fix**: Das Glocken-Icon für Benachrichtigungen wird nun direkt beim Start (wenn Daten aus dem lokalen Cache geladen werden) korrekt angezeigt.
|
|
||||||
|
|
||||||
## v1.4.8 (2026-02-24)
|
|
||||||
- **Fix**: Die Benachrichtigungs-Glocke wird nun korrekt in Gelb dargestellt, wenn beobachtete Menüs verfügbar sind.
|
|
||||||
- **Tools**: Fehler in Testskript behoben, der den CI/CD Build verlangsamt hat.
|
|
||||||
|
|
||||||
## v1.4.7 (2026-02-24)
|
|
||||||
- **Performance**: Die Bestellhistorie nutzt nun einen inkrementellen Delta-Cache anstatt immer alle Seiten von der API herunterzuladen, was die Ladezeiten für Vielbesteller enorm reduziert.
|
|
||||||
|
|
||||||
## v1.4.6 (2026-02-24)
|
|
||||||
- **Fix**: Die Umrandung für bereits bestellte Menüs der vergangenen Tage ist nun ebenfalls einheitlich violett statt blau.
|
|
||||||
|
|
||||||
## v1.4.5 (2026-02-24)
|
|
||||||
- **Fix**: Doppelten Scrollbalken in der Versionen-Liste entfernt.
|
|
||||||
|
|
||||||
## v1.4.4 (2026-02-24)
|
|
||||||
- **Feature**: Das Versionsmenü enthält nun direkte Links zu GitHub, um Fehler zu melden oder neue Features vorzuschlagen.
|
|
||||||
|
|
||||||
## v1.4.3 (2026-02-24)
|
|
||||||
- **Fix**: Der Rahmen des "Heute Bestellt" Menüs ist nun konsequent violett (passend zum Glow-Effekt).
|
|
||||||
|
|
||||||
## v1.4.2 (2026-02-23)
|
|
||||||
- **Fix**: Das "Heute Bestellt" Menü leuchtet nun stimmig im Design-Violett statt Blau.
|
|
||||||
- **Fix**: Abfangen des GitHub API Rate Limit (403) im Versionsdialog mit einer freundlicheren Fehlermeldung, da der User-Agent im Browser nicht manuell gesetzt werden darf.
|
|
||||||
|
|
||||||
## v1.4.1 (2026-02-22)
|
|
||||||
- **UX Verbesserungen**: Bestellhistorie gruppiert nach Jahren und Monaten mittels einklappbarem Akkordeon. Monatssummen integriert und Stati farblich abgehoben (Offen, Abgeschlossen, Storniert).
|
|
||||||
|
|
||||||
## v1.4.0 (2026-02-22)
|
## v1.4.0 (2026-02-22)
|
||||||
- **Feature**: Bestellhistorie per Knopfdruck abrufbar. Übersichtliche Darstellung, gruppiert nach Monaten und Kalenderwochen, inklusive Stornos. 📜✨
|
- **Feature**: Bestellhistorie per Knopfdruck abrufbar. Übersichtliche Darstellung, gruppiert nach Monaten und Kalenderwochen, inklusive Stornos. 📜✨
|
||||||
|
|||||||
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
152
dist/install.html
vendored
152
dist/install.html
vendored
File diff suppressed because one or more lines are too long
62
dist/kantine-standalone.html
vendored
62
dist/kantine-standalone.html
vendored
@@ -1979,8 +1979,8 @@ body {
|
|||||||
let currentWeekNumber = getISOWeek(new Date());
|
let currentWeekNumber = getISOWeek(new Date());
|
||||||
let currentYear = new Date().getFullYear();
|
let currentYear = new Date().getFullYear();
|
||||||
let displayMode = 'this-week';
|
let displayMode = 'this-week';
|
||||||
let authToken = sessionStorage.getItem('kantine_authToken');
|
let authToken = localStorage.getItem('kantine_authToken');
|
||||||
let currentUser = sessionStorage.getItem('kantine_currentUser');
|
let currentUser = localStorage.getItem('kantine_currentUser');
|
||||||
let orderMap = new Map();
|
let orderMap = new Map();
|
||||||
let userFlags = new Set(JSON.parse(localStorage.getItem('kantine_flags') || '[]'));
|
let userFlags = new Set(JSON.parse(localStorage.getItem('kantine_flags') || '[]'));
|
||||||
let pollIntervalId = null;
|
let pollIntervalId = null;
|
||||||
@@ -2007,7 +2007,7 @@ body {
|
|||||||
const favicon = document.createElement('link');
|
const favicon = document.createElement('link');
|
||||||
favicon.rel = 'icon';
|
favicon.rel = 'icon';
|
||||||
favicon.type = 'image/png';
|
favicon.type = 'image/png';
|
||||||
favicon.href = 'data:image/png;base64,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';
|
favicon.href = 'data:image/png;base64,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';
|
||||||
document.head.appendChild(favicon);
|
document.head.appendChild(favicon);
|
||||||
|
|
||||||
// Inject Google Fonts if not already present
|
// Inject Google Fonts if not already present
|
||||||
@@ -2031,7 +2031,7 @@ body {
|
|||||||
<div class="brand">
|
<div class="brand">
|
||||||
<span class="material-icons-round logo-icon">restaurant_menu</span>
|
<span class="material-icons-round logo-icon">restaurant_menu</span>
|
||||||
<div class="header-left">
|
<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.4.28</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.5.0</small></h1>
|
||||||
<div id="last-updated-subtitle" class="subtitle"></div>
|
<div id="last-updated-subtitle" class="subtitle"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-group" style="margin-left: 1rem;">
|
<div class="nav-group" style="margin-left: 1rem;">
|
||||||
@@ -2173,7 +2173,7 @@ body {
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div style="margin-bottom: 1rem;">
|
<div style="margin-bottom: 1rem;">
|
||||||
<strong>Aktuell:</strong> <span id="version-current">v1.4.28</span>
|
<strong>Aktuell:</strong> <span id="version-current">v1.5.0</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="dev-toggle">
|
<div class="dev-toggle">
|
||||||
<label style="display:flex;align-items:center;gap:8px;cursor:pointer;">
|
<label style="display:flex;align-items:center;gap:8px;cursor:pointer;">
|
||||||
@@ -2294,8 +2294,12 @@ body {
|
|||||||
if (btnClearCache) {
|
if (btnClearCache) {
|
||||||
btnClearCache.addEventListener('click', () => {
|
btnClearCache.addEventListener('click', () => {
|
||||||
if (confirm('Möchtest du wirklich alle lokalen Daten (inkl. Login-Session, Cache und Einstellungen) löschen? Die Seite wird danach neu geladen.')) {
|
if (confirm('Möchtest du wirklich alle lokalen Daten (inkl. Login-Session, Cache und Einstellungen) löschen? Die Seite wird danach neu geladen.')) {
|
||||||
localStorage.clear();
|
// Only clear our own keys so we don't destroy the host app's (Bessa's) session
|
||||||
sessionStorage.clear();
|
Object.keys(localStorage).forEach(key => {
|
||||||
|
if (key.startsWith('kantine_')) {
|
||||||
|
localStorage.removeItem(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -2409,8 +2413,8 @@ body {
|
|||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
authToken = data.key;
|
authToken = data.key;
|
||||||
currentUser = employeeId;
|
currentUser = employeeId;
|
||||||
sessionStorage.setItem('kantine_authToken', data.key);
|
localStorage.setItem('kantine_authToken', data.key);
|
||||||
sessionStorage.setItem('kantine_currentUser', employeeId);
|
localStorage.setItem('kantine_currentUser', employeeId);
|
||||||
|
|
||||||
// Fetch user name
|
// Fetch user name
|
||||||
try {
|
try {
|
||||||
@@ -2419,8 +2423,8 @@ body {
|
|||||||
});
|
});
|
||||||
if (userResp.ok) {
|
if (userResp.ok) {
|
||||||
const userData = await userResp.json();
|
const userData = await userResp.json();
|
||||||
if (userData.first_name) sessionStorage.setItem('kantine_firstName', userData.first_name);
|
if (userData.first_name) localStorage.setItem('kantine_firstName', userData.first_name);
|
||||||
if (userData.last_name) sessionStorage.setItem('kantine_lastName', userData.last_name);
|
if (userData.last_name) localStorage.setItem('kantine_lastName', userData.last_name);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to fetch user info:', err);
|
console.error('Failed to fetch user info:', err);
|
||||||
@@ -2450,10 +2454,10 @@ body {
|
|||||||
|
|
||||||
// Logout
|
// Logout
|
||||||
btnLogout.addEventListener('click', () => {
|
btnLogout.addEventListener('click', () => {
|
||||||
sessionStorage.removeItem('kantine_authToken');
|
localStorage.removeItem('kantine_authToken');
|
||||||
sessionStorage.removeItem('kantine_currentUser');
|
localStorage.removeItem('kantine_currentUser');
|
||||||
sessionStorage.removeItem('kantine_firstName');
|
localStorage.removeItem('kantine_firstName');
|
||||||
sessionStorage.removeItem('kantine_lastName');
|
localStorage.removeItem('kantine_lastName');
|
||||||
authToken = null;
|
authToken = null;
|
||||||
currentUser = null;
|
currentUser = null;
|
||||||
orderMap = new Map();
|
orderMap = new Map();
|
||||||
@@ -2474,13 +2478,13 @@ body {
|
|||||||
if (parsed.auth && parsed.auth.token) {
|
if (parsed.auth && parsed.auth.token) {
|
||||||
console.log('Found existing Bessa session!');
|
console.log('Found existing Bessa session!');
|
||||||
authToken = parsed.auth.token;
|
authToken = parsed.auth.token;
|
||||||
sessionStorage.setItem('kantine_authToken', authToken);
|
localStorage.setItem('kantine_authToken', authToken);
|
||||||
|
|
||||||
if (parsed.auth.user) {
|
if (parsed.auth.user) {
|
||||||
currentUser = parsed.auth.user.id || 'unknown';
|
currentUser = parsed.auth.user.id || 'unknown';
|
||||||
sessionStorage.setItem('kantine_currentUser', currentUser);
|
localStorage.setItem('kantine_currentUser', currentUser);
|
||||||
if (parsed.auth.user.firstName) sessionStorage.setItem('kantine_firstName', parsed.auth.user.firstName);
|
if (parsed.auth.user.firstName) localStorage.setItem('kantine_firstName', parsed.auth.user.firstName);
|
||||||
if (parsed.auth.user.lastName) sessionStorage.setItem('kantine_lastName', parsed.auth.user.lastName);
|
if (parsed.auth.user.lastName) localStorage.setItem('kantine_lastName', parsed.auth.user.lastName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2489,9 +2493,9 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
authToken = sessionStorage.getItem('kantine_authToken');
|
authToken = localStorage.getItem('kantine_authToken');
|
||||||
currentUser = sessionStorage.getItem('kantine_currentUser');
|
currentUser = localStorage.getItem('kantine_currentUser');
|
||||||
const firstName = sessionStorage.getItem('kantine_firstName');
|
const firstName = localStorage.getItem('kantine_firstName');
|
||||||
const btnLoginOpen = document.getElementById('btn-login-open');
|
const btnLoginOpen = document.getElementById('btn-login-open');
|
||||||
const userInfo = document.getElementById('user-info');
|
const userInfo = document.getElementById('user-info');
|
||||||
const userIdDisplay = document.getElementById('user-id-display');
|
const userIdDisplay = document.getElementById('user-id-display');
|
||||||
@@ -4026,7 +4030,7 @@ body {
|
|||||||
|
|
||||||
// Periodic update check (runs on init + every hour)
|
// Periodic update check (runs on init + every hour)
|
||||||
async function checkForUpdates() {
|
async function checkForUpdates() {
|
||||||
const currentVersion = 'v1.4.28';
|
const currentVersion = 'v1.5.0';
|
||||||
const devMode = localStorage.getItem('kantine_dev_mode') === 'true';
|
const devMode = localStorage.getItem('kantine_dev_mode') === 'true';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -4067,7 +4071,7 @@ body {
|
|||||||
const modal = document.getElementById('version-modal');
|
const modal = document.getElementById('version-modal');
|
||||||
const container = document.getElementById('version-list-container');
|
const container = document.getElementById('version-list-container');
|
||||||
const devToggle = document.getElementById('dev-mode-toggle');
|
const devToggle = document.getElementById('dev-mode-toggle');
|
||||||
const currentVersion = 'v1.4.28';
|
const currentVersion = 'v1.5.0';
|
||||||
|
|
||||||
if (!modal) return;
|
if (!modal) return;
|
||||||
modal.classList.remove('hidden');
|
modal.classList.remove('hidden');
|
||||||
@@ -4164,6 +4168,12 @@ body {
|
|||||||
|
|
||||||
// === Order Countdown ===
|
// === Order Countdown ===
|
||||||
function updateCountdown() {
|
function updateCountdown() {
|
||||||
|
// Only show order alarms for logged-in users
|
||||||
|
if (!authToken || !currentUser) {
|
||||||
|
removeCountdown();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const currentDay = now.getDay();
|
const currentDay = now.getDay();
|
||||||
// Skip weekends (0=Sun, 6=Sat)
|
// Skip weekends (0=Sun, 6=Sat)
|
||||||
@@ -4228,7 +4238,7 @@ body {
|
|||||||
|
|
||||||
// Notification logic (One time)
|
// Notification logic (One time)
|
||||||
const notifiedKey = `kantine_notified_${todayStr}`;
|
const notifiedKey = `kantine_notified_${todayStr}`;
|
||||||
if (!sessionStorage.getItem(notifiedKey)) {
|
if (!localStorage.getItem(notifiedKey)) {
|
||||||
if (Notification.permission === 'granted') {
|
if (Notification.permission === 'granted') {
|
||||||
new Notification('Kantine: Bestellschluss naht!', {
|
new Notification('Kantine: Bestellschluss naht!', {
|
||||||
body: 'Du hast heute noch nichts bestellt. Nur noch 1 Stunde!',
|
body: 'Du hast heute noch nichts bestellt. Nur noch 1 Stunde!',
|
||||||
@@ -4237,7 +4247,7 @@ body {
|
|||||||
} else if (Notification.permission === 'default') {
|
} else if (Notification.permission === 'default') {
|
||||||
Notification.requestPermission();
|
Notification.requestPermission();
|
||||||
}
|
}
|
||||||
sessionStorage.setItem(notifiedKey, 'true');
|
localStorage.setItem(notifiedKey, 'true');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
countdownEl.classList.remove('urgent');
|
countdownEl.classList.remove('urgent');
|
||||||
|
|||||||
BIN
favicon.png
BIN
favicon.png
Binary file not shown.
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.6 KiB |
BIN
favicon_base.png
BIN
favicon_base.png
Binary file not shown.
|
Before Width: | Height: | Size: 5.5 MiB After Width: | Height: | Size: 2.0 MiB |
52
kantine.js
52
kantine.js
@@ -29,8 +29,8 @@
|
|||||||
let currentWeekNumber = getISOWeek(new Date());
|
let currentWeekNumber = getISOWeek(new Date());
|
||||||
let currentYear = new Date().getFullYear();
|
let currentYear = new Date().getFullYear();
|
||||||
let displayMode = 'this-week';
|
let displayMode = 'this-week';
|
||||||
let authToken = sessionStorage.getItem('kantine_authToken');
|
let authToken = localStorage.getItem('kantine_authToken');
|
||||||
let currentUser = sessionStorage.getItem('kantine_currentUser');
|
let currentUser = localStorage.getItem('kantine_currentUser');
|
||||||
let orderMap = new Map();
|
let orderMap = new Map();
|
||||||
let userFlags = new Set(JSON.parse(localStorage.getItem('kantine_flags') || '[]'));
|
let userFlags = new Set(JSON.parse(localStorage.getItem('kantine_flags') || '[]'));
|
||||||
let pollIntervalId = null;
|
let pollIntervalId = null;
|
||||||
@@ -344,8 +344,12 @@
|
|||||||
if (btnClearCache) {
|
if (btnClearCache) {
|
||||||
btnClearCache.addEventListener('click', () => {
|
btnClearCache.addEventListener('click', () => {
|
||||||
if (confirm('Möchtest du wirklich alle lokalen Daten (inkl. Login-Session, Cache und Einstellungen) löschen? Die Seite wird danach neu geladen.')) {
|
if (confirm('Möchtest du wirklich alle lokalen Daten (inkl. Login-Session, Cache und Einstellungen) löschen? Die Seite wird danach neu geladen.')) {
|
||||||
localStorage.clear();
|
// Only clear our own keys so we don't destroy the host app's (Bessa's) session
|
||||||
sessionStorage.clear();
|
Object.keys(localStorage).forEach(key => {
|
||||||
|
if (key.startsWith('kantine_')) {
|
||||||
|
localStorage.removeItem(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -459,8 +463,8 @@
|
|||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
authToken = data.key;
|
authToken = data.key;
|
||||||
currentUser = employeeId;
|
currentUser = employeeId;
|
||||||
sessionStorage.setItem('kantine_authToken', data.key);
|
localStorage.setItem('kantine_authToken', data.key);
|
||||||
sessionStorage.setItem('kantine_currentUser', employeeId);
|
localStorage.setItem('kantine_currentUser', employeeId);
|
||||||
|
|
||||||
// Fetch user name
|
// Fetch user name
|
||||||
try {
|
try {
|
||||||
@@ -469,8 +473,8 @@
|
|||||||
});
|
});
|
||||||
if (userResp.ok) {
|
if (userResp.ok) {
|
||||||
const userData = await userResp.json();
|
const userData = await userResp.json();
|
||||||
if (userData.first_name) sessionStorage.setItem('kantine_firstName', userData.first_name);
|
if (userData.first_name) localStorage.setItem('kantine_firstName', userData.first_name);
|
||||||
if (userData.last_name) sessionStorage.setItem('kantine_lastName', userData.last_name);
|
if (userData.last_name) localStorage.setItem('kantine_lastName', userData.last_name);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to fetch user info:', err);
|
console.error('Failed to fetch user info:', err);
|
||||||
@@ -500,10 +504,10 @@
|
|||||||
|
|
||||||
// Logout
|
// Logout
|
||||||
btnLogout.addEventListener('click', () => {
|
btnLogout.addEventListener('click', () => {
|
||||||
sessionStorage.removeItem('kantine_authToken');
|
localStorage.removeItem('kantine_authToken');
|
||||||
sessionStorage.removeItem('kantine_currentUser');
|
localStorage.removeItem('kantine_currentUser');
|
||||||
sessionStorage.removeItem('kantine_firstName');
|
localStorage.removeItem('kantine_firstName');
|
||||||
sessionStorage.removeItem('kantine_lastName');
|
localStorage.removeItem('kantine_lastName');
|
||||||
authToken = null;
|
authToken = null;
|
||||||
currentUser = null;
|
currentUser = null;
|
||||||
orderMap = new Map();
|
orderMap = new Map();
|
||||||
@@ -524,13 +528,13 @@
|
|||||||
if (parsed.auth && parsed.auth.token) {
|
if (parsed.auth && parsed.auth.token) {
|
||||||
console.log('Found existing Bessa session!');
|
console.log('Found existing Bessa session!');
|
||||||
authToken = parsed.auth.token;
|
authToken = parsed.auth.token;
|
||||||
sessionStorage.setItem('kantine_authToken', authToken);
|
localStorage.setItem('kantine_authToken', authToken);
|
||||||
|
|
||||||
if (parsed.auth.user) {
|
if (parsed.auth.user) {
|
||||||
currentUser = parsed.auth.user.id || 'unknown';
|
currentUser = parsed.auth.user.id || 'unknown';
|
||||||
sessionStorage.setItem('kantine_currentUser', currentUser);
|
localStorage.setItem('kantine_currentUser', currentUser);
|
||||||
if (parsed.auth.user.firstName) sessionStorage.setItem('kantine_firstName', parsed.auth.user.firstName);
|
if (parsed.auth.user.firstName) localStorage.setItem('kantine_firstName', parsed.auth.user.firstName);
|
||||||
if (parsed.auth.user.lastName) sessionStorage.setItem('kantine_lastName', parsed.auth.user.lastName);
|
if (parsed.auth.user.lastName) localStorage.setItem('kantine_lastName', parsed.auth.user.lastName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -539,9 +543,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
authToken = sessionStorage.getItem('kantine_authToken');
|
authToken = localStorage.getItem('kantine_authToken');
|
||||||
currentUser = sessionStorage.getItem('kantine_currentUser');
|
currentUser = localStorage.getItem('kantine_currentUser');
|
||||||
const firstName = sessionStorage.getItem('kantine_firstName');
|
const firstName = localStorage.getItem('kantine_firstName');
|
||||||
const btnLoginOpen = document.getElementById('btn-login-open');
|
const btnLoginOpen = document.getElementById('btn-login-open');
|
||||||
const userInfo = document.getElementById('user-info');
|
const userInfo = document.getElementById('user-info');
|
||||||
const userIdDisplay = document.getElementById('user-id-display');
|
const userIdDisplay = document.getElementById('user-id-display');
|
||||||
@@ -2214,6 +2218,12 @@
|
|||||||
|
|
||||||
// === Order Countdown ===
|
// === Order Countdown ===
|
||||||
function updateCountdown() {
|
function updateCountdown() {
|
||||||
|
// Only show order alarms for logged-in users
|
||||||
|
if (!authToken || !currentUser) {
|
||||||
|
removeCountdown();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const currentDay = now.getDay();
|
const currentDay = now.getDay();
|
||||||
// Skip weekends (0=Sun, 6=Sat)
|
// Skip weekends (0=Sun, 6=Sat)
|
||||||
@@ -2278,7 +2288,7 @@
|
|||||||
|
|
||||||
// Notification logic (One time)
|
// Notification logic (One time)
|
||||||
const notifiedKey = `kantine_notified_${todayStr}`;
|
const notifiedKey = `kantine_notified_${todayStr}`;
|
||||||
if (!sessionStorage.getItem(notifiedKey)) {
|
if (!localStorage.getItem(notifiedKey)) {
|
||||||
if (Notification.permission === 'granted') {
|
if (Notification.permission === 'granted') {
|
||||||
new Notification('Kantine: Bestellschluss naht!', {
|
new Notification('Kantine: Bestellschluss naht!', {
|
||||||
body: 'Du hast heute noch nichts bestellt. Nur noch 1 Stunde!',
|
body: 'Du hast heute noch nichts bestellt. Nur noch 1 Stunde!',
|
||||||
@@ -2287,7 +2297,7 @@
|
|||||||
} else if (Notification.permission === 'default') {
|
} else if (Notification.permission === 'default') {
|
||||||
Notification.requestPermission();
|
Notification.requestPermission();
|
||||||
}
|
}
|
||||||
sessionStorage.setItem(notifiedKey, 'true');
|
localStorage.setItem(notifiedKey, 'true');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
countdownEl.classList.remove('urgent');
|
countdownEl.classList.remove('urgent');
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
v1.4.28
|
v1.5.0
|
||||||
|
|||||||
Reference in New Issue
Block a user