diff --git a/wwwroot/js/i18n.js b/wwwroot/js/i18n.js index 2fb592f..8e01ad2 100644 --- a/wwwroot/js/i18n.js +++ b/wwwroot/js/i18n.js @@ -98,6 +98,8 @@ const translations = { "modal.editTitle": "Edit game", "modal.addTitle": "Suggest a game", + "modal.confirmDeleteTitle": "Are you sure?", + "modal.confirmDelete": "Confirm delete", "modal.save": "Save changes", "modal.cancel": "Cancel", "modal.close": "Close", @@ -203,6 +205,8 @@ const translations = { "modal.editTitle": "Spiel bearbeiten", "modal.addTitle": "Spiel vorschlagen", + "modal.confirmDeleteTitle": "Bist du sicher?", + "modal.confirmDelete": "Löschen bestätigen", "modal.save": "Änderungen speichern", "modal.cancel": "Abbrechen", "modal.close": "Schließen", diff --git a/wwwroot/js/ui.js b/wwwroot/js/ui.js index 4648abb..d0af2ee 100644 --- a/wwwroot/js/ui.js +++ b/wwwroot/js/ui.js @@ -353,13 +353,7 @@ export function buildCard( if (allowDelete) { const del = card.querySelector("[data-delete]"); del.addEventListener("click", async () => { - try { - await api.deleteSuggestion(s.id); - toast(t("toast.suggestionDeleted")); - await window.loadSuggestData(); - } catch (err) { - toast(err.message, true); - } + openDeleteConfirmModal(s); }); } return card; @@ -596,6 +590,64 @@ function formatMyVote(score) { return `${score} ${scoreToEmoji(score)}`; } +function openDeleteConfirmModal(s) { + const overlay = document.createElement("div"); + overlay.className = "edit-modal"; + const panel = document.createElement("div"); + panel.className = "edit-panel"; + panel.innerHTML = ` +
+

${t("modal.confirmDeleteTitle")}

+ +
+
+ `; + + const preview = buildCard( + { ...s, id: s.id }, // shallow copy to avoid mutations + { showAuthor: true, allowDelete: false, allowEdit: false }, + ); + preview.classList.add("preview-card"); + + const actions = document.createElement("div"); + actions.className = "stack horizontal"; + const confirmBtn = document.createElement("button"); + confirmBtn.className = "danger"; + confirmBtn.textContent = t("modal.confirmDelete"); + const cancelBtn = document.createElement("button"); + cancelBtn.type = "button"; + cancelBtn.className = "ghost"; + cancelBtn.textContent = t("modal.cancel"); + actions.append(confirmBtn, cancelBtn); + + const body = panel.querySelector(".delete-body"); + body?.append(preview, actions); + + const close = () => overlay.remove(); + overlay.addEventListener("click", (e) => { + if ( + e.target.classList.contains("edit-modal") || + e.target.classList.contains("lightbox-close") + ) + close(); + }); + cancelBtn.addEventListener("click", close); + + confirmBtn.addEventListener("click", async () => { + try { + await api.deleteSuggestion(s.id); + toast(t("toast.suggestionDeleted")); + close(); + await window.loadSuggestData(); + } catch (err) { + toast(err.message, true); + } + }); + + overlay.appendChild(panel); + document.body.appendChild(overlay); +} + function isValidImageUrl(url) { if (!url) return true; try { diff --git a/wwwroot/styles.css b/wwwroot/styles.css index b3e9f67..4012bda 100644 --- a/wwwroot/styles.css +++ b/wwwroot/styles.css @@ -610,6 +610,14 @@ input[type="range"].full-slider::-moz-range-track { overflow: auto; max-height: 70vh; } +.edit-modal .delete-body { + display: flex; + flex-direction: column; + gap: 12px; +} +.preview-card { + pointer-events: none; +} .panel-header { display: flex;