diff --git a/api/Database/klapi.db b/api/Database/klapi.db index 322d07f..167565f 100644 Binary files a/api/Database/klapi.db and b/api/Database/klapi.db differ diff --git a/ui/src/components/ConfirmDialog.tsx b/ui/src/components/ConfirmDialog.tsx new file mode 100644 index 0000000..1bba917 --- /dev/null +++ b/ui/src/components/ConfirmDialog.tsx @@ -0,0 +1,83 @@ +import { useEffect } from "react"; + +type ConfirmDialogProps = { + open: boolean; + title: string; + description?: string; + contextText?: string; + confirmLabel: string; + cancelLabel: string; + busy?: boolean; + busyLabel?: string; + onConfirm: () => void; + onCancel: () => void; +}; + +export default function ConfirmDialog({ + open, + title, + description, + contextText, + confirmLabel, + cancelLabel, + busy = false, + busyLabel, + onConfirm, + onCancel, +}: ConfirmDialogProps) { + useEffect(() => { + if (!open) return; + + const onKeyDown = (event: KeyboardEvent) => { + if (event.key === "Escape" && !busy) { + onCancel(); + } + }; + + window.addEventListener("keydown", onKeyDown); + return () => { + window.removeEventListener("keydown", onKeyDown); + }; + }, [open, busy, onCancel]); + + if (!open) return null; + + return ( +
{ + if (!busy) onCancel(); + }} + > +
event.stopPropagation()} + > +

{title}

+ {description &&

{description}

} + {contextText &&

{contextText}

} + +
+ + +
+
+
+ ); +} \ No newline at end of file diff --git a/ui/src/components/OpenHoursForm.tsx b/ui/src/components/OpenHoursForm.tsx index 16dc9b2..fc4ff43 100644 --- a/ui/src/components/OpenHoursForm.tsx +++ b/ui/src/components/OpenHoursForm.tsx @@ -8,6 +8,7 @@ import { updateLokOpenHours, type LokOpenHours, } from "~/api"; +import ConfirmDialog from "~/components/ConfirmDialog"; import { useT } from "~/i18n"; import { openHoursAtom, toastsAtom, type Toast } from "~/state/appState"; @@ -38,6 +39,7 @@ export default function OpenHoursForm() { const [isEditing, setIsEditing] = useState(false); const [editingVersionId, setEditingVersionId] = useState(""); const [deletingId, setDeletingId] = useState(""); + const [confirmDeleteVersion, setConfirmDeleteVersion] = useState(null); const [activatingId, setActivatingId] = useState(""); const [saving, setSaving] = useState(false); const [form, setForm] = useState(EMPTY_FORM); @@ -217,6 +219,21 @@ export default function OpenHoursForm() { } }; + const askDeleteConfirmation = (version: LokOpenHours) => { + setConfirmDeleteVersion(version); + }; + + const cancelDeleteConfirmation = () => { + if (deletingId) return; + setConfirmDeleteVersion(null); + }; + + const confirmDelete = async () => { + if (!confirmDeleteVersion) return; + await onDelete(confirmDeleteVersion); + setConfirmDeleteVersion(null); + }; + const onSetActive = async (version: LokOpenHours) => { if (version.isActive) return; @@ -328,7 +345,7 @@ export default function OpenHoursForm() { disabled={active || deleting} onClick={(event) => { event.stopPropagation(); - void onDelete(version); + askDeleteConfirmation(version); }} className={`rounded-md border border-[#8E4F24] bg-[#EED5B8] px-3 py-1.5 text-sm text-[#70421E] disabled:cursor-not-allowed disabled:opacity-50 ${!active ? "hover:bg-[#E3A977]" : "" }`} @@ -416,6 +433,21 @@ export default function OpenHoursForm() { + + { + void confirmDelete(); + }} + /> ); } diff --git a/ui/src/i18n.ts b/ui/src/i18n.ts index a721bb9..8332e8a 100644 --- a/ui/src/i18n.ts +++ b/ui/src/i18n.ts @@ -44,6 +44,10 @@ const translations = { "home.openHours.saved": "New version saved", "home.openHours.updated": "Version updated", "home.openHours.deleted": "Version deleted", + "home.openHours.deleting": "Deleting...", + "home.openHours.deleteConfirmTitle": "Delete version?", + "home.openHours.deleteConfirmMessage": "This action cannot be undone.", + "home.openHours.deleteConfirmAction": "Delete version", "about.title": "About", "about.description": "Livonsaaren Tietokonepaja is a local project providing IT services for our dear archipelago.", @@ -125,6 +129,10 @@ const translations = { "home.openHours.saved": "Uusi versio tallennettu", "home.openHours.updated": "Versio päivitetty", "home.openHours.deleted": "Versio poistettu", + "home.openHours.deleting": "Poistetaan...", + "home.openHours.deleteConfirmTitle": "Poistetaanko versio?", + "home.openHours.deleteConfirmMessage": "Tätä toimintoa ei voi perua.", + "home.openHours.deleteConfirmAction": "Poista versio", "about.title": "Tietoja", "about.description": "Livonsaaren Tietokonepaja on paikallisprojekti, joka tuottaa IT-palveluita rakkaalle lähisaaristollemme.", @@ -207,6 +215,11 @@ const translations = { "home.openHours.saved": "Nová verzia uložená", "home.openHours.updated": "Verzia bola aktualizovaná", "home.openHours.deleted": "Verzia bola odstránená", + "home.openHours.deleting": "Odstraňuje sa...", + "home.openHours.deleteConfirmTitle": "Odstrániť verziu?", + "home.openHours.deleteConfirmMessage": + "Túto akciu nie je možné vrátiť späť.", + "home.openHours.deleteConfirmAction": "Odstrániť verziu", "about.title": "O aplikácii", "about.description": "Livonsaaren Tietokonepaja je lokálny projekt poskytujúci IT služby pre naše milované súostrovie.",