Skip to content

Settings UI — System & Notifications Tab #316

@mahid797

Description

@mahid797

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 → GET
    • useUpdateSystemSettingsMutation → PATCH
    • useTestEmailMutation → 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, and DEBUG_LOGS from .env.example; mark SEND_EMAILS as legacy (no longer read by code); keep SIGNED_URL_TTL_SECONDS.

🔧 Implementation Tasks

1️⃣ Tab Integration

  • Add a second MUI Tab labelled System & Notifications.
  • Support ?tab=system query 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/system and PATCH /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
      }
    • allowedMimeTypes must be parsed into a string array for the UI and rejoined as CSV on submit.

  • POST /api/settings/test-email accepts:

    { "to": "[email protected]" }

    and returns:

    { "success": true }
    • 400/500 errors always include a message, and either a code or errors key — surface message in toast.

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) and defaultValues from query data.


4️⃣ Notification Toggle & Brevo Section

  • MUI Switch for enableNotifications.

  • When ON, show:

    • Brevo API Key (TextField type="password"; helper: “Stored encrypted”).
    • Sender Name (TextField).
    • Sender Email (TextField type="email").
  • All fields required when toggle is ON.

  • Below: Test Email

    • Input for to email (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 TextField for value.
  • Select for 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 Checkbox labelled “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 null so backend falls back to defaults.

8️⃣ Form Actions

  • Save button (type="submit"):

    • Disabled unless formState.isDirty && formState.isValid && !mutation.isPending.
  • Reset button:

    • Calls reset(queryData); clears dirty flag.
  • 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 useSystemSettingsQuery is loading → show <CircularProgress> center-aligned.
  • If error → display fallback Alert with “Retry” button.

1️⃣1️⃣ UX & Accessibility

  • All inputs have label props and aria-describedby for helper text.
  • Switch has aria-label.
  • “Send Test Email” includes aria-live="polite" span for status.
  • Use MUI gap for 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 null fallback).
  • 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, and DEBUG_LOGS from .env.example; mark SEND_EMAILS as legacy (no longer read by code); keep SIGNED_URL_TTL_SECONDS.

Metadata

Metadata

Labels

CoreWork to do on the core system of the AppFrontendFrontend Related IssueNew FeatureNew feature to be implemented🌱Nice-to-HaveEnhancements, Refactors, UI tweaks, or non-critical optimizations

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions