92 lines
2.6 KiB
TypeScript
Executable File
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}</>;
|
|
}
|