haixunMaster/components/settings/api-keys-form.tsx

77 lines
2.6 KiB
TypeScript
Raw Normal View History

2026-06-21 12:50:31 +00:00
"use client";
import { ExternalLink, KeyRound } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { PROVIDER_KEY_LABELS, type ProviderId } from "@/lib/ai/keys";
const PROVIDER_ORDER: ProviderId[] = [
"opencode-go",
"xai",
"openai",
"anthropic",
"google",
];
interface ApiKeysFormProps {
values: Partial<Record<ProviderId, string>>;
configured: Partial<Record<ProviderId, boolean>>;
onChange: (provider: ProviderId, value: string) => void;
}
export function ApiKeysForm({ values, configured, onChange }: ApiKeysFormProps) {
return (
<div className="space-y-4">
{PROVIDER_ORDER.map((provider) => {
const meta = PROVIDER_KEY_LABELS[provider];
const isConfigured = configured[provider];
return (
<div
key={provider}
className="rounded-lg border border-border bg-muted p-4"
>
<div className="mb-3 flex items-center justify-between gap-3">
<div className="flex items-center gap-2">
<KeyRound className="h-4 w-4 text-muted-foreground" />
<Label className="normal-case text-sm font-semibold text-foreground">
{meta.label}
</Label>
</div>
<Badge variant={isConfigured ? "success" : "secondary"}>
{isConfigured ? "已設定" : "未設定"}
</Badge>
</div>
<p className="mb-3 text-xs leading-relaxed text-muted-foreground">{meta.hint}</p>
<Input
type="password"
value={values[provider] ?? ""}
onChange={(e) => onChange(provider, e.target.value)}
placeholder={isConfigured ? "留空則保留現有 key" : "貼上 API key"}
autoComplete="off"
/>
{meta.docsUrl && (
<a
href={meta.docsUrl}
target="_blank"
rel="noopener noreferrer"
className="mt-2 inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground hover:underline"
>
<ExternalLink className="h-3 w-3" />
{meta.label} API key
</a>
)}
</div>
);
})}
<p className="text-xs leading-relaxed text-muted-foreground">
AI Key Threads `.env`
</p>
</div>
);
}