mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 04:18:05 +00:00
fix(accounts-ui): move action center content into left column
This commit is contained in:
+162
-228
@@ -5,15 +5,7 @@
|
||||
|
||||
import { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import {
|
||||
AlertTriangle,
|
||||
ArrowRight,
|
||||
ChevronDown,
|
||||
ChevronLeft,
|
||||
Plus,
|
||||
Users,
|
||||
Zap,
|
||||
} from 'lucide-react';
|
||||
import { AlertTriangle, ArrowRight, ChevronDown, Plus, Users, Zap } from 'lucide-react';
|
||||
import { AccountsTable } from '@/components/account/accounts-table';
|
||||
import { CreateAuthProfileDialog } from '@/components/account/create-auth-profile-dialog';
|
||||
import { HistorySyncLearningMap } from '@/components/account/history-sync-learning-map';
|
||||
@@ -31,7 +23,6 @@ export function AccountsPage() {
|
||||
const { data, isLoading } = useAccounts();
|
||||
const confirmLegacyMutation = useConfirmLegacyAccountPolicies();
|
||||
const [createDialogOpen, setCreateDialogOpen] = useState(false);
|
||||
const [showGuideRail, setShowGuideRail] = useState(true);
|
||||
const [guideOpen, setGuideOpen] = useState(false);
|
||||
|
||||
const authAccounts = data?.accounts || [];
|
||||
@@ -63,34 +54,69 @@ export function AccountsPage() {
|
||||
return (
|
||||
<>
|
||||
<div className="h-[calc(100vh-100px)] hidden lg:flex">
|
||||
{/* Left rail */}
|
||||
<div className="w-80 border-r flex flex-col bg-muted/30 shrink-0">
|
||||
<div className="p-4 border-b bg-background space-y-3">
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Users className="h-5 w-5 text-primary" />
|
||||
<h1 className="font-semibold">Accounts</h1>
|
||||
</div>
|
||||
<p className="mt-1 text-xs text-muted-foreground">
|
||||
Dedicated
|
||||
<code className="mx-1 rounded bg-muted px-1 py-0.5">ccs auth</code>
|
||||
continuity controls.
|
||||
</p>
|
||||
{/* Left action column */}
|
||||
<div className="w-80 border-r flex flex-col bg-muted/20 shrink-0">
|
||||
<div className="p-4 border-b bg-background space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<Users className="h-5 w-5 text-primary" />
|
||||
<h1 className="font-semibold">Accounts</h1>
|
||||
<Badge variant="outline" className="ml-auto">
|
||||
Action Center
|
||||
</Badge>
|
||||
</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>
|
||||
</div>
|
||||
<p className="text-[11px] text-muted-foreground">
|
||||
Pool auth actions live in Action Center to avoid duplicate controls.
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Manage
|
||||
<code className="mx-1 rounded bg-muted px-1 py-0.5">ccs auth</code>
|
||||
accounts and pool onboarding from one panel.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<ScrollArea className="flex-1">
|
||||
<div className="p-3 space-y-3">
|
||||
<div className="p-4 space-y-3">
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-sm">Immediate Actions</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2">
|
||||
<Button
|
||||
size="sm"
|
||||
className="w-full justify-start"
|
||||
onClick={() => setCreateDialogOpen(true)}
|
||||
>
|
||||
<Plus className="w-4 h-4 mr-2" />
|
||||
Create Account
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
className="w-full justify-start"
|
||||
onClick={handleOpenClaudePoolAuth}
|
||||
>
|
||||
<Zap className="w-4 h-4 mr-2" />
|
||||
Authenticate Claude in Pool
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="w-full justify-start"
|
||||
onClick={handleOpenClaudePool}
|
||||
>
|
||||
Open Claude Pool Settings
|
||||
<ArrowRight className="w-4 h-4 ml-auto" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="w-full justify-start"
|
||||
onClick={handleConfirmLegacy}
|
||||
disabled={confirmLegacyMutation.isPending || legacyTargetCount === 0}
|
||||
>
|
||||
{confirmLegacyMutation.isPending
|
||||
? 'Confirming Legacy Policies...'
|
||||
: `Confirm Legacy Policies (${legacyTargetCount})`}
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{hasLegacyFollowUp && (
|
||||
<section className="space-y-2">
|
||||
<p className="text-[11px] font-medium uppercase tracking-wide text-muted-foreground">
|
||||
@@ -116,218 +142,126 @@ export function AccountsPage() {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
className="w-full justify-start"
|
||||
onClick={handleConfirmLegacy}
|
||||
disabled={confirmLegacyMutation.isPending || legacyTargetCount === 0}
|
||||
>
|
||||
{confirmLegacyMutation.isPending
|
||||
? 'Confirming Legacy Accounts...'
|
||||
: `Confirm Current Policy for ${legacyTargetCount} Legacy Account${legacyTargetCount > 1 ? 's' : ''}`}
|
||||
</Button>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{!hasLegacyFollowUp && (
|
||||
<div className="rounded-md border bg-background px-3 py-2 text-xs text-muted-foreground">
|
||||
No legacy follow-up pending. Manage pool auth from Action Center.
|
||||
No legacy follow-up pending.
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Collapsible open={guideOpen} onOpenChange={setGuideOpen}>
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CollapsibleTrigger asChild>
|
||||
<Button variant="ghost" className="h-auto w-full justify-between px-0 py-0">
|
||||
<div className="text-left">
|
||||
<CardTitle className="text-sm">Continuity Guide</CardTitle>
|
||||
<CardDescription className="mt-1">
|
||||
Expand only when needed.
|
||||
</CardDescription>
|
||||
</div>
|
||||
<ChevronDown
|
||||
className={cn('h-4 w-4 transition-transform', guideOpen && 'rotate-180')}
|
||||
/>
|
||||
</Button>
|
||||
</CollapsibleTrigger>
|
||||
</CardHeader>
|
||||
<CollapsibleContent>
|
||||
<CardContent className="space-y-3 text-xs text-muted-foreground">
|
||||
<div className="rounded-md border p-2.5">
|
||||
<p className="font-semibold text-foreground">Shared Standard</p>
|
||||
<p className="mt-1">
|
||||
Project workspace sync only. Best default for most teams.
|
||||
</p>
|
||||
</div>
|
||||
<div className="rounded-md border p-2.5">
|
||||
<p className="font-semibold text-foreground">Shared Deeper</p>
|
||||
<p className="mt-1">
|
||||
Adds <code>session-env</code>, <code>file-history</code>,{' '}
|
||||
<code>shell-snapshots</code>, <code>todos</code>.
|
||||
</p>
|
||||
</div>
|
||||
<div className="rounded-md border p-2.5">
|
||||
<p className="font-semibold text-foreground">Isolated</p>
|
||||
<p className="mt-1">No link. Best for strict separation.</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</CollapsibleContent>
|
||||
</Card>
|
||||
</Collapsible>
|
||||
|
||||
<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>
|
||||
|
||||
{/* 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>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="ml-auto"
|
||||
onClick={() => setShowGuideRail((prev) => !prev)}
|
||||
>
|
||||
{showGuideRail ? 'Hide Action Center' : 'Show Action Center'}
|
||||
</Button>
|
||||
</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. Use
|
||||
<code className="mx-1 rounded bg-muted px-1 py-0.5">Sync</code>
|
||||
for mode/group/depth changes.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 min-h-0 p-5 space-y-4 overflow-y-auto">
|
||||
<HistorySyncLearningMap
|
||||
isolatedCount={isolatedCount}
|
||||
sharedStandardCount={sharedStandardCount}
|
||||
deeperSharedCount={deeperSharedCount}
|
||||
sharedGroups={sharedGroups}
|
||||
legacyTargetCount={legacyTargetCount}
|
||||
cliproxyCount={cliproxyCount}
|
||||
/>
|
||||
|
||||
<Card className="flex flex-col">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-lg">Account Matrix</CardTitle>
|
||||
<CardDescription>
|
||||
Shared total: {sharedCount}. Actions include Sync settings and legacy
|
||||
confirmation.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{isLoading ? (
|
||||
<div className="text-muted-foreground">Loading accounts...</div>
|
||||
) : (
|
||||
<AccountsTable data={authAccounts} defaultAccount={data?.default ?? null} />
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
<div className="flex-1 min-w-0 flex flex-col 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. Use
|
||||
<code className="mx-1 rounded bg-muted px-1 py-0.5">Sync</code>
|
||||
for mode/group/depth changes.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Right action center */}
|
||||
{showGuideRail ? (
|
||||
<div className="w-80 shrink-0 flex flex-col bg-muted/20">
|
||||
<div className="p-4 border-b bg-background flex items-start justify-between gap-3">
|
||||
<div>
|
||||
<h3 className="font-semibold">Action Center</h3>
|
||||
<p className="mt-1 text-xs text-muted-foreground">
|
||||
High-value actions for pool auth and legacy cleanup.
|
||||
</p>
|
||||
</div>
|
||||
<Button variant="ghost" size="icon" onClick={() => setShowGuideRail(false)}>
|
||||
<ChevronLeft className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex-1 min-h-0 p-5 space-y-4 overflow-y-auto">
|
||||
<HistorySyncLearningMap
|
||||
isolatedCount={isolatedCount}
|
||||
sharedStandardCount={sharedStandardCount}
|
||||
deeperSharedCount={deeperSharedCount}
|
||||
sharedGroups={sharedGroups}
|
||||
legacyTargetCount={legacyTargetCount}
|
||||
cliproxyCount={cliproxyCount}
|
||||
/>
|
||||
|
||||
<ScrollArea className="flex-1">
|
||||
<div className="p-4 space-y-3">
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-sm">Immediate Actions</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2">
|
||||
<Button
|
||||
size="sm"
|
||||
className="w-full justify-start"
|
||||
onClick={handleOpenClaudePoolAuth}
|
||||
>
|
||||
<Zap className="w-4 h-4 mr-2" />
|
||||
Authenticate Claude in Pool
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="w-full justify-start"
|
||||
onClick={handleOpenClaudePool}
|
||||
>
|
||||
Open Claude Pool Settings
|
||||
<ArrowRight className="w-4 h-4 ml-auto" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="w-full justify-start"
|
||||
onClick={handleConfirmLegacy}
|
||||
disabled={confirmLegacyMutation.isPending || legacyTargetCount === 0}
|
||||
>
|
||||
{confirmLegacyMutation.isPending
|
||||
? 'Confirming Legacy Policies...'
|
||||
: `Confirm Legacy Policies (${legacyTargetCount})`}
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Collapsible open={guideOpen} onOpenChange={setGuideOpen}>
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CollapsibleTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="h-auto w-full justify-between px-0 py-0"
|
||||
>
|
||||
<div className="text-left">
|
||||
<CardTitle className="text-sm">Continuity Guide</CardTitle>
|
||||
<CardDescription className="mt-1">
|
||||
Expand only when needed.
|
||||
</CardDescription>
|
||||
</div>
|
||||
<ChevronDown
|
||||
className={cn(
|
||||
'h-4 w-4 transition-transform',
|
||||
guideOpen && 'rotate-180'
|
||||
)}
|
||||
/>
|
||||
</Button>
|
||||
</CollapsibleTrigger>
|
||||
</CardHeader>
|
||||
<CollapsibleContent>
|
||||
<CardContent className="space-y-3 text-xs text-muted-foreground">
|
||||
<div className="rounded-md border p-2.5">
|
||||
<p className="font-semibold text-foreground">Shared Standard</p>
|
||||
<p className="mt-1">
|
||||
Project workspace sync only. Best default for most teams.
|
||||
</p>
|
||||
</div>
|
||||
<div className="rounded-md border p-2.5">
|
||||
<p className="font-semibold text-foreground">Shared Deeper</p>
|
||||
<p className="mt-1">
|
||||
Adds <code>session-env</code>, <code>file-history</code>,{' '}
|
||||
<code>shell-snapshots</code>, <code>todos</code>.
|
||||
</p>
|
||||
</div>
|
||||
<div className="rounded-md border p-2.5">
|
||||
<p className="font-semibold text-foreground">Isolated</p>
|
||||
<p className="mt-1">No link. Best for strict separation.</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</CollapsibleContent>
|
||||
</Card>
|
||||
</Collapsible>
|
||||
|
||||
<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 className="w-14 shrink-0 border-l bg-muted/20 flex items-start justify-center pt-3">
|
||||
<Button variant="ghost" size="icon" onClick={() => setShowGuideRail(true)}>
|
||||
<ChevronLeft className="h-4 w-4 rotate-180" />
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
<Card className="flex flex-col">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-lg">Account Matrix</CardTitle>
|
||||
<CardDescription>
|
||||
Shared total: {sharedCount}. Actions include Sync settings and legacy
|
||||
confirmation.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{isLoading ? (
|
||||
<div className="text-muted-foreground">Loading accounts...</div>
|
||||
) : (
|
||||
<AccountsTable data={authAccounts} defaultAccount={data?.default ?? null} />
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user