"use client"; import { useState, Fragment } from "react"; import { useRouter } from "next/navigation"; import { useTranslations } from "next-intl"; import { Card } from "@/components/ui/card"; import type { SkillActivationRequest } from "@/types"; interface RowData extends SkillActivationRequest { skillName: string; companyName: string | null; } interface Props { initialRows: RowData[]; } /** * Admin queue table. Each row has Approve and Reject buttons. * Reject opens an inline reason input that must be filled before * the call goes through (the API also enforces this — empty * reasons are 400'd server-side). * * Actions hit the admin API endpoints, then router.refresh() to * re-render the server component with the new state (the row * disappears once flipped to approved/rejected). */ export function PendingSkillRequests({ initialRows }: Props) { const t = useTranslations("adminSkills"); const router = useRouter(); const [busyId, setBusyId] = useState(null); const [error, setError] = useState(""); // Per-row open-reject-input state. Key = request id. const [rejectingId, setRejectingId] = useState(null); const [reasonText, setReasonText] = useState(""); const approve = async (id: string) => { setError(""); setBusyId(id); try { const res = await fetch(`/api/admin/skills/pending/${id}/approve`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({}), }); if (!res.ok) { const j = await res.json().catch(() => ({})); throw new Error(j.error || `HTTP ${res.status}`); } router.refresh(); } catch (e: any) { setError(e.message); } finally { setBusyId(null); } }; const reject = async (id: string) => { if (!reasonText.trim()) { setError(t("reasonRequired")); return; } setError(""); setBusyId(id); try { const res = await fetch(`/api/admin/skills/pending/${id}/reject`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ reason: reasonText }), }); if (!res.ok) { const j = await res.json().catch(() => ({})); throw new Error(j.error || `HTTP ${res.status}`); } setRejectingId(null); setReasonText(""); router.refresh(); } catch (e: any) { setError(e.message); } finally { setBusyId(null); } }; if (initialRows.length === 0) { return (

{t("emptyQueue")}

); } return ( {error && (
{error}
)} {initialRows.map((row) => ( {rejectingId === row.id && (
{t("requestedAtCol")} {t("skillCol")} {t("tenantCol")} {t("orgCol")} {t("actionsCol")}
{row.requestedAt.slice(0, 16).replace("T", " ")}
{row.skillName}
{row.skillId}
{row.tenantName}
{row.companyName ?? "—"}
{row.zitadelOrgId.slice(0, 16)}…
{rejectingId !== row.id && (
)}