"use client"; import React, { useState } from "react"; import useSWR, { mutate } from "swr"; import axios from "@/lib/axios"; import ComponentCard from "../common/ComponentCard"; import Button from "../ui/button/Button"; import Badge from "../ui/badge/Badge"; import { Trash2, Copy, Check, Plus, Lock, RefreshCw } from "lucide-react"; import { useToast } from "@/context/ToastContext"; import ConfirmationModal from "../common/ConfirmationModal"; import { useTranslations } from "next-intl"; interface ApiKey { id: string; name: string; is_active: boolean; created_at: string; last_used_at: string | null; } const fetcher = (url: string) => axios.get(url).then((res) => res.data); export default function ApiKeyManagement() { const t = useTranslations("ApiKeys"); const { data, error, isLoading } = useSWR("/api/api-keys", fetcher); const [isCreating, setIsCreating] = useState(false); const [newKeyName, setNewKeyName] = useState(""); const [generatedKey, setGeneratedKey] = useState(null); const [isRevoking, setIsRevoking] = useState(null); const [isToggling, setIsToggling] = useState(null); const [isRegenerating, setIsRegenerating] = useState(null); const [copied, setCopied] = useState(false); const { addToast } = useToast(); // Confirmation states const [confirmRevokeId, setConfirmRevokeId] = useState(null); const [confirmRegenerateId, setConfirmRegenerateId] = useState(null); const handleCreate = async (e: React.FormEvent) => { e.preventDefault(); if (!newKeyName.trim()) return; setIsCreating(true); try { const response = await axios.post("/api/api-keys", { name: newKeyName }); setGeneratedKey(response.data.token); setNewKeyName(""); mutate("/api/api-keys"); addToast(t("toast_gen_success"), "success"); } catch (err) { addToast(t("toast_gen_failed"), "error"); } finally { setIsCreating(false); } }; const handleRevoke = async (id: string) => { setIsRevoking(id); try { await axios.delete(`/api/api-keys/${id}`); mutate("/api/api-keys"); addToast(t("toast_revoke_success"), "success"); setConfirmRevokeId(null); } catch (err) { addToast(t("toast_revoke_failed"), "error"); } finally { setIsRevoking(null); } }; const handleToggle = async (id: string) => { setIsToggling(id); try { await axios.patch(`/api/api-keys/${id}/toggle`); mutate("/api/api-keys"); addToast(t("toast_status_updated"), "success"); } catch (err) { addToast(t("toast_status_failed"), "error"); } finally { setIsToggling(null); } }; const handleRegenerate = async (id: string) => { setIsRegenerating(id); try { const response = await axios.post(`/api/api-keys/${id}/regenerate`); setGeneratedKey(response.data.token); mutate("/api/api-keys"); addToast(t("toast_regen_success"), "success"); setConfirmRegenerateId(null); } catch (err) { addToast(t("toast_regen_failed"), "error"); } finally { setIsRegenerating(null); } }; const copyToClipboard = () => { if (generatedKey) { navigator.clipboard.writeText(generatedKey); setCopied(true); setTimeout(() => setCopied(false), 2000); } }; const keys = data?.data || []; return (
{!generatedKey ? (
setNewKeyName(e.target.value)} className="w-full px-4 py-2 rounded-lg border border-gray-200 dark:border-gray-800 bg-transparent dark:bg-white/[0.03] text-gray-800 dark:text-white/90 focus:ring-brand-500 focus:border-brand-500" required />
) : (
{t("your_key")} {t("copy_warning")}
{generatedKey}
)}
{isLoading ? ( ) : keys.length === 0 ? ( ) : ( keys.map((key: ApiKey) => ( )) )}
{t("th_name")} {t("th_status")} {t("th_created")} {t("th_last_used")} {t("th_actions")}
{t("loading_keys")}
{t("no_keys")}
{key.name}
{new Date(key.created_at).toLocaleDateString()} {key.last_used_at ? new Date(key.last_used_at).toLocaleString() : t("never_used")}
setConfirmRevokeId(null)} onConfirm={() => confirmRevokeId && handleRevoke(confirmRevokeId)} title={t("revoke_title")} message={t("revoke_msg")} isLoading={isRevoking !== null} confirmLabel={t("revoke_confirm")} requiredInput="REVOKE" /> setConfirmRegenerateId(null)} onConfirm={() => confirmRegenerateId && handleRegenerate(confirmRegenerateId)} title={t("regen_title")} message={t("regen_msg")} isLoading={isRegenerating !== null} confirmLabel={t("regen_confirm")} variant="warning" />
); }