diff --git a/ui/src/components/monitoring/auth-monitor/index.tsx b/ui/src/components/monitoring/auth-monitor/index.tsx index f6fcb8fa..93202ba3 100644 --- a/ui/src/components/monitoring/auth-monitor/index.tsx +++ b/ui/src/components/monitoring/auth-monitor/index.tsx @@ -4,7 +4,7 @@ * Uses glass panel aesthetic with hover interactions and glow effects */ -import { useState } from 'react'; +import { useState, useMemo } from 'react'; import { STATUS_COLORS } from '@/lib/utils'; import { Skeleton } from '@/components/ui/skeleton'; import { AccountFlowViz } from '@/components/account-flow-viz'; @@ -17,6 +17,8 @@ import { LivePulse } from './components/live-pulse'; import { ProviderCard } from './components/provider-card'; import { SummaryCard } from './components/summary-card'; +const STORAGE_KEY = 'auth-monitor-selected-provider'; + export function AuthMonitor() { const { accounts, @@ -31,7 +33,32 @@ export function AuthMonitor() { } = useAuthMonitorData(); const { privacyMode } = usePrivacy(); - const [selectedProvider, setSelectedProvider] = useState(null); + + // Persist selected provider in localStorage + const [selectedProvider, setSelectedProviderState] = useState(() => { + if (typeof window !== 'undefined') { + return localStorage.getItem(STORAGE_KEY); + } + return null; + }); + + // Wrapper to persist selection + const setSelectedProvider = (provider: string | null) => { + setSelectedProviderState(provider); + if (provider) { + localStorage.setItem(STORAGE_KEY, provider); + } else { + localStorage.removeItem(STORAGE_KEY); + } + }; + + // Effective provider: prefer saved (if still exists) > null (show grid) + const effectiveProvider = useMemo(() => { + if (selectedProvider && providerStats.some((p) => p.provider === selectedProvider)) { + return selectedProvider; + } + return null; + }, [selectedProvider, providerStats]); const [hoveredProvider, setHoveredProvider] = useState(null); // Account control mutations for flow viz @@ -39,16 +66,16 @@ export function AuthMonitor() { const resumeMutation = useResumeAccount(); // Get selected provider data for detail view - const selectedProviderData = selectedProvider - ? providerStats.find((ps) => ps.provider === selectedProvider) + const selectedProviderData = effectiveProvider + ? providerStats.find((ps) => ps.provider === effectiveProvider) : null; const handlePauseToggle = (accountId: string, paused: boolean) => { - if (!selectedProvider || pauseMutation.isPending || resumeMutation.isPending) return; + if (!effectiveProvider || pauseMutation.isPending || resumeMutation.isPending) return; if (paused) { - pauseMutation.mutate({ provider: selectedProvider, accountId }); + pauseMutation.mutate({ provider: effectiveProvider, accountId }); } else { - resumeMutation.mutate({ provider: selectedProvider, accountId }); + resumeMutation.mutate({ provider: effectiveProvider, accountId }); } }; diff --git a/ui/src/pages/cliproxy.tsx b/ui/src/pages/cliproxy.tsx index 3a1ed931..3640565f 100644 --- a/ui/src/pages/cliproxy.tsx +++ b/ui/src/pages/cliproxy.tsx @@ -194,7 +194,13 @@ export function CliproxyPage() { const deleteMutation = useDeleteVariant(); // Selection state: either a provider or a variant - const [selectedProvider, setSelectedProvider] = useState(null); + // Initialize from localStorage if available + const [selectedProvider, setSelectedProviderState] = useState(() => { + if (typeof window !== 'undefined') { + return localStorage.getItem('cliproxy-selected-provider'); + } + return null; + }); const [selectedVariant, setSelectedVariant] = useState(null); const [wizardOpen, setWizardOpen] = useState(false); const [addAccountProvider, setAddAccountProvider] = useState<{ @@ -207,14 +213,29 @@ export function CliproxyPage() { const isRemoteMode = authData?.source === 'remote'; const variants = useMemo(() => variantsData?.variants || [], [variantsData?.variants]); - // Auto-select first provider if nothing selected + // Wrapper to persist provider selection to localStorage + const setSelectedProvider = (provider: string | null) => { + setSelectedProviderState(provider); + if (provider) { + localStorage.setItem('cliproxy-selected-provider', provider); + } + }; + + // Effective provider: prefer saved > first with accounts > first const effectiveProvider = useMemo(() => { - // If a variant is selected, no provider is effective if (selectedVariant) return null; + + // If saved/selected provider is valid, use it if (selectedProvider && providers.some((p) => p.provider === selectedProvider)) { return selectedProvider; } - return providers.length > 0 ? providers[0].provider : null; + + // Auto-select: prefer first provider with accounts (better UX) + if (providers.length > 0) { + const providerWithAccounts = providers.find((p) => (p.accounts?.length || 0) > 0); + return providerWithAccounts?.provider || providers[0]?.provider || null; + } + return null; }, [selectedProvider, selectedVariant, providers]); const selectedStatus = providers.find((p) => p.provider === effectiveProvider);