diff --git a/ui/src/components/add-account-dialog.tsx b/ui/src/components/add-account-dialog.tsx new file mode 100644 index 00000000..0fac8fdc --- /dev/null +++ b/ui/src/components/add-account-dialog.tsx @@ -0,0 +1,96 @@ +/** + * Add Account Dialog Component + * Simple dialog to add another OAuth account to a provider + * + * Shows auth command + refresh button (no variant creation) + */ + +import { useState } from 'react'; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogDescription, +} from '@/components/ui/dialog'; +import { Button } from '@/components/ui/button'; +import { Card, CardContent } from '@/components/ui/card'; +import { Copy, Check, RefreshCw, Terminal } from 'lucide-react'; +import { useCliproxyAuth } from '@/hooks/use-cliproxy'; + +interface AddAccountDialogProps { + open: boolean; + onClose: () => void; + provider: string; + displayName: string; +} + +export function AddAccountDialog({ open, onClose, provider, displayName }: AddAccountDialogProps) { + const [copied, setCopied] = useState(false); + const [isRefreshing, setIsRefreshing] = useState(false); + const { refetch } = useCliproxyAuth(); + + const authCommand = `ccs ${provider} --auth --add`; + + const copyCommand = async () => { + await navigator.clipboard.writeText(authCommand); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + }; + + const handleRefresh = async () => { + setIsRefreshing(true); + await refetch(); + setIsRefreshing(false); + onClose(); + }; + + return ( + + + + Add {displayName} Account + + Run the command below in your terminal to authenticate a new account + + + +
+ + +
+ + Run this command: +
+
+ + {authCommand} + + +
+
+ This will open your browser to authenticate with {displayName} +
+
+
+ +
+ + +
+
+
+
+ ); +} diff --git a/ui/src/pages/cliproxy.tsx b/ui/src/pages/cliproxy.tsx index 808d82cf..7fc098de 100644 --- a/ui/src/pages/cliproxy.tsx +++ b/ui/src/pages/cliproxy.tsx @@ -16,8 +16,8 @@ import { } from '@/components/ui/dropdown-menu'; import { Plus, Check, X, User, ChevronDown, Star, Trash2, Sparkles } from 'lucide-react'; import { CliproxyTable } from '@/components/cliproxy-table'; -import { CliproxyDialog } from '@/components/cliproxy-dialog'; import { QuickSetupWizard } from '@/components/quick-setup-wizard'; +import { AddAccountDialog } from '@/components/add-account-dialog'; import { useCliproxy, useCliproxyAuth, @@ -85,10 +85,12 @@ function ProviderRow({ status, setDefaultMutation, removeMutation, + onAddAccount, }: { status: AuthStatus; setDefaultMutation: ReturnType; removeMutation: ReturnType; + onAddAccount: () => void; }) { const accounts = status.accounts || []; @@ -148,35 +150,22 @@ function ProviderRow({
- {!status.authenticated && ( -
- ccs {status.provider} --auth -
- )} - {status.authenticated && ( - - )} + {/* Show Add Account button for all - opens dialog with instructions */} +
); } export function CliproxyPage() { - const [dialogOpen, setDialogOpen] = useState(false); const [wizardOpen, setWizardOpen] = useState(false); + const [addAccountProvider, setAddAccountProvider] = useState<{ + provider: string; + displayName: string; + } | null>(null); const { data, isLoading } = useCliproxy(); const { data: authData, isLoading: authLoading } = useCliproxyAuth(); const setDefaultMutation = useSetDefaultAccount(); @@ -191,16 +180,10 @@ export function CliproxyPage() { Manage OAuth-based provider variants and multi-account configurations

-
- - -
+ {/* Built-in Profiles with Account Management */} @@ -226,6 +209,12 @@ export function CliproxyPage() { status={status} setDefaultMutation={setDefaultMutation} removeMutation={removeMutation} + onAddAccount={() => + setAddAccountProvider({ + provider: status.provider, + displayName: status.displayName, + }) + } /> ))} @@ -252,8 +241,13 @@ export function CliproxyPage() { )} - setDialogOpen(false)} /> setWizardOpen(false)} /> + setAddAccountProvider(null)} + provider={addAccountProvider?.provider || ''} + displayName={addAccountProvider?.displayName || ''} + /> ); }