diff --git a/src/lib/components/ConfirmDialog.svelte b/src/lib/components/ConfirmDialog.svelte
new file mode 100644
index 0000000..cd3b0c4
--- /dev/null
+++ b/src/lib/components/ConfirmDialog.svelte
@@ -0,0 +1,142 @@
+
+
+{#if confirmState.isOpen}
+
+
+
{
+ if (e.target === e.currentTarget) confirmState.cancel();
+ }}
+ >
+
+
+
{confirmState.message}
+
+
+
+
+
+
+
+{/if}
+
+
diff --git a/src/lib/stores/confirm.svelte.ts b/src/lib/stores/confirm.svelte.ts
new file mode 100644
index 0000000..2ca89fc
--- /dev/null
+++ b/src/lib/stores/confirm.svelte.ts
@@ -0,0 +1,36 @@
+import { untrack } from 'svelte';
+
+class ConfirmState {
+ isOpen = $state(false);
+ message = $state('');
+ private resolve: ((value: boolean) => void) | null = null;
+
+ async show(message: string): Promise {
+ this.message = message;
+ this.isOpen = true;
+ return new Promise((res) => {
+ this.resolve = res;
+ });
+ }
+
+ confirm() {
+ untrack(() => {
+ if (this.resolve) this.resolve(true);
+ this.close();
+ });
+ }
+
+ cancel() {
+ untrack(() => {
+ if (this.resolve) this.resolve(false);
+ this.close();
+ });
+ }
+
+ private close() {
+ this.isOpen = false;
+ this.resolve = null;
+ }
+}
+
+export const confirmState = new ConfirmState();
diff --git a/src/routes/admin/+layout.svelte b/src/routes/admin/+layout.svelte
index 06ad37e..c4ee8b9 100644
--- a/src/routes/admin/+layout.svelte
+++ b/src/routes/admin/+layout.svelte
@@ -3,6 +3,7 @@
import { page } from '$app/stores';
import { onMount } from 'svelte';
import Toast from '$lib/components/Toast.svelte';
+ import ConfirmDialog from '$lib/components/ConfirmDialog.svelte';
let { children } = $props();
@@ -102,6 +103,7 @@
+