From 1183a4b02aeb100f856ca7d67db2a570d279450a Mon Sep 17 00:00:00 2001 From: Brad Groux Date: Sat, 7 Feb 2026 08:24:45 -0600 Subject: [PATCH] feat: wire DelegationTab into settings dialog + merge all feature branches --- .../components/settings/SettingsDialog.tsx | 11 ++ .../settings/tabs/DelegationTab.tsx | 101 ++++++++++-------- 2 files changed, 68 insertions(+), 44 deletions(-) diff --git a/web/src/components/settings/SettingsDialog.tsx b/web/src/components/settings/SettingsDialog.tsx index a47744db..e703739a 100644 --- a/web/src/components/settings/SettingsDialog.tsx +++ b/web/src/components/settings/SettingsDialog.tsx @@ -34,6 +34,7 @@ import { Upload, RotateCcw, Shield, + Plane, } from 'lucide-react'; import { DEFAULT_FEATURE_SETTINGS } from '@veritas-kanban/shared'; import { cn } from '@/lib/utils'; @@ -59,6 +60,9 @@ const LazyManageTab = lazy(() => const LazySecurityTab = lazy(() => import('./tabs/SecurityTab').then((m) => ({ default: m.SecurityTab })) ); +const LazyDelegationTab = lazy(() => + import('./tabs/DelegationTab').then((m) => ({ default: m.DelegationTab })) +); // ============ Tab Skeleton ============ @@ -85,6 +89,7 @@ type TabId = | 'data' | 'notifications' | 'security' + | 'delegation' | 'manage'; interface TabDef { @@ -101,6 +106,7 @@ const TABS: TabDef[] = [ { id: 'data', label: 'Data', icon: Database }, { id: 'notifications', label: 'Notifications', icon: Bell }, { id: 'security', label: 'Security', icon: Shield }, + { id: 'delegation', label: 'Delegation', icon: Plane }, { id: 'manage', label: 'Manage', icon: Archive }, ]; @@ -279,6 +285,11 @@ export function SettingsDialog({ open, onOpenChange, defaultTab }: SettingsDialo )} + {activeTab === 'delegation' && ( + + + + )} {activeTab === 'manage' && ( diff --git a/web/src/components/settings/tabs/DelegationTab.tsx b/web/src/components/settings/tabs/DelegationTab.tsx index 6d3ad03b..b00760c1 100644 --- a/web/src/components/settings/tabs/DelegationTab.tsx +++ b/web/src/components/settings/tabs/DelegationTab.tsx @@ -22,6 +22,24 @@ interface DelegationResponse { delegation: DelegationSettings | null; } +function formatDateTime(isoString: string): string { + const date = new Date(isoString); + return date.toLocaleString('en-US', { + month: 'short', + day: 'numeric', + year: 'numeric', + hour: 'numeric', + minute: '2-digit', + hour12: true, + }); +} + +function addHours(date: Date, hours: number): Date { + const result = new Date(date); + result.setHours(result.getHours() + hours); + return result; +} + export function DelegationTab() { const { toast } = useToast(); const queryClient = useQueryClient(); @@ -141,26 +159,26 @@ export function DelegationTab() { {/* Active Delegation Banner */} {isActive && !hasExpired && delegation && ( - - -
-
- - Delegation Active -
- - Active - +
+
+
+ + Delegation Active
- - + + Active + +
+
🤖 Delegate Agent: - {delegation.delegateAgent} + + {delegation.delegateAgent} +
- Expires: {format(new Date(delegation.expires), 'PPp')} + Expires: {formatDateTime(delegation.expires)}
{delegation.excludePriorities && delegation.excludePriorities.length > 0 && (
@@ -177,36 +195,33 @@ export function DelegationTab() { > Revoke Delegation - - +
+
)} {/* Expired Notice */} {delegation && hasExpired && ( - - -
- - Delegation Expired -
-
- -

The delegation expired on {format(new Date(delegation.expires), 'PPp')}

-
-
+
+
+ + Delegation Expired +
+

The delegation expired on {formatDateTime(delegation.expires)}

+
)} - +
{/* Setup Form */} - - - Set Up Delegation - +
+
+

Set Up Delegation

+

Configure approval delegation for a specific time period - - - +

+
+ +