mirror of
https://github.com/Luchexx/wacrm.git
synced 2026-11-02 09:19:51 +00:00
Merge pull request #11 from ArnasDon/fix/inbox-refresh-loop-and-banner
fix: inbox refresh loop, wrong connection status, overlapping banner
This commit is contained in:
commit
2446056842
@ -8,7 +8,7 @@ import { ConversationList } from "@/components/inbox/conversation-list";
|
||||
import { MessageThread } from "@/components/inbox/message-thread";
|
||||
import { ContactSidebar } from "@/components/inbox/contact-sidebar";
|
||||
import { toast } from "sonner";
|
||||
import { Wifi, WifiOff } from "lucide-react";
|
||||
import { WifiOff } from "lucide-react";
|
||||
|
||||
export default function InboxPage() {
|
||||
const [conversations, setConversations] = useState<Conversation[]>([]);
|
||||
@ -31,11 +31,13 @@ export default function InboxPage() {
|
||||
|
||||
if (!user) return;
|
||||
|
||||
// Table is `whatsapp_config` (singular) — the previous "whatsapp_configs"
|
||||
// query always returned no rows, so the banner always showed "not connected".
|
||||
const { data } = await supabase
|
||||
.from("whatsapp_configs")
|
||||
.from("whatsapp_config")
|
||||
.select("status")
|
||||
.eq("user_id", user.id)
|
||||
.single();
|
||||
.maybeSingle();
|
||||
|
||||
setWhatsappConnected(data?.status === "connected");
|
||||
};
|
||||
@ -167,10 +169,11 @@ export default function InboxPage() {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="-m-6 flex h-[calc(100vh-3.5rem)] overflow-hidden">
|
||||
{/* WhatsApp connection banner */}
|
||||
<div className="-m-6 flex h-[calc(100vh-3.5rem)] flex-col overflow-hidden">
|
||||
{/* WhatsApp connection banner — in the flex column, not absolute,
|
||||
so it pushes the panels down instead of overlapping them. */}
|
||||
{whatsappConnected === false && (
|
||||
<div className="absolute left-60 right-0 top-14 z-10 flex items-center justify-center gap-2 bg-amber-500/10 px-4 py-2">
|
||||
<div className="flex shrink-0 items-center justify-center gap-2 border-b border-amber-500/20 bg-amber-500/10 px-4 py-2">
|
||||
<WifiOff className="h-4 w-4 text-amber-400" />
|
||||
<p className="text-xs text-amber-400">
|
||||
WhatsApp is not connected. Go to Settings to connect your account.
|
||||
@ -178,6 +181,7 @@ export default function InboxPage() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-1 overflow-hidden">
|
||||
{/* Left panel: Conversation list */}
|
||||
<ConversationList
|
||||
activeConversationId={activeConversation?.id ?? null}
|
||||
@ -201,5 +205,6 @@ export default function InboxPage() {
|
||||
<ContactSidebar contact={activeContact} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -101,36 +101,61 @@ export function MessageThread({
|
||||
return { expired, remaining };
|
||||
}, [messages]);
|
||||
|
||||
const fetchMessages = useCallback(async () => {
|
||||
if (!conversation) return;
|
||||
setLoading(true);
|
||||
// Store latest callback in a ref so fetchMessages doesn't need to
|
||||
// depend on `onMessagesLoaded` — otherwise parent re-renders cause
|
||||
// fetchMessages to change → useEffect re-fires → refetch → realtime
|
||||
// UPDATE on conversations.unread_count → parent re-renders → LOOP.
|
||||
const onMessagesLoadedRef = useRef(onMessagesLoaded);
|
||||
onMessagesLoadedRef.current = onMessagesLoaded;
|
||||
|
||||
const conversationId = conversation?.id;
|
||||
const hasUnread = (conversation?.unread_count ?? 0) > 0;
|
||||
|
||||
useEffect(() => {
|
||||
if (!conversationId) return;
|
||||
|
||||
const supabase = createClient();
|
||||
let cancelled = false;
|
||||
|
||||
(async () => {
|
||||
setLoading(true);
|
||||
|
||||
const { data, error } = await supabase
|
||||
.from("messages")
|
||||
.select("*")
|
||||
.eq("conversation_id", conversation.id)
|
||||
.eq("conversation_id", conversationId)
|
||||
.order("created_at", { ascending: true });
|
||||
|
||||
if (cancelled) return;
|
||||
|
||||
if (error) {
|
||||
console.error("Failed to fetch messages:", error);
|
||||
} else {
|
||||
onMessagesLoaded(data ?? []);
|
||||
onMessagesLoadedRef.current(data ?? []);
|
||||
}
|
||||
|
||||
// Reset unread count
|
||||
// Only issue the unread_count reset when there's actually something
|
||||
// to reset. Unconditional updates fire a realtime UPDATE event every
|
||||
// time, which — combined with the parent's conversation-event handler
|
||||
// — used to retrigger this effect in a loop.
|
||||
if (hasUnread) {
|
||||
await supabase
|
||||
.from("conversations")
|
||||
.update({ unread_count: 0 })
|
||||
.eq("id", conversation.id);
|
||||
.eq("id", conversationId);
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
}, [conversation, onMessagesLoaded]);
|
||||
if (!cancelled) setLoading(false);
|
||||
})();
|
||||
|
||||
useEffect(() => {
|
||||
fetchMessages();
|
||||
}, [fetchMessages]);
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
// Re-fetch only when the selected conversation changes. `hasUnread`
|
||||
// is used inside but is a boolean derived from conversation; the
|
||||
// conversationId dep is the real trigger.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [conversationId]);
|
||||
|
||||
// Auto-scroll to bottom on new messages
|
||||
useEffect(() => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user