diff --git a/src/components/moderation/ModerationQueue.tsx b/src/components/moderation/ModerationQueue.tsx index 2abb2e48..b5d8f156 100644 --- a/src/components/moderation/ModerationQueue.tsx +++ b/src/components/moderation/ModerationQueue.tsx @@ -9,6 +9,7 @@ import { useUserRole } from '@/hooks/useUserRole'; import { useAuth } from '@/hooks/useAuth'; import { getErrorMessage } from '@/lib/errorHandler'; import { supabase } from '@/lib/supabaseClient'; +import * as localStorage from '@/lib/localStorage'; import { PhotoModal } from './PhotoModal'; import { SubmissionReviewManager } from './SubmissionReviewManager'; import { ItemEditDialog } from './ItemEditDialog'; @@ -76,7 +77,10 @@ export const ModerationQueue = forwardRef>({}); - const [transactionStatuses, setTransactionStatuses] = useState>({}); + const [transactionStatuses, setTransactionStatuses] = useState>(() => { + // Restore from localStorage on mount + return localStorage.getJSON('moderation-queue-transaction-statuses', {}); + }); const [photoModalOpen, setPhotoModalOpen] = useState(false); const [selectedPhotos, setSelectedPhotos] = useState([]); const [selectedPhotoIndex, setSelectedPhotoIndex] = useState(0); @@ -111,6 +115,11 @@ export const ModerationQueue = forwardRef { + localStorage.setJSON('moderation-queue-transaction-statuses', transactionStatuses); + }, [transactionStatuses]); + // Offline detection effect useEffect(() => { const handleOnline = () => { diff --git a/src/components/moderation/SubmissionReviewManager.tsx b/src/components/moderation/SubmissionReviewManager.tsx index 2ca96eee..fe0ebfb5 100644 --- a/src/components/moderation/SubmissionReviewManager.tsx +++ b/src/components/moderation/SubmissionReviewManager.tsx @@ -7,6 +7,7 @@ import { invokeWithTracking } from '@/lib/edgeFunctionTracking'; import { moderationReducer, canApprove, canReject, hasActiveLock } from '@/lib/moderationStateMachine'; import { useLockMonitor } from '@/lib/moderation/lockMonitor'; import { useTransactionResilience } from '@/hooks/useTransactionResilience'; +import * as localStorage from '@/lib/localStorage'; import { fetchSubmissionItems, buildDependencyTree, @@ -84,8 +85,17 @@ export function SubmissionReviewManager({ message: string; errorId?: string; } | null>(null); - const [transactionStatus, setTransactionStatus] = useState<'idle' | 'processing' | 'timeout' | 'cached' | 'completed' | 'failed'>('idle'); - const [transactionMessage, setTransactionMessage] = useState(); + const [transactionStatus, setTransactionStatus] = useState<'idle' | 'processing' | 'timeout' | 'cached' | 'completed' | 'failed'>(() => { + // Restore from localStorage on mount + const stored = localStorage.getJSON<{ status: string; message?: string }>(`moderation-transaction-status-${submissionId}`, { status: 'idle' }); + const validStatuses = ['idle', 'processing', 'timeout', 'cached', 'completed', 'failed']; + return validStatuses.includes(stored.status) ? stored.status as 'idle' | 'processing' | 'timeout' | 'cached' | 'completed' | 'failed' : 'idle'; + }); + const [transactionMessage, setTransactionMessage] = useState(() => { + // Restore from localStorage on mount + const stored = localStorage.getJSON<{ status: string; message?: string }>(`moderation-transaction-status-${submissionId}`, { status: 'idle' }); + return stored.message; + }); const { toast } = useToast(); const { isAdmin, isSuperuser } = useUserRole(); @@ -116,6 +126,14 @@ export function SubmissionReviewManager({ } }); + // Persist transaction status to localStorage + useEffect(() => { + localStorage.setJSON(`moderation-transaction-status-${submissionId}`, { + status: transactionStatus, + message: transactionMessage, + }); + }, [transactionStatus, transactionMessage, submissionId]); + // Auto-claim on mount useEffect(() => { if (open && submissionId && state.status === 'idle') {