# Moderation Queue Components ## Component Reference ### ModerationQueue (Root Component) **Location:** `src/components/moderation/ModerationQueue.tsx` **Purpose:** Root component for moderation interface. Orchestrates all sub-components and manages UI state. **Props:** ```typescript interface ModerationQueueProps { optimisticallyUpdateStats?: (delta: Partial<{ pendingSubmissions: number; openReports: number; flaggedContent: number; }>) => void; } ``` **Ref API:** ```typescript interface ModerationQueueRef { refresh: () => void; } ``` **Usage:** ```tsx import { useRef } from 'react'; import { ModerationQueue } from '@/components/moderation/ModerationQueue'; function AdminPanel() { const queueRef = useRef(null); return (
); } ``` --- ### ModerationErrorBoundary **Location:** `src/components/error/ModerationErrorBoundary.tsx` **Purpose:** Catches React render errors in queue items, preventing full queue crashes. **Props:** ```typescript interface ModerationErrorBoundaryProps { children: ReactNode; submissionId?: string; fallback?: ReactNode; onError?: (error: Error, errorInfo: ErrorInfo) => void; } ``` **Features:** - Automatic error logging - User-friendly error UI - Retry functionality - Copy error details button - Development-mode stack traces **Usage:** ```tsx ``` **Custom Fallback:** ```tsx Custom error message} onError={(error, info) => { // Send to monitoring service trackError(error, info); }} > ``` --- ### QueueItem **Location:** `src/components/moderation/QueueItem.tsx` **Purpose:** Renders individual submission in queue with all interaction controls. **Props:** ```typescript interface QueueItemProps { item: ModerationItem; isMobile: boolean; actionLoading: string | null; isLockedByMe: boolean; isLockedByOther: boolean; lockStatus: LockStatus; currentLockSubmissionId?: string; notes: Record; isAdmin: boolean; isSuperuser: boolean; queueIsLoading: boolean; onNoteChange: (id: string, value: string) => void; onApprove: (item: ModerationItem, action: 'approved' | 'rejected', notes?: string) => void; onResetToPending: (item: ModerationItem) => void; onRetryFailed: (item: ModerationItem) => void; onOpenPhotos: (photos: PhotoForDisplay[], index: number) => void; onOpenReviewManager: (submissionId: string) => void; onOpenItemEditor: (submissionId: string) => void; onClaimSubmission: (submissionId: string) => void; onDeleteSubmission: (item: ModerationItem) => void; onInteractionFocus: (id: string) => void; onInteractionBlur: (id: string) => void; } ``` **Key Features:** - Displays submission type, status, timestamps - User profile with avatar - Validation summary (errors, warnings) - Lock status indicators - Moderator edit badges - Action buttons (approve, reject, claim) - Responsive mobile/desktop layouts **Accessibility:** - Keyboard navigation support - ARIA labels on interactive elements - Focus management - Screen reader compatible --- ### QueueFilters **Location:** `src/components/moderation/QueueFilters.tsx` **Purpose:** Filter and sort controls for moderation queue. **Props:** ```typescript interface QueueFiltersProps { activeEntityFilter: EntityFilter; activeStatusFilter: StatusFilter; sortConfig: SortConfig; isMobile: boolean; isLoading?: boolean; onEntityFilterChange: (filter: EntityFilter) => void; onStatusFilterChange: (filter: StatusFilter) => void; onSortChange: (config: SortConfig) => void; onClearFilters: () => void; showClearButton: boolean; } ``` **Features:** - Entity type filter (all, reviews, submissions, photos) - Status filter (pending, approved, rejected, etc.) - Sort controls (date, type, status) - Clear filters button - Fully accessible (ARIA labels, keyboard navigation) **Usage:** ```tsx ``` --- ### ValidationSummary **Location:** `src/components/moderation/ValidationSummary.tsx` **Purpose:** Displays validation results for submission items. **Props:** ```typescript interface ValidationSummaryProps { item: { item_type: string; item_data: SubmissionItemData; id?: string; }; onValidationChange?: (result: ValidationResult) => void; compact?: boolean; validationKey?: number; } ``` **View Modes:** **Compact (for queue items):** - Status badges (Valid, Errors, Warnings) - Always-visible error details (no hover needed) - Minimal space usage **Detailed (for review manager):** - Expandable validation details - Full error, warning, and suggestion lists - Re-validate button **Usage:** ```tsx {/* Compact view in queue */} { if (result.blockingErrors.length > 0) { setCanApprove(false); } }} /> {/* Detailed view in editor */} ``` --- ## Hooks Reference ### useModerationQueueManager **Location:** `src/hooks/moderation/useModerationQueueManager.ts` **Purpose:** Orchestrator hook combining all moderation queue logic. **Usage:** ```typescript const queueManager = useModerationQueueManager({ user, isAdmin: isAdmin(), isSuperuser: isSuperuser(), toast, settings: { refreshMode: 'auto', pollInterval: 30000, refreshStrategy: 'merge', preserveInteraction: true, useRealtimeQueue: true, }, }); // Access sub-hooks queueManager.filters.setEntityFilter('reviews'); queueManager.pagination.setCurrentPage(2); queueManager.queue.claimSubmission(itemId); // Perform actions await queueManager.performAction(item, 'approved', 'Looks good!'); await queueManager.deleteSubmission(item); ``` --- ### useModerationQueue **Location:** `src/hooks/useModerationQueue.ts` **Purpose:** Lock management and queue statistics. **Features:** - Claim/release submission locks - Lock expiry countdown - Lock status checking - Queue statistics **Usage:** ```typescript const queue = useModerationQueue({ onLockStateChange: () => { console.log('Lock state changed'); } }); // Claim submission await queue.claimSubmission('submission-123'); // Extend lock (adds 15 minutes) await queue.extendLock(); // Release lock await queue.releaseLock('submission-123'); // Check lock status const timeRemaining = queue.getTimeRemaining(); const progress = queue.getLockProgress(); ``` --- ## Testing Components ### Unit Testing Example ```typescript import { render, screen } from '@testing-library/react'; import { ModerationErrorBoundary } from '@/components/error/ModerationErrorBoundary'; describe('ModerationErrorBoundary', () => { it('catches errors and shows fallback UI', () => { const ThrowError = () => { throw new Error('Test error'); }; render( ); expect(screen.getByText(/queue item error/i)).toBeInTheDocument(); expect(screen.getByText(/test error/i)).toBeInTheDocument(); }); it('shows retry button', () => { const ThrowError = () => { throw new Error('Test error'); }; render( ); expect(screen.getByRole('button', { name: /retry/i })).toBeInTheDocument(); }); }); ``` ### Integration Testing Example ```typescript import { renderHook, act } from '@testing-library/react'; import { useModerationQueueManager } from '@/hooks/moderation/useModerationQueueManager'; describe('useModerationQueueManager', () => { it('filters items correctly', async () => { const { result } = renderHook(() => useModerationQueueManager(config)); act(() => { result.current.filters.setEntityFilter('reviews'); }); await waitFor(() => { expect(result.current.items.every(item => item.type === 'review')).toBe(true); }); }); }); ``` --- ## Accessibility Guidelines ### Keyboard Navigation **Queue Filters:** - `Tab`: Navigate between filter controls - `Enter`/`Space`: Open dropdown - `Arrow keys`: Navigate dropdown options - `Escape`: Close dropdown **Queue Items:** - `Tab`: Navigate between interactive elements - `Enter`/`Space`: Activate buttons - `Escape`: Close expanded sections ### Screen Reader Support All components include: - Semantic HTML (`