diff --git a/src/lib/client/ui/modal/UnsavedChangesModal.svelte b/src/lib/client/ui/modal/UnsavedChangesModal.svelte new file mode 100644 index 0000000..f3c0e66 --- /dev/null +++ b/src/lib/client/ui/modal/UnsavedChangesModal.svelte @@ -0,0 +1,31 @@ + + + unsavedChanges.confirmDiscard()} + on:cancel={() => unsavedChanges.cancelDiscard()} +/> diff --git a/src/lib/client/utils/unsavedChanges.svelte.ts b/src/lib/client/utils/unsavedChanges.svelte.ts new file mode 100644 index 0000000..2c02f64 --- /dev/null +++ b/src/lib/client/utils/unsavedChanges.svelte.ts @@ -0,0 +1,78 @@ +/** + * Utility for detecting and handling unsaved changes + */ + +let hasUnsavedChanges = $state(false); +let showWarningModal = $state(false); +let resolveNavigation: ((value: boolean) => void) | null = null; + +export function useUnsavedChanges() { + return { + /** + * Mark the page as having unsaved changes + */ + markDirty() { + hasUnsavedChanges = true; + }, + + /** + * Mark the page as clean (changes saved) + */ + markClean() { + hasUnsavedChanges = false; + }, + + /** + * Check if there are unsaved changes + */ + get isDirty() { + return hasUnsavedChanges; + }, + + /** + * Get modal state + */ + get showModal() { + return showWarningModal; + }, + + /** + * Request navigation confirmation + * Returns a promise that resolves to true if navigation should proceed + */ + confirmNavigation(): Promise { + if (!hasUnsavedChanges) { + return Promise.resolve(true); + } + + showWarningModal = true; + + return new Promise((resolve) => { + resolveNavigation = resolve; + }); + }, + + /** + * User confirmed navigation (discard changes) + */ + confirmDiscard() { + showWarningModal = false; + hasUnsavedChanges = false; + if (resolveNavigation) { + resolveNavigation(true); + resolveNavigation = null; + } + }, + + /** + * User cancelled navigation (stay on page) + */ + cancelDiscard() { + showWarningModal = false; + if (resolveNavigation) { + resolveNavigation(false); + resolveNavigation = null; + } + } + }; +}