"use client"; import * as React from "react"; import { ExternalLink, KeyRound, MoreHorizontal, Trash2, CheckCircle2, XCircle, CircleDashed, CircleOff, Activity, RefreshCw, Zap } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Tooltip } from "@/components/ui/tooltip"; import { ActionSheet } from "@/components/ui/sheet"; import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator } from "@/components/ui/dropdown-menu"; import { ProviderIcon } from "@/components/brand/provider-icon"; import { PROVIDERS } from "@/lib/client/providers"; import { useIsMobile } from "@/lib/client/hooks"; import { formatRelative, formatMs, formatNumber, cn } from "@/lib/utils"; import type { ProviderId, PublicConnection } from "@/lib/client/types"; export type ConnectionStatus = "connected" | "failed" | "unverified" | "missing"; export function statusOf(c: PublicConnection | undefined): ConnectionStatus { if (!c) return "missing"; if (c.status === "valid") return "connected"; if (c.status === "invalid" || c.status === "error") return "failed"; return "unverified"; } export const STATUS_UI: Record = { connected: { label: "Connected", variant: "success", icon: }, failed: { label: "Validation failed", variant: "danger", icon: }, unverified: { label: "Not validated yet", variant: "warning", icon: }, missing: { label: "Not connected", variant: "default", icon: }, }; export interface TestResult { ok: boolean; latencyMs: number; modelsAvailable: number | null; error?: string; at: number; } export function ProviderRow({ provider, connection, modelCount, testing, lastTest, onAddKey, onTest, onRemove }: { provider: ProviderId; connection?: PublicConnection; modelCount: number | null; testing: boolean; lastTest?: TestResult; onAddKey: () => void; onTest: () => void; onRemove: () => void }) { const meta = PROVIDERS[provider]; const status = statusOf(connection); const ui = STATUS_UI[status]; const isMobile = useIsMobile(); const [more, setMore] = React.useState(false); const models = connection?.modelsAvailable ?? modelCount; const lastError = connection?.lastValidationError || connection?.lastErrorCode || null; const moreItems = [ { key: "replace", label: "Replace key", icon: , onSelect: onAddKey }, { key: "test", label: "Test connection", icon: , onSelect: onTest, disabled: testing }, { key: "console", label: `Open ${meta.shortName} console`, icon: , onSelect: () => window.open(meta.consoleUrl, "_blank", "noopener,noreferrer") }, "separator" as const, { key: "remove", label: "Remove key", icon: , onSelect: onRemove, destructive: true }, ]; return (
  • {meta.name}

    {ui.icon} {ui.label}

    {meta.description}

    {connection ? (
    Key
    {connection.keyHint}
    Last validated
    {formatRelative(connection.lastValidatedAt)}
    Models available
    {models === null ? "—" : formatNumber(models)}
    {lastTest ? "Latency" : "Last success"}
    {lastTest ? ( {formatMs(lastTest.latencyMs)} ) : ( formatRelative(connection.lastSuccessAt) )}
    {lastError || (lastTest && !lastTest.ok) ? (
    Last error
    {connection.lastErrorCode ? {connection.lastErrorCode} : null} {lastTest && !lastTest.ok ? lastTest.error : connection.lastValidationError} {connection.lastErrorAt ? · {formatRelative(connection.lastErrorAt)} : null}
    ) : null}
    ) : (

    {meta.keyHelp}{" "} Open console

    )}
    {/* Desktop actions */}
    {connection ? ( <> Replace key window.open(meta.consoleUrl, "_blank", "noopener,noreferrer")}> Open {meta.shortName} console Remove key ) : ( )}
    {/* Phone actions: 44 px targets in one row */}
    {connection ? ( <> ) : ( )}
    {isMobile ? : null}
  • ); }