mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-21 22:11:11 -05:00
feat: Implement Phase 4 Streamlined Enhancements
This commit is contained in:
@@ -184,6 +184,18 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig):
|
||||
}
|
||||
}, [queueQuery.isLoading, queueQuery.isRefreshing]);
|
||||
|
||||
// Show error toast when query fails
|
||||
useEffect(() => {
|
||||
if (queueQuery.error) {
|
||||
console.error('❌ Queue query error:', queueQuery.error);
|
||||
toast({
|
||||
variant: 'destructive',
|
||||
title: 'Failed to Load Queue',
|
||||
description: queueQuery.error.message || 'An error occurred while fetching the moderation queue.',
|
||||
});
|
||||
}
|
||||
}, [queueQuery.error, toast]);
|
||||
|
||||
// Update total count for pagination
|
||||
useEffect(() => {
|
||||
paginationRef.current.setTotalCount(queueQuery.totalCount);
|
||||
|
||||
@@ -8,7 +8,14 @@
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { fetchSubmissions, type QueryConfig } from '@/lib/moderation/queries';
|
||||
import { supabase } from '@/integrations/supabase/client';
|
||||
import type { ModerationItem } from '@/types/moderation';
|
||||
import type {
|
||||
ModerationItem,
|
||||
EntityFilter,
|
||||
StatusFilter,
|
||||
QueueTab,
|
||||
SortField,
|
||||
SortDirection
|
||||
} from '@/types/moderation';
|
||||
|
||||
/**
|
||||
* Configuration for queue query
|
||||
@@ -24,13 +31,13 @@ export interface UseQueueQueryConfig {
|
||||
isSuperuser: boolean;
|
||||
|
||||
/** Entity filter */
|
||||
entityFilter: string;
|
||||
entityFilter: EntityFilter;
|
||||
|
||||
/** Status filter */
|
||||
statusFilter: string;
|
||||
statusFilter: StatusFilter;
|
||||
|
||||
/** Active tab */
|
||||
tab: 'mainQueue' | 'archive';
|
||||
tab: QueueTab;
|
||||
|
||||
/** Current page */
|
||||
currentPage: number;
|
||||
@@ -40,8 +47,8 @@ export interface UseQueueQueryConfig {
|
||||
|
||||
/** Sort configuration */
|
||||
sortConfig: {
|
||||
field: string;
|
||||
direction: 'asc' | 'desc';
|
||||
field: SortField;
|
||||
direction: SortDirection;
|
||||
};
|
||||
|
||||
/** Whether query is enabled (defaults to true) */
|
||||
@@ -85,12 +92,12 @@ export function useQueueQuery(config: UseQueueQueryConfig): UseQueueQueryReturn
|
||||
userId: config.userId || '',
|
||||
isAdmin: config.isAdmin,
|
||||
isSuperuser: config.isSuperuser,
|
||||
entityFilter: config.entityFilter as any,
|
||||
statusFilter: config.statusFilter as any,
|
||||
entityFilter: config.entityFilter,
|
||||
statusFilter: config.statusFilter,
|
||||
tab: config.tab,
|
||||
currentPage: config.currentPage,
|
||||
pageSize: config.pageSize,
|
||||
sortConfig: config.sortConfig as any,
|
||||
sortConfig: config.sortConfig,
|
||||
};
|
||||
|
||||
// Create stable query key (TanStack Query uses this for caching/deduplication)
|
||||
@@ -113,6 +120,7 @@ export function useQueueQuery(config: UseQueueQueryConfig): UseQueueQueryReturn
|
||||
const result = await fetchSubmissions(supabase, queryConfig);
|
||||
|
||||
if (result.error) {
|
||||
console.error('❌ [TanStack Query] Error:', result.error);
|
||||
throw result.error;
|
||||
}
|
||||
|
||||
@@ -122,6 +130,8 @@ export function useQueueQuery(config: UseQueueQueryConfig): UseQueueQueryReturn
|
||||
enabled: config.enabled !== false && !!config.userId,
|
||||
staleTime: 30000, // 30 seconds
|
||||
gcTime: 5 * 60 * 1000, // 5 minutes
|
||||
retry: 2, // Retry failed requests up to 2 times
|
||||
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000), // Exponential backoff
|
||||
});
|
||||
|
||||
// Invalidate helper
|
||||
|
||||
@@ -47,7 +47,7 @@ export interface RealtimeSubscriptionConfig {
|
||||
/** Pause subscriptions when tab is hidden (default: true) */
|
||||
pauseWhenHidden?: boolean;
|
||||
|
||||
/** Debounce delay for UPDATE events in milliseconds (default: 1000) */
|
||||
/** Debounce delay for UPDATE events in milliseconds (default: 500) */
|
||||
debounceMs?: number;
|
||||
|
||||
/** Entity cache for resolving entity names */
|
||||
@@ -95,7 +95,7 @@ export function useRealtimeSubscriptions(
|
||||
onUpdateItem,
|
||||
onItemRemoved,
|
||||
pauseWhenHidden = true,
|
||||
debounceMs = 1000,
|
||||
debounceMs = 500,
|
||||
entityCache,
|
||||
profileCache,
|
||||
recentlyRemovedIds,
|
||||
@@ -314,6 +314,7 @@ export function useRealtimeSubscriptions(
|
||||
*/
|
||||
const handleUpdate = useCallback(async (payload: any) => {
|
||||
const updatedSubmission = payload.new as any;
|
||||
const oldSubmission = payload.old as any;
|
||||
|
||||
console.log('🔄 Realtime UPDATE:', updatedSubmission.id);
|
||||
|
||||
@@ -335,7 +336,24 @@ export function useRealtimeSubscriptions(
|
||||
return;
|
||||
}
|
||||
|
||||
// Debounce the update
|
||||
// Skip debounce for status changes (critical updates)
|
||||
const isStatusChange = oldSubmission?.status !== updatedSubmission.status;
|
||||
|
||||
if (isStatusChange) {
|
||||
console.log('⚡ Status change detected, invalidating immediately');
|
||||
await queryClient.invalidateQueries({ queryKey: ['moderation-queue'] });
|
||||
|
||||
const matchesEntity = matchesEntityFilter(updatedSubmission, filters.entityFilter);
|
||||
const matchesStatus = matchesStatusFilter(updatedSubmission, filters.statusFilter);
|
||||
const shouldBeInQueue = matchesEntity && matchesStatus;
|
||||
|
||||
if (!shouldBeInQueue) {
|
||||
onItemRemoved(updatedSubmission.id);
|
||||
}
|
||||
return; // Skip debounced update
|
||||
}
|
||||
|
||||
// Use debounce for non-critical updates
|
||||
debouncedUpdate(updatedSubmission.id, async () => {
|
||||
console.log('🔄 Invalidating query due to UPDATE:', updatedSubmission.id);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user