diff --git a/docker/index.html b/docker/index.html index 790e601..dd4a32c 100644 --- a/docker/index.html +++ b/docker/index.html @@ -2341,6 +2341,7 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food- let dagboek = {}; // { "2026-07-23": { "Ontbijt": [{item, portie}, ...], ... } } let activeDate = formatDate(new Date()); let activeTab = 'zoeken'; + let lastClickY = null; // tracked for toast positioning let selectedCategory = null; // null = alle let searchQuery = ''; let searchIndex = null; // Map @@ -4139,6 +4140,13 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food- toast.className = 'toast'; toast.textContent = message; container.appendChild(toast); + // Position at last click Y, or default bottom + const y = lastClickY || window.innerHeight - 120; + const h = toast.offsetHeight || 50; + const maxY = window.innerHeight - h - 16; + const top = Math.min(y, maxY); + toast.style.top = top + 'px'; + toast.style.bottom = 'auto'; setTimeout(() => { toast.classList.add('hiding'); setTimeout(() => toast.remove(), 300); @@ -4667,15 +4675,16 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food- } // Start the app - // Haptic feedback: vibrate on every button press (native Vibration API — Android only, iOS silently ignores) + // Track last click position for toast positioning + haptic feedback (function setupHaptics() { - if (typeof navigator !== 'undefined' && navigator.vibrate) { - document.addEventListener('click', (e) => { + document.addEventListener('click', (e) => { + lastClickY = e.clientY; + if (typeof navigator !== 'undefined' && navigator.vibrate) { if (e.target.tagName === 'BUTTON' || e.target.closest('button')) { navigator.vibrate(8); } - }, { passive: true }); - } + } + }, { passive: true }); })(); if (document.readyState === 'loading') { diff --git a/index.html b/index.html index 790e601..dd4a32c 100644 --- a/index.html +++ b/index.html @@ -2341,6 +2341,7 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food- let dagboek = {}; // { "2026-07-23": { "Ontbijt": [{item, portie}, ...], ... } } let activeDate = formatDate(new Date()); let activeTab = 'zoeken'; + let lastClickY = null; // tracked for toast positioning let selectedCategory = null; // null = alle let searchQuery = ''; let searchIndex = null; // Map @@ -4139,6 +4140,13 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food- toast.className = 'toast'; toast.textContent = message; container.appendChild(toast); + // Position at last click Y, or default bottom + const y = lastClickY || window.innerHeight - 120; + const h = toast.offsetHeight || 50; + const maxY = window.innerHeight - h - 16; + const top = Math.min(y, maxY); + toast.style.top = top + 'px'; + toast.style.bottom = 'auto'; setTimeout(() => { toast.classList.add('hiding'); setTimeout(() => toast.remove(), 300); @@ -4667,15 +4675,16 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food- } // Start the app - // Haptic feedback: vibrate on every button press (native Vibration API — Android only, iOS silently ignores) + // Track last click position for toast positioning + haptic feedback (function setupHaptics() { - if (typeof navigator !== 'undefined' && navigator.vibrate) { - document.addEventListener('click', (e) => { + document.addEventListener('click', (e) => { + lastClickY = e.clientY; + if (typeof navigator !== 'undefined' && navigator.vibrate) { if (e.target.tagName === 'BUTTON' || e.target.closest('button')) { navigator.vibrate(8); } - }, { passive: true }); - } + } + }, { passive: true }); })(); if (document.readyState === 'loading') { diff --git a/tests/e2e.spec.js b/tests/e2e.spec.js index 449c175..9babde2 100644 --- a/tests/e2e.spec.js +++ b/tests/e2e.spec.js @@ -290,29 +290,45 @@ test.describe('Karby Eetdagboek', () => { test('meal-group uitklappen: saved meal toggles expand/collapse in dagboek', async ({ page }) => { await page.goto(BASE); - // Stap 1: Zoek voedingsmiddel + // Stap 1: Zoek voedingsmiddel en voeg toe aan dagboek await page.locator('.search-input').fill('brood'); await page.waitForTimeout(800); await page.locator('.food-item').first().click(); await page.waitForTimeout(500); - // Stap 2: Voeg toe via detailAddBtn → addMealModal await page.locator('#detailAddBtn').click(); await page.waitForTimeout(500); - // Stap 3: Klik Toevoegen in addMealModal → item in dagboek await page.locator('#addMealSubmit').click(); await page.waitForTimeout(800); - // Stap 4: Opslaan als maaltijd + // Stap 2: Sla op als maaltijd const saveBtn = page.locator('.save-meal-btn'); await expect(saveBtn.first()).toBeVisible({ timeout: 5000 }); await saveBtn.first().click(); await page.waitForTimeout(500); - // Stap 5: Naam invullen en opslaan const nameInput = page.locator('#mealNameInput'); await expect(nameInput).toBeVisible({ timeout: 5000 }); await nameInput.fill('Test ontbijt'); await page.locator('#mealNameSave').click(); await page.waitForTimeout(600); - // Stap 6: Ga naar dagboek om meal-group te zien + // Stap 3: Ga naar maaltijden tab om de maaltijd toe te voegen aan dagboek + await page.locator('#navMaaltijden').click(); + await page.waitForTimeout(600); + // Stap 4: Klik "Toevoegen aan dagboek" op de opgeslagen maaltijd + const mealCardAdd = page.locator('.meal-card-add').first(); + await expect(mealCardAdd).toBeVisible({ timeout: 5000 }); + await mealCardAdd.click(); + await page.waitForTimeout(500); + // Stap 5: Klik op een eetmoment-optie in de modal (bv. Ontbijt) + const mealOption = page.locator('.meal-add-option').first(); + await expect(mealOption).toBeVisible({ timeout: 3000 }); + await mealOption.click(); + await page.waitForTimeout(600); + // Sluit eventuele resteerde modals door op de overlay te klikken + const anyOverlay = page.locator('.modal-overlay:not(.hidden)').first(); + if (await anyOverlay.isVisible().catch(() => false)) { + await anyOverlay.click({ position: { x: 10, y: 10 } }); + await page.waitForTimeout(300); + } + // Stap 6: Ga naar dagboek om de meal-group te zien await page.locator('#navDagboek').click(); await page.waitForTimeout(800); // Stap 7: Zoek meal-group