# Unsaved Changes Guard Pattern

A reusable component and utility system for warning users when they try to exit a modal or edit form with unsaved changes.

## Components

### `UnsavedChangesDialog.svelte`
A confirmation dialog component that appears when the user attempts to close a modal with unsaved changes.

**Props:**
- `isOpen` (boolean) - Controls visibility
- `title` (string) - Dialog title (default: "Unsaved Changes")
- `message` (string) - Warning message (default: "You have unsaved changes...")
- `onDiscard` (function) - Called when user confirms discard
- `onCancel` (function) - Called when user clicks keep editing

### `dirtyStateGuard.ts`
A composable hook that tracks dirty state and manages the confirmation flow.

```typescript
const { isDirty, markDirty, markClean, checkBeforeClose, reset } = unsavedChangesGuard(options);
```

**Methods:**
- `markDirty()` - Mark the form as having changes
- `markClean()` - Clear the dirty flag (call after successful save)
- `reset()` - Reset state completely
- `checkBeforeClose(callback?)` - Check if confirmation is needed before closing
- `getConfirmationOptions()` - Get the title/message for the dialog
- `isDirty` - Getter to check if there are unsaved changes

## How to Use

### Basic Pattern

```svelte
<script lang="ts">
  import UnsavedChangesDialog from "./UnsavedChangesDialog.svelte";
  import ModalShell from "./ModalShell.svelte";
  import { unsavedChangesGuard } from "$lib/dirtyStateGuard";

  export let isOpen = false;
  export let onClose = () => {};
  export let onSave = async (data) => {};

  let formData = { name: "", email: "" };
  let showConfirmation = false;

  const guard = unsavedChangesGuard({
    title: "Unsaved Changes",
    message: "Discard your changes?",
  });

  // Mark dirty when user changes anything
  function handleInputChange() {
    guard.markDirty();
  }

  // Check for unsaved changes before closing
  function handleCloseClick() {
    if (guard.isDirty) {
      showConfirmation = true; // Show confirmation dialog
    } else {
      isOpen = false; // Safe to close
    }
  }

  // Save and mark clean
  async function handleSave() {
    await onSave(formData);
    guard.markClean();
    isOpen = false;
  }

  function discardChanges() {
    guard.reset();
    isOpen = false;
  }
</script>

<ModalShell {isOpen} title="Edit Form" onClose={handleCloseClick}>
  <div class="modal-body">
    <input
      type="text"
      bind:value={formData.name}
      on:input={handleInputChange}
    />
  </div>
  <svelte:fragment slot="footer">
    <button on:click={handleCloseClick}>
      {guard.isDirty ? "Cancel" : "Close"}
    </button>
    <button on:click={handleSave} disabled={!guard.isDirty}>
      Save
    </button>
  </svelte:fragment>
</ModalShell>

<UnsavedChangesDialog
  bind:isOpen={showConfirmation}
  onDiscard={discardChanges}
  onCancel={() => showConfirmation = false}
/>
```

## Integration Examples

### For AddProductModal

Add to the script section:

```typescript
import { unsavedChangesGuard } from "$lib/dirtyStateGuard";

const guard = unsavedChangesGuard({
  title: "Unsaved Products",
  message: "You have products in your cart. Discard them?",
});

// When adding to cart or modifying special order form
function handleAddToCart() {
  guard.markDirty();
  // ... existing code ...
}

// When closing modal
function handleClose() {
  if (guard.isDirty && cart.length > 0) {
    showConfirmation = true;
  } else {
    reset();
    isOpen = false;
  }
}
```

### For CreateCredentialModal or Any Edit Form

```typescript
import { unsavedChangesGuard } from "$lib/dirtyStateGuard";

const guard = unsavedChangesGuard({
  title: "Unsaved Credential",
  message: "You have unsaved credential details. Discard them?",
});

// Mark dirty on any input
function handleInputChange() {
  guard.markDirty();
}

// Mark clean after successful creation
async function handleSubmit() {
  // ... existing submit logic ...
  guard.markClean();
}

// Check before closing
function handleClose() {
  if (guard.isDirty) {
    showConfirmation = true;
  } else {
    reset();
    isOpen = false;
  }
}
```

## Key Design Principles

1. **Optional Integration** - Works as a drop-in addition to existing modals
2. **Simple API** - Just `markDirty()`, `markClean()`, and `isDirty` check
3. **No Breaking Changes** - Doesn't modify your existing save/close logic
4. **Flexible** - Works with any form, modal, or edit interface
5. **Reusable Dialog** - Single confirmation dialog component handles all cases

## Customization

You can customize the warning message per instance:

```typescript
const guard = unsavedChangesGuard({
  title: "Unsaved Changes",
  message: "Are you sure? Your changes will be lost.",
});
```

The dialog styling uses your theme variables and adapts to dark/light modes automatically.

## See Also

- `FormGuardExample.svelte` - Complete working example
- `UnsavedChangesDialog.svelte` - Dialog component
- `dirtyStateGuard.ts` - Guard utility
