Files
cirux/src/components/providers/index.tsx
T

92 lines
2.6 KiB
TypeScript
Executable File

"use client";
import { useEffect, useMemo } from "react";
import { createClient } from "@/utils/supabase/client";
import { useAuthStore } from "@/lib/stores/authStore";
import { useNotificationStore } from "@/lib/stores/notificationStore";
import type { Conversation } from "@/lib/types";
/**
* Proveedor global React que:
* 1. Sincroniza la sesión de Supabase Auth con authStore.
* 2. Suscribe a Supabase Realtime en conversations.
*/
export function Providers({ children }: { children: React.ReactNode }) {
const { setUser, setSession, setLoading } = useAuthStore();
const { setPendingConversations, addPendingConversation } = useNotificationStore();
const supabase = useMemo(() => createClient(), []);
useEffect(() => {
// Sincronizar sesión inicial
const init = async () => {
setLoading(true);
const { data } = await supabase.auth.getSession();
setSession(data.session);
setUser(data.session?.user ?? null);
setLoading(false);
};
void init();
// Listener para cambios de auth
const { data: { subscription } } = supabase.auth.onAuthStateChange(
(_event, session) => {
setSession(session);
setUser(session?.user ?? null);
}
);
return () => subscription.unsubscribe();
}, [setSession, setUser, setLoading, supabase]);
useEffect(() => {
// Cargar conversaciones pendientes iniciales
const loadPending = async () => {
const { data } = await supabase
.from("conversations")
.select("*, patient:patients(id, name, phone)")
.eq("status", "pending_human")
.order("last_message_at", { ascending: false });
if (data) setPendingConversations(data as Conversation[]);
};
void loadPending();
// Suscripción Realtime a conversaciones (INSERT y UPDATE)
const channel = supabase
.channel("conversations-realtime")
.on(
"postgres_changes",
{
event: "INSERT",
schema: "public",
table: "conversations",
filter: "status=eq.pending_human",
},
(payload) => {
addPendingConversation(payload.new as Conversation);
}
)
.on(
"postgres_changes",
{
event: "UPDATE",
schema: "public",
table: "conversations",
filter: "status=eq.pending_human",
},
(payload) => {
addPendingConversation(payload.new as Conversation);
}
)
.subscribe();
return () => {
void supabase.removeChannel(channel);
};
}, [setPendingConversations, addPendingConversation, supabase]);
return <>{children}</>;
}