Files
workspace/docs/PROMPT-sonner-notifications.md
2026-04-15 11:26:46 +02:00

9.6 KiB

Sonner Global Notification System — Ralph Loop Prompt

You are implementing a global toast notification system in the adiuvAI Electron app using shadcn's sonner component.

Full plan: Read docs/plan-sonner-notifications.md for the complete architecture, file list, i18n keys, and categorization of every mutation.

Rules

  • Always read the plan first at docs/plan-sonner-notifications.md before doing any work.
  • Always read a file before editing it. Never edit blind.
  • One phase per iteration. Complete one phase fully, verify it compiles, then move on.
  • Run cd adiuvAI && npx tsc --noEmit after each phase to catch type errors early.
  • Run cd adiuvAI && npm run lint after Phase 3 and Phase 4 to catch lint issues.
  • Commit after each phase with a descriptive message.
  • i18n: add keys to ALL 5 language files (en, it, es, fr, de). The plan has complete translations for each.
  • Do NOT touch silent mutations (note auto-save, kanban drag, sidebar toggle, AI chat/streaming). For these, add onError only if missing.
  • When removing saved/setSaved state patterns: also remove the setTimeout, the button text ternary, and any setSaved(false) in onChange handlers. Replace button text with {t('common.save')}.
  • Import path for useNotify: import { useNotify } from '@/hooks/useNotify';
  • Import path for toast (direct): import { toast } from 'sonner'; (only in useNotify.ts itself)

Progress Tracking

Check the state of the codebase to determine which phase to work on:

  1. If src/renderer/components/ui/sonner.tsx does NOT exist → Start Phase 1
  2. If sonner.tsx exists but settings components still have setSaved → Do Phase 2
  3. If settings are done but CRUD components lack useNotify → Do Phase 3
  4. If CRUD is done but auth/onboarding lack useNotify → Do Phase 4
  5. If all phases are done and npx tsc --noEmit + npm run lint pass → Do Phase 5 (verification)

Phase 1: Foundation

Step 1: Install sonner

cd adiuvAI && npx shadcn@latest add sonner --yes

Step 2: Fix theme import in generated sonner.tsx

The generated file imports useTheme from next-themes. This app does NOT use next-themes. Fix the import:

// WRONG (generated):
import { useTheme } from "next-themes"

// CORRECT:
import { useTheme } from "@/components/theme-provider"

Also set position="bottom-right" and add richColors on the <Sonner> component.

Step 3: Add <Toaster /> to src/renderer/index.tsx

Import Toaster from @/components/ui/sonner and render it as the last child inside <QueryClientProvider>, AFTER <RouterProvider />. This ensures toasts work during login, onboarding, AND normal app usage.

Step 4: Create src/renderer/hooks/useNotify.ts

Create the hook exactly as specified in the plan (Section 1.4). The hook exports { notify, notifyError, notifyPromise }.

Step 5: Add i18n keys to all 5 translation files

Add the "toast" top-level key with all sub-keys to:

  • src/renderer/locales/en/translation.json (English — from plan)
  • src/renderer/locales/it/translation.json (Italian — from plan)
  • src/renderer/locales/es/translation.json (Spanish — from plan)
  • src/renderer/locales/fr/translation.json (French — from plan)
  • src/renderer/locales/de/translation.json (German — from plan)

Step 6: Verify

cd adiuvAI && npx tsc --noEmit

Step 7: Commit

cd adiuvAI && git add -A && git commit -m "feat(notifications): add sonner toast foundation with useNotify hook and i18n keys"

Phase 2: Settings Components

For each of these 5 files, apply the pattern: add useNotify(), remove saved/setSaved state, remove setTimeout, replace button text ternary, add notify() in onSuccess, add notifyError() in onError.

Files (in order):

  1. src/renderer/components/settings/GeneralSection.tsx

    • Remove: saved, setSaved, error, setError, setTimeout, inline <p> error, setSaved(false) in onChange
    • Add: notify('success', 'toast.profile.updated') in handleSave onSuccess
    • Add: notifyError('toast.profile.updateError', err) in handleSave onError
    • Add: notify('info', 'toast.settings.languageChanged') in handleLanguageChange
    • Button text: {t('common.save')}
  2. src/renderer/components/settings/ProfileSection.tsx

    • Remove: profileSaved, displaySaved states and their setTimeouts
    • Profile save → notify('success', 'toast.settings.memorySaved')
    • Display save → notify('success', 'toast.settings.formatPrefsSaved')
    • Reset onboarding → notify('info', 'toast.onboarding.reset')
  3. src/renderer/components/settings/AccountSection.tsx

    • Remove: urlSaved, setUrlSaved state and setTimeout
    • Backend URL save → notify('success', 'toast.settings.backendUrlSaved')
    • Add onError → notifyError('toast.settings.backendUrlError', err)
    • Logout → notify('info', 'toast.auth.loggedOut')
  4. src/renderer/components/settings/LocalAgentConfigPanel.tsx

    • Remove: saved state and setTimeout
    • Save → notify('success', 'toast.agent.updated')
    • Add onError → notifyError('toast.agent.updateError', err)
  5. src/renderer/components/settings/CloudAgentConfigPanel.tsx

    • Same as LocalAgentConfigPanel

Verify and Commit:

cd adiuvAI && npx tsc --noEmit && npm run lint
cd adiuvAI && git add -A && git commit -m "feat(notifications): replace settings saved-state patterns with sonner toasts"

Phase 3: CRUD Operations

Add useNotify() to each component and wire notify / notifyError into existing onSuccess / onError callbacks. If onError doesn't exist, add it.

Files and mutations:

Tasks:

  • src/renderer/components/tasks/NewTaskDialog.tsxtasks.create: success toast.task.created + inline clients.create: success toast.client.created
  • src/renderer/components/tasks/EditTaskDialog.tsxtasks.update: success toast.task.updated
  • src/renderer/components/tasks/TaskDetailDialog.tsxtaskComments.create: success toast.comment.created, taskComments.delete: warning toast.comment.deleted
  • src/renderer/routes/tasks.tsxtasks.delete: warning toast.task.deleted, tasks.update status toggle: onError only
  • src/renderer/components/projects/KanbanBoard.tsxtasks.update drag: onError only, tasks.delete: warning toast.task.deleted
  • src/renderer/components/projects/ProjectDetail.tsxtasks.delete: warning toast.task.deleted, tasks.update toggle: onError only, notes.create: success toast.note.created
  • src/renderer/components/ai/blocks/ChatEntityBlock.tsxtasks.delete: warning toast.task.deleted, tasks.update toggle: onError only

Projects & Clients:

  • src/renderer/components/projects/ProjectSidebar.tsxprojects.create: success, projects.update: success, projects.delete: warning, projects.archiveByClient: warning (check if archiving or unarchiving), clients.create: success, clients.update: success, clients.deleteWithCascade: warning

Notes:

  • src/renderer/routes/notes.$noteId.tsxnotes.delete: warning toast.note.deleted, notes.update auto-save: onError only (SILENT)

Timeline:

  • src/renderer/components/timeline/AddEventDialog.tsxtimelineEvents.create: success
  • src/renderer/components/timeline/EditEventDialog.tsxtimelineEvents.update: success
  • src/renderer/routes/timeline.tsxtimelineEvents.delete: warning, timelineEvents.update: success

Agents:

  • src/renderer/components/settings/AgentsSection.tsxagent.*.delete: warning, agent.*.update toggle: onError only, agent.runNow: use notifyPromise
  • src/renderer/components/settings/InlineAgentCreationStepper.tsxagent.*.create: success

Verify and Commit:

cd adiuvAI && npx tsc --noEmit && npm run lint
cd adiuvAI && git add -A && git commit -m "feat(notifications): add sonner toasts to all CRUD operations"

Phase 4: Auth + Onboarding

Files:

  1. src/renderer/components/auth/LoginForm.tsx

    • auth.login onError → notifyError('toast.auth.loginError', err) (KEEP inline error too)
    • auth.register onError → notifyError('toast.auth.registerError', err) (KEEP inline error too)
    • auth.loginWithOAuth onError → notifyError('toast.auth.oauthError', err)
  2. src/renderer/components/layout/AppShell.tsx

    • auth.logout onSuccess → notify('info', 'toast.auth.loggedOut') (add before utils.auth.status.invalidate())
  3. src/renderer/components/onboarding/OnboardingFlow.tsx

    • Final save onSuccess → notify('success', 'toast.onboarding.completed', { descriptionKey: 'toast.onboarding.completedDescription' })
    • Final save onError → notifyError('toast.onboarding.error', err)
    • Normalize call → use notifyPromise with loading/success/error keys

Verify and Commit:

cd adiuvAI && npx tsc --noEmit && npm run lint
cd adiuvAI && git add -A && git commit -m "feat(notifications): add sonner toasts to auth and onboarding flows"

Phase 5: Final Verification

Run these checks:

cd adiuvAI && npx tsc --noEmit
cd adiuvAI && npm run lint
cd adiuvAI && npm run knip

Verify:

  • No remaining setSaved or setTimeout.*setSaved patterns in src/renderer/components/settings/
  • All 5 translation files have the toast key with matching sub-keys
  • sonner.tsx imports from @/components/theme-provider (NOT next-themes)
  • <Toaster /> renders in index.tsx inside <ThemeProvider>
  • useNotify.ts exists in src/renderer/hooks/

If everything passes:

SONNER NOTIFICATIONS COMPLETE