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