From 3ff7df6f883243ef52badfe7c574e11a83fe7576 Mon Sep 17 00:00:00 2001 From: Harkamal Randhawa Date: Wed, 15 Apr 2026 22:46:49 -0600 Subject: [PATCH] fix chat escalation and sidebar --- web/app/ai-chat/page.js | 166 ++++++++++++++++++++++++++++++++++------ web/app/chat/page.js | 65 +++++++++++++--- 2 files changed, 195 insertions(+), 36 deletions(-) diff --git a/web/app/ai-chat/page.js b/web/app/ai-chat/page.js index ce8895b8..c059e3f4 100644 --- a/web/app/ai-chat/page.js +++ b/web/app/ai-chat/page.js @@ -82,6 +82,7 @@ function AiChatPage() { const [error, setError] = useState(null); const [conversations, setConversations] = useState([]); const [convsLoading, setConvsLoading] = useState(false); + const [closedExpanded, setClosedExpanded] = useState(false); const [selectedFile, setSelectedFile] = useState(null); const messagesEndRef = useRef(null); @@ -418,12 +419,28 @@ function AiChatPage() { method: "POST", headers: { Authorization: `Bearer ${token}` }, }); - router.push(`/chat?id=${conversation.id}`); + setConversation((prev) => prev ? { ...prev, mode: "HUMAN" } : prev); } catch { setError("Could not connect to live support. Please try again."); } } + async function handleCloseConversation() { + if (!conversation || conversation.status === "CLOSED") return; + try { + const res = await fetch(`${API_BASE}/api/v1/chat/conversations/${conversation.id}`, { + method: "PUT", + headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` }, + body: JSON.stringify({ status: "CLOSED" }), + }); + if (!res.ok) return; + const updated = await res.json(); + setConversation(updated); + await fetchConversations(); + } catch { + } + } + if (authLoading || loadingConv) { return (
@@ -436,6 +453,8 @@ function AiChatPage() { const isEscalated = conversation?.mode === "HUMAN"; const isClosed = conversation?.status === "CLOSED"; + const hasStaff = !!conversation?.staffId; + const hasStaffMessage = messages.some((m) => m.senderId !== user?.id); return (
@@ -456,7 +475,7 @@ function AiChatPage() {

No conversations yet.

)}
- {conversations.map((conv) => ( + {conversations.filter(c => c.status !== "CLOSED").map((conv) => ( ))} + {conversations.some(c => c.status === "CLOSED") && ( + <> + + {closedExpanded && conversations.filter(c => c.status === "CLOSED").map((conv) => ( + + ))} + + )}
)} - + {isEscalated && !isClosed && ( + + )} + {isEscalated && !hasStaff && !hasStaffMessage && !isClosed && ( +
+ + A support agent will be with you shortly. You can send messages while you wait. +
+ )} +
{messages.length === 0 && (
-
🐾
+
{isEscalated ? "💬" : "🐾"}

- Hello{user.fullName ? `, ${user.fullName.split(" ")[0]}` : ""}! I'm your pet care assistant. - Ask me about pet recommendations, care tips, supplies, or anything pet-related! + {isEscalated ? "Your conversation has started. A support agent will join soon." : `Hello${user.fullName ? `, ${user.fullName.split(" ")[0]}` : ""}! I'm your pet care assistant. Ask me about pet recommendations, care tips, supplies, or anything pet-related!`}

)} @@ -547,7 +594,7 @@ function AiChatPage() { ...(isOwn ? s.messageRowUser : s.messageRowAgent), }} > - {!isOwn &&
🐾
} + {!isOwn &&
{isEscalated ? "👤" : "🐾"}
}
No conversations yet.

)}
- {conversations.map((conv) => ( + {conversations.filter(c => c.status !== "CLOSED").map((conv) => ( ))} + {conversations.some(c => c.status === "CLOSED") && ( + <> + + {closedExpanded && conversations.filter(c => c.status === "CLOSED").map((conv) => ( + + ))} + + )}
)} - + {!isHuman && ( + + )}
@@ -1145,6 +1173,21 @@ const s = { }, convStatusOpen: { background: "#e6f9ee", color: "#1a7a3c" }, convStatusClosed: { background: "#f0f0f0", color: "#888" }, + convItemClosed: { opacity: 0.7 }, + closedSectionToggle: { + width: "100%", + background: "#f5f5f5", + border: "none", + borderTop: "1px solid #e8e8e8", + padding: "0.5rem 1rem", + fontSize: "0.78rem", + fontWeight: 600, + color: "#666", + cursor: "pointer", + display: "flex", + justifyContent: "space-between", + alignItems: "center", + }, newConvSidebarBtn: { margin: "0.65rem 1rem", background: "#333",