From d3484a4b50c97924e4b44a603b8881cd8894b21c Mon Sep 17 00:00:00 2001 From: Djeex Date: Sun, 17 Aug 2025 00:37:55 +0200 Subject: [PATCH] Confirmation modale for deletion --- config/gallery.yaml | 1 - src/webui/index.html | 12 ++++ src/webui/js/main.js | 132 +++++++++++++++++++++++++------------- src/webui/style/style.css | 63 +++++++++++++++++- 4 files changed, 160 insertions(+), 48 deletions(-) diff --git a/config/gallery.yaml b/config/gallery.yaml index 7463218..fc1920d 100644 --- a/config/gallery.yaml +++ b/config/gallery.yaml @@ -2,4 +2,3 @@ hero: images: [] gallery: images: [] - diff --git a/src/webui/index.html b/src/webui/index.html index 9ba2a23..e7f2406 100644 --- a/src/webui/index.html +++ b/src/webui/index.html @@ -75,5 +75,17 @@ + + diff --git a/src/webui/js/main.js b/src/webui/js/main.js index bf2968c..bb23d95 100644 --- a/src/webui/js/main.js +++ b/src/webui/js/main.js @@ -44,7 +44,7 @@ function renderGallery() {
- +
@@ -208,56 +208,13 @@ function renderHero() {
- +
`; container.appendChild(div); }); } -// --- Delete gallery image --- -async function deleteGalleryImage(index) { - const img = galleryImages[index]; - try { - const res = await fetch('/api/gallery/delete', { - method: 'POST', - headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({ src: img.src.split('/').pop() }) - }); - const data = await res.json(); - if (res.ok) { - galleryImages.splice(index, 1); - renderGallery(); - await saveGallery(); - showToast("✅ Gallery image deleted!", "success"); - } else showToast("Error: " + data.error, "error"); - } catch(err) { - console.error(err); - showToast("Server error!", "error"); - } -} - -// --- Delete hero image --- -async function deleteHeroImage(index) { - const img = heroImages[index]; - try { - const res = await fetch('/api/hero/delete', { - method: 'POST', - headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({ src: img.src.split('/').pop() }) - }); - const data = await res.json(); - if (res.ok) { - heroImages.splice(index, 1); - renderHero(); - await saveHero(); - showToast("✅ Hero image deleted!", "success"); - } else showToast("Error: " + data.error, "error"); - } catch(err) { - console.error(err); - showToast("Server error!", "error"); - } -} // --- Save gallery to server --- async function saveGallery() { @@ -316,5 +273,90 @@ function showToast(message, type = "success", duration = 3000) { }, duration); } +let pendingDelete = null; // { type: 'gallery'|'hero', index: number } + +// --- Show delete confirmation modal --- +function showDeleteModal(type, index) { + pendingDelete = { type, index }; + document.getElementById('delete-modal').style.display = 'flex'; +} + +// --- Hide modal --- +function hideDeleteModal() { + document.getElementById('delete-modal').style.display = 'none'; + pendingDelete = null; +} + +// --- Confirm deletion --- +async function confirmDelete() { + if (!pendingDelete) return; + if (pendingDelete.type === 'gallery') { + await actuallyDeleteGalleryImage(pendingDelete.index); + } else if (pendingDelete.type === 'hero') { + await actuallyDeleteHeroImage(pendingDelete.index); + } + hideDeleteModal(); +} + + +// --- Modal event listeners --- +document.addEventListener('DOMContentLoaded', () => { + document.getElementById('delete-modal-close').onclick = hideDeleteModal; + document.getElementById('delete-modal-cancel').onclick = hideDeleteModal; + document.getElementById('delete-modal-confirm').onclick = confirmDelete; +}); + +// --- Actual delete functions --- +async function actuallyDeleteGalleryImage(index) { + const img = galleryImages[index]; + try { + const res = await fetch('/api/gallery/delete', { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({ src: img.src.split('/').pop() }) + }); + const data = await res.json(); + if (res.ok) { + galleryImages.splice(index, 1); + renderGallery(); + await saveGallery(); + showToast("✅ Gallery image deleted!", "success"); + } else showToast("Error: " + data.error, "error"); + } catch(err) { + console.error(err); + showToast("Server error!", "error"); + } +} + +async function actuallyDeleteHeroImage(index) { + const img = heroImages[index]; + try { + const res = await fetch('/api/hero/delete', { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({ src: img.src.split('/').pop() }) + }); + const data = await res.json(); + if (res.ok) { + heroImages.splice(index, 1); + renderHero(); + await saveHero(); + showToast("✅ Hero image deleted!", "success"); + } else showToast("Error: " + data.error, "error"); + } catch(err) { + console.error(err); + showToast("Server error!", "error"); + } +} + +// --- Modal event listeners --- +document.addEventListener('DOMContentLoaded', () => { + document.getElementById('delete-modal-close').onclick = hideDeleteModal; + document.getElementById('delete-modal-cancel').onclick = hideDeleteModal; + document.getElementById('delete-modal-confirm').onclick = confirmDelete; +}); + + + // --- Initialize --- loadData(); diff --git a/src/webui/style/style.css b/src/webui/style/style.css index c715583..417b64b 100644 --- a/src/webui/style/style.css +++ b/src/webui/style/style.css @@ -51,7 +51,7 @@ h1, h2 { } .photo { - background-color: rgba(58, 62, 65, 0.26); + background-color: rgb(67 67 67 / 26%); border-radius: 6px; padding: 10px; text-align: center; @@ -163,6 +163,7 @@ h1, h2 { border-radius: 15px; display: flex; align-items: center; + font-size: 14px; } .tag .remove-tag { @@ -273,7 +274,7 @@ h1, h2 { .nav > .nav-links { display: inline; float: right; - font-size: 12px; + font-size: 14px; height: 100%; line-height: 70px; } @@ -367,3 +368,61 @@ h1, h2 { .custom-upload-btn:hover { background: #55c3ec; } + +/* Modal styles */ +.modal { + position: fixed; + top: 0; left: 0; right: 0; bottom: 0; + z-index: 10000; + display: flex; + align-items: center; + justify-content: center; + +} +.modal-content { + background: #ffffff29; + color: #fff; + padding: 2rem 2.5rem; + border-radius: 10px; + box-shadow: 0 4px 24px rgba(0,0,0,0.25); + min-width: 300px; + max-width: 90vw; + position: relative; + text-align: center; + backdrop-filter: blur(20px); +} +.modal-close { + position: absolute; + top: 12px; right: 18px; + font-size: 1.5rem; + cursor: pointer; + color: #fff; + opacity: 0.7; +} +.modal-close:hover { opacity: 1; } +.modal-actions { + margin-top: 2rem; + display: flex; + gap: 1rem; + justify-content: center; +} +.modal-btn { + padding: 0.5em 1.5em; + border-radius: 30px; + border: none; + background: #09A0C1; + color: #fff; + font-weight: bold; + cursor: pointer; + font-size: 1rem; + transition: background 0.2s; +} +.modal-btn.danger { + background: #c62828; +} +.modal-btn:hover { + background: #55c3ec; +} +.modal-btn.danger:hover { + background: #d32f2f; +} \ No newline at end of file