Add reusable toast notification system
Introduces a runes-based toast module (`$lib/toast.svelte.ts`) with success/info/warning/error variants, auto-dismiss, optional action button, plus a `Toaster` viewport mounted in the root layout. Migrates the lone `alert(e.message)` call site (stores delete) to `toast.error()`. Backlog updated to remove the now-completed foundational item and rewrite dependent items to reference the shipped API. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+3
-13
@@ -15,14 +15,6 @@ Prerequisite for the product catalog and unit catalog work — both rely on a `F
|
||||
- **Bootstrap migration for the existing single-family deployment:** at upgrade time, auto-create one `Family` from the current `FAMILY_CODE` env value, assign all existing rows to it, and migrate the env var off. Flag explicitly in the runbook so deployment isn't a surprise.
|
||||
- Auth changes: JWT carries `FamilyId` claim. `OnTokenValidated` rejects tokens whose user has been removed from the family.
|
||||
|
||||
### Toast / notification component (foundational)
|
||||
- App has no toast system today; current error UX is `alert()` on `stores/+page.svelte` delete failures. Several tracked items depend on this:
|
||||
- Duplicate store name → toast (Stores section)
|
||||
- Block create-list when no stores → toast (Lists section)
|
||||
- Confirm-before-delete error surfacing (Stores section)
|
||||
- Build a small reusable Svelte component (success / info / warning / error variants, auto-dismiss with timeout, optional action button for "Undo"), expose via `$lib/toast.ts`.
|
||||
- Migrate existing `alert(e.message)` call sites as part of landing it.
|
||||
|
||||
### Account & session lifecycle
|
||||
- **Password reset.** Currently no flow, no email infrastructure. Required before multi-family launches publicly. Needs SMTP config, email template, single-use token table, rate limiting on the reset endpoint.
|
||||
- **JWT refresh tokens.** Today's tokens are signed with HS256 and (per `Program.cs`) likely have no refresh path; they expire and the user gets bounced to login. Add refresh tokens with rotation + revocation list.
|
||||
@@ -221,8 +213,7 @@ Replace free-form `Quantity` strings with a structured `(Quantity, UnitOfMeasure
|
||||
|
||||
### Block create-list flow when no stores exist
|
||||
- A shopping list requires a `Store` (see `ListSummary.store` and the `newStoreId` state in `lists/+page.svelte`), so the create-list flow shouldn't be available until at least one store exists.
|
||||
- Behavior: if user tries to open the create-list UI (or hits the create-list page directly via URL) with zero stores, surface a toast or modal that says "You need to create a store first" with a CTA linking to `/stores`. Don't render the empty/broken create form.
|
||||
- Belongs with the toast-component work above.
|
||||
- Behavior: if user tries to open the create-list UI (or hits the create-list page directly via URL) with zero stores, surface a `toast.warning()` (or modal) that says "You need to create a store first" with a CTA linking to `/stores`. Don't render the empty/broken create form.
|
||||
|
||||
## Stores
|
||||
|
||||
@@ -239,12 +230,11 @@ Replace free-form `Quantity` strings with a structured `(Quantity, UnitOfMeasure
|
||||
- Add a modal confirmation prompt before deleting a store (currently one click → gone, no undo).
|
||||
- Disallow deletion of a store that has any active shopping lists associated with it.
|
||||
- Backend status: `StoreEndpoints.cs` DELETE already returns 400 with `{error: "Store has shopping lists. Remove them first."}` if any list references the store. Consider switching to 409 Conflict for semantic correctness.
|
||||
- Frontend status: `stores/+page.svelte` `deleteStore` currently shows the backend message via `alert()`. Replace with the new confirmation modal that also surfaces this error inline.
|
||||
- Frontend status: `stores/+page.svelte` `deleteStore` currently surfaces the backend message via `toast.error()`. Replace with the new confirmation modal that also surfaces this error inline (or as a toast on confirm-action failure).
|
||||
- Open question: what counts as "active"? Backend currently blocks on *any* list. Decide whether archived/completed lists should still block deletion.
|
||||
|
||||
### Duplicate store name → 500 + silent frontend (bug)
|
||||
- Adding a store with a name that already exists triggers the unique constraint on `Store.Name`, which leaks out as a 500 from `StoreEndpoints.cs` POST (no exception handling).
|
||||
- Frontend `addStore` in `stores/+page.svelte` swallows the error — the form just sits there with no feedback.
|
||||
- Fix: backend should pre-check (or catch the unique-violation) and return 409 with a helpful message; frontend should display a **toast** (e.g. "A store named 'Kroger' already exists") rather than a silent failure or a blocking `alert()`.
|
||||
- Fix: backend should pre-check (or catch the unique-violation) and return 409 with a helpful message; frontend should display a `toast.error()` (e.g. "A store named 'Kroger' already exists") rather than failing silently.
|
||||
- Same pattern likely affects PUT (rename to an existing name).
|
||||
- Note: app does not currently have a toast system. This work probably needs a small reusable toast component before the duplicate-name handling can land — worth adopting it across the app (the existing `alert(e.message)` calls on delete failures should also move to toasts).
|
||||
|
||||
Reference in New Issue
Block a user