Swap LockProvider to outer wrapper so AlertsProvider can read isLocked.
When locked, dismiss all visible reminder toasts and skip firing new ones.
Toasts re-fire normally on unlock via the firedRef.clear() reset.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- W3: Merge route-change and new-alert effects into single unified effect
- W6: Migration 018 extends due_lookup index with snoozed_until column
- S1: Extract useConfirmAction hook from TodoItem/ReminderItem
- S7: Update summary toast count on dismiss/snooze instead of dismissing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- C1: Add onError handlers to dismiss/snooze mutations in useAlerts
- C2: Clear snoozed_until when dismissing via update endpoint
- W1: Handle future dates in getRelativeTime
- W2+S3: Add Escape key, aria-expanded, role=menu to SnoozeDropdown
- W4: Remove redundant field_validator (Literal suffices)
- W7: Validate recurrence_rule with Literal['daily','weekly','monthly']
- S2: Clean up delete confirmation setTimeout on unmount
- S6: Cap AlertBanner height with scroll for many alerts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- SnoozeDropdown: added direction prop (up/down), toasts use 'down'
so dropdown opens below the button instead of clipping off-screen
- AlertBanner dismiss button now shows X icon + 'Dismiss' text to
match toast style
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Toast dismiss button now shows X icon + 'Dismiss' text to match
the snooze button style
- Updating remind_at on a dismissed reminder clears is_dismissed
and snoozed_until, making the reminder active again
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Docker container datetime.now() returns UTC, but all stored datetimes
are naive local time from the browser. Both /due and /snooze now
accept client_now from the frontend, ensuring snooze computes from
the user's actual current time, not the container's clock.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Single clock icon opens a dropdown with 5/10/15 min options instead
of three inline buttons. Shared SnoozeDropdown component used in
both AlertBanner and toast notifications.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- S1: Add composite index (is_active, is_dismissed, remind_at) for
/due query performance with multi-user scaling
- W3: Snooze endpoint rejects dismissed/inactive reminders (409)
- W4: Custom field_validator on ReminderSnooze for clear error message
- S2: aria-label on all snooze/dismiss buttons in banner and toasts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- C1: Replaced duplicate useAlerts() calls with AlertsProvider context
wrapping AppLayout — single hook instance, no double polling/toasts
- C2: Added null guard on remind_at in Active Reminders card format()
- W2: Clear snoozed_until when dismissing a reminder
- W5: Extracted getRelativeTime to shared lib/date-utils.ts
- S3: Replaced inline SVG with Lucide Bell component in toasts
- S4: Clear snoozed_until when remind_at is updated via PUT
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>