Files
thrilltrack-explorer/src/hooks/useDataCompleteness.ts
gpt-engineer-app[bot] b58a0a7741 Fix analyze_data_completeness and admin guard
- Add migration to fix JSONB array filtering in analyze_data_completeness
- Update useDataCompleteness to run only on admin pages via isAdminPage check
- Prepare for replacing invalid JSONB subtraction with proper filtering in RPCs
2025-11-12 01:44:58 +00:00

111 lines
3.3 KiB
TypeScript

/**
* Data Completeness Hook
*
* React Query hook for fetching and caching data completeness analysis
* with real-time updates via Supabase subscriptions
*/
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useLocation } from 'react-router-dom';
import { supabase } from '@/integrations/supabase/client';
import { useEffect } from 'react';
import type { CompletenessAnalysis, CompletenessFilters } from '@/types/data-completeness';
import { handleError } from '@/lib/errorHandler';
export function useDataCompleteness(filters: CompletenessFilters = {}) {
const location = useLocation();
const isAdminPage = location.pathname.startsWith('/admin');
const queryClient = useQueryClient();
const query = useQuery({
queryKey: ['data-completeness', filters],
queryFn: async (): Promise<CompletenessAnalysis> => {
try {
const { data, error } = await supabase.rpc('analyze_data_completeness', {
p_entity_type: filters.entityType ?? undefined,
p_min_score: filters.minScore ?? undefined,
p_max_score: filters.maxScore ?? undefined,
p_missing_category: filters.missingCategory ?? undefined,
p_limit: 1000,
p_offset: 0,
});
if (error) throw error;
return data as unknown as CompletenessAnalysis;
} catch (error) {
handleError(error, {
action: 'fetch_data_completeness',
metadata: {
filters,
},
});
throw error;
}
},
enabled: isAdminPage, // Only run on admin pages
staleTime: 5 * 60 * 1000, // Cache for 5 minutes
refetchOnWindowFocus: false,
});
// Real-time subscriptions for data updates
useEffect(() => {
// Subscribe to parks changes
const parksChannel = supabase
.channel('parks-completeness-updates')
.on(
'postgres_changes',
{ event: '*', schema: 'public', table: 'parks' },
() => {
queryClient.invalidateQueries({ queryKey: ['data-completeness'] });
}
)
.subscribe();
// Subscribe to rides changes
const ridesChannel = supabase
.channel('rides-completeness-updates')
.on(
'postgres_changes',
{ event: '*', schema: 'public', table: 'rides' },
() => {
queryClient.invalidateQueries({ queryKey: ['data-completeness'] });
}
)
.subscribe();
// Subscribe to companies changes
const companiesChannel = supabase
.channel('companies-completeness-updates')
.on(
'postgres_changes',
{ event: '*', schema: 'public', table: 'companies' },
() => {
queryClient.invalidateQueries({ queryKey: ['data-completeness'] });
}
)
.subscribe();
// Subscribe to ride_models changes
const modelsChannel = supabase
.channel('ride-models-completeness-updates')
.on(
'postgres_changes',
{ event: '*', schema: 'public', table: 'ride_models' },
() => {
queryClient.invalidateQueries({ queryKey: ['data-completeness'] });
}
)
.subscribe();
return () => {
supabase.removeChannel(parksChannel);
supabase.removeChannel(ridesChannel);
supabase.removeChannel(companiesChannel);
supabase.removeChannel(modelsChannel);
};
}, [queryClient]);
return query;
}