mirror of
https://github.com/Luchexx/wacrm.git
synced 2026-11-02 09:19:51 +00:00
fix(dashboard): open the clicked conversation when deep-linking from dashboard
Clicking a row in the dashboard's "Recent Conversations" routed to /inbox with no hint about which conversation to open, so the user landed on the empty center panel and had to find the thread again. - Dashboard now routes to /inbox?c=<conversation_id> for per-row clicks. "View all" still goes to plain /inbox. - Inbox page reads ?c=<id> and auto-selects the matching conversation in handleConversationsLoaded (event handler, not an effect, so react-hooks/set-state-in-effect stays happy). A ref guards against resnapping the selection on later realtime list refreshes. - Inbox also now replaces the URL with ?c=<id> when the user picks a conversation, so a page refresh / shared link lands on the same thread. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a5f2a40b37
commit
03c53905c1
@ -261,7 +261,7 @@ export default function DashboardPage() {
|
||||
recentConversations.map((conv) => (
|
||||
<button
|
||||
key={conv.id}
|
||||
onClick={() => router.push("/inbox")}
|
||||
onClick={() => router.push(`/inbox?c=${conv.id}`)}
|
||||
className="flex w-full items-center gap-3 px-5 py-3 text-left transition-colors hover:bg-slate-800/50"
|
||||
>
|
||||
<div className="flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-emerald-500/10 text-sm font-medium text-emerald-500">
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useCallback, useEffect } from "react";
|
||||
import { useState, useCallback, useEffect, useRef } from "react";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { createClient } from "@/lib/supabase/client";
|
||||
import type { Conversation, Message, Contact, ConversationStatus } from "@/types";
|
||||
import { useRealtime } from "@/hooks/use-realtime";
|
||||
@ -11,6 +12,15 @@ import { toast } from "sonner";
|
||||
import { WifiOff } from "lucide-react";
|
||||
|
||||
export default function InboxPage() {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
/**
|
||||
* `?c=<id>` deep-link support. Used when landing here from the
|
||||
* dashboard's recent-conversations list so the right thread opens
|
||||
* automatically instead of showing the empty center panel.
|
||||
*/
|
||||
const deepLinkConvId = searchParams.get("c");
|
||||
|
||||
const [conversations, setConversations] = useState<Conversation[]>([]);
|
||||
const [activeConversation, setActiveConversation] =
|
||||
useState<Conversation | null>(null);
|
||||
@ -20,6 +30,12 @@ export default function InboxPage() {
|
||||
null
|
||||
);
|
||||
|
||||
// Fire the deep-link auto-select exactly once per URL — subsequent
|
||||
// list refreshes (realtime, manual refetch) must not snap the user
|
||||
// back to the deep-linked conversation if they've already clicked
|
||||
// elsewhere.
|
||||
const autoSelectedForDeepLinkRef = useRef<string | null>(null);
|
||||
|
||||
// Check WhatsApp connection status on mount
|
||||
useEffect(() => {
|
||||
const checkConnection = async () => {
|
||||
@ -135,8 +151,26 @@ export default function InboxPage() {
|
||||
const handleConversationsLoaded = useCallback(
|
||||
(loaded: Conversation[]) => {
|
||||
setConversations(loaded);
|
||||
// Resolve a pending deep-link here rather than in an effect — this
|
||||
// is an event handler, so the setState calls below are allowed by
|
||||
// react-hooks/set-state-in-effect. Runs once per ?c=<id> URL value
|
||||
// via the ref, so realtime refreshes of the list can't snap the
|
||||
// user back to the deep-linked thread after they've navigated.
|
||||
if (
|
||||
deepLinkConvId &&
|
||||
autoSelectedForDeepLinkRef.current !== deepLinkConvId &&
|
||||
loaded.length > 0
|
||||
) {
|
||||
autoSelectedForDeepLinkRef.current = deepLinkConvId;
|
||||
const match = loaded.find((c) => c.id === deepLinkConvId);
|
||||
if (match) {
|
||||
setActiveConversation(match);
|
||||
setActiveContact(match.contact ?? null);
|
||||
setMessages([]);
|
||||
}
|
||||
}
|
||||
},
|
||||
[]
|
||||
[deepLinkConvId]
|
||||
);
|
||||
|
||||
const handleSelectConversation = useCallback(
|
||||
@ -149,10 +183,15 @@ export default function InboxPage() {
|
||||
setActiveConversation(conv);
|
||||
setActiveContact(conv.contact ?? null);
|
||||
setMessages([]);
|
||||
// Reflect the selection in the URL so a refresh lands the user
|
||||
// back in the same thread, and so copy-paste links work. Use
|
||||
// replace() to avoid polluting browser history with every click.
|
||||
router.replace(`/inbox?c=${conv.id}`, { scroll: false });
|
||||
},
|
||||
[activeConversation?.id]
|
||||
[activeConversation?.id, router]
|
||||
);
|
||||
|
||||
|
||||
const handleMessagesLoaded = useCallback((loaded: Message[]) => {
|
||||
setMessages(loaded);
|
||||
}, []);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user