diff --git a/src/app/dashboard/reports/page.tsx b/src/app/dashboard/reports/page.tsx new file mode 100644 index 0000000..e8c225e --- /dev/null +++ b/src/app/dashboard/reports/page.tsx @@ -0,0 +1,253 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { useRouter } from 'next/navigation'; +import { userReportsService, type UserReport, type ReportCounts } from '@/services/user-reports.service'; +import { getErrorMessage } from '@/services'; + +function getUserName(user: UserReport['reporter']): string { + const profile = user.userProfile || user.agentProfile; + if (profile?.firstName || profile?.lastName) { + return [profile.firstName, profile.lastName].filter(Boolean).join(' '); + } + return user.email; +} + +const STATUS_COLORS: Record = { + PENDING: 'bg-yellow-100 text-yellow-800', + REVIEWED: 'bg-blue-100 text-blue-800', + RESOLVED: 'bg-green-100 text-green-800', + DISMISSED: 'bg-gray-100 text-gray-800', +}; + +export default function ReportsPage() { + const router = useRouter(); + const [reports, setReports] = useState([]); + const [counts, setCounts] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(''); + const [statusFilter, setStatusFilter] = useState(''); + const [selectedReport, setSelectedReport] = useState(null); + const [adminNotes, setAdminNotes] = useState(''); + const [updatingId, setUpdatingId] = useState(null); + + const fetchData = async () => { + try { + setLoading(true); + setError(''); + const [reportsList, reportCounts] = await Promise.all([ + userReportsService.getAllReports(statusFilter || undefined), + userReportsService.getReportCounts(), + ]); + setReports(reportsList); + setCounts(reportCounts); + } catch (err) { + const msg = getErrorMessage(err); + setError(msg); + if (msg.includes('Unauthorized')) router.push('/login'); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + fetchData(); + }, [statusFilter]); + + const handleUpdateStatus = async (reportId: string, status: string) => { + try { + setUpdatingId(reportId); + const updated = await userReportsService.updateReport(reportId, status, adminNotes || undefined); + setReports((prev) => prev.map((r) => (r.id === reportId ? updated : r))); + setSelectedReport(null); + setAdminNotes(''); + // Refresh counts + const reportCounts = await userReportsService.getReportCounts(); + setCounts(reportCounts); + } catch (err) { + setError(getErrorMessage(err)); + } finally { + setUpdatingId(null); + } + }; + + return ( +
+

User Reports

+ + {/* Status Counts */} + {counts && ( +
+ {[ + { label: 'Total', value: counts.total, color: 'bg-gray-50' }, + { label: 'Pending', value: counts.pending, color: 'bg-yellow-50' }, + { label: 'Reviewed', value: counts.reviewed, color: 'bg-blue-50' }, + { label: 'Resolved', value: counts.resolved, color: 'bg-green-50' }, + { label: 'Dismissed', value: counts.dismissed, color: 'bg-gray-50' }, + ].map((stat) => ( +
+

{stat.label}

+

{stat.value}

+
+ ))} +
+ )} + + {/* Filter */} +
+ + +
+ + {error && ( +
+

{error}

+
+ )} + + {loading ? ( +
+
+
+ ) : reports.length === 0 ? ( +
+

No reports found

+
+ ) : ( +
+ + + + + + + + + + + + + {reports.map((report) => ( + + + + + + + + + ))} + +
ReporterReported UserReasonStatusDateActions
+

{getUserName(report.reporter)}

+

{report.reporter.email}

+
+

{getUserName(report.reportedUser)}

+

{report.reportedUser.email}

+
+

{report.reason}

+ {report.description && ( +

{report.description}

+ )} +
+ + {report.status} + + + {new Date(report.createdAt).toLocaleDateString()} + + +
+
+ )} + + {/* Review Modal */} + {selectedReport && ( +
+
+
+

Review Report

+
+
+
+

Reporter

+

{getUserName(selectedReport.reporter)} ({selectedReport.reporter.email})

+
+
+

Reported User

+

{getUserName(selectedReport.reportedUser)} ({selectedReport.reportedUser.email})

+
+
+

Reason

+

{selectedReport.reason}

+
+ {selectedReport.description && ( +
+

Description

+

{selectedReport.description}

+
+ )} +
+ +