feat: user notification preferences UI and API endpoints

GET/PUT /api/user/notification-preferences with partial update support.
Toggle section in /account Admin tab (Email, SMS, Browser push).
3 new tests: defaults, full update, partial update.
Fix pre-existing timezone bug in exceptional hours tests (Truncate vs time.Date).
Update README, Technical Manual, and gap backlog (#15 struck out).
This commit is contained in:
2026-05-17 00:24:13 +01:00
parent 7fc58f58d9
commit b08df624a8
9 changed files with 462 additions and 62 deletions
@@ -36,7 +36,7 @@ No external dependencies. No paid services. No API keys needed.
| # | Gap | Effort | Area | Notes |
|---|-----|--------|------|-------|
| 14 | ~~`delete_guest_user()` SQL function missing~~ ✅ | S (1h) | DB | Created next to `anonymize_user()` in init-script.sql. Called by `DeleteAccountHandler` for guest users. |
| 15 | **User notification preferences UI** | S (2-3h) | Frontend | DB table `user_notification_preferences` exists with email/sms/push flags. No settings page to toggle them. |
| ~~15~~ | ~~**User notification preferences UI**~~ ✅ | ~~S (2-3h)~~ | ~~Frontend~~ | ~~DB table `user_notification_preferences` exists with email/sms/push flags. No settings page to toggle them.~~ GET/PUT endpoints wired. Toggle section in /account Admin tab. Email, SMS, Browser push channels. Auto-save on toggle. |
| 16 | **One-off custom services** | M (1-2d) | Full-stack | Admin can't create single-use services outside the catalog. Every custom job (bridal party, special request) must be added to permanent service list. |
| 17 | **One-off exceptional hours** | M (1d) | Full-stack | Single-day overrides (dentist appointment, afternoon off) require creating a full exceptional group. Should support one-off date blocks without group overhead. |
| 18 | ~~**HSTS header**~~ ✅ | XS (15min) | Backend | Added as a TODO-comment in the security headers middleware. Will be uncommented when HTTPS is enabled in production. |
@@ -143,7 +143,7 @@ Require paid accounts, API approval, or external service credentials. **Do not a
│ │
│ #3 Approval decline ✅──→ #13 Booking reschedule │
│ │
│ ~~#5 Admin notification panel~~ ✅ ──→ #15 Preferences UI │
│ ~~#5 Admin notification panel~~ ✅ ──→ ~~#15 Preferences UI~~ ✅
│ ──→ #48 Waitlist (removed) │
│ │
│ #2 Walk-in guest fix ──→ #9 Reservation transition │
+9
View File
@@ -189,6 +189,8 @@ src/lib/components/
| PUT | `/api/user/profile` | Update profile |
| POST | `/api/user/profile-picture` | Upload profile picture (cropper) |
| PUT | `/api/user/change-password` | Change password |
| GET | `/api/user/notification-preferences` | Get notification preferences |
| PUT | `/api/user/notification-preferences` | Update notification preferences |
| DELETE | `/api/user/account` | Delete account (GDPR anonymization) |
| GET | `/api/user/loyalty` | Get loyalty stamp count |
| GET | `/api/bookings` | List user's bookings |
@@ -484,6 +486,13 @@ src/lib/components/
- Edit requests (`POST /api/bookings/{id}/edit-request`) → always `edit_requested`, plus `pending_booking` if booking status is pending
- Admin bookings (`POST /api/admin/bookings`) → no notifications (admin already knows)
**User notification preferences:**
Users manage their preferred notification channels via `/account` → Admin tab → Notifications section. The `user_notification_preferences` table stores per-user flags for email, SMS, and browser push. These flags are not yet used by any delivery system — they will be consumed when the email/SMS notification system (E5) is built.
**Endpoints:**
- `GET /api/user/notification-preferences` — Returns `{emailEnabled, smsEnabled, browserPushEnabled}`. Defaults to all `true` if no row exists.
- `PUT /api/user/notification-preferences` — Accepts partial updates (only provided fields change, unset fields retain current value). Upserts on first call.
### Loyalty & Discount System
**Loyalty Stamps:**