import React, { useState } from "react"; import { Box, Button, Chip, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography, } from "@mui/material"; import { api } from "../api"; import { useToast } from "../toast"; import { useI18n } from "../i18n/I18nProvider"; import { useViewResource } from "../hooks/useViewResource"; import ViewStateNotice from "../components/ViewStateNotice"; type AuditItem = { id: number; type: string; oldValue?: string | null; newValue?: string | null; note?: string | null; at: string; jobApplicationId: number; jobTitle?: string | null; companyName?: string | null; ownerUserId?: string | null; ownerEmail?: string | null; ownerUserName?: string | null; }; function canUndo(type: string) { return ["StatusChanged", "FollowUpSet", "ResponseUpdated", "Deleted", "Restored"].includes(type); } export default function AdminAuditPage() { const { toast } = useToast(); const { language, t } = useI18n(); const [busyId, setBusyId] = useState(null); const auditResource = useViewResource( async () => { const r = await api.get("/admin/audit?take=200"); return r.data ?? []; }, { initialData: [], errorMessage: t("adminAuditLoadFailed"), deps: [t] }, ); const undo = async (e: AuditItem) => { if (!canUndo(e.type)) return; setBusyId(e.id); try { const res = await api.post<{ ok: boolean; message: string }>(`/admin/audit/${e.id}/undo`, {}); toast(res.data?.message || t("adminAuditUndone"), "success"); await auditResource.reload(); } catch (err: any) { const msg = err?.response?.data?.message || err?.response?.data || err?.message || t("adminAuditUndoFailed"); toast(String(msg), "error"); } finally { setBusyId(null); } }; const restore = async (e: AuditItem) => { setBusyId(e.id); try { await api.post(`/jobapplications/${e.jobApplicationId}/restore`, {}); toast(t("adminAuditRestored"), "success"); await auditResource.reload(); } catch (err: any) { const msg = err?.response?.data || err?.message || t("adminAuditRestoreFailed"); toast(String(msg), "error"); } finally { setBusyId(null); } }; const rows = auditResource.data; return ( {t("adminAuditTitle")} {t("adminAuditSubtitle")} {!auditResource.error ? {t("adminAuditAt")} {t("adminAuditType")} {t("adminAuditJob")} {t("adminAuditUser")} {t("adminAuditDetails")} {t("adminAuditActions")} {auditResource.loading ? ( {t("loading")} ) : rows.length === 0 ? ( {t("adminAuditNoEvents")} ) : ( rows.map((e) => { const jobLabel = e.jobTitle || t("adminAuditJobFallback", { id: e.jobApplicationId }); const ownerLabel = e.ownerEmail || e.ownerUserName || e.ownerUserId || "-"; const details = e.oldValue || e.newValue ? `${e.oldValue ?? ""} -> ${e.newValue ?? ""}` : ""; const disabled = busyId === e.id; const showRestore = e.type === "Deleted"; return ( {e.at ? new Date(e.at).toLocaleString(language === "nb" ? "nb-NO" : "en-GB") : ""} {e.companyName ? `${e.companyName} - ` : ""} {jobLabel} jobId={e.jobApplicationId} {ownerLabel} {details} {e.note ? `${details ? "\n" : ""}${e.note}` : ""} {canUndo(e.type) ? ( ) : null} {showRestore ? ( ) : null} ); }) )}
: null}
); }