import { memo, useCallback } from 'react'; import { CheckCircle, XCircle, RefreshCw, AlertCircle, Lock, Trash2, Edit, Info, ExternalLink, ChevronDown, ListTree, Calendar } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'; import { UserAvatar } from '@/components/ui/user-avatar'; import { format } from 'date-fns'; import type { ModerationItem } from '@/types/moderation'; import { sanitizeURL, sanitizePlainText } from '@/lib/sanitize'; interface QueueItemActionsProps { item: ModerationItem; isMobile: boolean; actionLoading: string | null; isLockedByMe: boolean; isLockedByOther: boolean; currentLockSubmissionId?: string; notes: Record; isAdmin: boolean; isSuperuser: boolean; queueIsLoading: boolean; isClaiming: boolean; onNoteChange: (id: string, value: string) => void; onApprove: (item: ModerationItem, action: 'approved' | 'rejected', notes?: string) => void; onResetToPending: (item: ModerationItem) => void; onRetryFailed: (item: ModerationItem) => void; onOpenReviewManager: (submissionId: string) => void; onOpenItemEditor: (submissionId: string) => void; onDeleteSubmission: (item: ModerationItem) => void; onInteractionFocus: (id: string) => void; onInteractionBlur: (id: string) => void; onClaim: () => void; } export const QueueItemActions = memo(({ item, isMobile, actionLoading, isLockedByMe, isLockedByOther, currentLockSubmissionId, notes, isAdmin, isSuperuser, queueIsLoading, isClaiming, onNoteChange, onApprove, onResetToPending, onRetryFailed, onOpenReviewManager, onOpenItemEditor, onDeleteSubmission, onInteractionFocus, onInteractionBlur, onClaim }: QueueItemActionsProps) => { // Memoize all handlers to prevent re-renders const handleNoteChange = useCallback((e: React.ChangeEvent) => { onNoteChange(item.id, e.target.value); }, [onNoteChange, item.id]); const handleApprove = useCallback(() => { onApprove(item, 'approved', notes[item.id]); }, [onApprove, item, notes]); const handleReject = useCallback(() => { onApprove(item, 'rejected', notes[item.id]); }, [onApprove, item, notes]); const handleResetToPending = useCallback(() => { onResetToPending(item); }, [onResetToPending, item]); const handleRetryFailed = useCallback(() => { onRetryFailed(item); }, [onRetryFailed, item]); const handleOpenReviewManager = useCallback(() => { onOpenReviewManager(item.id); }, [onOpenReviewManager, item.id]); const handleOpenItemEditor = useCallback(() => { onOpenItemEditor(item.id); }, [onOpenItemEditor, item.id]); const handleDeleteSubmission = useCallback(() => { onDeleteSubmission(item); }, [onDeleteSubmission, item]); const handleFocus = useCallback(() => { onInteractionFocus(item.id); }, [onInteractionFocus, item.id]); const handleBlur = useCallback(() => { onInteractionBlur(item.id); }, [onInteractionBlur, item.id]); const handleReverseNoteChange = useCallback((e: React.ChangeEvent) => { onNoteChange(`reverse-${item.id}`, e.target.value); }, [onNoteChange, item.id]); const handleReverseApprove = useCallback(() => { onApprove(item, 'approved', notes[`reverse-${item.id}`]); }, [onApprove, item, notes]); const handleReverseReject = useCallback(() => { onApprove(item, 'rejected', notes[`reverse-${item.id}`]); }, [onApprove, item, notes]); return ( <> {/* Action buttons based on status */} {(item.status === 'pending' || item.status === 'flagged') && ( <> {/* Claim button for unclaimed submissions */} {!isLockedByOther && currentLockSubmissionId !== item.id && (
Unclaimed Submission
Claim this submission to lock it for 15 minutes while you review
)}
{/* Submitter Context - shown before moderator can add their notes */} {(item.submission_items?.[0]?.item_data?.source_url || item.submission_items?.[0]?.item_data?.submission_notes) && (

Submitter Context

{item.submission_items?.[0]?.item_data?.source_url && ( )} {item.submission_items?.[0]?.item_data?.submission_notes && (
Submitter Notes:

{sanitizePlainText(item.submission_items[0].item_data.submission_notes)}

)}
)} {/* Left: Notes textarea */}