feat: Replaced inline language selection with a dropdown menu and removed the weekly cost display.
This commit is contained in:
@@ -39,7 +39,7 @@ Das System umfasst die Darstellung von Menüplänen in einer Wochenübersicht, d
|
|||||||
| FR-032 | Nach Bestellschluss (Cutoff-Zeit) dürfen keine neuen Bestellungen oder Stornierungen für diesen Tag möglich sein. | Hoch | v1.0.1 |
|
| FR-032 | Nach Bestellschluss (Cutoff-Zeit) dürfen keine neuen Bestellungen oder Stornierungen für diesen Tag möglich sein. | Hoch | v1.0.1 |
|
||||||
| FR-033 | Es muss möglich sein, dasselbe Menü mehrfach zu bestellen. Bei Mehrfachbestellungen muss die Anzahl angezeigt werden. | Niedrig | v1.0.1 |
|
| FR-033 | Es muss möglich sein, dasselbe Menü mehrfach zu bestellen. Bei Mehrfachbestellungen muss die Anzahl angezeigt werden. | Niedrig | v1.0.1 |
|
||||||
| **Kostentransparenz & Bestellhistorie** | | | |
|
| **Kostentransparenz & Bestellhistorie** | | | |
|
||||||
| FR-040 | Das System muss die Gesamtkosten aller Bestellungen einer Woche automatisch berechnen und anzeigen. | Mittel | v1.1.0 |
|
| ~~FR-040~~ | ~~Das System muss die Gesamtkosten aller Bestellungen einer Woche automatisch berechnen und anzeigen.~~ | ~~Mittel~~ | ~~v1.1.0~~ (Obsolet: Display entfernt auf User-Wunsch) |
|
||||||
| FR-041 | Das System muss dem Benutzer eine Bestellhistorie (gruppiert nach Monat und KW) mit Fortschrittsanzeige auf Abruf in einem Modal bereitstellen. Die Historie muss über ein lokales Delta-Caching verfügen, um Ladezeiten zu minimieren. | Mittel | v1.4.0 (Update v1.4.7) |
|
| FR-041 | Das System muss dem Benutzer eine Bestellhistorie (gruppiert nach Monat und KW) mit Fortschrittsanzeige auf Abruf in einem Modal bereitstellen. Die Historie muss über ein lokales Delta-Caching verfügen, um Ladezeiten zu minimieren. | Mittel | v1.4.0 (Update v1.4.7) |
|
||||||
| **Bestell-Countdown** | | | |
|
| **Bestell-Countdown** | | | |
|
||||||
| FR-050 | Das System muss vor Bestellschluss einen visuell hervorgehobenen Countdown anzeigen. | Mittel | v1.1.0 |
|
| FR-050 | Das System muss vor Bestellschluss einen visuell hervorgehobenen Countdown anzeigen. | Mittel | v1.1.0 |
|
||||||
@@ -63,7 +63,7 @@ Das System umfasst die Darstellung von Menüplänen in einer Wochenübersicht, d
|
|||||||
| FR-092 | Solange bestellbare Menüs für nächste Woche vorhanden sind, aber noch keine Bestellungen getätigt wurden (Prüfung Montag–Donnerstag; Freitag ist ausgenommen), muss der entsprechende Navigation-Button animiert und farblich hervorgehoben werden. Nach der ersten Bestellung muss die Hervorhebung erlöschen. Zusätzlich muss beim erstmaligen Erscheinen der Daten ein einmaliger Toast-Hinweis angezeigt werden. | Mittel | v1.6.0 (Update v1.7.0) |
|
| FR-092 | Solange bestellbare Menüs für nächste Woche vorhanden sind, aber noch keine Bestellungen getätigt wurden (Prüfung Montag–Donnerstag; Freitag ist ausgenommen), muss der entsprechende Navigation-Button animiert und farblich hervorgehoben werden. Nach der ersten Bestellung muss die Hervorhebung erlöschen. Zusätzlich muss beim erstmaligen Erscheinen der Daten ein einmaliger Toast-Hinweis angezeigt werden. | Mittel | v1.6.0 (Update v1.7.0) |
|
||||||
| FR-093 | Das System muss dem Benutzer ermöglichen, durch Klicken auf das Alarm-Icon im Header eine manuelle Prüfung der geflaggten Menüs auszulösen. Während der Prüfung muss das Icon visuell animiert sein (Rotation). Nach Abschluss der Prüfung muss eine Toast-Nachricht mit der Anzahl der geprüften Menüs angezeigt werden. | Mittel | v1.6.13 |
|
| FR-093 | Das System muss dem Benutzer ermöglichen, durch Klicken auf das Alarm-Icon im Header eine manuelle Prüfung der geflaggten Menüs auszulösen. Während der Prüfung muss das Icon visuell animiert sein (Rotation). Nach Abschluss der Prüfung muss eine Toast-Nachricht mit der Anzahl der geprüften Menüs angezeigt werden. | Mittel | v1.6.13 |
|
||||||
| **Sprachfilter** | | | |
|
| **Sprachfilter** | | | |
|
||||||
| FR-120 | Das System muss zweisprachige Menübeschreibungen (Deutsch/Englisch) erkennen und dem Benutzer erlauben, via UI-Toggle zwischen DE, EN und ALL (beide Sprachen) zu wechseln. Die Sprachpräferenz muss persistent gespeichert werden. Allergen-Codes müssen in allen Modi angezeigt werden. | Mittel | v1.6.0 |
|
| FR-120 | Das System muss zweisprachige Menübeschreibungen (Deutsch/Englisch) erkennen und dem Benutzer erlauben, via UI-Dropdown (Icon mit Label) zwischen DE, EN und ALL (beide Sprachen) zu wechseln. Die Sprachpräferenz muss persistent gespeichert werden. Allergen-Codes müssen in allen Modi angezeigt werden. | Mittel | v1.6.0 (Update v1.6.21) |
|
||||||
| FR-121 | Das System muss bei fehlenden Übersetzungen in zweisprachigen Menüs robust reagieren. Wenn ein Gang nur in einer Sprache vorliegt, muss dieser Teil für beide Sprachansichten herangezogen werden, um die Konsistenz der Ganganzahl zu gewährleisten. | Mittel | v1.6.10 |
|
| FR-121 | Das System muss bei fehlenden Übersetzungen in zweisprachigen Menüs robust reagieren. Wenn ein Gang nur in einer Sprache vorliegt, muss dieser Teil für beide Sprachansichten herangezogen werden, um die Konsistenz der Ganganzahl zu gewährleisten. | Mittel | v1.6.10 |
|
||||||
| FR-122 | Bei Auswahl von EN muss die gesamte Benutzeroberfläche (Buttons, Tooltips, Modale, Status-Badges) auf Englisch umgestellt werden. Bei DE oder ALL verbleibt die GUI auf Deutsch. | Mittel | v1.7.0 |
|
| FR-122 | Bei Auswahl von EN muss die gesamte Benutzeroberfläche (Buttons, Tooltips, Modale, Status-Badges) auf Englisch umgestellt werden. Bei DE oder ALL verbleibt die GUI auf Deutsch. | Mittel | v1.7.0 |
|
||||||
| **Benutzer-Feedback** | | | |
|
| **Benutzer-Feedback** | | | |
|
||||||
|
|||||||
Binary file not shown.
@@ -1,3 +1,12 @@
|
|||||||
|
## v1.6.22 (2026-03-12)
|
||||||
|
- 🧹 **UX Cleanup**: Text-Label am Sprachumschalter entfernt. Der Button zeigt nun nur noch das `translate`-Icon an, was die Controls-Bar ruhiger macht.
|
||||||
|
|
||||||
|
## v1.6.21 (2026-03-12)
|
||||||
|
- ✨ **Feature**: Sprachumschaltung Redesign – Die Sprachwahl (DE/EN/ALL) wurde von der Header-Mitte in den rechten Controls-Bereich verschoben. Sie ist nun als Icon-Dropdown mit aktueller Status-Anzeige (z.B. "DE") verfügbar. Für die deutsche Sprache wird die 🇦🇹 Flagge verwendet.
|
||||||
|
|
||||||
|
## v1.6.20 (2026-03-12)
|
||||||
|
- 🧹 **Cleanup**: Wochenkosten-Anzeige entfernt (Weekly Cost Display) – Auf User-Wunsch wurde die Anzeige der wöchentlichen Gesamtkosten im Header entfernt, um die UI zu entschlacken. FR-040 als obsolet markiert.
|
||||||
|
|
||||||
## v1.6.19 (2026-03-11)
|
## v1.6.19 (2026-03-11)
|
||||||
- 🎨 **UX**: Grid-Layout & Glow Overlap Fix – Die Karten-Inhalte wurden auf ein sauberes Grid-Gap-Modell umgestellt (`row-gap: 1.5rem`). Dies verhindert technische Überlappungen von Menü-Items und stellt sicher, dass Glow-Effekte (Bestellt, Highlight) alle Inhalte korrekt umschließen. Manuelle Abstände wurden bereinigt.
|
- 🎨 **UX**: Grid-Layout & Glow Overlap Fix – Die Karten-Inhalte wurden auf ein sauberes Grid-Gap-Modell umgestellt (`row-gap: 1.5rem`). Dies verhindert technische Überlappungen von Menü-Items und stellt sicher, dass Glow-Effekte (Bestellt, Highlight) alle Inhalte korrekt umschließen. Manuelle Abstände wurden bereinigt.
|
||||||
|
|
||||||
|
|||||||
4
dist/bookmarklet-payload.js
vendored
4
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
24
dist/install.html
vendored
24
dist/install.html
vendored
File diff suppressed because one or more lines are too long
144
dist/kantine-standalone.html
vendored
144
dist/kantine-standalone.html
vendored
File diff suppressed because one or more lines are too long
58
dist/kantine.bundle.js
vendored
58
dist/kantine.bundle.js
vendored
@@ -1292,7 +1292,6 @@ const TRANSLATIONS = {
|
|||||||
noMenuDataHint: 'Versuchen Sie eine andere Woche oder schauen Sie später vorbei.',
|
noMenuDataHint: 'Versuchen Sie eine andere Woche oder schauen Sie später vorbei.',
|
||||||
|
|
||||||
// Weekly cost
|
// Weekly cost
|
||||||
costLabel: 'Gesamt',
|
|
||||||
|
|
||||||
// Countdown
|
// Countdown
|
||||||
orderDeadline: 'Bestellschluss',
|
orderDeadline: 'Bestellschluss',
|
||||||
@@ -1428,7 +1427,6 @@ const TRANSLATIONS = {
|
|||||||
noMenuDataHint: 'Try another week or check back later.',
|
noMenuDataHint: 'Try another week or check back later.',
|
||||||
|
|
||||||
// Weekly cost
|
// Weekly cost
|
||||||
costLabel: 'Total',
|
|
||||||
|
|
||||||
// Countdown
|
// Countdown
|
||||||
orderDeadline: 'Order deadline',
|
orderDeadline: 'Order deadline',
|
||||||
@@ -1582,7 +1580,7 @@ function setLangMode(lang) {
|
|||||||
/* harmony export */ gJ: () => (/* binding */ updateNextWeekBadge),
|
/* harmony export */ gJ: () => (/* binding */ updateNextWeekBadge),
|
||||||
/* harmony export */ showErrorModal: () => (/* binding */ showErrorModal)
|
/* harmony export */ showErrorModal: () => (/* binding */ showErrorModal)
|
||||||
/* harmony export */ });
|
/* harmony export */ });
|
||||||
/* unused harmony exports updateWeeklyCost, syncMenuItemHeights, createDayCard, fetchVersions, updateCountdown, removeCountdown */
|
/* unused harmony exports syncMenuItemHeights, createDayCard, fetchVersions, updateCountdown, removeCountdown */
|
||||||
/* harmony import */ var _state_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(901);
|
/* harmony import */ var _state_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(901);
|
||||||
/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(413);
|
/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(413);
|
||||||
/* harmony import */ var _constants_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(521);
|
/* harmony import */ var _constants_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(521);
|
||||||
@@ -1681,29 +1679,6 @@ function updateNextWeekBadge() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateWeeklyCost(days) {
|
|
||||||
let totalCost = 0;
|
|
||||||
if (days && days.length > 0) {
|
|
||||||
days.forEach(day => {
|
|
||||||
if (day.items) {
|
|
||||||
day.items.forEach(item => {
|
|
||||||
const articleId = item.articleId || parseInt(item.id.split('_')[1]);
|
|
||||||
const key = `${day.date}_${articleId}`;
|
|
||||||
const orders = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .orderMap */ .L.get(key) || [];
|
|
||||||
if (orders.length > 0) totalCost += item.price * orders.length;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const costDisplay = document.getElementById('weekly-cost-display');
|
|
||||||
if (totalCost > 0) {
|
|
||||||
costDisplay.innerHTML = `<span class="material-icons-round">shopping_bag</span> <span>${(0,_i18n_js__WEBPACK_IMPORTED_MODULE_5__.t)('costLabel')}: ${totalCost.toFixed(2).replace('.', ',')} €</span>`;
|
|
||||||
costDisplay.classList.remove('hidden');
|
|
||||||
} else {
|
|
||||||
costDisplay.classList.add('hidden');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderVisibleWeeks() {
|
function renderVisibleWeeks() {
|
||||||
const menuContainer = document.getElementById('menu-container');
|
const menuContainer = document.getElementById('menu-container');
|
||||||
@@ -1730,11 +1705,9 @@ function renderVisibleWeeks() {
|
|||||||
<p>${(0,_i18n_js__WEBPACK_IMPORTED_MODULE_5__.t)('noMenuData')} ${targetWeek} (${targetYear}).</p>
|
<p>${(0,_i18n_js__WEBPACK_IMPORTED_MODULE_5__.t)('noMenuData')} ${targetWeek} (${targetYear}).</p>
|
||||||
<small>${(0,_i18n_js__WEBPACK_IMPORTED_MODULE_5__.t)('noMenuDataHint')}</small>
|
<small>${(0,_i18n_js__WEBPACK_IMPORTED_MODULE_5__.t)('noMenuDataHint')}</small>
|
||||||
</div>`;
|
</div>`;
|
||||||
document.getElementById('weekly-cost-display').classList.add('hidden');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateWeeklyCost(daysInTargetWeek);
|
|
||||||
|
|
||||||
const headerWeekInfo = document.getElementById('header-week-info');
|
const headerWeekInfo = document.getElementById('header-week-info');
|
||||||
const weekTitle = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .displayMode */ .sw === 'this-week' ? (0,_i18n_js__WEBPACK_IMPORTED_MODULE_5__.t)('thisWeek') : (0,_i18n_js__WEBPACK_IMPORTED_MODULE_5__.t)('nextWeek');
|
const weekTitle = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .displayMode */ .sw === 'this-week' ? (0,_i18n_js__WEBPACK_IMPORTED_MODULE_5__.t)('thisWeek') : (0,_i18n_js__WEBPACK_IMPORTED_MODULE_5__.t)('nextWeek');
|
||||||
@@ -2718,13 +2691,7 @@ function injectUI() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center-wrapper">
|
<div class="header-center-wrapper">
|
||||||
<div id="lang-toggle" class="lang-toggle" title="Sprache der Menübeschreibung">
|
|
||||||
<button class="lang-btn${state/* langMode */.Kl === 'de' ? ' active' : ''}" data-lang="de">DE</button>
|
|
||||||
<button class="lang-btn${state/* langMode */.Kl === 'en' ? ' active' : ''}" data-lang="en">EN</button>
|
|
||||||
<button class="lang-btn${state/* langMode */.Kl === 'all' ? ' active' : ''}" data-lang="all">ALL</button>
|
|
||||||
</div>
|
|
||||||
<div id="header-week-info" class="header-week-info"></div>
|
<div id="header-week-info" class="header-week-info"></div>
|
||||||
<div id="weekly-cost-display" class="weekly-cost hidden"></div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<button id="btn-refresh" class="icon-btn" aria-label="Menüdaten aktualisieren" title="Menüdaten neu laden">
|
<button id="btn-refresh" class="icon-btn" aria-label="Menüdaten aktualisieren" title="Menüdaten neu laden">
|
||||||
@@ -2739,6 +2706,16 @@ function injectUI() {
|
|||||||
<button id="theme-toggle" class="icon-btn" aria-label="Toggle Theme" title="Erscheinungsbild (Hell/Dunkel) wechseln">
|
<button id="theme-toggle" class="icon-btn" aria-label="Toggle Theme" title="Erscheinungsbild (Hell/Dunkel) wechseln">
|
||||||
<span class="material-icons-round theme-icon">light_mode</span>
|
<span class="material-icons-round theme-icon">light_mode</span>
|
||||||
</button>
|
</button>
|
||||||
|
<div id="lang-toggle" class="lang-toggle-dropdown" title="Sprache der Menübeschreibung">
|
||||||
|
<button id="btn-lang-toggle" class="icon-btn" aria-label="Sprache wählen" title="Sprache der Menübeschreibung">
|
||||||
|
<span class="material-icons-round">translate</span>
|
||||||
|
</button>
|
||||||
|
<div id="lang-dropdown" class="lang-dropdown-menu hidden">
|
||||||
|
<button class="lang-btn${state/* langMode */.Kl === 'de' ? ' active' : ''}" data-lang="de">🇦🇹 DE</button>
|
||||||
|
<button class="lang-btn${state/* langMode */.Kl === 'en' ? ' active' : ''}" data-lang="en">🇬🇧 EN</button>
|
||||||
|
<button class="lang-btn${state/* langMode */.Kl === 'all' ? ' active' : ''}" data-lang="all">🌐 ALL</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<button id="btn-login-open" class="user-badge-btn icon-btn-small" title="Mit Bessa.app Account anmelden">
|
<button id="btn-login-open" class="user-badge-btn icon-btn-small" title="Mit Bessa.app Account anmelden">
|
||||||
<span class="material-icons-round">login</span>
|
<span class="material-icons-round">login</span>
|
||||||
<span>Anmelden</span>
|
<span>Anmelden</span>
|
||||||
@@ -3030,12 +3007,22 @@ function bindEvents() {
|
|||||||
const historyModal = document.getElementById('history-modal');
|
const historyModal = document.getElementById('history-modal');
|
||||||
const btnHistoryClose = document.getElementById('btn-history-close');
|
const btnHistoryClose = document.getElementById('btn-history-close');
|
||||||
|
|
||||||
|
const btnLangToggle = document.getElementById('btn-lang-toggle');
|
||||||
|
const langDropdown = document.getElementById('lang-dropdown');
|
||||||
|
if (btnLangToggle && langDropdown) {
|
||||||
|
btnLangToggle.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
langDropdown.classList.toggle('hidden');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
document.querySelectorAll('.lang-btn').forEach(btn => {
|
document.querySelectorAll('.lang-btn').forEach(btn => {
|
||||||
btn.addEventListener('click', () => {
|
btn.addEventListener('click', () => {
|
||||||
(0,state/* setLangMode */.UD)(btn.dataset.lang);
|
(0,state/* setLangMode */.UD)(btn.dataset.lang);
|
||||||
localStorage.setItem(constants.LS.LANG, btn.dataset.lang);
|
localStorage.setItem(constants.LS.LANG, btn.dataset.lang);
|
||||||
document.querySelectorAll('.lang-btn').forEach(b => b.classList.remove('active'));
|
document.querySelectorAll('.lang-btn').forEach(b => b.classList.remove('active'));
|
||||||
btn.classList.add('active');
|
btn.classList.add('active');
|
||||||
|
if (langDropdown) langDropdown.classList.add('hidden');
|
||||||
updateUILanguage();
|
updateUILanguage();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -3069,6 +3056,9 @@ function bindEvents() {
|
|||||||
window.addEventListener('click', (e) => {
|
window.addEventListener('click', (e) => {
|
||||||
if (e.target === historyModal) historyModal.classList.add('hidden');
|
if (e.target === historyModal) historyModal.classList.add('hidden');
|
||||||
if (e.target === highlightsModal) highlightsModal.classList.add('hidden');
|
if (e.target === highlightsModal) highlightsModal.classList.add('hidden');
|
||||||
|
if (langDropdown && !langDropdown.classList.contains('hidden') && !e.target.closest('#lang-toggle')) {
|
||||||
|
langDropdown.classList.add('hidden');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const versionTag = document.querySelector('.version-tag');
|
const versionTag = document.querySelector('.version-tag');
|
||||||
|
|||||||
@@ -120,12 +120,22 @@ export function bindEvents() {
|
|||||||
const historyModal = document.getElementById('history-modal');
|
const historyModal = document.getElementById('history-modal');
|
||||||
const btnHistoryClose = document.getElementById('btn-history-close');
|
const btnHistoryClose = document.getElementById('btn-history-close');
|
||||||
|
|
||||||
|
const btnLangToggle = document.getElementById('btn-lang-toggle');
|
||||||
|
const langDropdown = document.getElementById('lang-dropdown');
|
||||||
|
if (btnLangToggle && langDropdown) {
|
||||||
|
btnLangToggle.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
langDropdown.classList.toggle('hidden');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
document.querySelectorAll('.lang-btn').forEach(btn => {
|
document.querySelectorAll('.lang-btn').forEach(btn => {
|
||||||
btn.addEventListener('click', () => {
|
btn.addEventListener('click', () => {
|
||||||
setLangMode(btn.dataset.lang);
|
setLangMode(btn.dataset.lang);
|
||||||
localStorage.setItem(LS.LANG, btn.dataset.lang);
|
localStorage.setItem(LS.LANG, btn.dataset.lang);
|
||||||
document.querySelectorAll('.lang-btn').forEach(b => b.classList.remove('active'));
|
document.querySelectorAll('.lang-btn').forEach(b => b.classList.remove('active'));
|
||||||
btn.classList.add('active');
|
btn.classList.add('active');
|
||||||
|
if (langDropdown) langDropdown.classList.add('hidden');
|
||||||
updateUILanguage();
|
updateUILanguage();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -159,6 +169,9 @@ export function bindEvents() {
|
|||||||
window.addEventListener('click', (e) => {
|
window.addEventListener('click', (e) => {
|
||||||
if (e.target === historyModal) historyModal.classList.add('hidden');
|
if (e.target === historyModal) historyModal.classList.add('hidden');
|
||||||
if (e.target === highlightsModal) highlightsModal.classList.add('hidden');
|
if (e.target === highlightsModal) highlightsModal.classList.add('hidden');
|
||||||
|
if (langDropdown && !langDropdown.classList.contains('hidden') && !e.target.closest('#lang-toggle')) {
|
||||||
|
langDropdown.classList.add('hidden');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const versionTag = document.querySelector('.version-tag');
|
const versionTag = document.querySelector('.version-tag');
|
||||||
|
|||||||
@@ -100,7 +100,6 @@ const TRANSLATIONS = {
|
|||||||
noMenuDataHint: 'Versuchen Sie eine andere Woche oder schauen Sie später vorbei.',
|
noMenuDataHint: 'Versuchen Sie eine andere Woche oder schauen Sie später vorbei.',
|
||||||
|
|
||||||
// Weekly cost
|
// Weekly cost
|
||||||
costLabel: 'Gesamt',
|
|
||||||
|
|
||||||
// Countdown
|
// Countdown
|
||||||
orderDeadline: 'Bestellschluss',
|
orderDeadline: 'Bestellschluss',
|
||||||
@@ -236,7 +235,6 @@ const TRANSLATIONS = {
|
|||||||
noMenuDataHint: 'Try another week or check back later.',
|
noMenuDataHint: 'Try another week or check back later.',
|
||||||
|
|
||||||
// Weekly cost
|
// Weekly cost
|
||||||
costLabel: 'Total',
|
|
||||||
|
|
||||||
// Countdown
|
// Countdown
|
||||||
orderDeadline: 'Order deadline',
|
orderDeadline: 'Order deadline',
|
||||||
|
|||||||
16
src/ui.js
16
src/ui.js
@@ -54,13 +54,7 @@ export function injectUI() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center-wrapper">
|
<div class="header-center-wrapper">
|
||||||
<div id="lang-toggle" class="lang-toggle" title="Sprache der Menübeschreibung">
|
|
||||||
<button class="lang-btn${langMode === 'de' ? ' active' : ''}" data-lang="de">DE</button>
|
|
||||||
<button class="lang-btn${langMode === 'en' ? ' active' : ''}" data-lang="en">EN</button>
|
|
||||||
<button class="lang-btn${langMode === 'all' ? ' active' : ''}" data-lang="all">ALL</button>
|
|
||||||
</div>
|
|
||||||
<div id="header-week-info" class="header-week-info"></div>
|
<div id="header-week-info" class="header-week-info"></div>
|
||||||
<div id="weekly-cost-display" class="weekly-cost hidden"></div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<button id="btn-refresh" class="icon-btn" aria-label="Menüdaten aktualisieren" title="Menüdaten neu laden">
|
<button id="btn-refresh" class="icon-btn" aria-label="Menüdaten aktualisieren" title="Menüdaten neu laden">
|
||||||
@@ -75,6 +69,16 @@ export function injectUI() {
|
|||||||
<button id="theme-toggle" class="icon-btn" aria-label="Toggle Theme" title="Erscheinungsbild (Hell/Dunkel) wechseln">
|
<button id="theme-toggle" class="icon-btn" aria-label="Toggle Theme" title="Erscheinungsbild (Hell/Dunkel) wechseln">
|
||||||
<span class="material-icons-round theme-icon">light_mode</span>
|
<span class="material-icons-round theme-icon">light_mode</span>
|
||||||
</button>
|
</button>
|
||||||
|
<div id="lang-toggle" class="lang-toggle-dropdown" title="Sprache der Menübeschreibung">
|
||||||
|
<button id="btn-lang-toggle" class="icon-btn" aria-label="Sprache wählen" title="Sprache der Menübeschreibung">
|
||||||
|
<span class="material-icons-round">translate</span>
|
||||||
|
</button>
|
||||||
|
<div id="lang-dropdown" class="lang-dropdown-menu hidden">
|
||||||
|
<button class="lang-btn${langMode === 'de' ? ' active' : ''}" data-lang="de">🇦🇹 DE</button>
|
||||||
|
<button class="lang-btn${langMode === 'en' ? ' active' : ''}" data-lang="en">🇬🇧 EN</button>
|
||||||
|
<button class="lang-btn${langMode === 'all' ? ' active' : ''}" data-lang="all">🌐 ALL</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<button id="btn-login-open" class="user-badge-btn icon-btn-small" title="Mit Bessa.app Account anmelden">
|
<button id="btn-login-open" class="user-badge-btn icon-btn-small" title="Mit Bessa.app Account anmelden">
|
||||||
<span class="material-icons-round">login</span>
|
<span class="material-icons-round">login</span>
|
||||||
<span>Anmelden</span>
|
<span>Anmelden</span>
|
||||||
|
|||||||
@@ -90,29 +90,6 @@ export function updateNextWeekBadge() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateWeeklyCost(days) {
|
|
||||||
let totalCost = 0;
|
|
||||||
if (days && days.length > 0) {
|
|
||||||
days.forEach(day => {
|
|
||||||
if (day.items) {
|
|
||||||
day.items.forEach(item => {
|
|
||||||
const articleId = item.articleId || parseInt(item.id.split('_')[1]);
|
|
||||||
const key = `${day.date}_${articleId}`;
|
|
||||||
const orders = orderMap.get(key) || [];
|
|
||||||
if (orders.length > 0) totalCost += item.price * orders.length;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const costDisplay = document.getElementById('weekly-cost-display');
|
|
||||||
if (totalCost > 0) {
|
|
||||||
costDisplay.innerHTML = `<span class="material-icons-round">shopping_bag</span> <span>${t('costLabel')}: ${totalCost.toFixed(2).replace('.', ',')} €</span>`;
|
|
||||||
costDisplay.classList.remove('hidden');
|
|
||||||
} else {
|
|
||||||
costDisplay.classList.add('hidden');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function renderVisibleWeeks() {
|
export function renderVisibleWeeks() {
|
||||||
const menuContainer = document.getElementById('menu-container');
|
const menuContainer = document.getElementById('menu-container');
|
||||||
@@ -139,11 +116,9 @@ export function renderVisibleWeeks() {
|
|||||||
<p>${t('noMenuData')} ${targetWeek} (${targetYear}).</p>
|
<p>${t('noMenuData')} ${targetWeek} (${targetYear}).</p>
|
||||||
<small>${t('noMenuDataHint')}</small>
|
<small>${t('noMenuDataHint')}</small>
|
||||||
</div>`;
|
</div>`;
|
||||||
document.getElementById('weekly-cost-display').classList.add('hidden');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateWeeklyCost(daysInTargetWeek);
|
|
||||||
|
|
||||||
const headerWeekInfo = document.getElementById('header-week-info');
|
const headerWeekInfo = document.getElementById('header-week-info');
|
||||||
const weekTitle = displayMode === 'this-week' ? t('thisWeek') : t('nextWeek');
|
const weekTitle = displayMode === 'this-week' ? t('thisWeek') : t('nextWeek');
|
||||||
|
|||||||
77
style.css
77
style.css
@@ -404,23 +404,6 @@ body {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.weekly-cost {
|
|
||||||
background-color: rgba(59, 130, 246, 0.1);
|
|
||||||
/* Blue tint */
|
|
||||||
color: var(--accent-color);
|
|
||||||
padding: 0.4rem 0.8rem;
|
|
||||||
border-radius: 8px;
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
border: 1px solid rgba(59, 130, 246, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.weekly-cost .material-icons-round {
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Container - flex column, full width so child scrollbar is at edge */
|
/* Container - flex column, full width so child scrollbar is at edge */
|
||||||
.container {
|
.container {
|
||||||
@@ -470,6 +453,64 @@ body {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Language Toggle */
|
||||||
|
.lang-toggle-dropdown {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#btn-lang-toggle {
|
||||||
|
padding: 0;
|
||||||
|
min-width: 42px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lang-dropdown-menu {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% + 8px);
|
||||||
|
right: 0;
|
||||||
|
background: var(--bg-card);
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||||
|
z-index: 1001;
|
||||||
|
min-width: 120px;
|
||||||
|
padding: 8px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
animation: modalSlide 0.2s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lang-dropdown-menu .lang-btn {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
padding: 10px 14px;
|
||||||
|
border-radius: 8px;
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
text-align: left;
|
||||||
|
transition: all 0.2s;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lang-dropdown-menu .lang-btn:hover {
|
||||||
|
background: rgba(59, 130, 246, 0.1);
|
||||||
|
color: var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.lang-dropdown-menu .lang-btn.active {
|
||||||
|
background: rgba(59, 130, 246, 0.15);
|
||||||
|
color: var(--accent-color);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
.icon-btn-small {
|
.icon-btn-small {
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
@@ -829,7 +870,7 @@ body {
|
|||||||
|
|
||||||
.days-grid {
|
.days-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|||||||
@@ -63,9 +63,14 @@ const html = `
|
|||||||
<button id="btn-next-week">Next Week</button>
|
<button id="btn-next-week">Next Week</button>
|
||||||
|
|
||||||
<!-- Mocks for Language Toggle -->
|
<!-- Mocks for Language Toggle -->
|
||||||
<button class="lang-btn" data-lang="de">DE</button>
|
<div id="lang-toggle">
|
||||||
<button class="lang-btn" data-lang="en">EN</button>
|
<button id="btn-lang-toggle"><span class="material-icons-round">translate</span></button>
|
||||||
<button class="lang-btn" data-lang="all">ALL</button>
|
<div id="lang-dropdown" class="hidden">
|
||||||
|
<button class="lang-btn" data-lang="de">🇦🇹 DE</button>
|
||||||
|
<button class="lang-btn" data-lang="en">🇬🇧 EN</button>
|
||||||
|
<button class="lang-btn" data-lang="all">🌐 ALL</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button id="btn-refresh">Refresh</button>
|
<button id="btn-refresh">Refresh</button>
|
||||||
<button id="btn-logout">Logout</button>
|
<button id="btn-logout">Logout</button>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
v1.6.19
|
v1.6.22
|
||||||
|
|||||||
Reference in New Issue
Block a user