mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 14:31:12 -05:00
147 lines
4.1 KiB
TypeScript
147 lines
4.1 KiB
TypeScript
import { useState, useEffect, useCallback } from 'react';
|
|
import { QueuedSubmission } from '@/components/submission/SubmissionQueueIndicator';
|
|
import { useNetworkStatus } from './useNetworkStatus';
|
|
import {
|
|
getPendingSubmissions,
|
|
processQueue,
|
|
removeFromQueue,
|
|
clearQueue as clearQueueStorage,
|
|
getPendingCount,
|
|
} from '@/lib/submissionQueue';
|
|
import { logger } from '@/lib/logger';
|
|
|
|
interface UseSubmissionQueueOptions {
|
|
autoRetry?: boolean;
|
|
retryDelayMs?: number;
|
|
maxRetries?: number;
|
|
}
|
|
|
|
export function useSubmissionQueue(options: UseSubmissionQueueOptions = {}) {
|
|
const {
|
|
autoRetry = true,
|
|
retryDelayMs = 5000,
|
|
maxRetries = 3,
|
|
} = options;
|
|
|
|
const [queuedItems, setQueuedItems] = useState<QueuedSubmission[]>([]);
|
|
const [lastSyncTime, setLastSyncTime] = useState<Date | null>(null);
|
|
const [nextRetryTime, setNextRetryTime] = useState<Date | null>(null);
|
|
const { isOnline } = useNetworkStatus();
|
|
|
|
// Load queued items from IndexedDB on mount
|
|
useEffect(() => {
|
|
loadQueueFromStorage();
|
|
}, []);
|
|
|
|
// Auto-retry when back online
|
|
useEffect(() => {
|
|
if (isOnline && autoRetry && queuedItems.length > 0) {
|
|
const timer = setTimeout(() => {
|
|
retryAll();
|
|
}, retryDelayMs);
|
|
|
|
setNextRetryTime(new Date(Date.now() + retryDelayMs));
|
|
|
|
return () => clearTimeout(timer);
|
|
}
|
|
}, [isOnline, autoRetry, queuedItems.length, retryDelayMs]);
|
|
|
|
const loadQueueFromStorage = useCallback(async () => {
|
|
try {
|
|
const pending = await getPendingSubmissions();
|
|
|
|
// Transform to QueuedSubmission format
|
|
const items: QueuedSubmission[] = pending.map(item => ({
|
|
id: item.id,
|
|
type: item.type,
|
|
entityName: item.data?.name || item.data?.title || 'Unknown',
|
|
timestamp: new Date(item.timestamp),
|
|
status: item.retries >= 3 ? 'failed' : (item.lastAttempt ? 'retrying' : 'pending'),
|
|
retryCount: item.retries,
|
|
error: item.error || undefined,
|
|
}));
|
|
|
|
setQueuedItems(items);
|
|
logger.info('[SubmissionQueue] Loaded queue', { count: items.length });
|
|
} catch (error) {
|
|
logger.error('[SubmissionQueue] Failed to load queue', { error });
|
|
}
|
|
}, []);
|
|
|
|
const retryItem = useCallback(async (id: string) => {
|
|
setQueuedItems(prev =>
|
|
prev.map(item =>
|
|
item.id === id
|
|
? { ...item, status: 'retrying' as const }
|
|
: item
|
|
)
|
|
);
|
|
|
|
try {
|
|
// Placeholder: Retry the submission
|
|
// await retrySubmission(id);
|
|
|
|
// Remove from queue on success
|
|
setQueuedItems(prev => prev.filter(item => item.id !== id));
|
|
setLastSyncTime(new Date());
|
|
} catch (error) {
|
|
// Mark as failed
|
|
setQueuedItems(prev =>
|
|
prev.map(item =>
|
|
item.id === id
|
|
? {
|
|
...item,
|
|
status: 'failed' as const,
|
|
retryCount: (item.retryCount || 0) + 1,
|
|
error: error instanceof Error ? error.message : 'Unknown error',
|
|
}
|
|
: item
|
|
)
|
|
);
|
|
}
|
|
}, []);
|
|
|
|
const retryAll = useCallback(async () => {
|
|
const pendingItems = queuedItems.filter(
|
|
item => item.status === 'pending' || item.status === 'failed'
|
|
);
|
|
|
|
for (const item of pendingItems) {
|
|
if ((item.retryCount || 0) < maxRetries) {
|
|
await retryItem(item.id);
|
|
}
|
|
}
|
|
}, [queuedItems, maxRetries, retryItem]);
|
|
|
|
const removeItem = useCallback(async (id: string) => {
|
|
try {
|
|
await removeFromQueue(id);
|
|
setQueuedItems(prev => prev.filter(item => item.id !== id));
|
|
logger.info('[SubmissionQueue] Removed item', { id });
|
|
} catch (error) {
|
|
logger.error('[SubmissionQueue] Failed to remove item', { id, error });
|
|
}
|
|
}, []);
|
|
|
|
const clearQueue = useCallback(async () => {
|
|
try {
|
|
const count = await clearQueueStorage();
|
|
setQueuedItems([]);
|
|
logger.info('[SubmissionQueue] Cleared queue', { count });
|
|
} catch (error) {
|
|
logger.error('[SubmissionQueue] Failed to clear queue', { error });
|
|
}
|
|
}, []);
|
|
|
|
return {
|
|
queuedItems,
|
|
lastSyncTime,
|
|
nextRetryTime,
|
|
retryItem,
|
|
retryAll,
|
|
removeItem,
|
|
clearQueue,
|
|
refresh: loadQueueFromStorage,
|
|
};
|
|
}
|