diff --git a/package.json b/package.json index 80895d1..a8e0f9d 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "test:dashboard": "node --experimental-sqlite test-dashboard.js", "test:tasks": "node --experimental-sqlite test-tasks.js", "test:shopping": "node --experimental-sqlite test-shopping.js", - "test": "node --experimental-sqlite test-db.js && node --experimental-sqlite test-dashboard.js && node --experimental-sqlite test-tasks.js && node --experimental-sqlite test-shopping.js" + "test:meals": "node --experimental-sqlite test-meals.js", + "test": "node --experimental-sqlite test-db.js && node --experimental-sqlite test-dashboard.js && node --experimental-sqlite test-tasks.js && node --experimental-sqlite test-shopping.js && node --experimental-sqlite test-meals.js" }, "dependencies": { "bcrypt": "^5.1.1", diff --git a/public/index.html b/public/index.html index ab09bcb..9f4b52f 100644 --- a/public/index.html +++ b/public/index.html @@ -19,6 +19,7 @@ + diff --git a/public/pages/meals.js b/public/pages/meals.js index db1103a..84ff9ee 100644 --- a/public/pages/meals.js +++ b/public/pages/meals.js @@ -1,25 +1,592 @@ /** - * Modul: Meals - * Zweck: Seite für das Meals-Modul - * Abhängigkeiten: /api.js + * Modul: Essensplan (Meals) + * Zweck: Wochenansicht mit Mahlzeit-CRUD, Zutaten-Verwaltung und Einkaufslisten-Integration + * Abhängigkeiten: /api.js, /router.js (window.oikos) */ import { api } from '/api.js'; -/** - * @param {HTMLElement} container - * @param {{ user: object }} context - */ +// -------------------------------------------------------- +// Konstanten +// -------------------------------------------------------- + +const MEAL_TYPES = [ + { key: 'breakfast', label: 'Frühstück', icon: 'sunrise' }, + { key: 'lunch', label: 'Mittagessen', icon: 'sun' }, + { key: 'dinner', label: 'Abendessen', icon: 'moon' }, + { key: 'snack', label: 'Snack', icon: 'cookie' }, +]; + +const DAY_NAMES = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']; + +// -------------------------------------------------------- +// State +// -------------------------------------------------------- + +let state = { + currentWeek: null, // YYYY-MM-DD (Montag) + meals: [], + lists: [], // Einkaufslisten für Transfer-Dropdown + modal: null, +}; + +// -------------------------------------------------------- +// Datumshelfer +// -------------------------------------------------------- + +function getMondayOf(dateStr) { + const d = new Date(dateStr + 'T00:00:00Z'); + const day = d.getUTCDay(); + const diff = (day === 0 ? -6 : 1 - day); + d.setUTCDate(d.getUTCDate() + diff); + return d.toISOString().slice(0, 10); +} + +function addDays(dateStr, n) { + const d = new Date(dateStr + 'T00:00:00Z'); + d.setUTCDate(d.getUTCDate() + n); + return d.toISOString().slice(0, 10); +} + +function formatWeekLabel(monday) { + const sunday = addDays(monday, 6); + const fmt = (s) => { + const d = new Date(s + 'T00:00:00Z'); + return `${d.getUTCDate().toString().padStart(2, '0')}.${(d.getUTCMonth() + 1).toString().padStart(2, '0')}.${d.getUTCFullYear()}`; + }; + return `${fmt(monday)} – ${fmt(sunday)}`; +} + +function isToday(dateStr) { + return dateStr === new Date().toISOString().slice(0, 10); +} + +function formatDayDate(dateStr) { + const d = new Date(dateStr + 'T00:00:00Z'); + return `${d.getUTCDate()}.${d.getUTCMonth() + 1}.`; +} + +// -------------------------------------------------------- +// API-Wrapper +// -------------------------------------------------------- + +async function loadWeek(week) { + const res = await api.get(`/meals?week=${week}`); + state.meals = res.data; + state.currentWeek = getMondayOf(week); +} + +async function loadLists() { + try { + const res = await api.get('/shopping'); + state.lists = res.data; + } catch { + state.lists = []; + } +} + +// -------------------------------------------------------- +// Render +// -------------------------------------------------------- + export async function render(container, { user }) { container.innerHTML = ` -
-