import { useEffect, useState } from 'react'; import type { ContentReviewStatus } from '@sauci/shared'; import { Archive, CheckCircle2, ClipboardCheck, Loader2 } from 'lucide-react'; import { toast } from 'sonner'; import { useAuth } from '@/contexts/AuthContext'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Textarea } from '@/components/ui/textarea'; import { CONTENT_STATUS_LABELS, type ReviewableContentTable, updateContentReviewStatus, } from '@/services/contentReviews'; interface ContentReviewControlProps { table: ReviewableContentTable; entityId: string; entityLabel: string; status?: ContentReviewStatus | null; reason?: string | null; onChanged: () => void | Promise; compact?: boolean; } const badgeClasses: Record = { unreviewed: 'border-amber-500 text-amber-500', allowed: 'border-green-500 text-green-500', archived: 'border-slate-500 text-slate-400', }; const statusIcons: Record = { unreviewed: ClipboardCheck, allowed: CheckCircle2, archived: Archive, }; export function ContentReviewControl({ table, entityId, entityLabel, status, reason, onChanged, compact = false, }: ContentReviewControlProps) { const { isSuperAdmin } = useAuth(); const resolvedStatus = status ?? 'unreviewed'; const StatusIcon = statusIcons[resolvedStatus]; const [open, setOpen] = useState(false); const [nextStatus, setNextStatus] = useState(resolvedStatus); const [nextReason, setNextReason] = useState(reason ?? ''); const [saving, setSaving] = useState(false); useEffect(() => { if (!open) { setNextStatus(resolvedStatus); setNextReason(reason ?? ''); } }, [open, reason, resolvedStatus]); const save = async () => { if (!nextReason.trim()) { toast.error('A review reason is required'); return; } setSaving(true); try { await updateContentReviewStatus(table, entityId, nextStatus, nextReason); toast.success(`${entityLabel} marked ${CONTENT_STATUS_LABELS[nextStatus].toLowerCase()}`); setOpen(false); await onChanged(); } catch (error) { toast.error('Failed to update catalogue status'); console.error(error); } finally { setSaving(false); } }; return (
{CONTENT_STATUS_LABELS[resolvedStatus]} {isSuperAdmin && ( <> Review catalogue status This records a reversible editorial decision for {entityLabel}. Current customer apps do not filter this status yet.