mirror of
https://github.com/tiennm99/ccs.git
synced 2026-08-21 08:25:23 +00:00
feat(ui): persist provider selection in cliproxy and auth-monitor
- save selected provider to localStorage on both pages - restore selection on page load - validate saved provider still exists before restoring - improves UX by eliminating need to re-select provider after reload
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
* Uses glass panel aesthetic with hover interactions and glow effects
|
* 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 { STATUS_COLORS } from '@/lib/utils';
|
||||||
import { Skeleton } from '@/components/ui/skeleton';
|
import { Skeleton } from '@/components/ui/skeleton';
|
||||||
import { AccountFlowViz } from '@/components/account-flow-viz';
|
import { AccountFlowViz } from '@/components/account-flow-viz';
|
||||||
@@ -17,6 +17,8 @@ import { LivePulse } from './components/live-pulse';
|
|||||||
import { ProviderCard } from './components/provider-card';
|
import { ProviderCard } from './components/provider-card';
|
||||||
import { SummaryCard } from './components/summary-card';
|
import { SummaryCard } from './components/summary-card';
|
||||||
|
|
||||||
|
const STORAGE_KEY = 'auth-monitor-selected-provider';
|
||||||
|
|
||||||
export function AuthMonitor() {
|
export function AuthMonitor() {
|
||||||
const {
|
const {
|
||||||
accounts,
|
accounts,
|
||||||
@@ -31,7 +33,32 @@ export function AuthMonitor() {
|
|||||||
} = useAuthMonitorData();
|
} = useAuthMonitorData();
|
||||||
|
|
||||||
const { privacyMode } = usePrivacy();
|
const { privacyMode } = usePrivacy();
|
||||||
const [selectedProvider, setSelectedProvider] = useState<string | null>(null);
|
|
||||||
|
// Persist selected provider in localStorage
|
||||||
|
const [selectedProvider, setSelectedProviderState] = useState<string | null>(() => {
|
||||||
|
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<string | null>(null);
|
const [hoveredProvider, setHoveredProvider] = useState<string | null>(null);
|
||||||
|
|
||||||
// Account control mutations for flow viz
|
// Account control mutations for flow viz
|
||||||
@@ -39,16 +66,16 @@ export function AuthMonitor() {
|
|||||||
const resumeMutation = useResumeAccount();
|
const resumeMutation = useResumeAccount();
|
||||||
|
|
||||||
// Get selected provider data for detail view
|
// Get selected provider data for detail view
|
||||||
const selectedProviderData = selectedProvider
|
const selectedProviderData = effectiveProvider
|
||||||
? providerStats.find((ps) => ps.provider === selectedProvider)
|
? providerStats.find((ps) => ps.provider === effectiveProvider)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const handlePauseToggle = (accountId: string, paused: boolean) => {
|
const handlePauseToggle = (accountId: string, paused: boolean) => {
|
||||||
if (!selectedProvider || pauseMutation.isPending || resumeMutation.isPending) return;
|
if (!effectiveProvider || pauseMutation.isPending || resumeMutation.isPending) return;
|
||||||
if (paused) {
|
if (paused) {
|
||||||
pauseMutation.mutate({ provider: selectedProvider, accountId });
|
pauseMutation.mutate({ provider: effectiveProvider, accountId });
|
||||||
} else {
|
} else {
|
||||||
resumeMutation.mutate({ provider: selectedProvider, accountId });
|
resumeMutation.mutate({ provider: effectiveProvider, accountId });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -194,7 +194,13 @@ export function CliproxyPage() {
|
|||||||
const deleteMutation = useDeleteVariant();
|
const deleteMutation = useDeleteVariant();
|
||||||
|
|
||||||
// Selection state: either a provider or a variant
|
// Selection state: either a provider or a variant
|
||||||
const [selectedProvider, setSelectedProvider] = useState<string | null>(null);
|
// Initialize from localStorage if available
|
||||||
|
const [selectedProvider, setSelectedProviderState] = useState<string | null>(() => {
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
return localStorage.getItem('cliproxy-selected-provider');
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
const [selectedVariant, setSelectedVariant] = useState<string | null>(null);
|
const [selectedVariant, setSelectedVariant] = useState<string | null>(null);
|
||||||
const [wizardOpen, setWizardOpen] = useState(false);
|
const [wizardOpen, setWizardOpen] = useState(false);
|
||||||
const [addAccountProvider, setAddAccountProvider] = useState<{
|
const [addAccountProvider, setAddAccountProvider] = useState<{
|
||||||
@@ -207,14 +213,29 @@ export function CliproxyPage() {
|
|||||||
const isRemoteMode = authData?.source === 'remote';
|
const isRemoteMode = authData?.source === 'remote';
|
||||||
const variants = useMemo(() => variantsData?.variants || [], [variantsData?.variants]);
|
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(() => {
|
const effectiveProvider = useMemo(() => {
|
||||||
// If a variant is selected, no provider is effective
|
|
||||||
if (selectedVariant) return null;
|
if (selectedVariant) return null;
|
||||||
|
|
||||||
|
// If saved/selected provider is valid, use it
|
||||||
if (selectedProvider && providers.some((p) => p.provider === selectedProvider)) {
|
if (selectedProvider && providers.some((p) => p.provider === selectedProvider)) {
|
||||||
return 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]);
|
}, [selectedProvider, selectedVariant, providers]);
|
||||||
|
|
||||||
const selectedStatus = providers.find((p) => p.provider === effectiveProvider);
|
const selectedStatus = providers.find((p) => p.provider === effectiveProvider);
|
||||||
|
|||||||
Reference in New Issue
Block a user