import { useEffect, useRef, useState, useCallback } from 'react'; import { supabase } from '@/integrations/supabase/client'; import { RealtimeChannel } from '@supabase/supabase-js'; import { useUserRole } from './useUserRole'; type ConnectionState = 'connecting' | 'connected' | 'disconnected' | 'error'; interface UseRealtimeSubmissionsOptions { onInsert?: (payload: any) => void; onUpdate?: (payload: any) => void; onDelete?: (payload: any) => void; enabled?: boolean; } export const useRealtimeSubmissions = (options: UseRealtimeSubmissionsOptions = {}) => { const { onInsert, onUpdate, onDelete, enabled = true } = options; const { isModerator, loading: roleLoading } = useUserRole(); const [channel, setChannel] = useState(null); const [connectionState, setConnectionState] = useState('disconnected'); // Only enable realtime when user is confirmed as moderator const realtimeEnabled = enabled && !roleLoading && isModerator(); // Use refs to store latest callbacks without triggering re-subscriptions const onInsertRef = useRef(onInsert); const onUpdateRef = useRef(onUpdate); const onDeleteRef = useRef(onDelete); // Update refs when callbacks change useEffect(() => { onInsertRef.current = onInsert; onUpdateRef.current = onUpdate; onDeleteRef.current = onDelete; }, [onInsert, onUpdate, onDelete]); const reconnect = useCallback(() => { if (channel) { supabase.removeChannel(channel); } setConnectionState('connecting'); }, [channel]); useEffect(() => { if (!realtimeEnabled) { console.log('[Realtime:content-submissions] Realtime disabled'); return; } console.log('[Realtime:content-submissions] Creating new broadcast channel'); setConnectionState('connecting'); const setupChannel = async () => { // Set auth token for private channel await supabase.realtime.setAuth(); const newChannel = supabase .channel('moderation:content_submissions', { config: { private: true }, }) .on('broadcast', { event: 'INSERT' }, (payload) => { console.log('Submission inserted:', payload); onInsertRef.current?.(payload); }) .on('broadcast', { event: 'UPDATE' }, (payload) => { console.log('Submission updated:', payload); onUpdateRef.current?.(payload); }) .on('broadcast', { event: 'DELETE' }, (payload) => { console.log('Submission deleted:', payload); onDeleteRef.current?.(payload); }) .subscribe((status) => { console.log('[Realtime:content-submissions] Subscription status:', status); if (status === 'SUBSCRIBED') { setConnectionState('connected'); } else if (status === 'CHANNEL_ERROR') { setConnectionState('error'); } else if (status === 'TIMED_OUT') { setConnectionState('disconnected'); } else if (status === 'CLOSED') { setConnectionState('disconnected'); } }); setChannel(newChannel); }; setupChannel(); return () => { if (channel) { console.log('[Realtime:content-submissions] Cleaning up channel'); supabase.removeChannel(channel); } }; }, [realtimeEnabled]); return { channel, connectionState, reconnect }; };