From 130c47fd0b397d3ba1e363498ec67cd65d9933e6 Mon Sep 17 00:00:00 2001 From: chasprowebdev Date: Tue, 7 Jul 2026 11:15:23 -0400 Subject: [PATCH 1/3] fix(app): refresh SWR cache after upload, delete, and replace --- .../people/org-chart/components/OrgChartContent.tsx | 12 ++++++++++-- .../org-chart/components/OrgChartEmptyState.tsx | 13 +++++++++++-- .../org-chart/components/OrgChartImageView.tsx | 13 +++++++++---- .../org-chart/components/OrgChartTabContent.tsx | 10 ++++++++-- .../org-chart/components/UploadOrgChartDialog.tsx | 10 ++++++---- 5 files changed, 44 insertions(+), 14 deletions(-) diff --git a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartContent.tsx b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartContent.tsx index 107e837068..4ff5fd00c8 100644 --- a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartContent.tsx +++ b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartContent.tsx @@ -20,11 +20,18 @@ interface OrgChartData { interface OrgChartContentProps { chartData: OrgChartData | null; members: OrgChartMember[]; + onChartChange: () => void | Promise; } -export function OrgChartContent({ chartData, members }: OrgChartContentProps) { +export function OrgChartContent({ + chartData, + members, + onChartChange, +}: OrgChartContentProps) { if (!chartData) { - return ; + return ( + + ); } if (chartData.type === 'uploaded' && chartData.signedImageUrl) { @@ -32,6 +39,7 @@ export function OrgChartContent({ chartData, members }: OrgChartContentProps) { ); } diff --git a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartEmptyState.tsx b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartEmptyState.tsx index e677a87262..f03c190086 100644 --- a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartEmptyState.tsx +++ b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartEmptyState.tsx @@ -9,9 +9,13 @@ import type { OrgChartMember } from '../types'; interface OrgChartEmptyStateProps { members: OrgChartMember[]; + onChartChange: () => void | Promise; } -export function OrgChartEmptyState({ members }: OrgChartEmptyStateProps) { +export function OrgChartEmptyState({ + members, + onChartChange, +}: OrgChartEmptyStateProps) { const [mode, setMode] = useState<'empty' | 'create' | 'upload'>('empty'); if (mode === 'create') { @@ -26,7 +30,12 @@ export function OrgChartEmptyState({ members }: OrgChartEmptyStateProps) { } if (mode === 'upload') { - return setMode('empty')} />; + return ( + setMode('empty')} + onUploaded={onChartChange} + /> + ); } return ( diff --git a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartImageView.tsx b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartImageView.tsx index 6eeed4d7f0..1d8eee34bd 100644 --- a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartImageView.tsx +++ b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartImageView.tsx @@ -5,20 +5,20 @@ import { Button } from '@trycompai/design-system'; import { TrashCan, Upload } from '@trycompai/design-system/icons'; import { useApi } from '@/hooks/use-api'; import { toast } from 'sonner'; -import { useRouter } from 'next/navigation'; import { UploadOrgChartDialog } from './UploadOrgChartDialog'; interface OrgChartImageViewProps { imageUrl: string; chartName: string; + onChartChange: () => void | Promise; } export function OrgChartImageView({ imageUrl, chartName, + onChartChange, }: OrgChartImageViewProps) { const api = useApi(); - const router = useRouter(); const [isDeleting, setIsDeleting] = useState(false); const [showReplace, setShowReplace] = useState(false); @@ -33,7 +33,7 @@ export function OrgChartImageView({ } toast.success('Org chart deleted'); - router.refresh(); + await onChartChange(); } catch { toast.error('Failed to delete org chart'); } finally { @@ -42,7 +42,12 @@ export function OrgChartImageView({ }; if (showReplace) { - return setShowReplace(false)} />; + return ( + setShowReplace(false)} + onUploaded={onChartChange} + /> + ); } return ( diff --git a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartTabContent.tsx b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartTabContent.tsx index a0cc7f7129..7a01fc0e3c 100644 --- a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartTabContent.tsx +++ b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartTabContent.tsx @@ -10,7 +10,7 @@ interface OrgChartTabContentProps { } export function OrgChartTabContent({ organizationId }: OrgChartTabContentProps) { - const { orgChart } = useOrgChart(); + const { orgChart, mutate } = useOrgChart(); const { members } = useTeamMembers({ organizationId }); const chartMembers: OrgChartMember[] = members @@ -25,5 +25,11 @@ export function OrgChartTabContent({ organizationId }: OrgChartTabContentProps) jobTitle: m.jobTitle ?? null, })); - return ; + return ( + + ); } diff --git a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/UploadOrgChartDialog.tsx b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/UploadOrgChartDialog.tsx index 56fa6b55a4..41cd3d189f 100644 --- a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/UploadOrgChartDialog.tsx +++ b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/UploadOrgChartDialog.tsx @@ -6,15 +6,17 @@ import { Button } from '@trycompai/design-system'; import { Upload, Close } from '@trycompai/design-system/icons'; import { useApi } from '@/hooks/use-api'; import { toast } from 'sonner'; -import { useRouter } from 'next/navigation'; interface UploadOrgChartDialogProps { onClose: () => void; + onUploaded: () => void | Promise; } -export function UploadOrgChartDialog({ onClose }: UploadOrgChartDialogProps) { +export function UploadOrgChartDialog({ + onClose, + onUploaded, +}: UploadOrgChartDialogProps) { const api = useApi(); - const router = useRouter(); const [isUploading, setIsUploading] = useState(false); const [selectedFile, setSelectedFile] = useState(null); @@ -60,7 +62,7 @@ export function UploadOrgChartDialog({ onClose }: UploadOrgChartDialogProps) { } toast.success('Org chart uploaded'); - router.refresh(); + await onUploaded(); onClose(); } catch { toast.error('Failed to upload org chart'); From c20088923f6f9320049930412e026ae344c1a95d Mon Sep 17 00:00:00 2001 From: chasprowebdev Date: Tue, 7 Jul 2026 11:38:09 -0400 Subject: [PATCH 2/3] fix(app): revalidate SWR cache after editor save --- .../[orgId]/people/org-chart/components/OrgChartContent.tsx | 1 + .../[orgId]/people/org-chart/components/OrgChartEditor.tsx | 6 +++--- .../people/org-chart/components/OrgChartEmptyState.tsx | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartContent.tsx b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartContent.tsx index 4ff5fd00c8..c4cbbc5c47 100644 --- a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartContent.tsx +++ b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartContent.tsx @@ -65,6 +65,7 @@ export function OrgChartContent({ initialEdges={chartData.edges} members={members} updatedAt={chartData.updatedAt ?? null} + onChartChange={onChartChange} /> ); } diff --git a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartEditor.tsx b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartEditor.tsx index 077c2970a4..bcd52f54ee 100644 --- a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartEditor.tsx +++ b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartEditor.tsx @@ -18,7 +18,6 @@ import { } from '@xyflow/react'; import '@xyflow/react/dist/style.css'; import { formatDistanceToNow } from 'date-fns'; -import { useRouter } from 'next/navigation'; import { useCallback, useMemo, useRef, useState } from 'react'; import { toast } from 'sonner'; import type { OrgChartMember } from '../types'; @@ -30,6 +29,7 @@ interface OrgChartEditorProps { initialEdges: Edge[]; members: OrgChartMember[]; updatedAt: string | null; + onChartChange: () => void | Promise; } export function OrgChartEditor({ @@ -37,9 +37,9 @@ export function OrgChartEditor({ initialEdges, members, updatedAt, + onChartChange, }: OrgChartEditorProps) { const api = useApi(); - const router = useRouter(); const reactFlowWrapper = useRef(null); const [reactFlowInstance, setReactFlowInstance] = useState(null); @@ -161,7 +161,7 @@ export function OrgChartEditor({ setLastSavedAt(new Date().toISOString()); } toast.success('Org chart saved'); - router.refresh(); + await onChartChange(); } catch { toast.error('Failed to save org chart'); } finally { diff --git a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartEmptyState.tsx b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartEmptyState.tsx index f03c190086..2da1050a56 100644 --- a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartEmptyState.tsx +++ b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartEmptyState.tsx @@ -25,6 +25,7 @@ export function OrgChartEmptyState({ initialEdges={[]} members={members} updatedAt={null} + onChartChange={onChartChange} /> ); } From 7f733c6d7bb29efaca9da3288cf9d0f30aa9bfbf Mon Sep 17 00:00:00 2001 From: chasprowebdev Date: Tue, 7 Jul 2026 11:41:34 -0400 Subject: [PATCH 3/3] fix(app): isolate SWR refresh failures from upload/delete/save results --- .../[orgId]/people/org-chart/components/OrgChartEditor.tsx | 7 ++++++- .../people/org-chart/components/OrgChartImageView.tsx | 7 ++++++- .../people/org-chart/components/UploadOrgChartDialog.tsx | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartEditor.tsx b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartEditor.tsx index bcd52f54ee..c2fad40905 100644 --- a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartEditor.tsx +++ b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartEditor.tsx @@ -161,7 +161,12 @@ export function OrgChartEditor({ setLastSavedAt(new Date().toISOString()); } toast.success('Org chart saved'); - await onChartChange(); + + try { + await onChartChange(); + } catch { + // Save already succeeded; a refresh failure shouldn't surface as a save error. + } } catch { toast.error('Failed to save org chart'); } finally { diff --git a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartImageView.tsx b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartImageView.tsx index 1d8eee34bd..f0c0bbd3f9 100644 --- a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartImageView.tsx +++ b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/OrgChartImageView.tsx @@ -33,7 +33,12 @@ export function OrgChartImageView({ } toast.success('Org chart deleted'); - await onChartChange(); + + try { + await onChartChange(); + } catch { + // Delete already succeeded; a refresh failure shouldn't surface as a delete error. + } } catch { toast.error('Failed to delete org chart'); } finally { diff --git a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/UploadOrgChartDialog.tsx b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/UploadOrgChartDialog.tsx index 41cd3d189f..41e5683aea 100644 --- a/apps/app/src/app/(app)/[orgId]/people/org-chart/components/UploadOrgChartDialog.tsx +++ b/apps/app/src/app/(app)/[orgId]/people/org-chart/components/UploadOrgChartDialog.tsx @@ -62,8 +62,13 @@ export function UploadOrgChartDialog({ } toast.success('Org chart uploaded'); - await onUploaded(); onClose(); + + try { + await onUploaded(); + } catch { + // Upload already succeeded; a refresh failure shouldn't surface as an upload error. + } } catch { toast.error('Failed to upload org chart'); } finally {