mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-13 04:14:57 +00:00
feat(accounts-ui): redesign accounts dashboard to column layout
This commit is contained in:
1 parent
b6475baab3
commit
12c7a218b7
1 file changed
+329
-147
+329
-147
@@ -5,14 +5,87 @@
|
|||||||
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { ArrowRight, Link2, Plus, Unlink, Users, Waves, Zap } from 'lucide-react';
|
import { AlertTriangle, ArrowRight, Link2, Plus, Unlink, Users, Waves, Zap } from 'lucide-react';
|
||||||
import { AccountsTable } from '@/components/account/accounts-table';
|
import { AccountsTable } from '@/components/account/accounts-table';
|
||||||
import { CreateAuthProfileDialog } from '@/components/account/create-auth-profile-dialog';
|
import { CreateAuthProfileDialog } from '@/components/account/create-auth-profile-dialog';
|
||||||
|
import { CopyButton } from '@/components/ui/copy-button';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
|
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
|
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||||
import { useAccounts } from '@/hooks/use-accounts';
|
import { useAccounts } from '@/hooks/use-accounts';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
import type { LucideIcon } from 'lucide-react';
|
||||||
|
|
||||||
|
type MetricTone = 'default' | 'shared' | 'deeper' | 'isolated';
|
||||||
|
|
||||||
|
function MetricTile({
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
icon: Icon,
|
||||||
|
tone = 'default',
|
||||||
|
}: {
|
||||||
|
label: string;
|
||||||
|
value: number;
|
||||||
|
icon: LucideIcon;
|
||||||
|
tone?: MetricTone;
|
||||||
|
}) {
|
||||||
|
const toneClasses: Record<MetricTone, { border: string; icon: string }> = {
|
||||||
|
default: {
|
||||||
|
border: 'border-border',
|
||||||
|
icon: 'text-primary',
|
||||||
|
},
|
||||||
|
shared: {
|
||||||
|
border: 'border-emerald-300/60 dark:border-emerald-900/40',
|
||||||
|
icon: 'text-emerald-700 dark:text-emerald-400',
|
||||||
|
},
|
||||||
|
deeper: {
|
||||||
|
border: 'border-indigo-300/60 dark:border-indigo-900/40',
|
||||||
|
icon: 'text-indigo-700 dark:text-indigo-400',
|
||||||
|
},
|
||||||
|
isolated: {
|
||||||
|
border: 'border-blue-300/60 dark:border-blue-900/40',
|
||||||
|
icon: 'text-blue-700 dark:text-blue-400',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={cn('rounded-md border bg-card px-3 py-2.5', toneClasses[tone].border)}>
|
||||||
|
<div className="flex items-center justify-between gap-2">
|
||||||
|
<span className="text-[11px] uppercase tracking-wide text-muted-foreground">{label}</span>
|
||||||
|
<Icon className={cn('h-3.5 w-3.5', toneClasses[tone].icon)} />
|
||||||
|
</div>
|
||||||
|
<p className={cn('mt-1 text-xl font-mono font-semibold', toneClasses[tone].icon)}>{value}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function StrategyCard({
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
variant,
|
||||||
|
}: {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
variant: 'auth' | 'pool';
|
||||||
|
}) {
|
||||||
|
const variantClasses =
|
||||||
|
variant === 'auth'
|
||||||
|
? 'border-emerald-300/70 bg-emerald-50/40 dark:border-emerald-900/40 dark:bg-emerald-900/10'
|
||||||
|
: 'border-blue-300/70 bg-blue-50/40 dark:border-blue-900/40 dark:bg-blue-900/10';
|
||||||
|
const titleClasses =
|
||||||
|
variant === 'auth'
|
||||||
|
? 'text-emerald-800 dark:text-emerald-300'
|
||||||
|
: 'text-blue-800 dark:text-blue-300';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={cn('rounded-md border px-3 py-2.5', variantClasses)}>
|
||||||
|
<p className={cn('text-sm font-semibold', titleClasses)}>{title}</p>
|
||||||
|
<p className="mt-1 text-xs text-muted-foreground">{description}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function AccountsPage() {
|
export function AccountsPage() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -26,169 +99,278 @@ export function AccountsPage() {
|
|||||||
const sharedStandardCount = data?.sharedStandardCount || 0;
|
const sharedStandardCount = data?.sharedStandardCount || 0;
|
||||||
const deeperSharedCount = data?.deeperSharedCount || 0;
|
const deeperSharedCount = data?.deeperSharedCount || 0;
|
||||||
const isolatedCount = data?.isolatedCount || 0;
|
const isolatedCount = data?.isolatedCount || 0;
|
||||||
|
const hasLegacyFollowUp = legacyContextCount > 0 || legacyContinuityCount > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-6 max-w-6xl mx-auto space-y-8">
|
<>
|
||||||
<div className="rounded-xl border bg-gradient-to-br from-background via-background to-muted/40 p-5 sm:p-6">
|
<div className="h-[calc(100vh-100px)] hidden lg:flex">
|
||||||
<div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
|
{/* Left rail */}
|
||||||
<div className="space-y-2">
|
<div className="w-80 border-r flex flex-col bg-muted/30 shrink-0">
|
||||||
<Badge variant="outline">ccs auth Continuity</Badge>
|
<div className="p-4 border-b bg-background space-y-3">
|
||||||
<h1 className="text-2xl font-bold tracking-tight">Accounts</h1>
|
<div>
|
||||||
<p className="text-sm text-muted-foreground max-w-2xl">
|
<div className="flex items-center gap-2">
|
||||||
This page manages
|
<Users className="h-5 w-5 text-primary" />
|
||||||
<code className="mx-1 rounded bg-muted px-1 py-0.5">ccs auth</code>
|
<h1 className="font-semibold">Accounts</h1>
|
||||||
accounts only. Choose isolated, shared-standard, or shared-deeper continuity per
|
</div>
|
||||||
account.
|
<p className="mt-1 text-xs text-muted-foreground">
|
||||||
</p>
|
Dedicated
|
||||||
|
<code className="mx-1 rounded bg-muted px-1 py-0.5">ccs auth</code>
|
||||||
|
continuity controls.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 gap-2">
|
||||||
|
<Button onClick={() => setCreateDialogOpen(true)} size="sm" className="justify-start">
|
||||||
|
<Plus className="w-4 h-4 mr-2" />
|
||||||
|
Create Account
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
className="justify-start"
|
||||||
|
onClick={() => navigate('/cliproxy')}
|
||||||
|
>
|
||||||
|
Open CLIProxy Claude Pool
|
||||||
|
<ArrowRight className="w-4 h-4 ml-auto" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col items-stretch gap-2 sm:flex-row sm:items-center">
|
<ScrollArea className="flex-1">
|
||||||
<Button onClick={() => setCreateDialogOpen(true)}>
|
<div className="p-3 space-y-4">
|
||||||
<Plus className="w-4 h-4 mr-2" />
|
<section className="space-y-2">
|
||||||
Create Account
|
<p className="text-[11px] font-medium uppercase tracking-wide text-muted-foreground">
|
||||||
</Button>
|
Snapshot
|
||||||
<Button variant="outline" onClick={() => navigate('/cliproxy')}>
|
</p>
|
||||||
Open CLIProxy Claude Pool
|
<div className="grid grid-cols-2 gap-2">
|
||||||
<ArrowRight className="w-4 h-4 ml-2" />
|
<MetricTile label="Total" value={authAccounts.length} icon={Users} />
|
||||||
</Button>
|
<MetricTile label="Shared" value={sharedCount} icon={Link2} tone="shared" />
|
||||||
|
<MetricTile label="Deeper" value={deeperSharedCount} icon={Waves} tone="deeper" />
|
||||||
|
<MetricTile
|
||||||
|
label="Isolated"
|
||||||
|
value={isolatedCount}
|
||||||
|
icon={Unlink}
|
||||||
|
tone="isolated"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="space-y-2">
|
||||||
|
<p className="text-[11px] font-medium uppercase tracking-wide text-muted-foreground">
|
||||||
|
Strategy Lanes
|
||||||
|
</p>
|
||||||
|
<StrategyCard
|
||||||
|
variant="auth"
|
||||||
|
title="Lane A: ccs auth continuity"
|
||||||
|
description="Isolation-first accounts with explicit shared/deeper controls per profile."
|
||||||
|
/>
|
||||||
|
<StrategyCard
|
||||||
|
variant="pool"
|
||||||
|
title="Lane B: CLIProxy Claude pool"
|
||||||
|
description="OAuth pool routing for lower manual account switching."
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{hasLegacyFollowUp && (
|
||||||
|
<section className="space-y-2">
|
||||||
|
<p className="text-[11px] font-medium uppercase tracking-wide text-muted-foreground">
|
||||||
|
Migration Follow-up
|
||||||
|
</p>
|
||||||
|
<div className="rounded-md border border-amber-500/50 bg-amber-500/10 p-3">
|
||||||
|
<div className="flex items-start gap-2">
|
||||||
|
<AlertTriangle className="h-4 w-4 mt-0.5 text-amber-700 dark:text-amber-400 shrink-0" />
|
||||||
|
<div className="space-y-1 text-xs">
|
||||||
|
{legacyContextCount > 0 && (
|
||||||
|
<p className="text-amber-800 dark:text-amber-300">
|
||||||
|
{legacyContextCount} account
|
||||||
|
{legacyContextCount > 1 ? 's still need' : ' still needs'} first-time
|
||||||
|
mode confirmation.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
{legacyContinuityCount > 0 && (
|
||||||
|
<p className="text-amber-800 dark:text-amber-300">
|
||||||
|
{legacyContinuityCount} shared account
|
||||||
|
{legacyContinuityCount > 1 ? 's remain' : ' remains'} on standard legacy
|
||||||
|
continuity depth.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</ScrollArea>
|
||||||
|
|
||||||
|
<div className="p-3 border-t bg-background text-xs text-muted-foreground">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span>Standard shared</span>
|
||||||
|
<span className="font-mono">{sharedStandardCount}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-between mt-1">
|
||||||
|
<span>CLIProxy hidden</span>
|
||||||
|
<span className="font-mono">{cliproxyCount}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Main workspace */}
|
||||||
|
<div className="flex-1 min-w-0 flex">
|
||||||
|
{/* Table column */}
|
||||||
|
<div className="flex-1 min-w-0 flex flex-col border-r bg-background">
|
||||||
|
<div className="px-5 py-4 border-b bg-background">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Badge variant="outline">ccs auth Workspace</Badge>
|
||||||
|
<Badge variant="secondary">History Sync Controls</Badge>
|
||||||
|
</div>
|
||||||
|
<h2 className="mt-2 text-xl font-semibold tracking-tight">Auth Accounts</h2>
|
||||||
|
<p className="mt-1 text-sm text-muted-foreground">
|
||||||
|
This table is intentionally scoped to
|
||||||
|
<code className="mx-1 rounded bg-muted px-1 py-0.5">ccs auth</code>
|
||||||
|
accounts. Edit each account for isolated, shared-standard, or shared-deeper
|
||||||
|
continuity behavior.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex-1 min-h-0 p-5 overflow-auto">
|
||||||
|
{cliproxyCount > 0 && (
|
||||||
|
<Alert variant="info" className="mb-4">
|
||||||
|
<Zap className="h-4 w-4" />
|
||||||
|
<AlertTitle>CLIProxy pool accounts are managed in their own page</AlertTitle>
|
||||||
|
<AlertDescription>
|
||||||
|
{cliproxyCount} OAuth account{cliproxyCount > 1 ? 's are' : ' is'} available in
|
||||||
|
CLIProxy. This table only covers local
|
||||||
|
<code className="mx-1 rounded bg-muted px-1 py-0.5">ccs auth</code>
|
||||||
|
profiles.
|
||||||
|
</AlertDescription>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Card className="h-full flex flex-col">
|
||||||
|
<CardHeader className="pb-3">
|
||||||
|
<CardTitle className="text-lg">Account Matrix</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
Shared total: {sharedCount}. Update sync behavior from the pencil action in each
|
||||||
|
row.
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="flex-1 min-h-0">
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="text-muted-foreground">Loading accounts...</div>
|
||||||
|
) : (
|
||||||
|
<AccountsTable data={authAccounts} defaultAccount={data?.default ?? null} />
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Right guidance column */}
|
||||||
|
<div className="w-80 shrink-0 flex flex-col bg-muted/20">
|
||||||
|
<div className="p-4 border-b bg-background">
|
||||||
|
<h3 className="font-semibold">Continuity Guide</h3>
|
||||||
|
<p className="mt-1 text-xs text-muted-foreground">
|
||||||
|
Choose the lightest mode that solves your workflow.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ScrollArea className="flex-1">
|
||||||
|
<div className="p-4 space-y-3">
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="pb-2">
|
||||||
|
<CardTitle className="text-sm">Shared Standard</CardTitle>
|
||||||
|
<CardDescription>Project workspace sync only.</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="text-xs text-muted-foreground">
|
||||||
|
Best default when users need continuity but want minimal coupling.
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="pb-2">
|
||||||
|
<CardTitle className="text-sm">Shared Deeper (Advanced)</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
Adds <code>session-env</code>, <code>file-history</code>,{' '}
|
||||||
|
<code>shell-snapshots</code>, <code>todos</code>.
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="text-xs text-muted-foreground">
|
||||||
|
Use only when cross-account continuity is worth stronger coupling.
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="pb-2">
|
||||||
|
<CardTitle className="text-sm">Quick Commands</CardTitle>
|
||||||
|
<CardDescription>Copy and run in terminal.</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-2">
|
||||||
|
<div className="rounded-md border bg-background px-2 py-2 font-mono text-[11px] flex items-start gap-2">
|
||||||
|
<span className="flex-1 break-all">
|
||||||
|
ccs auth create work --context-group sprint-a --deeper-continuity
|
||||||
|
</span>
|
||||||
|
<CopyButton
|
||||||
|
value="ccs auth create work --context-group sprint-a --deeper-continuity"
|
||||||
|
size="icon"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="rounded-md border bg-background px-2 py-2 font-mono text-[11px] flex items-start gap-2">
|
||||||
|
<span className="flex-1 break-all">ccs cliproxy auth claude</span>
|
||||||
|
<CopyButton value="ccs cliproxy auth claude" size="icon" />
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</ScrollArea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid gap-4 md:grid-cols-2">
|
{/* Mobile fallback */}
|
||||||
<Card className="border-emerald-200/70 bg-emerald-50/40 dark:border-emerald-900/40 dark:bg-emerald-900/10">
|
<div className="p-4 space-y-4 lg:hidden">
|
||||||
<CardHeader className="pb-2">
|
|
||||||
<CardDescription className="text-emerald-800/90 dark:text-emerald-300">
|
|
||||||
Lane A: ccs auth continuity
|
|
||||||
</CardDescription>
|
|
||||||
<CardTitle className="text-lg text-emerald-700 dark:text-emerald-300 flex items-center gap-2">
|
|
||||||
<Users className="w-5 h-5" />
|
|
||||||
Profile isolation + opt-in sync
|
|
||||||
</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent className="text-sm text-muted-foreground">
|
|
||||||
Use this when you want per-account control over isolated vs shared history behavior.
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Card className="border-blue-200/70 bg-blue-50/40 dark:border-blue-900/40 dark:bg-blue-900/10">
|
|
||||||
<CardHeader className="pb-2">
|
|
||||||
<CardDescription className="text-blue-800/90 dark:text-blue-300">
|
|
||||||
Lane B: CLIProxy Claude pool
|
|
||||||
</CardDescription>
|
|
||||||
<CardTitle className="text-lg text-blue-700 dark:text-blue-300 flex items-center gap-2">
|
|
||||||
<Zap className="w-5 h-5" />
|
|
||||||
OAuth pool and lower manual switching
|
|
||||||
</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent className="text-sm text-muted-foreground">
|
|
||||||
Use CLIProxy when you want pooled Claude OAuth accounts and easier account routing
|
|
||||||
behavior.
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid gap-4 md:grid-cols-4">
|
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader className="pb-2">
|
<CardHeader>
|
||||||
<CardDescription>Total Auth Accounts</CardDescription>
|
<CardTitle className="text-lg">Accounts</CardTitle>
|
||||||
<CardTitle className="text-2xl font-mono flex items-center gap-2">
|
<CardDescription>
|
||||||
<Users className="w-5 h-5 text-primary" />
|
Manage
|
||||||
{authAccounts.length}
|
<code className="mx-1 rounded bg-muted px-1 py-0.5">ccs auth</code>
|
||||||
</CardTitle>
|
continuity per account.
|
||||||
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-2">
|
||||||
|
<Button className="w-full" onClick={() => setCreateDialogOpen(true)}>
|
||||||
|
<Plus className="w-4 h-4 mr-2" />
|
||||||
|
Create Account
|
||||||
|
</Button>
|
||||||
|
<Button variant="outline" className="w-full" onClick={() => navigate('/cliproxy')}>
|
||||||
|
Open CLIProxy Claude Pool
|
||||||
|
<ArrowRight className="w-4 h-4 ml-2" />
|
||||||
|
</Button>
|
||||||
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card className="border-emerald-200/70 bg-emerald-50/40 dark:border-emerald-900/40 dark:bg-emerald-900/10">
|
<div className="grid grid-cols-2 gap-2">
|
||||||
<CardHeader className="pb-2">
|
<MetricTile label="Total" value={authAccounts.length} icon={Users} />
|
||||||
<CardDescription className="text-emerald-800/90 dark:text-emerald-300">
|
<MetricTile label="Shared" value={sharedCount} icon={Link2} tone="shared" />
|
||||||
Shared Standard
|
<MetricTile label="Deeper" value={deeperSharedCount} icon={Waves} tone="deeper" />
|
||||||
</CardDescription>
|
<MetricTile label="Isolated" value={isolatedCount} icon={Unlink} tone="isolated" />
|
||||||
<CardTitle className="text-2xl font-mono text-emerald-700 dark:text-emerald-300 flex items-center gap-2">
|
</div>
|
||||||
<Link2 className="w-5 h-5" />
|
|
||||||
{sharedStandardCount}
|
|
||||||
</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Card className="border-indigo-200/70 bg-indigo-50/40 dark:border-indigo-900/40 dark:bg-indigo-900/10">
|
<Card>
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-3">
|
||||||
<CardDescription className="text-indigo-800/90 dark:text-indigo-300">
|
<CardTitle className="text-base">Account Matrix</CardTitle>
|
||||||
Shared Deeper
|
|
||||||
</CardDescription>
|
|
||||||
<CardTitle className="text-2xl font-mono text-indigo-700 dark:text-indigo-300 flex items-center gap-2">
|
|
||||||
<Waves className="w-5 h-5" />
|
|
||||||
{deeperSharedCount}
|
|
||||||
</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Card className="border-blue-200/70 bg-blue-50/40 dark:border-blue-900/40 dark:bg-blue-900/10">
|
|
||||||
<CardHeader className="pb-2">
|
|
||||||
<CardDescription className="text-blue-800/90 dark:text-blue-300">
|
|
||||||
Isolated
|
|
||||||
</CardDescription>
|
|
||||||
<CardTitle className="text-2xl font-mono text-blue-700 dark:text-blue-300 flex items-center gap-2">
|
|
||||||
<Unlink className="w-5 h-5" />
|
|
||||||
{isolatedCount}
|
|
||||||
</CardTitle>
|
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="text-muted-foreground">Loading accounts...</div>
|
||||||
|
) : (
|
||||||
|
<AccountsTable data={authAccounts} defaultAccount={data?.default ?? null} />
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{cliproxyCount > 0 && (
|
|
||||||
<Alert variant="info">
|
|
||||||
<Zap className="h-4 w-4" />
|
|
||||||
<AlertTitle>CLIProxy accounts are intentionally excluded from this table</AlertTitle>
|
|
||||||
<AlertDescription>
|
|
||||||
{cliproxyCount} CLIProxy OAuth account{cliproxyCount > 1 ? 's are' : ' is'} available.
|
|
||||||
Manage them in <strong>CLIProxy Plus</strong> to enable account pool usage.
|
|
||||||
</AlertDescription>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{legacyContextCount > 0 && (
|
|
||||||
<Alert variant="warning">
|
|
||||||
<Users className="h-4 w-4" />
|
|
||||||
<AlertTitle>Legacy accounts need first-time sync mode review</AlertTitle>
|
|
||||||
<AlertDescription>
|
|
||||||
{legacyContextCount} account{legacyContextCount > 1 ? 's were' : ' was'} onboarded
|
|
||||||
before explicit context controls. Use the pencil action to confirm isolated or shared
|
|
||||||
behavior.
|
|
||||||
</AlertDescription>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{legacyContinuityCount > 0 && (
|
|
||||||
<Alert variant="warning">
|
|
||||||
<Waves className="h-4 w-4" />
|
|
||||||
<AlertTitle>Shared legacy accounts default to standard continuity</AlertTitle>
|
|
||||||
<AlertDescription>
|
|
||||||
{legacyContinuityCount} shared account
|
|
||||||
{legacyContinuityCount > 1 ? 's are' : ' is'} currently on legacy standard depth. Edit
|
|
||||||
and switch to deeper continuity only when you intentionally want broader history sync.
|
|
||||||
</AlertDescription>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Card>
|
|
||||||
<CardHeader className="pb-4">
|
|
||||||
<CardTitle className="text-lg">ccs auth Accounts</CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
Shared total: {sharedCount}. Create accounts here, then tune per-account sync mode and
|
|
||||||
continuity depth from the table.
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
{isLoading ? (
|
|
||||||
<div className="text-muted-foreground">Loading accounts...</div>
|
|
||||||
) : (
|
|
||||||
<AccountsTable data={authAccounts} defaultAccount={data?.default ?? null} />
|
|
||||||
)}
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<CreateAuthProfileDialog open={createDialogOpen} onClose={() => setCreateDialogOpen(false)} />
|
<CreateAuthProfileDialog open={createDialogOpen} onClose={() => setCreateDialogOpen(false)} />
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user