Persist transaction statuses to localStorage

Add persistence for transaction statuses to localStorage in ModerationQueue and SubmissionReviewManager components. This ensures that transaction statuses (processing, timeout, cached, completed, failed) are preserved across page refreshes, providing a more robust user experience during active transactions.
This commit is contained in:
gpt-engineer-app[bot]
2025-11-07 16:17:34 +00:00
parent e4bcad9680
commit c7e18206b1
2 changed files with 30 additions and 3 deletions

View File

@@ -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<ModerationQueueRef, ModerationQueuePro
// UI-only state
const [notes, setNotes] = useState<Record<string, string>>({});
const [transactionStatuses, setTransactionStatuses] = useState<Record<string, { status: 'idle' | 'processing' | 'timeout' | 'cached' | 'completed' | 'failed'; message?: string }>>({});
const [transactionStatuses, setTransactionStatuses] = useState<Record<string, { status: 'idle' | 'processing' | 'timeout' | 'cached' | 'completed' | 'failed'; message?: string }>>(() => {
// Restore from localStorage on mount
return localStorage.getJSON('moderation-queue-transaction-statuses', {});
});
const [photoModalOpen, setPhotoModalOpen] = useState(false);
const [selectedPhotos, setSelectedPhotos] = useState<PhotoItem[]>([]);
const [selectedPhotoIndex, setSelectedPhotoIndex] = useState(0);
@@ -111,6 +115,11 @@ export const ModerationQueue = forwardRef<ModerationQueueRef, ModerationQueuePro
// Offline detection state
const [isOffline, setIsOffline] = useState(!navigator.onLine);
// Persist transaction statuses to localStorage
useEffect(() => {
localStorage.setJSON('moderation-queue-transaction-statuses', transactionStatuses);
}, [transactionStatuses]);
// Offline detection effect
useEffect(() => {
const handleOnline = () => {

View File

@@ -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<string | undefined>();
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<string | undefined>(() => {
// 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') {