/** * Hook for Supabase Realtime Submissions * Subscribes to submissions table changes and updates UI in realtime */ import { useEffect, useCallback, useRef } from 'react'; import { RealtimeChannel } from '@supabase/supabase-js'; import { supabase } from './supabase'; export interface SubmissionRecord { id: string; submission_id: string; status: 'pending' | 'processing' | 'completed' | 'failed'; input: any; results: any[] | null; error_message: string | null; created_at: string; updated_at: string; submission_type: 'tms_permission' | 'raw_download'; } interface UseRealtimeSubmissionsOptions { onInsert?: (record: SubmissionRecord) => void; onUpdate?: (record: SubmissionRecord) => void; onDelete?: (record: SubmissionRecord) => void; /** Optional: filter by submission_type */ submissionType?: 'tms_permission' | 'raw_download'; } /** * Subscribe to realtime changes on submissions table */ export function useRealtimeSubmissions(options: UseRealtimeSubmissionsOptions = {}) { const { onInsert, onUpdate, onDelete, submissionType } = options; const channelRef = useRef(null); const subscribe = useCallback(() => { // Unsubscribe existing channel if (channelRef.current) { channelRef.current.unsubscribe(); } // Create filter if submissionType provided const filter = submissionType ? `submission_type=eq.${submissionType}` : undefined; const channel = supabase .channel('submissions-changes') .on( 'postgres_changes', { event: 'INSERT', schema: 'public', table: 'submissions', filter, }, (payload) => { onInsert?.(payload.new as SubmissionRecord); } ) .on( 'postgres_changes', { event: 'UPDATE', schema: 'public', table: 'submissions', filter, }, (payload) => { onUpdate?.(payload.new as SubmissionRecord); } ) .on( 'postgres_changes', { event: 'DELETE', schema: 'public', table: 'submissions', filter, }, (payload) => { onDelete?.(payload.old as SubmissionRecord); } ) .subscribe(); channelRef.current = channel; return () => { channel.unsubscribe(); }; }, [onInsert, onUpdate, onDelete, submissionType]); useEffect(() => { const cleanup = subscribe(); return cleanup; }, [subscribe]); return { /** Manually resubscribe */ resubscribe: subscribe, }; }