import { useEffect, useState, useCallback } from "react"; import { supabase } from "@/integrations/supabase/client"; import { useAuth } from "@/lib/auth"; interface Counts { messages: number; tasks: number; notifications: number; } export function useBubbleCounts(): Counts { const { user } = useAuth(); const [counts, setCounts] = useState({ messages: 0, tasks: 0, notifications: 0 }); const load = useCallback(async () => { if (!user) { setCounts({ messages: 0, tasks: 0, notifications: 0 }); return; } const [memberRes, msgRes, taskRes, notifRes] = await Promise.all([ supabase.from("conversation_members").select("conversation_id, last_read_at").eq("user_id", user.id), // unread messages: query per-convo handled below Promise.resolve(null), supabase .from("task_assignees") .select("task_id, tasks!inner(status, due_date)") .eq("user_id", user.id) .eq("tasks.status", "incomplete"), supabase .from("notifications") .select("id", { count: "exact", head: true }) .eq("user_id", user.id) .is("read_at", null), ]); let unreadMessages = 0; const memberRows = memberRes.data ?? []; if (memberRows.length) { // For each conversation, count messages newer than last_read_at and not from self const results = await Promise.all( memberRows.map(async (m) => { const { count } = await supabase .from("messages") .select("id", { count: "exact", head: true }) .eq("conversation_id", m.conversation_id) .gt("created_at", m.last_read_at) .neq("sender_id", user.id); return count ?? 0; }), ); unreadMessages = results.reduce((a, b) => a + b, 0); } const taskCount = (taskRes.data ?? []).length; setCounts({ messages: unreadMessages, tasks: taskCount, notifications: notifRes.count ?? 0, }); }, [user]); useEffect(() => { if (!user) return; load(); const ch = supabase .channel(`bubbles-${user.id}-${Math.random().toString(36).slice(2)}`) .on("postgres_changes", { event: "*", schema: "public", table: "messages" }, () => load()) .on("postgres_changes", { event: "*", schema: "public", table: "task_assignees" }, () => load()) .on("postgres_changes", { event: "*", schema: "public", table: "tasks" }, () => load()) .on("postgres_changes", { event: "*", schema: "public", table: "notifications", filter: `user_id=eq.${user.id}` }, () => load()) .on("postgres_changes", { event: "*", schema: "public", table: "conversation_members", filter: `user_id=eq.${user.id}` }, () => load()) .subscribe(); return () => { supabase.removeChannel(ch); }; }, [user, load]); return counts; }