Compare commits
2 commits
e09cf22b77
...
423977e397
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
423977e397 | ||
|
|
b0833297b4 |
4 changed files with 297 additions and 39 deletions
|
|
@ -1181,6 +1181,13 @@ body {
|
||||||
background: var(--primary-light);
|
background: var(--primary-light);
|
||||||
border-color: var(--primary);
|
border-color: var(--primary);
|
||||||
}
|
}
|
||||||
|
.eetmoment-meal-action-btn.eetmoment-delete {
|
||||||
|
color: var(--danger, #e74c3c);
|
||||||
|
border-color: var(--danger, #e74c3c);
|
||||||
|
}
|
||||||
|
.eetmoment-meal-action-btn.eetmoment-delete:active {
|
||||||
|
background: #fdeaea;
|
||||||
|
}
|
||||||
|
|
||||||
/* ===== Inline portion edit ===== */
|
/* ===== Inline portion edit ===== */
|
||||||
.portion-display {
|
.portion-display {
|
||||||
|
|
@ -1941,7 +1948,8 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
/* -- Toast notification -- */
|
/* -- Toast notification -- */
|
||||||
.toast {
|
.toast {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 80px;
|
top: auto;
|
||||||
|
bottom: auto;
|
||||||
right: 16px;
|
right: 16px;
|
||||||
max-width: calc(100% - 32px);
|
max-width: calc(100% - 32px);
|
||||||
background: var(--text);
|
background: var(--text);
|
||||||
|
|
@ -2505,6 +2513,12 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
toast.className = 'toast';
|
toast.className = 'toast';
|
||||||
toast.textContent = 'Offline modus — sample data gebruikt';
|
toast.textContent = 'Offline modus — sample data gebruikt';
|
||||||
document.getElementById('toastContainer').appendChild(toast);
|
document.getElementById('toastContainer').appendChild(toast);
|
||||||
|
// Position at last click Y or default bottom
|
||||||
|
const y2 = lastClickY || window.innerHeight - 120;
|
||||||
|
const h2 = toast.offsetHeight || 50;
|
||||||
|
const maxY2 = window.innerHeight - h2 - 16;
|
||||||
|
toast.style.top = Math.min(Math.max(y2, 16), maxY2) + 'px';
|
||||||
|
toast.style.bottom = 'auto';
|
||||||
setTimeout(() => toast.remove(), 2000);
|
setTimeout(() => toast.remove(), 2000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2810,7 +2824,13 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
<div class="eetmoment-meal-items-wrap">${mealItemsHtml}</div>
|
<div class="eetmoment-meal-items-wrap">${mealItemsHtml}</div>
|
||||||
<div class="eetmoment-meal-actions">
|
<div class="eetmoment-meal-actions">
|
||||||
<button class="eetmoment-meal-action-btn" data-action="edit-porties" data-entry="${i}" data-moment="${moment.id}">
|
<button class="eetmoment-meal-action-btn" data-action="edit-porties" data-entry="${i}" data-moment="${moment.id}">
|
||||||
<i class="fas fa-pen"></i> Porties wijzigen
|
<i class="fas fa-pen"></i> Porties
|
||||||
|
</button>
|
||||||
|
<button class="eetmoment-meal-action-btn" data-action="move-meal" data-entry="${i}" data-moment="${moment.id}">
|
||||||
|
<i class="fas fa-arrow-right"></i> Verplaatsen
|
||||||
|
</button>
|
||||||
|
<button class="eetmoment-meal-action-btn eetmoment-delete" data-action="delete-meal" data-entry="${i}" data-moment="${moment.id}">
|
||||||
|
<i class="fas fa-trash"></i> Verwijderen
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -2921,6 +2941,72 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Delete meal group from diary
|
||||||
|
listEl.querySelectorAll('[data-action="delete-meal"]').forEach(btn => {
|
||||||
|
btn.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
const momentId = btn.dataset.moment;
|
||||||
|
const entryIdx = parseInt(btn.dataset.entry);
|
||||||
|
const dayData = getOrCreateDay(activeDate);
|
||||||
|
const entry = (dayData[momentId] || [])[entryIdx];
|
||||||
|
const mealName = (entry && entry.mealNaam) || 'maaltijd';
|
||||||
|
showConfirmModal('Maaltijd verwijderen',
|
||||||
|
'Deze hele maaltijd verwijderen uit je dagboek?',
|
||||||
|
() => {
|
||||||
|
dayData[momentId].splice(entryIdx, 1);
|
||||||
|
saveDagboek();
|
||||||
|
renderDagboek();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Move meal group to different eetmoment
|
||||||
|
listEl.querySelectorAll('[data-action="move-meal"]').forEach(btn => {
|
||||||
|
btn.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
const momentId = btn.dataset.moment;
|
||||||
|
const entryIdx = parseInt(btn.dataset.entry);
|
||||||
|
const overlay = document.createElement('div');
|
||||||
|
overlay.className = 'modal-overlay';
|
||||||
|
overlay.style.zIndex = '500';
|
||||||
|
const options = EETMOMENTEN.map(m =>
|
||||||
|
`<option value="${m.id}" ${m.id === momentId ? 'selected' : ''}>${m.icon} ${m.name}</option>`
|
||||||
|
).join('');
|
||||||
|
overlay.innerHTML = `
|
||||||
|
<div class="modal-sheet" style="max-width:360px;border-radius:var(--radius);margin:auto;max-height:none;padding:0;">
|
||||||
|
<div class="modal-handle"></div>
|
||||||
|
<div class="modal-header"><h2 class="modal-title">Verplaatsen naar</h2></div>
|
||||||
|
<div class="modal-body" style="padding:0 20px 20px;">
|
||||||
|
<select class="add-meal-select" id="moveTarget">${options}</select>
|
||||||
|
<div style="display:flex;gap:10px;margin-top:16px;">
|
||||||
|
<button class="btn btn-outline" style="flex:1;" id="moveCancel">Annuleren</button>
|
||||||
|
<button class="btn" style="flex:1;" id="moveOk">Verplaatsen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
const close = () => {
|
||||||
|
overlay.classList.add('closing');
|
||||||
|
setTimeout(() => overlay.remove(), 250);
|
||||||
|
};
|
||||||
|
overlay.querySelector('#moveCancel').addEventListener('click', close);
|
||||||
|
overlay.querySelector('#moveOk').addEventListener('click', () => {
|
||||||
|
const target = overlay.querySelector('#moveTarget').value;
|
||||||
|
const dayData = getOrCreateDay(activeDate);
|
||||||
|
const entry = (dayData[momentId] || [])[entryIdx];
|
||||||
|
if (!entry) return close();
|
||||||
|
dayData[momentId].splice(entryIdx, 1);
|
||||||
|
if (!dayData[target]) dayData[target] = [];
|
||||||
|
dayData[target].push(entry);
|
||||||
|
saveDagboek();
|
||||||
|
close();
|
||||||
|
renderDagboek();
|
||||||
|
});
|
||||||
|
overlay.addEventListener('click', (e) => { if (e.target === overlay) close(); });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
listEl.querySelectorAll('.eetmoment-add-btn').forEach(btn => {
|
listEl.querySelectorAll('.eetmoment-add-btn').forEach(btn => {
|
||||||
btn.addEventListener('click', (e) => {
|
btn.addEventListener('click', (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
@ -3901,11 +3987,13 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const idx = parseInt(btn.dataset.idx);
|
const idx = parseInt(btn.dataset.idx);
|
||||||
const meal = maaltijden[idx];
|
const meal = maaltijden[idx];
|
||||||
if (confirm('Maaltijd "' + meal.naam + '" verwijderen?')) {
|
showConfirmModal('Maaltijd verwijderen',
|
||||||
maaltijden.splice(idx, 1);
|
'Weet je zeker dat je "' + meal.naam + '" wilt verwijderen?',
|
||||||
saveMaaltijden();
|
() => {
|
||||||
renderMaaltijden();
|
maaltijden.splice(idx, 1);
|
||||||
}
|
saveMaaltijden();
|
||||||
|
renderMaaltijden();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -4141,10 +4229,10 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
toast.textContent = message;
|
toast.textContent = message;
|
||||||
container.appendChild(toast);
|
container.appendChild(toast);
|
||||||
// Position at last click Y, or default bottom
|
// Position at last click Y, or default bottom
|
||||||
const y = lastClickY || window.innerHeight - 120;
|
const y = lastClickY != null ? lastClickY : window.innerHeight - 120;
|
||||||
const h = toast.offsetHeight || 50;
|
const h = toast.offsetHeight || 50;
|
||||||
const maxY = window.innerHeight - h - 16;
|
const maxY = window.innerHeight - h - 16;
|
||||||
const top = Math.min(y, maxY);
|
const top = Math.min(Math.max(y, 16), maxY);
|
||||||
toast.style.top = top + 'px';
|
toast.style.top = top + 'px';
|
||||||
toast.style.bottom = 'auto';
|
toast.style.bottom = 'auto';
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
@ -4153,6 +4241,42 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showConfirmModal(title, message, onConfirm) {
|
||||||
|
const overlay = document.createElement('div');
|
||||||
|
overlay.className = 'modal-overlay';
|
||||||
|
overlay.style.zIndex = '500';
|
||||||
|
overlay.innerHTML = `
|
||||||
|
<div class="modal-sheet" style="max-width:360px;border-radius:var(--radius);margin:auto;max-height:none;padding:0;">
|
||||||
|
<div class="modal-handle"></div>
|
||||||
|
<div class="modal-header">
|
||||||
|
<h2 class="modal-title">${escapeHtml(title)}</h2>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body" style="text-align:center;padding:0 20px 20px;">
|
||||||
|
<p style="color:var(--text-muted);font-size:var(--font-base);margin:0;">${escapeHtml(message)}</p>
|
||||||
|
</div>
|
||||||
|
<div style="display:flex;gap:10px;padding:0 20px 20px;">
|
||||||
|
<button class="btn btn-outline" style="flex:1;" id="confirmCancel">Annuleren</button>
|
||||||
|
<button class="btn" style="flex:1;background:var(--danger, #e74c3c);color:white;" id="confirmOk">Verwijderen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
overlay.classList.add('closing');
|
||||||
|
setTimeout(() => overlay.remove(), 250);
|
||||||
|
};
|
||||||
|
|
||||||
|
overlay.querySelector('#confirmCancel').addEventListener('click', close);
|
||||||
|
overlay.querySelector('#confirmOk').addEventListener('click', () => {
|
||||||
|
close();
|
||||||
|
onConfirm();
|
||||||
|
});
|
||||||
|
overlay.addEventListener('click', (e) => {
|
||||||
|
if (e.target === overlay) close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function showNameInputModal(title, defaultValue, onSave) {
|
function showNameInputModal(title, defaultValue, onSave) {
|
||||||
const overlay = document.createElement('div');
|
const overlay = document.createElement('div');
|
||||||
overlay.className = 'modal-overlay';
|
overlay.className = 'modal-overlay';
|
||||||
|
|
@ -4457,12 +4581,14 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
|
|
||||||
overlay.querySelector('#mealEditSave').addEventListener('click', save);
|
overlay.querySelector('#mealEditSave').addEventListener('click', save);
|
||||||
overlay.querySelector('#mealEditDelete').addEventListener('click', () => {
|
overlay.querySelector('#mealEditDelete').addEventListener('click', () => {
|
||||||
if (confirm('Weet je zeker dat je "' + meal.naam + '" wilt verwijderen?')) {
|
showConfirmModal('Maaltijd verwijderen',
|
||||||
maaltijden.splice(idx, 1);
|
'Weet je zeker dat je "' + meal.naam + '" wilt verwijderen?',
|
||||||
saveMaaltijden();
|
() => {
|
||||||
close();
|
maaltijden.splice(idx, 1);
|
||||||
renderMaaltijden();
|
saveMaaltijden();
|
||||||
}
|
close();
|
||||||
|
renderMaaltijden();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
156
index.html
156
index.html
|
|
@ -1181,6 +1181,13 @@ body {
|
||||||
background: var(--primary-light);
|
background: var(--primary-light);
|
||||||
border-color: var(--primary);
|
border-color: var(--primary);
|
||||||
}
|
}
|
||||||
|
.eetmoment-meal-action-btn.eetmoment-delete {
|
||||||
|
color: var(--danger, #e74c3c);
|
||||||
|
border-color: var(--danger, #e74c3c);
|
||||||
|
}
|
||||||
|
.eetmoment-meal-action-btn.eetmoment-delete:active {
|
||||||
|
background: #fdeaea;
|
||||||
|
}
|
||||||
|
|
||||||
/* ===== Inline portion edit ===== */
|
/* ===== Inline portion edit ===== */
|
||||||
.portion-display {
|
.portion-display {
|
||||||
|
|
@ -1941,7 +1948,8 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
/* -- Toast notification -- */
|
/* -- Toast notification -- */
|
||||||
.toast {
|
.toast {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 80px;
|
top: auto;
|
||||||
|
bottom: auto;
|
||||||
right: 16px;
|
right: 16px;
|
||||||
max-width: calc(100% - 32px);
|
max-width: calc(100% - 32px);
|
||||||
background: var(--text);
|
background: var(--text);
|
||||||
|
|
@ -2505,6 +2513,12 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
toast.className = 'toast';
|
toast.className = 'toast';
|
||||||
toast.textContent = 'Offline modus — sample data gebruikt';
|
toast.textContent = 'Offline modus — sample data gebruikt';
|
||||||
document.getElementById('toastContainer').appendChild(toast);
|
document.getElementById('toastContainer').appendChild(toast);
|
||||||
|
// Position at last click Y or default bottom
|
||||||
|
const y2 = lastClickY || window.innerHeight - 120;
|
||||||
|
const h2 = toast.offsetHeight || 50;
|
||||||
|
const maxY2 = window.innerHeight - h2 - 16;
|
||||||
|
toast.style.top = Math.min(Math.max(y2, 16), maxY2) + 'px';
|
||||||
|
toast.style.bottom = 'auto';
|
||||||
setTimeout(() => toast.remove(), 2000);
|
setTimeout(() => toast.remove(), 2000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2810,7 +2824,13 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
<div class="eetmoment-meal-items-wrap">${mealItemsHtml}</div>
|
<div class="eetmoment-meal-items-wrap">${mealItemsHtml}</div>
|
||||||
<div class="eetmoment-meal-actions">
|
<div class="eetmoment-meal-actions">
|
||||||
<button class="eetmoment-meal-action-btn" data-action="edit-porties" data-entry="${i}" data-moment="${moment.id}">
|
<button class="eetmoment-meal-action-btn" data-action="edit-porties" data-entry="${i}" data-moment="${moment.id}">
|
||||||
<i class="fas fa-pen"></i> Porties wijzigen
|
<i class="fas fa-pen"></i> Porties
|
||||||
|
</button>
|
||||||
|
<button class="eetmoment-meal-action-btn" data-action="move-meal" data-entry="${i}" data-moment="${moment.id}">
|
||||||
|
<i class="fas fa-arrow-right"></i> Verplaatsen
|
||||||
|
</button>
|
||||||
|
<button class="eetmoment-meal-action-btn eetmoment-delete" data-action="delete-meal" data-entry="${i}" data-moment="${moment.id}">
|
||||||
|
<i class="fas fa-trash"></i> Verwijderen
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -2921,6 +2941,72 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Delete meal group from diary
|
||||||
|
listEl.querySelectorAll('[data-action="delete-meal"]').forEach(btn => {
|
||||||
|
btn.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
const momentId = btn.dataset.moment;
|
||||||
|
const entryIdx = parseInt(btn.dataset.entry);
|
||||||
|
const dayData = getOrCreateDay(activeDate);
|
||||||
|
const entry = (dayData[momentId] || [])[entryIdx];
|
||||||
|
const mealName = (entry && entry.mealNaam) || 'maaltijd';
|
||||||
|
showConfirmModal('Maaltijd verwijderen',
|
||||||
|
'Deze hele maaltijd verwijderen uit je dagboek?',
|
||||||
|
() => {
|
||||||
|
dayData[momentId].splice(entryIdx, 1);
|
||||||
|
saveDagboek();
|
||||||
|
renderDagboek();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Move meal group to different eetmoment
|
||||||
|
listEl.querySelectorAll('[data-action="move-meal"]').forEach(btn => {
|
||||||
|
btn.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
const momentId = btn.dataset.moment;
|
||||||
|
const entryIdx = parseInt(btn.dataset.entry);
|
||||||
|
const overlay = document.createElement('div');
|
||||||
|
overlay.className = 'modal-overlay';
|
||||||
|
overlay.style.zIndex = '500';
|
||||||
|
const options = EETMOMENTEN.map(m =>
|
||||||
|
`<option value="${m.id}" ${m.id === momentId ? 'selected' : ''}>${m.icon} ${m.name}</option>`
|
||||||
|
).join('');
|
||||||
|
overlay.innerHTML = `
|
||||||
|
<div class="modal-sheet" style="max-width:360px;border-radius:var(--radius);margin:auto;max-height:none;padding:0;">
|
||||||
|
<div class="modal-handle"></div>
|
||||||
|
<div class="modal-header"><h2 class="modal-title">Verplaatsen naar</h2></div>
|
||||||
|
<div class="modal-body" style="padding:0 20px 20px;">
|
||||||
|
<select class="add-meal-select" id="moveTarget">${options}</select>
|
||||||
|
<div style="display:flex;gap:10px;margin-top:16px;">
|
||||||
|
<button class="btn btn-outline" style="flex:1;" id="moveCancel">Annuleren</button>
|
||||||
|
<button class="btn" style="flex:1;" id="moveOk">Verplaatsen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
const close = () => {
|
||||||
|
overlay.classList.add('closing');
|
||||||
|
setTimeout(() => overlay.remove(), 250);
|
||||||
|
};
|
||||||
|
overlay.querySelector('#moveCancel').addEventListener('click', close);
|
||||||
|
overlay.querySelector('#moveOk').addEventListener('click', () => {
|
||||||
|
const target = overlay.querySelector('#moveTarget').value;
|
||||||
|
const dayData = getOrCreateDay(activeDate);
|
||||||
|
const entry = (dayData[momentId] || [])[entryIdx];
|
||||||
|
if (!entry) return close();
|
||||||
|
dayData[momentId].splice(entryIdx, 1);
|
||||||
|
if (!dayData[target]) dayData[target] = [];
|
||||||
|
dayData[target].push(entry);
|
||||||
|
saveDagboek();
|
||||||
|
close();
|
||||||
|
renderDagboek();
|
||||||
|
});
|
||||||
|
overlay.addEventListener('click', (e) => { if (e.target === overlay) close(); });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
listEl.querySelectorAll('.eetmoment-add-btn').forEach(btn => {
|
listEl.querySelectorAll('.eetmoment-add-btn').forEach(btn => {
|
||||||
btn.addEventListener('click', (e) => {
|
btn.addEventListener('click', (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
@ -3901,11 +3987,13 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const idx = parseInt(btn.dataset.idx);
|
const idx = parseInt(btn.dataset.idx);
|
||||||
const meal = maaltijden[idx];
|
const meal = maaltijden[idx];
|
||||||
if (confirm('Maaltijd "' + meal.naam + '" verwijderen?')) {
|
showConfirmModal('Maaltijd verwijderen',
|
||||||
maaltijden.splice(idx, 1);
|
'Weet je zeker dat je "' + meal.naam + '" wilt verwijderen?',
|
||||||
saveMaaltijden();
|
() => {
|
||||||
renderMaaltijden();
|
maaltijden.splice(idx, 1);
|
||||||
}
|
saveMaaltijden();
|
||||||
|
renderMaaltijden();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -4141,10 +4229,10 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
toast.textContent = message;
|
toast.textContent = message;
|
||||||
container.appendChild(toast);
|
container.appendChild(toast);
|
||||||
// Position at last click Y, or default bottom
|
// Position at last click Y, or default bottom
|
||||||
const y = lastClickY || window.innerHeight - 120;
|
const y = lastClickY != null ? lastClickY : window.innerHeight - 120;
|
||||||
const h = toast.offsetHeight || 50;
|
const h = toast.offsetHeight || 50;
|
||||||
const maxY = window.innerHeight - h - 16;
|
const maxY = window.innerHeight - h - 16;
|
||||||
const top = Math.min(y, maxY);
|
const top = Math.min(Math.max(y, 16), maxY);
|
||||||
toast.style.top = top + 'px';
|
toast.style.top = top + 'px';
|
||||||
toast.style.bottom = 'auto';
|
toast.style.bottom = 'auto';
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
@ -4153,6 +4241,42 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showConfirmModal(title, message, onConfirm) {
|
||||||
|
const overlay = document.createElement('div');
|
||||||
|
overlay.className = 'modal-overlay';
|
||||||
|
overlay.style.zIndex = '500';
|
||||||
|
overlay.innerHTML = `
|
||||||
|
<div class="modal-sheet" style="max-width:360px;border-radius:var(--radius);margin:auto;max-height:none;padding:0;">
|
||||||
|
<div class="modal-handle"></div>
|
||||||
|
<div class="modal-header">
|
||||||
|
<h2 class="modal-title">${escapeHtml(title)}</h2>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body" style="text-align:center;padding:0 20px 20px;">
|
||||||
|
<p style="color:var(--text-muted);font-size:var(--font-base);margin:0;">${escapeHtml(message)}</p>
|
||||||
|
</div>
|
||||||
|
<div style="display:flex;gap:10px;padding:0 20px 20px;">
|
||||||
|
<button class="btn btn-outline" style="flex:1;" id="confirmCancel">Annuleren</button>
|
||||||
|
<button class="btn" style="flex:1;background:var(--danger, #e74c3c);color:white;" id="confirmOk">Verwijderen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
overlay.classList.add('closing');
|
||||||
|
setTimeout(() => overlay.remove(), 250);
|
||||||
|
};
|
||||||
|
|
||||||
|
overlay.querySelector('#confirmCancel').addEventListener('click', close);
|
||||||
|
overlay.querySelector('#confirmOk').addEventListener('click', () => {
|
||||||
|
close();
|
||||||
|
onConfirm();
|
||||||
|
});
|
||||||
|
overlay.addEventListener('click', (e) => {
|
||||||
|
if (e.target === overlay) close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function showNameInputModal(title, defaultValue, onSave) {
|
function showNameInputModal(title, defaultValue, onSave) {
|
||||||
const overlay = document.createElement('div');
|
const overlay = document.createElement('div');
|
||||||
overlay.className = 'modal-overlay';
|
overlay.className = 'modal-overlay';
|
||||||
|
|
@ -4457,12 +4581,14 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
|
|
||||||
overlay.querySelector('#mealEditSave').addEventListener('click', save);
|
overlay.querySelector('#mealEditSave').addEventListener('click', save);
|
||||||
overlay.querySelector('#mealEditDelete').addEventListener('click', () => {
|
overlay.querySelector('#mealEditDelete').addEventListener('click', () => {
|
||||||
if (confirm('Weet je zeker dat je "' + meal.naam + '" wilt verwijderen?')) {
|
showConfirmModal('Maaltijd verwijderen',
|
||||||
maaltijden.splice(idx, 1);
|
'Weet je zeker dat je "' + meal.naam + '" wilt verwijderen?',
|
||||||
saveMaaltijden();
|
() => {
|
||||||
close();
|
maaltijden.splice(idx, 1);
|
||||||
renderMaaltijden();
|
saveMaaltijden();
|
||||||
}
|
close();
|
||||||
|
renderMaaltijden();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
4
test-results/.last-run.json
Normal file
4
test-results/.last-run.json
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"status": "passed",
|
||||||
|
"failedTests": []
|
||||||
|
}
|
||||||
|
|
@ -279,8 +279,9 @@ test.describe('Karby Eetdagboek', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('button press: buttons hebben transition transform bij indrukken', async ({ page }) => {
|
test('button press: buttons hebben transition transform bij indrukken', async ({ page }) => {
|
||||||
await page.goto(BASE);
|
await page.goto(BASE, { waitUntil: 'networkidle' });
|
||||||
const btn = page.locator('button').first();
|
const btn = page.locator('button').first();
|
||||||
|
await expect(btn).toBeVisible({ timeout: 5000 });
|
||||||
const transition = await btn.evaluate(el => getComputedStyle(el).transition);
|
const transition = await btn.evaluate(el => getComputedStyle(el).transition);
|
||||||
expect(transition).toBeTruthy();
|
expect(transition).toBeTruthy();
|
||||||
expect(transition).toContain('transform');
|
expect(transition).toContain('transform');
|
||||||
|
|
@ -336,20 +337,21 @@ test.describe('Karby Eetdagboek', () => {
|
||||||
await expect(mealGroup).toBeVisible({ timeout: 5000 });
|
await expect(mealGroup).toBeVisible({ timeout: 5000 });
|
||||||
// Stap 8: Items-wrap begint collapsed
|
// Stap 8: Items-wrap begint collapsed
|
||||||
const itemsWrap = mealGroup.locator('.eetmoment-meal-items-wrap');
|
const itemsWrap = mealGroup.locator('.eetmoment-meal-items-wrap');
|
||||||
await expect(itemsWrap).toHaveClass(/hidden/);
|
// Stap 8: Items-wrap start zichtbaar (geen hidden class)
|
||||||
// Stap 9: Klik header om uit te klappen
|
|
||||||
const header = mealGroup.locator('.eetmoment-meal-header');
|
|
||||||
await header.click();
|
|
||||||
await page.waitForTimeout(300);
|
|
||||||
await expect(itemsWrap).not.toHaveClass(/hidden/);
|
await expect(itemsWrap).not.toHaveClass(/hidden/);
|
||||||
const chevronUp = header.locator('i.fa-chevron-up');
|
// Stap 9: Klik header om in te klappen → hidden aan
|
||||||
await expect(chevronUp).toBeVisible();
|
const header = mealGroup.locator('.eetmoment-meal-header');
|
||||||
// Stap 10: Klik opnieuw om in te klappen
|
|
||||||
await header.click();
|
await header.click();
|
||||||
await page.waitForTimeout(300);
|
await page.waitForTimeout(300);
|
||||||
await expect(itemsWrap).toHaveClass(/hidden/);
|
await expect(itemsWrap).toHaveClass(/hidden/);
|
||||||
const chevronDown = header.locator('i.fa-chevron-down');
|
const chevronDown = header.locator('i.fa-chevron-down');
|
||||||
await expect(chevronDown).toBeVisible();
|
await expect(chevronDown).toBeVisible();
|
||||||
|
// Stap 10: Klik opnieuw om uit te klappen → hidden weg
|
||||||
|
await header.click();
|
||||||
|
await page.waitForTimeout(300);
|
||||||
|
await expect(itemsWrap).not.toHaveClass(/hidden/);
|
||||||
|
const chevronUp = header.locator('i.fa-chevron-up');
|
||||||
|
await expect(chevronUp).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue