feat: add Daily Digest and Push Notifications toggles to User Profile with corresponding functionality
Some checks failed
Chore App Build, Test, and Push Docker Images / build-and-push (push) Failing after 2m4s
Some checks failed
Chore App Build, Test, and Push Docker Images / build-and-push (push) Failing after 2m4s
This commit is contained in:
11
.github/specs/feat-parent-chore-notifications.md
vendored
11
.github/specs/feat-parent-chore-notifications.md
vendored
@@ -191,7 +191,9 @@ email_digest_enabled: boolean;
|
||||
6. `ParentView` uses vertically stacked `ScrollingList` sections (not tabs). The existing `scrollTo` + `entityType` query params call `scrollToItem()` on the correct list ref, which scrolls the card into view and centers it. After scrolling, apply a temporary pulse/highlight CSS animation (e.g. a 2-second `@keyframes highlight-pulse` using `--item-card-ready-shadow` or `--accent`) to draw the parent's eye to the target card. The animation class should be removed after it completes.
|
||||
7. **Parent mode timeout — return URL:** When the router guard redirects a non-parent-authenticated user away from a `/parent/...` deep link (e.g. from a notification body tap or email digest redirect), it saves the intended URL to `localStorage['parentReturnUrl']`. `LoginButton` checks for a pending return URL on mount and auto-opens the PIN modal. On successful PIN entry, `consumePendingReturnUrl()` is called and the user is redirected to the saved deep link instead of the default `/parent`. If the parent cancels the PIN modal, `clearPendingReturnUrl()` removes the saved URL so the prompt does not re-appear. The URL is validated to start with `/parent` before saving to prevent open redirect.
|
||||
8. Existing SSE in-app toast/badge behavior is unchanged — it remains the secondary channel when the tab is active.
|
||||
9. On `UserProfile.vue`, add an "Email Digest" toggle below the existing action buttons. When toggled, call `PUT /api/user/profile` with `{ email_digest_enabled: <value> }`. Initialize the toggle state from the `GET /api/user/profile` response (which now includes `email_digest_enabled`).
|
||||
9. On `UserProfile.vue`, add a **Daily Digest** `ToggleField` and a **Push Notifications** `ToggleField` below the email field.
|
||||
- **Daily Digest**: When toggled, call `PUT /api/user/profile` with `{ email_digest_enabled: <value> }`. Initialize from `GET /api/user/profile` (`email_digest_enabled` field).
|
||||
- **Push Notifications**: When toggled on, call `subscribeToPushWithResult()` from `pushSubscription.ts`; on `permission_denied` show an inline error message. When toggled off, call `unsubscribeFromPush()`. Initialize by calling `isSubscribedToPush()` in `onMounted`. Disable the toggle (but keep it visible) when `getPushPermissionState() === 'denied'`.
|
||||
|
||||
## Frontend Tests
|
||||
|
||||
@@ -214,6 +216,13 @@ email_digest_enabled: boolean;
|
||||
- [x] User Profile page shows an "Email Digest" toggle
|
||||
- [x] Toggling Email Digest off calls `PUT /api/user/profile` with `email_digest_enabled: false`
|
||||
- [x] Toggling Email Digest on calls `PUT /api/user/profile` with `email_digest_enabled: true`
|
||||
- [x] User Profile page shows a "Push Notifications" toggle
|
||||
- [x] Push Notifications toggle initialises to `true` when the browser already has an active push subscription
|
||||
- [x] Push Notifications toggle initialises to `false` when no subscription exists
|
||||
- [x] Toggling Push Notifications on triggers `subscribeToPushWithResult()` and posts subscription to the backend
|
||||
- [x] Toggling Push Notifications off calls `unsubscribeFromPush()` and removes the subscription from the backend
|
||||
- [x] Push Notifications toggle is disabled (not hidden) when browser notification permission is `"denied"`
|
||||
- [x] An inline error message is shown when enabling push notifications is blocked by the browser
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user