Compare commits
8 Commits
v1.4.18
...
6b1bd46210
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b1bd46210 | ||
|
|
a429148324 | ||
|
|
5caaf7dcad | ||
|
|
122c1078cf | ||
|
|
ff48befb8a | ||
|
|
9391dfd8d7 | ||
|
|
467e48e1da | ||
|
|
566410eea5 |
51
README.md
51
README.md
@@ -8,9 +8,14 @@ Ein intelligentes Bookmarklet für die Mitarbeiter-Kantine der Bessa App. Dieses
|
|||||||
* **Bestell-Countdown:** ⏳ Roter Alarm 1h vor Bestellschluss.
|
* **Bestell-Countdown:** ⏳ Roter Alarm 1h vor Bestellschluss.
|
||||||
* **Smart Highlights:** 🌟 Markiere deine Favoriten (z.B. "Schnitzel", "Vegetarisch").
|
* **Smart Highlights:** 🌟 Markiere deine Favoriten (z.B. "Schnitzel", "Vegetarisch").
|
||||||
* **Bestellstatus:** Farbige Indikatoren für bestellte Menüs.
|
* **Bestellstatus:** Farbige Indikatoren für bestellte Menüs.
|
||||||
* **Kostenkontrolle:** Summiert automatisch den Gesamtpreis der Woche.
|
* **Kostenkontrolle:** 💰 Summiert automatisch den Gesamtpreis der Woche.
|
||||||
* **Session Reuse:** Nutzt automatisch eine bestehende Login-Session (Loggt dich automatisch ein).
|
* **Bestellhistorie:** 📜 Gruppiert nach Monat & KW mit inkrementellem Delta-Cache.
|
||||||
* **Menu Badges:** Zeigt Menü-Codes (M1, M2+) direkt im Header.
|
* **Session Reuse:** 🔑 Nutzt automatisch eine bestehende Login-Session.
|
||||||
|
* **Menu Badges:** 🏷️ Zeigt Menü-Codes (M1, M2+) direkt im Header.
|
||||||
|
* **Menü-Flagging:** 🔔 Ausverkaufte Menüs beobachten und bei Verfügbarkeit benachrichtigt werden.
|
||||||
|
* **Version-Menü:** 📦 Versionsliste mit Installer-Links, Dev-Mode Toggle und Downgrade-Support.
|
||||||
|
* **Cache leeren:** 🗑️ Lokalen Cache mit einem Klick bereinigen (im Version-Menü).
|
||||||
|
* **Favicon:** 🍽️ Eigenes Icon für die Lesezeichenleiste.
|
||||||
* **Changelog:** Übersicht über neue Funktionen direkt im Installer.
|
* **Changelog:** Übersicht über neue Funktionen direkt im Installer.
|
||||||
|
|
||||||
## 📦 Installation
|
## 📦 Installation
|
||||||
@@ -19,7 +24,7 @@ Ein intelligentes Bookmarklet für die Mitarbeiter-Kantine der Bessa App. Dieses
|
|||||||
2. Ziehe den blauen Button **"Kantine Wrapper"** in deine Lesezeichen-Leiste.
|
2. Ziehe den blauen Button **"Kantine Wrapper"** in deine Lesezeichen-Leiste.
|
||||||
3. Fertig!
|
3. Fertig!
|
||||||
|
|
||||||
## usage
|
## 🍽️ Nutzung
|
||||||
|
|
||||||
1. Navigiere zu [https://web.bessa.app/knapp-kantine](https://web.bessa.app/knapp-kantine).
|
1. Navigiere zu [https://web.bessa.app/knapp-kantine](https://web.bessa.app/knapp-kantine).
|
||||||
2. Klicke auf das **"Kantine Wrapper"** Lesezeichen.
|
2. Klicke auf das **"Kantine Wrapper"** Lesezeichen.
|
||||||
@@ -28,24 +33,38 @@ Ein intelligentes Bookmarklet für die Mitarbeiter-Kantine der Bessa App. Dieses
|
|||||||
## 🛠️ Entwicklung
|
## 🛠️ Entwicklung
|
||||||
|
|
||||||
### Voraussetzungen
|
### Voraussetzungen
|
||||||
* Node.js (optional, nur für Build-Scripts)
|
* Node.js (für Build- und Test-Scripts)
|
||||||
|
* Python 3 (für Build-Tests)
|
||||||
* Bash (für `build-bookmarklet.sh`)
|
* Bash (für `build-bookmarklet.sh`)
|
||||||
|
|
||||||
### Projektstruktur
|
### Projektstruktur
|
||||||
|
|
||||||
#### Quelldateien
|
#### Quelldateien
|
||||||
* `kantine.js`: Der Haupt-Quellcode des Bookmarklets (UI, API-Logik, Rendering).
|
| Datei | Beschreibung |
|
||||||
* `style.css`: Das komplette Design (CSS mit Light/Dark Mode).
|
|-------|-------------|
|
||||||
* `mock-data.js`: Mock-Fetch-Interceptor mit realistischen Dummy-Menüdaten für Standalone-Tests.
|
| `kantine.js` | Haupt-Quellcode des Bookmarklets (UI, API-Logik, Rendering). |
|
||||||
* `build-bookmarklet.sh`: Build-Skript – erzeugt alle `dist/`-Artefakte.
|
| `style.css` | Komplettes Design (CSS mit Light/Dark Mode). |
|
||||||
* `test_build.py`: Automatische Build-Tests, laufen am Ende jedes Builds.
|
| `favicon.svg` | Favicon für die Installer-Seite (Dreieck + Gabel & Messer). |
|
||||||
|
| `mock-data.js` | Mock-Fetch-Interceptor mit realistischen Dummy-Menüdaten für Standalone-Tests. |
|
||||||
|
| `build-bookmarklet.sh` | Build-Skript – erzeugt alle `dist/`-Artefakte und führt alle Tests aus. |
|
||||||
|
| `release.sh` | Release-Skript – Commit, Tag, Push zu allen Remotes. |
|
||||||
|
| `version.txt` | Aktuelle Versionsnummer (SemVer). |
|
||||||
|
| `changelog.md` | Änderungshistorie aller Versionen. |
|
||||||
|
| `REQUIREMENTS.md` | System Requirements Specification (SRS). |
|
||||||
|
|
||||||
|
#### Tests
|
||||||
|
| Datei | Beschreibung |
|
||||||
|
|-------|-------------|
|
||||||
|
| `test_logic.js` | Logik-Unit-Tests (statische Analyse, Syntax-Check, Sandbox-Ausführung). |
|
||||||
|
| `tests/test_dom.js` | DOM-Interaktionstests via JSDOM (prüft Event-Listener-Bindung aller UI-Komponenten). |
|
||||||
|
| `test_build.py` | Build-Artefakt-Validierung (Existenz, Inhalt). |
|
||||||
|
|
||||||
#### `dist/` – Build-Artefakte
|
#### `dist/` – Build-Artefakte
|
||||||
| Datei | Beschreibung |
|
| Datei | Beschreibung |
|
||||||
|-------|-------------|
|
|-------|-------------|
|
||||||
| `bookmarklet.txt` | Die rohe Bookmarklet-URL (`javascript:...`). Enthält CSS + JS als selbstextrahierendes IIFE. Kann direkt als Lesezeichen-URL eingefügt werden. |
|
| `bookmarklet.txt` | Die rohe Bookmarklet-URL (`javascript:...`). Enthält CSS + JS als selbstextrahierendes IIFE. Kann direkt als Lesezeichen-URL eingefügt werden. |
|
||||||
| `bookmarklet-payload.js` | Der entpackte Bookmarklet-Payload (JS). Erstellt `<style>` + `<script>` Elemente und injiziert sie in die Seite. Nützlich zum Debuggen. |
|
| `bookmarklet-payload.js` | Der entpackte Bookmarklet-Payload (JS). Erstellt `<style>` + `<script>` Elemente und injiziert sie in die Seite. Nützlich zum Debuggen. |
|
||||||
| `install.html` | Installer-Seite mit Drag & Drop Button, Anleitung, Feature-Liste und Changelog. Kann lokal oder gehostet geöffnet werden. |
|
| `install.html` | Installer-Seite mit Drag & Drop Button, Favicon, Anleitung, Feature-Liste und Changelog. Kann lokal oder gehostet geöffnet werden. |
|
||||||
| `kantine-standalone.html` | Eigenständige HTML-Datei mit eingebettetem CSS + JS + **Mock-Daten**. Lädt automatisch Dummy-Menüs für UI-Tests ohne API-Zugriff. |
|
| `kantine-standalone.html` | Eigenständige HTML-Datei mit eingebettetem CSS + JS + **Mock-Daten**. Lädt automatisch Dummy-Menüs für UI-Tests ohne API-Zugriff. |
|
||||||
|
|
||||||
### Build
|
### Build
|
||||||
@@ -55,5 +74,15 @@ Um Änderungen an `kantine.js` oder `style.css` wirksam zu machen, führe den Bu
|
|||||||
./build-bookmarklet.sh
|
./build-bookmarklet.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Release
|
||||||
|
Erstellt einen Git-Tag, committet Build-Artefakte und pusht zu allen Remotes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./release.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚠️ Hinweis
|
||||||
|
Dieses Projekt enthält zum überwiegenden Teil **KI-generierten Code**. Der Code wurde mithilfe von KI-Assistenten erstellt, überprüft und iterativ verfeinert.
|
||||||
|
|
||||||
## 📝 Lizenz
|
## 📝 Lizenz
|
||||||
Internes Tool.
|
Internes Tool.
|
||||||
|
|||||||
@@ -60,10 +60,10 @@ Das System umfasst die Darstellung von Menüplänen in einer Wochenübersicht, d
|
|||||||
| **Header UI & Navigation** | | | |
|
| **Header UI & Navigation** | | | |
|
||||||
| FR-090 | Die Hauptnavigation (Wochen-Toggles) muss linksbündig neben dem App-Titel positioniert sein. | Niedrig | v1.5.0 |
|
| FR-090 | Die Hauptnavigation (Wochen-Toggles) muss linksbündig neben dem App-Titel positioniert sein. | Niedrig | v1.5.0 |
|
||||||
| FR-091 | Ein dynamisches Alarm-Icon im Header muss den Überwachungsstatus geflaggter Menüs anzeigen (Gelb=Überwachung aktiv aber kein Menü verfügbar, Grün=Mindestens ein Menü verfügbar, Versteckt=keine Flags). Der Tooltip muss den Zeitpunkt der letzten Prüfung als relativen String (z.B. "vor 4 Min.") enthalten. | Mittel | v1.5.0 (Update v1.4.10) |
|
| FR-091 | Ein dynamisches Alarm-Icon im Header muss den Überwachungsstatus geflaggter Menüs anzeigen (Gelb=Überwachung aktiv aber kein Menü verfügbar, Grün=Mindestens ein Menü verfügbar, Versteckt=keine Flags). Der Tooltip muss den Zeitpunkt der letzten Prüfung als relativen String (z.B. "vor 4 Min.") enthalten. | Mittel | v1.5.0 (Update v1.4.10) |
|
||||||
| FR-092 | Sobald über den Daten-Refresh erstmals Menüdaten für die Nächste Woche geladen werden, muss der entsprechende Navigation-Button animiert und farblich (Gelb) hervorgehoben werden. Zusätzlich muss einmalig ein Hinweis eingeblendet werden. Bei Klick auf den Button muss die Hervorhebung erlöschen. | Mittel | v1.6.0 |
|
| FR-092 | Solange Menüdaten für die Nächste Woche verfügbar sind, aber noch keine Bestellungen getätigt wurden, muss der entsprechende Navigation-Button animiert und farblich (Gelb) hervorgehoben werden. Nach der ersten Bestellung muss die Hervorhebung automatisch erlöschen. Zusätzlich muss beim erstmaligen Erscheinen der Daten ein einmaliger Toast-Hinweis angezeigt werden. | Mittel | v1.6.0 (Update v1.4.21) |
|
||||||
| **Benutzer-Feedback** | | | |
|
| **Benutzer-Feedback** | | | |
|
||||||
| FR-090 | Alle benutzerrelevanten Aktionen (Bestellung, Stornierung, Fehler) müssen durch nicht-blockierende Benachrichtigungen (Toasts) bestätigt werden. | Mittel | v1.0.1 |
|
| FR-095 | Alle benutzerrelevanten Aktionen (Bestellung, Stornierung, Fehler) müssen durch nicht-blockierende Benachrichtigungen (Toasts) bestätigt werden. | Mittel | v1.0.1 |
|
||||||
| FR-091 | Bei einem Verbindungsfehler muss ein Fehlerdialog mit Fallback-Link zur Originalseite angezeigt werden. | Mittel | v1.0.1 |
|
| FR-096 | Bei einem Verbindungsfehler muss ein Fehlerdialog mit Fallback-Link zur Originalseite angezeigt werden. | Mittel | v1.0.1 |
|
||||||
| **Nächste-Woche-Badge** | | | |
|
| **Nächste-Woche-Badge** | | | |
|
||||||
| FR-100 | Die Navigation zur nächsten Woche muss ein Badge anzeigen, das den Überblick über den Bestellstatus der kommenden Woche visualisiert (bestellt / bestellbar / gesamt). | Niedrig | v1.0.1 |
|
| FR-100 | Die Navigation zur nächsten Woche muss ein Badge anzeigen, das den Überblick über den Bestellstatus der kommenden Woche visualisiert (bestellt / bestellbar / gesamt). | Niedrig | v1.0.1 |
|
||||||
| **Update-Management** | | | |
|
| **Update-Management** | | | |
|
||||||
@@ -73,6 +73,8 @@ Das System umfasst die Darstellung von Menüplänen in einer Wochenübersicht, d
|
|||||||
| FR-113 | Es muss möglich sein, zu einer älteren Version zurückzukehren (Downgrade). | Niedrig | v1.3.0 |
|
| FR-113 | Es muss möglich sein, zu einer älteren Version zurückzukehren (Downgrade). | Niedrig | v1.3.0 |
|
||||||
| FR-114 | Ein Dev-Mode muss es ermöglichen, zwischen stabilen Releases und Entwicklungs-Tags umzuschalten. | Niedrig | v1.3.0 |
|
| FR-114 | Ein Dev-Mode muss es ermöglichen, zwischen stabilen Releases und Entwicklungs-Tags umzuschalten. | Niedrig | v1.3.0 |
|
||||||
| FR-115 | Das Versionsmenü muss Links zur Erstellung von Feature-Requests und Bug-Reports auf GitHub enthalten. | Niedrig | v1.4.4 |
|
| FR-115 | Das Versionsmenü muss Links zur Erstellung von Feature-Requests und Bug-Reports auf GitHub enthalten. | Niedrig | v1.4.4 |
|
||||||
|
| FR-116 | Das Versionsmenü muss eine Funktion zum Leeren des lokalen Caches bereitstellen, um bei hartnäckigen Fehlern alle gespeicherten Daten bereinigen zu können. | Niedrig | v1.4.16 |
|
||||||
|
| FR-117 | Die Installer-Seite muss ein eingebettetes Favicon bereitstellen, das beim Drag & Drop in die Lesezeichenleiste als Icon für das Bookmarklet übernommen wird. | Niedrig | v1.4.19 |
|
||||||
|
|
||||||
## 3. Nicht-funktionale Anforderungen
|
## 3. Nicht-funktionale Anforderungen
|
||||||
|
|
||||||
@@ -85,7 +87,7 @@ Das System umfasst die Darstellung von Menüplänen in einer Wochenübersicht, d
|
|||||||
| **Benutzbarkeit** | NFR-005 | Die Oberfläche muss auf mobilen Geräten fehlerfrei nutzbar sein. | Viewports ab 320px Breite |
|
| **Benutzbarkeit** | NFR-005 | Die Oberfläche muss auf mobilen Geräten fehlerfrei nutzbar sein. | Viewports ab 320px Breite |
|
||||||
| **Benutzbarkeit** | NFR-006 | Alle interaktiven Elemente müssen Tooltips oder Hilfetexte bieten. | 100% Coverage |
|
| **Benutzbarkeit** | NFR-006 | Alle interaktiven Elemente müssen Tooltips oder Hilfetexte bieten. | 100% Coverage |
|
||||||
| **Benutzbarkeit** | NFR-007 | Die Benutzeroberfläche muss vollständig in deutscher Sprache sein. | Vollständige Lokalisierung |
|
| **Benutzbarkeit** | NFR-007 | Die Benutzeroberfläche muss vollständig in deutscher Sprache sein. | Vollständige Lokalisierung |
|
||||||
| **Wartbarkeit** | NFR-008 | Die Build-Artefakte müssen durch automatisierte Tests validiert werden. | Build-Tests + Logik-Tests |
|
| **Wartbarkeit** | NFR-008 | Die Build-Artefakte müssen durch automatisierte Tests validiert werden. | Build-Tests + Logik-Tests + DOM-Tests |
|
||||||
|
|
||||||
## 4. Technische Randbedingungen
|
## 4. Technische Randbedingungen
|
||||||
* **Deployment**: Das System wird als Bookmarklet ausgeliefert, das auf der Bessa-Webseite ausgeführt wird.
|
* **Deployment**: Das System wird als Bookmarklet ausgeliefert, das auf der Bessa-Webseite ausgeführt wird.
|
||||||
@@ -93,4 +95,4 @@ Das System umfasst die Darstellung von Menüplänen in einer Wochenübersicht, d
|
|||||||
* **Datenhaltung**: Clientseitig via `localStorage` (Menü-Cache, Flags, Highlights, Theme) und `sessionStorage` (Auth-Token).
|
* **Datenhaltung**: Clientseitig via `localStorage` (Menü-Cache, Flags, Highlights, Theme) und `sessionStorage` (Auth-Token).
|
||||||
* **Build**: Bash-basiertes Build-Script, das Bookmarklet-URL, Standalone-HTML und Installer-Seite generiert.
|
* **Build**: Bash-basiertes Build-Script, das Bookmarklet-URL, Standalone-HTML und Installer-Seite generiert.
|
||||||
* **Versionierung**: SemVer, verwaltet über GitHub Releases/Tags.
|
* **Versionierung**: SemVer, verwaltet über GitHub Releases/Tags.
|
||||||
* **Tests**: Python-basierte Build-Tests (`python3`) + Node.js-basierte Logik-Tests.
|
* **Tests**: Python-basierte Build-Tests (`python3`) + Node.js-basierte Logik-Tests + Node.js-basierte DOM-Interaktionstests (JSDOM).
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|||||||
DIST_DIR="$SCRIPT_DIR/dist"
|
DIST_DIR="$SCRIPT_DIR/dist"
|
||||||
CSS_FILE="$SCRIPT_DIR/style.css"
|
CSS_FILE="$SCRIPT_DIR/style.css"
|
||||||
JS_FILE="$SCRIPT_DIR/kantine.js"
|
JS_FILE="$SCRIPT_DIR/kantine.js"
|
||||||
|
FAVICON_FILE="$SCRIPT_DIR/favicon.svg"
|
||||||
|
|
||||||
# === VERSION ===
|
# === VERSION ===
|
||||||
if [ -f "$SCRIPT_DIR/version.txt" ]; then
|
if [ -f "$SCRIPT_DIR/version.txt" ]; then
|
||||||
@@ -23,6 +24,11 @@ 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
|
||||||
|
if [ ! -f "$FAVICON_FILE" ]; then echo "ERROR: $FAVICON_FILE not found"; exit 1; fi
|
||||||
|
|
||||||
|
# Generate favicon Base64 data URI
|
||||||
|
FAVICON_B64=$(base64 -w0 "$FAVICON_FILE")
|
||||||
|
FAVICON_URI="data:image/svg+xml;base64,${FAVICON_B64}"
|
||||||
|
|
||||||
CSS_CONTENT=$(cat "$CSS_FILE")
|
CSS_CONTENT=$(cat "$CSS_FILE")
|
||||||
|
|
||||||
@@ -101,6 +107,7 @@ cat > "$DIST_DIR/install.html" << INSTALLEOF
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Kantine Wrapper Installer ($VERSION)</title>
|
<title>Kantine Wrapper Installer ($VERSION)</title>
|
||||||
|
<link rel="icon" type="image/svg+xml" href="$FAVICON_URI">
|
||||||
<style>
|
<style>
|
||||||
body { font-family: 'Inter', sans-serif; max-width: 600px; margin: 40px auto; padding: 20px; background: #1a1a2e; color: #eee; }
|
body { font-family: 'Inter', sans-serif; max-width: 600px; margin: 40px auto; padding: 20px; background: #1a1a2e; color: #eee; }
|
||||||
h1 { color: #029AA8; } /* Knapp Teal */
|
h1 { color: #029AA8; } /* Knapp Teal */
|
||||||
|
|||||||
12
changelog.md
12
changelog.md
@@ -1,3 +1,15 @@
|
|||||||
|
## 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
|
## 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.
|
- 🧪 **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.
|
||||||
|
|
||||||
|
|||||||
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
29
dist/install.html
vendored
29
dist/install.html
vendored
File diff suppressed because one or more lines are too long
18
dist/kantine-standalone.html
vendored
18
dist/kantine-standalone.html
vendored
@@ -2021,7 +2021,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.18</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.4.22</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;">
|
||||||
@@ -2163,7 +2163,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.18</span>
|
<strong>Aktuell:</strong> <span id="version-current">v1.4.22</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;">
|
||||||
@@ -2531,6 +2531,7 @@ body {
|
|||||||
}
|
}
|
||||||
console.log(`Fetched ${results.length} orders, mapped active ones.`);
|
console.log(`Fetched ${results.length} orders, mapped active ones.`);
|
||||||
renderVisibleWeeks();
|
renderVisibleWeeks();
|
||||||
|
updateNextWeekBadge();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching orders:', error);
|
console.error('Error fetching orders:', error);
|
||||||
@@ -3596,13 +3597,18 @@ body {
|
|||||||
badge.classList.add('has-highlights');
|
badge.classList.add('has-highlights');
|
||||||
}
|
}
|
||||||
|
|
||||||
// FR-092: Highlight Next Week Button when new data arrives
|
// FR-092: Glow Next Week button while data exists but no orders placed
|
||||||
|
if (daysWithOrders === 0) {
|
||||||
|
btnNextWeek.classList.add('new-week-available');
|
||||||
|
// One-time toast notification when new data first arrives
|
||||||
const storageKey = `kantine_notified_nextweek_${nextYear}_${nextWeek}`;
|
const storageKey = `kantine_notified_nextweek_${nextYear}_${nextWeek}`;
|
||||||
if (!localStorage.getItem(storageKey)) {
|
if (!localStorage.getItem(storageKey)) {
|
||||||
localStorage.setItem(storageKey, 'true');
|
localStorage.setItem(storageKey, 'true');
|
||||||
btnNextWeek.classList.add('new-week-available');
|
|
||||||
showToast('Neue Menüdaten für nächste Woche verfügbar!', 'info');
|
showToast('Neue Menüdaten für nächste Woche verfügbar!', 'info');
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
btnNextWeek.classList.remove('new-week-available');
|
||||||
|
}
|
||||||
|
|
||||||
} else if (badge) {
|
} else if (badge) {
|
||||||
badge.remove();
|
badge.remove();
|
||||||
@@ -4010,7 +4016,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.18';
|
const currentVersion = 'v1.4.22';
|
||||||
const devMode = localStorage.getItem('kantine_dev_mode') === 'true';
|
const devMode = localStorage.getItem('kantine_dev_mode') === 'true';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -4051,7 +4057,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.18';
|
const currentVersion = 'v1.4.22';
|
||||||
|
|
||||||
if (!modal) return;
|
if (!modal) return;
|
||||||
modal.classList.remove('hidden');
|
modal.classList.remove('hidden');
|
||||||
|
|||||||
29
favicon.svg
Executable file
29
favicon.svg
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
|
||||||
|
<!-- Fork (left, with gap to triangle) -->
|
||||||
|
<g transform="translate(2, 10)">
|
||||||
|
<!-- Tines -->
|
||||||
|
<rect x="1" y="0" width="1.8" height="16" rx="0.9" fill="#333"/>
|
||||||
|
<rect x="4.6" y="0" width="1.8" height="16" rx="0.9" fill="#333"/>
|
||||||
|
<rect x="8.2" y="0" width="1.8" height="16" rx="0.9" fill="#333"/>
|
||||||
|
<!-- Connector -->
|
||||||
|
<rect x="1" y="14" width="9" height="3.5" rx="1.5" fill="#333"/>
|
||||||
|
<!-- Handle -->
|
||||||
|
<rect x="3.5" y="16.5" width="4" height="24" rx="2" fill="#333"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Triangle (center, equilateral aspect ratio ~1:0.866) -->
|
||||||
|
<!-- Equilateral: base=28, height=24.25 => keeps proper ratio -->
|
||||||
|
<polygon points="32,8 47,48 17,48" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||||
|
|
||||||
|
<!-- Knife (right, with gap to triangle) -->
|
||||||
|
<g transform="translate(50, 10)">
|
||||||
|
<!-- Blade (slight curve) -->
|
||||||
|
<path d="M3,0 C3,0 3,0 3,0 L3,17 L10,14 C10,6 7,0 3,0 Z" fill="#333"/>
|
||||||
|
<!-- Spine -->
|
||||||
|
<rect x="1.5" y="0" width="2" height="18" rx="1" fill="#333"/>
|
||||||
|
<!-- Bolster -->
|
||||||
|
<rect x="1.5" y="16.5" width="8.5" height="3.5" rx="1.2" fill="#333"/>
|
||||||
|
<!-- Handle -->
|
||||||
|
<rect x="3.5" y="19" width="4" height="22" rx="2" fill="#333"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
10
kantine.js
10
kantine.js
@@ -581,6 +581,7 @@
|
|||||||
}
|
}
|
||||||
console.log(`Fetched ${results.length} orders, mapped active ones.`);
|
console.log(`Fetched ${results.length} orders, mapped active ones.`);
|
||||||
renderVisibleWeeks();
|
renderVisibleWeeks();
|
||||||
|
updateNextWeekBadge();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching orders:', error);
|
console.error('Error fetching orders:', error);
|
||||||
@@ -1646,13 +1647,18 @@
|
|||||||
badge.classList.add('has-highlights');
|
badge.classList.add('has-highlights');
|
||||||
}
|
}
|
||||||
|
|
||||||
// FR-092: Highlight Next Week Button when new data arrives
|
// FR-092: Glow Next Week button while data exists but no orders placed
|
||||||
|
if (daysWithOrders === 0) {
|
||||||
|
btnNextWeek.classList.add('new-week-available');
|
||||||
|
// One-time toast notification when new data first arrives
|
||||||
const storageKey = `kantine_notified_nextweek_${nextYear}_${nextWeek}`;
|
const storageKey = `kantine_notified_nextweek_${nextYear}_${nextWeek}`;
|
||||||
if (!localStorage.getItem(storageKey)) {
|
if (!localStorage.getItem(storageKey)) {
|
||||||
localStorage.setItem(storageKey, 'true');
|
localStorage.setItem(storageKey, 'true');
|
||||||
btnNextWeek.classList.add('new-week-available');
|
|
||||||
showToast('Neue Menüdaten für nächste Woche verfügbar!', 'info');
|
showToast('Neue Menüdaten für nächste Woche verfügbar!', 'info');
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
btnNextWeek.classList.remove('new-week-available');
|
||||||
|
}
|
||||||
|
|
||||||
} else if (badge) {
|
} else if (badge) {
|
||||||
badge.remove();
|
badge.remove();
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
v1.4.18
|
v1.4.22
|
||||||
|
|||||||
Reference in New Issue
Block a user