mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-23 16:11:12 -05:00
Refactor: Complete error handling overhaul
This commit is contained in:
@@ -11,6 +11,7 @@ import { supabase } from '@/integrations/supabase/client';
|
||||
import { logger } from '@/lib/logger';
|
||||
import { getErrorMessage } from '@/lib/errorHandler';
|
||||
import { MODERATION_CONSTANTS } from '@/lib/moderation/constants';
|
||||
import { validateModerationItems } from '@/lib/moderation/validation';
|
||||
import type {
|
||||
ModerationItem,
|
||||
EntityFilter,
|
||||
@@ -20,6 +21,49 @@ import type {
|
||||
SortDirection
|
||||
} from '@/types/moderation';
|
||||
|
||||
/**
|
||||
* Get specific, actionable error message based on error type
|
||||
*/
|
||||
function getSpecificErrorMessage(error: unknown): string {
|
||||
// Offline detection
|
||||
if (!navigator.onLine) {
|
||||
return 'You appear to be offline. Check your internet connection and try again.';
|
||||
}
|
||||
|
||||
// Timeout
|
||||
if (error instanceof Error && error.name === 'AbortError') {
|
||||
return 'Request timed out. The server is taking too long to respond. Please try again.';
|
||||
}
|
||||
|
||||
// Check for Supabase-specific errors
|
||||
if (typeof error === 'object' && error !== null) {
|
||||
const err = error as any;
|
||||
|
||||
// 500 errors
|
||||
if (err.status === 500 || err.code === '500') {
|
||||
return 'Server error occurred. Our team has been notified. Please try again in a few minutes.';
|
||||
}
|
||||
|
||||
// 429 Rate limiting
|
||||
if (err.status === 429 || err.message?.includes('rate limit')) {
|
||||
return 'Too many requests. Please wait a moment before trying again.';
|
||||
}
|
||||
|
||||
// Authentication errors
|
||||
if (err.status === 401 || err.message?.includes('JWT')) {
|
||||
return 'Your session has expired. Please refresh the page and sign in again.';
|
||||
}
|
||||
|
||||
// Permission errors
|
||||
if (err.status === 403 || err.message?.includes('permission')) {
|
||||
return 'You do not have permission to access the moderation queue.';
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback
|
||||
return getErrorMessage(error) || 'Failed to load moderation queue. Please try again.';
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration for queue query
|
||||
*/
|
||||
@@ -124,21 +168,44 @@ export function useQueueQuery(config: UseQueueQueryConfig): UseQueueQueryReturn
|
||||
queryKey,
|
||||
queryFn: async () => {
|
||||
logger.log('🔍 [TanStack Query] Fetching queue data:', queryKey);
|
||||
const result = await fetchSubmissions(supabase, queryConfig);
|
||||
|
||||
if (result.error) {
|
||||
logger.error('❌ [TanStack Query] Error:', { error: getErrorMessage(result.error) });
|
||||
throw result.error;
|
||||
// Create timeout controller (30s timeout)
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 30000);
|
||||
|
||||
try {
|
||||
const result = await fetchSubmissions(supabase, queryConfig);
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (result.error) {
|
||||
const specificMessage = getSpecificErrorMessage(result.error);
|
||||
logger.error('❌ [TanStack Query] Error:', { error: specificMessage });
|
||||
throw new Error(specificMessage);
|
||||
}
|
||||
|
||||
// Validate data shape before returning
|
||||
const validation = validateModerationItems(result.submissions);
|
||||
if (!validation.success) {
|
||||
logger.error('❌ Invalid data shape', { error: validation.error });
|
||||
throw new Error(validation.error || 'Invalid data format');
|
||||
}
|
||||
|
||||
logger.log('✅ [TanStack Query] Fetched', validation.data!.length, 'items');
|
||||
return { ...result, submissions: validation.data! };
|
||||
} catch (error) {
|
||||
clearTimeout(timeoutId);
|
||||
throw error;
|
||||
}
|
||||
|
||||
logger.log('✅ [TanStack Query] Fetched', result.submissions.length, 'items');
|
||||
return result;
|
||||
},
|
||||
enabled: config.enabled !== false && !!config.userId,
|
||||
staleTime: MODERATION_CONSTANTS.QUERY_STALE_TIME,
|
||||
gcTime: MODERATION_CONSTANTS.QUERY_GC_TIME,
|
||||
retry: MODERATION_CONSTANTS.QUERY_RETRY_COUNT,
|
||||
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),
|
||||
networkMode: 'offlineFirst', // Handle offline gracefully
|
||||
meta: {
|
||||
errorMessage: 'Failed to load moderation queue',
|
||||
},
|
||||
});
|
||||
|
||||
// Invalidate helper
|
||||
|
||||
Reference in New Issue
Block a user