From 6f31fa2503b11e3a9a37d753086bbb74b42f7bc4 Mon Sep 17 00:00:00 2001 From: Dries Augustyns Date: Fri, 24 Apr 2026 14:58:06 +0200 Subject: [PATCH] feat: add updateActiveProject function for in-place project updates --- apps/web/src/components/SecuritySettings.tsx | 52 ++++++++++--------- .../lib/contexts/ActiveProjectProvider.tsx | 8 +++ apps/web/src/pages/settings/index.tsx | 42 +++++++-------- 3 files changed, 57 insertions(+), 45 deletions(-) diff --git a/apps/web/src/components/SecuritySettings.tsx b/apps/web/src/components/SecuritySettings.tsx index ca9093e..8024cc9 100644 --- a/apps/web/src/components/SecuritySettings.tsx +++ b/apps/web/src/components/SecuritySettings.tsx @@ -107,17 +107,19 @@ export function SecuritySettings({metrics, isLoading}: SecuritySettingsProps) { Bounce Rate Hard bounces indicate invalid or non-existent email addresses - - - + +
+ + +
@@ -127,17 +129,19 @@ export function SecuritySettings({metrics, isLoading}: SecuritySettingsProps) { Complaint Rate Complaints occur when recipients mark emails as spam - - - + +
+ + +
@@ -155,10 +159,10 @@ function HealthMetric({label, level, detail}: HealthMetricProps) { const Icon = config.icon; return ( -
+

{label}

-

{detail}

+

{detail}

diff --git a/apps/web/src/lib/contexts/ActiveProjectProvider.tsx b/apps/web/src/lib/contexts/ActiveProjectProvider.tsx index 6f78a6d..9f9c3fb 100644 --- a/apps/web/src/lib/contexts/ActiveProjectProvider.tsx +++ b/apps/web/src/lib/contexts/ActiveProjectProvider.tsx @@ -7,6 +7,7 @@ import {useProjects} from '../hooks/useProject'; interface ActiveProjectContextValue { activeProject: Project | null; setActiveProject: (project: Project) => void; + updateActiveProject: (project: Project) => void; availableProjects: Project[]; isLoading: boolean; } @@ -55,9 +56,16 @@ export function ActiveProjectProvider({children}: {children: ReactNode}) { void mutate(() => true, undefined, {revalidate: true}); }; + // Updates the active project's data in-place without invalidating the SWR cache. + // Use this when saving settings for the current project, not when switching projects. + const updateActiveProject = (project: Project) => { + setActiveProjectState(project); + }; + const value: ActiveProjectContextValue = { activeProject, setActiveProject, + updateActiveProject, availableProjects: projects ?? [], isLoading, }; diff --git a/apps/web/src/pages/settings/index.tsx b/apps/web/src/pages/settings/index.tsx index d449460..f93e107 100644 --- a/apps/web/src/pages/settings/index.tsx +++ b/apps/web/src/pages/settings/index.tsx @@ -86,7 +86,7 @@ const buildTabs = (options: {billingEnabled: boolean; smtpEnabled: boolean}): Ta export default function Settings() { const router = useRouter(); - const {activeProject, setActiveProject} = useActiveProject(); + const {activeProject, setActiveProject, updateActiveProject} = useActiveProject(); const {mutate: projectsMutate} = useProjects(); const {data: config} = useConfig(); const {data: user} = useUser(); @@ -201,8 +201,8 @@ export default function Settings() { values, ); - // Update the active project in context - setActiveProject(updatedProject); + // Update the active project in context without invalidating the full SWR cache + updateActiveProject(updatedProject); // Refresh projects list await projectsMutate(); @@ -395,6 +395,7 @@ export default function Settings() { {/* General Tab */} +
Project Settings @@ -491,12 +492,6 @@ export default function Settings() { )} /> -
- -
- {/* Success/Error Messages */} {successMessage && ( @@ -520,13 +515,19 @@ export default function Settings() { )} + +
+ +
{/* API Keys - Separate Card */} - +
@@ -554,7 +555,7 @@ export default function Settings() { {/* Danger Zone - Separate Card */} - +
@@ -568,12 +569,12 @@ export default function Settings() {
- - {/* Reset Project */} -
-
+ +
+ {/* Reset Project */} +
-
+

Reset Project Data

@@ -590,13 +591,11 @@ export default function Settings() { Reset Data
-
- {/* Delete Project */} -
-
+ {/* Delete Project */} +
-
+

Delete Project Permanently

@@ -624,6 +623,7 @@ export default function Settings() {
+
{/* Billing Tab */}