"use client"; import { useState } from "react"; import { useTranslations } from "next-intl"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Badge } from "@/components/ui/badge"; type ApiKey = { id: string; name: string; lastUsedAt: string | null; createdAt: string; }; type CreateApiKeyResponse = { id: string; name: string; key: string; createdAt: string; }; function formatDate(iso: string) { return new Date(iso).toLocaleDateString(undefined, { year: "numeric", month: "short", day: "numeric", }); } export function ApiKeysManager({ initialKeys }: { initialKeys: ApiKey[] }) { const t = useTranslations("settingsForm"); const [keys, setKeys] = useState(initialKeys); const [name, setName] = useState(""); const [creating, setCreating] = useState(false); const [newKey, setNewKey] = useState(null); const [copied, setCopied] = useState(false); async function handleCreate(e: React.FormEvent) { e.preventDefault(); if (!name.trim()) return; setCreating(true); try { const res = await fetch("/api/v1/api-keys", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: name.trim() }), }); if (!res.ok) { const data = await res.json() as { error?: string }; throw new Error(data.error ?? t("apiKeyCreateFailed")); } const data = await res.json() as CreateApiKeyResponse; setNewKey(data.key); setKeys((prev) => [ { id: data.id, name: data.name, lastUsedAt: null, createdAt: data.createdAt }, ...prev, ]); setName(""); } catch (err) { toast.error(err instanceof Error ? err.message : t("apiKeyCreateFailed")); } finally { setCreating(false); } } async function handleRevoke(id: string) { try { const res = await fetch(`/api/v1/api-keys/${id}`, { method: "DELETE" }); if (!res.ok) { const data = await res.json() as { error?: string }; throw new Error(data.error ?? t("apiKeyRevokeFailed")); } setKeys((prev) => prev.filter((k) => k.id !== id)); } catch (err) { toast.error(err instanceof Error ? err.message : t("apiKeyRevokeFailed")); } } async function handleCopy() { if (!newKey) return; try { await navigator.clipboard.writeText(newKey); setCopied(true); setTimeout(() => setCopied(false), 2000); } catch { toast.error(t("copyFailed")); } } return (
{/* Create form */}
setName(e.target.value)} maxLength={100} required />
{/* New key reveal */} {newKey && (

{t("apiKeyRevealNotice")}

{newKey}
)} {/* Keys list */} {keys.length === 0 ? (

{t("noApiKeys")}

) : (
{keys.map((k) => (

{k.name}

{t("createdOn", { date: formatDate(k.createdAt) })} ยท {k.lastUsedAt ? ( {t("lastUsedOn", { date: formatDate(k.lastUsedAt) })} ) : ( {t("neverUsed")} )}
))}
)}
); }