"use client"; import { useState } from "react"; import { useQuery } from "@tanstack/react-query"; import { ChevronDown, Key, Loader2 } from "lucide-react"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { EmptyState } from "@/components/ui/empty-state"; import { formatDate, formatDateTime } from "@/lib/format"; import { useTranslations } from "@/lib/i18n/context"; import { type ApiTokenInfo } from "./_shared"; export function ApiTokenOverviewSection() { const { t } = useTranslations(); // v1.5 phase-4b moved this to a dedicated route (`/admin/api-tokens`), // so the user has already opted into seeing tokens by visiting the // page. Default to expanded; the toggle stays as an escape hatch. const [expanded, setExpanded] = useState(true); const { data: tokens, isLoading } = useQuery({ queryKey: ["admin", "tokens"], queryFn: async () => { const res = await fetch("/api/admin/tokens"); if (!res.ok) throw new Error("Failed"); return (await res.json()).data as ApiTokenInfo[]; }, enabled: expanded, }); return (
| {t("admin.tokenUser")} | {t("admin.tokenName")} | {t("admin.tokenPermissions")} | {t("admin.tokenStatus")} | {t("admin.tokenLastUsed")} | {t("admin.tokenCreated")} |
|---|---|---|---|---|---|
| {token.user.username} | {token.name} |
{token.permissions.map((p) => (
|
{token.revoked ? (
|
{token.lastUsedAt ? formatDateTime(token.lastUsedAt) : t("admin.tokenNeverUsed")} | {formatDate(token.createdAt)} |
{token.user.username}
{t("admin.tokenLastUsed")}:{" "} {token.lastUsedAt ? formatDateTime(token.lastUsedAt) : t("admin.tokenNeverUsed")}
{t("admin.tokenCreated")}: {formatDate(token.createdAt)}