-
Notifications
You must be signed in to change notification settings - Fork 19
Description
Goal:
Build the admin-facing React interface for Phase 2 that lets a logged-in user manage runtime system settings: toggle visitor notifications, store Brevo credentials, send test emails, set default link expiry, enable debug logging, and optionally adjust upload limits — all round-tripping via the new backend APIs (chosen path co-located with GET/PATCH for consistency).
🎯 Key Deliverables
- New “System & Notifications” tab beside “Branding & Layout” in
src/app/settings/page.tsx. - Fully functional React-Hook-Form bound to
SystemSettingsUpdateSchema(Zod resolver). - TanStack Query hooks:
useSystemSettingsQuery→ GETuseUpdateSystemSettingsMutation→ PATCHuseTestEmailMutation→ POST test email
- Dynamic UI:
- Notifications toggle shows/hides Brevo API key + sender fields.
- “Send Test Email” sub-section with real-time toast feedback.
- Default Link Expiry with unit selector (auto-converts to seconds).
- Debug Logs checkbox.
- (Optional) Advanced Upload Limits collapsible section.
- Manual field validation, helper text, tooltips, toasts, disabled states.
- Loading spinner and fallback error alert.
- Keyboard navigation and proper accessibility attributes.
- README update: remove
ENABLE_NOTIFICATIONS,DEFAULT_TTL, andDEBUG_LOGSfrom.env.example; markSEND_EMAILSas legacy (no longer read by code); keepSIGNED_URL_TTL_SECONDS.
🔧 Implementation Tasks
1️⃣ Tab Integration
- Add a second MUI
Tablabelled System & Notifications. - Support
?tab=systemquery param to auto-select the tab. - Fallback to local state if no query.
2️⃣ Hooks
- Create
src/hooks/systemSettings.ts:export const useSystemSettingsQuery = () => useQuery(['system-settings'], fetchSystemSettings); export const useUpdateSystemSettingsMutation = () => useMutation(patchSystemSettings, { onSuccess: invalidateQuery }); export const useTestEmailMutation = () => useMutation(sendTestEmail);
-
GET /api/settings/systemandPATCH /api/settings/system:-
PATCH accepts plain JSON — no need for multipart/form-data.
-
PATCH should only include fields that changed.
-
Returned DTO fields include:
{ enableNotifications: boolean emailFromName: string | null emailFromAddr: string | null defaultTtlSeconds: number maxFileSizeMb: number | null allowedMimeTypes: string | null // CSV string debugLogs: boolean updatedAt: string }
-
allowedMimeTypesmust be parsed into a string array for the UI and rejoined as CSV on submit.
-
-
POST /api/settings/test-emailaccepts:{ "to": "[email protected]" }and returns:
{ "success": true }- 400/500 errors always include a
message, and either acodeorerrorskey — surfacemessagein toast.
- 400/500 errors always include a
3️⃣ Form Skeleton
-
Wrap tab body in:
<FormProvider {...methods}> <Box component="form" onSubmit={handleSubmit(onSubmit)} sx={{ maxWidth: 640 }}> {/* Fields */} </Box> </FormProvider>
-
Initialise RHF with
resolver: zodResolver(SystemSettingsUpdateSchema)anddefaultValuesfrom query data.
4️⃣ Notification Toggle & Brevo Section
-
MUI
SwitchforenableNotifications. -
When ON, show:
- Brevo API Key (
TextFieldtype="password"; helper: “Stored encrypted”). - Sender Name (
TextField). - Sender Email (
TextFieldtype="email").
- Brevo API Key (
-
All fields required when toggle is ON.
-
Below: Test Email
-
Input for
toemail (defaults to session user email). -
“Send Test Email” button → calls POST, shows toast for success/failure, handles loading state.
-
Toast message on success:
“Test e-mail sent ✔”. -
On error: show toast with backend
message. Common messages:- “Notifications are disabled”
- “Email sender identity not configured”
- “Stored Brevo key is invalid”
-
5️⃣ Default Link Expiry
- Numeric
TextFieldfor value. -
Selectfor unit: seconds, minutes, hours, days. - On submit, convert to seconds for payload.
- Helper: “Used when you click ‘Copy link’; can still override per-link in the Share dialog (future).”
- Acceptable range: 60 to 31,556,952 seconds i.e. 1 min to 1 year
6️⃣ Debug Logs
- MUI
Checkboxlabelled “Enable debug logging”. - Helper: “Print verbose output; may include personal info.”
7️⃣ Optional — Upload Limits
- Collapsible panel titled Advanced Upload Limits (collapsed by default).
- Numeric MB limit (1 – 50 MB).
- Multi-select (Chip) for MIME types.
- If not used → send
nullso backend falls back to defaults.
8️⃣ Form Actions
-
Save button (
type="submit"):- Disabled unless
formState.isDirty && formState.isValid && !mutation.isPending.
- Disabled unless
-
Reset button:
- Calls
reset(queryData); clears dirty flag.
- Calls
-
On successful save → show toast “System settings updated”.
9️⃣ Validation
- Brevo key must be ≥ 30 characters (Zod).
- Sender Email must pass HTML or
validator.isEmail. - Expiry must be in 60 – 31 556 952 seconds after unit conversion.
- Upload limit MB: 1 – 50 MB.
- PATCH must only send fields that changed — missing fields preserve existing DB values.
🔟 Loading & Fallback
- While
useSystemSettingsQueryis loading → show<CircularProgress>center-aligned. - If error → display fallback
Alertwith “Retry” button.
1️⃣1️⃣ UX & Accessibility
- All inputs have
labelprops andaria-describedbyfor helper text. - Switch has
aria-label. - “Send Test Email” includes
aria-live="polite"span for status. - Use MUI
gapfor spacing; keep form width ≤ 640 px.
✅ Acceptance Criteria
- Visiting
/settings→ System tab loads existing values within ~1 second. - Toggling visitor notifications ON requires valid Brevo key, sender name, and sender email.
- “Send Test Email” works with valid creds, shows success toast; fails gracefully with invalid creds.
- Saving updates backend (verified via refresh) and resets dirty state.
- Changing TTL affects newly generated links.
- Debug logs toggle controls server verbosity on next request.
- Upload limits and MIME types correctly round-trip to and from backend (with
nullfallback). - Form accessible and fully keyboard-navigable.
- Manual QA passes for edge cases (invalid input, switch toggles, reset clears dirty).
🗂 Notes
- No mobile-specific layout or dark-mode tweaks.
- No env-variable UI for storage/auth.
- Per-link overrides not included.
- Encryption handled entirely server-side.
- Brevo DevAdapter still logs to terminal in dev — no UI change needed.
- README update: remove
ENABLE_NOTIFICATIONS,DEFAULT_TTL, andDEBUG_LOGSfrom.env.example; markSEND_EMAILSas legacy (no longer read by code); keepSIGNED_URL_TTL_SECONDS.
- ➡️ Part of: Parent: Settings Page (Branding, Layout & System Controls) #311