'use client'; import AdminShell from '@/components/AdminShell'; import SelectionBar from '@/components/SelectionBar'; import { api } from '@/lib/api'; import { statusColor, formatDateTime } from '@/lib/utils'; import { useEffect, useState } from 'react'; import { Shield, CheckCircle, XCircle, Trash2, Ban, AlertTriangle } from 'lucide-react'; function ScoreBar({ label, value }: { label: string; value: number }) { const pct = Math.round(value * 100); const color = pct > 70 ? 'bg-red-500' : pct > 40 ? 'bg-yellow-500' : 'bg-green-500'; return (
{label}
{pct}%
); } export default function ModerationPage() { const [items, setItems] = useState([]); const [total, setTotal] = useState(0); const [loading, setLoading] = useState(true); const [statusFilter, setStatusFilter] = useState('pending'); const [reviewingId, setReviewingId] = useState(null); const [reason, setReason] = useState(''); const [selected, setSelected] = useState>(new Set()); const [bulkLoading, setBulkLoading] = useState(false); const fetchQueue = () => { setLoading(true); api.getModerationQueue({ limit: 50, status: statusFilter }) .then((data) => { setItems(data.items); setTotal(data.total); }) .catch(() => {}) .finally(() => setLoading(false)); }; useEffect(() => { fetchQueue(); }, [statusFilter]); const handleReview = async (id: string, action: string) => { try { await api.reviewModerationFlag(id, action, reason || 'Admin review'); setReviewingId(null); setReason(''); fetchQueue(); } catch {} }; const toggleSelect = (id: string) => { setSelected((prev) => { const s = new Set(prev); s.has(id) ? s.delete(id) : s.add(id); return s; }); }; const handleBulkAction = async (action: string) => { setBulkLoading(true); try { await api.bulkReviewModeration(Array.from(selected), action, 'Bulk admin review'); setSelected(new Set()); fetchQueue(); } catch {} setBulkLoading(false); }; return (

Moderation Queue

{total} items {statusFilter}

{statusFilter === 'pending' && ( setSelected(new Set(items.map((i) => i.id)))} onClearSelection={() => setSelected(new Set())} loading={bulkLoading} actions={[ { label: 'Approve All', action: 'approve', color: 'bg-green-50 text-green-700 hover:bg-green-100', icon: }, { label: 'Dismiss All', action: 'dismiss', color: 'bg-gray-100 text-gray-700 hover:bg-gray-200', icon: }, { label: 'Remove Content', action: 'remove_content', confirm: true, color: 'bg-red-50 text-red-700 hover:bg-red-100', icon: }, ]} onAction={handleBulkAction} /> )} {loading ? (
{[...Array(3)].map((_, i) =>
)}
) : items.length === 0 ? (

No {statusFilter} items in the queue

All clear! The AI moderation system hasn't flagged any new content.

) : (
{items.map((item) => (
{statusFilter === 'pending' && ( toggleSelect(item.id)} /> )}
{/* Header */}
{item.status} {item.content_type} {item.flag_reason} {formatDateTime(item.created_at)}
{/* Content */}
{item.content_type === 'post' ? (

{item.post_body || 'No text content'}

{item.post_image && (
📷 Has image: {item.post_image}
)} {item.post_video && (
🎬 Has video: {item.post_video}
)}
) : (

{item.comment_body || 'No content'}

)}
{/* Author */}

By @{item.author_handle || '—'} {item.author_name && ` (${item.author_name})`}

{/* AI Scores */} {item.scores && (
{item.scores.hate != null && } {item.scores.greed != null && } {item.scores.delusion != null && }
)}
{/* Actions */} {item.status === 'pending' && (
)}
{/* Ban modal inline */} {reviewingId === item.id && (

Ban user and remove content

setReason(e.target.value)} />
)}
))}
)} ); }