"use client"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { CheckCircle2, RefreshCcw, ShieldAlert } from "lucide-react"; import { NoPermissionState } from "@/components/auth/no-permission-state"; import { useSuperAdminSession } from "@/components/auth/session-context"; import { PageHeader } from "@/components/dashboard/page-header"; import { PaginationControls } from "@/components/dashboard/pagination-controls"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { EmptyState } from "@/components/ui/empty-state"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { Textarea } from "@/components/ui/textarea"; import { useToast } from "@/components/ui/toast"; import { getItems, getPagination } from "@/lib/api/core"; import { listPlatformReports, updatePlatformReportStatus } from "@/lib/api/reports"; import { formatDateTime } from "@/lib/format"; import { SUPERADMIN_PERMISSIONS, hasPermission } from "@/lib/permissions"; import type { ApiUser, PlatformReport, ReportsResponse, ReportStatus, ReportTargetType } from "@/types/api"; const reportStatuses: Array<{ value: ReportStatus; label: string }> = [ { value: "open", label: "Open" }, { value: "in_review", label: "In review" }, { value: "resolved", label: "Resolved" }, { value: "rejected", label: "Rejected" }, ]; const targetTypes: Array<{ value: ReportTargetType; label: string }> = [ { value: "user", label: "User" }, { value: "post", label: "Post" }, { value: "comment", label: "Comment" }, { value: "listing", label: "Listing" }, { value: "repair_shop", label: "Repair shop" }, ]; const reasonLabels: Record = { spam: "Spam", harassment: "Harassment", hate_speech: "Hate speech", nudity: "Nudity", violence: "Violence", scam: "Scam", intellectual_property: "Intellectual property", self_harm: "Self harm", other: "Other", }; function reporterLabel(reporter: PlatformReport["reporterId"]) { if (!reporter || typeof reporter === "string") { return reporter || "-"; } const user = reporter as ApiUser; return user.stageName || user.name || user.username || user.email || user._id || "-"; } function statusVariant(status: ReportStatus): "success" | "muted" | "warning" | "danger" { if (status === "resolved") return "success"; if (status === "rejected") return "muted"; if (status === "in_review") return "warning"; return "danger"; } export default function ReportsPage() { const { permissions } = useSuperAdminSession(); const [statusFilter, setStatusFilter] = useState("open"); const [targetFilter, setTargetFilter] = useState("all"); const [page, setPage] = useState(1); const [response, setResponse] = useState(null); const [selectedReport, setSelectedReport] = useState(null); const [resolutionNote, setResolutionNote] = useState(""); const [updating, setUpdating] = useState(false); const [loading, setLoading] = useState(true); const { toast } = useToast(); const filtersRef = useRef({ statusFilter, targetFilter }); const canModerateContent = hasPermission(permissions, SUPERADMIN_PERMISSIONS.CONTENT_MODERATE); filtersRef.current = { statusFilter, targetFilter }; const loadReports = useCallback(async () => { if (!canModerateContent) { setLoading(false); return; } setLoading(true); try { const { statusFilter: currentStatus, targetFilter: currentTarget } = filtersRef.current; const reports = await listPlatformReports({ page, limit: 15, status: currentStatus === "all" ? undefined : currentStatus, targetType: currentTarget === "all" ? undefined : currentTarget, sortOrder: "desc", }); setResponse(reports); const items = getItems(reports) as PlatformReport[]; setSelectedReport((current) => current ? items.find((item) => item._id === current._id) ?? items[0] ?? null : items[0] ?? null, ); } catch (error) { toast({ title: "Failed to load reports", description: String(error), variant: "danger" }); } finally { setLoading(false); } }, [canModerateContent, page, toast]); useEffect(() => { void loadReports(); }, [loadReports]); const reports = getItems(response) as PlatformReport[]; const summary = useMemo( () => ({ open: reports.filter((item) => item.status === "open").length, inReview: reports.filter((item) => item.status === "in_review").length, resolved: reports.filter((item) => item.status === "resolved").length, rejected: reports.filter((item) => item.status === "rejected").length, }), [reports], ); const applyFilters = () => { if (page === 1) { void loadReports(); return; } setPage(1); }; const updateStatus = async (status: ReportStatus) => { if (!selectedReport) return; setUpdating(true); try { const updated = await updatePlatformReportStatus(selectedReport._id, status, resolutionNote); setSelectedReport(updated); setResolutionNote(""); await loadReports(); toast({ title: "Report updated", description: `${selectedReport._id} -> ${status}`, variant: "success" }); } catch (error) { toast({ title: "Report update failed", description: String(error), variant: "danger" }); } finally { setUpdating(false); } }; if (!canModerateContent) { return (
); } return (
void loadReports()} disabled={loading}> Refresh } />
Open {summary.open} In review {summary.inReview} Resolved {summary.resolved} Rejected {summary.rejected}
Filters
Report queue {!reports.length && !loading ? ( ) : ( Reporter Target Reason Status Date {reports.map((report) => ( setSelectedReport(report)} > {reporterLabel(report.reporterId)}
{report.targetType}
{report.targetId}
{reasonLabels[report.reason] ?? report.reason} {report.status} {formatDateTime(report.createdAt)}
))}
)}
Report details {!selectedReport ? ( ) : ( <>
{selectedReport.status}
{selectedReport.details || "No additional details."}
{selectedReport._id}