chat UI updates #303
@@ -22,7 +22,6 @@ function ChatPage() {
|
||||
const [error, setError] = useState(null);
|
||||
const [conversations, setConversations] = useState([]);
|
||||
const [convsLoading, setConvsLoading] = useState(false);
|
||||
const [showSidebar, setShowSidebar] = useState(false);
|
||||
const [selectedFile, setSelectedFile] = useState(null);
|
||||
|
||||
const messagesEndRef = useRef(null);
|
||||
@@ -172,13 +171,17 @@ function ChatPage() {
|
||||
}
|
||||
|
||||
if (!convId) {
|
||||
await fetchConversations();
|
||||
setLoadingConv(false);
|
||||
setConversation(null);
|
||||
return;
|
||||
}
|
||||
|
||||
await fetchConversation(convId);
|
||||
await fetchMessages(convId);
|
||||
await Promise.all([
|
||||
fetchConversation(convId),
|
||||
fetchMessages(convId),
|
||||
fetchConversations(),
|
||||
]);
|
||||
setLoadingConv(false);
|
||||
startPolling(convId);
|
||||
}
|
||||
@@ -188,11 +191,7 @@ function ChatPage() {
|
||||
return () => {
|
||||
if (pollRef.current) clearInterval(pollRef.current);
|
||||
};
|
||||
}, [token, authLoading, conversationIdParam, fetchConversation, fetchMessages, startPolling]);
|
||||
|
||||
useEffect(() => {
|
||||
if (showSidebar && token) fetchConversations();
|
||||
}, [showSidebar, token, fetchConversations]);
|
||||
}, [token, authLoading, conversationIdParam, fetchConversation, fetchMessages, startPolling, fetchConversations]);
|
||||
|
||||
async function handleSend(e) {
|
||||
e?.preventDefault();
|
||||
@@ -334,7 +333,7 @@ function ChatPage() {
|
||||
});
|
||||
|
||||
setConversation(conv);
|
||||
await fetchMessages(conv.id);
|
||||
await Promise.all([fetchMessages(conv.id), fetchConversations()]);
|
||||
setLoadingConv(false);
|
||||
startPolling(conv.id);
|
||||
router.replace(`/chat?id=${conv.id}`, { scroll: false });
|
||||
@@ -354,7 +353,26 @@ function ChatPage() {
|
||||
setLoadingConv(false);
|
||||
startPolling(convId);
|
||||
router.replace(`/chat?id=${convId}`, { scroll: false });
|
||||
setShowSidebar(false);
|
||||
}
|
||||
|
||||
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 {
|
||||
// silent
|
||||
}
|
||||
}
|
||||
|
||||
if (authLoading || loadingConv) {
|
||||
@@ -392,11 +410,9 @@ function ChatPage() {
|
||||
|
||||
<section style={s.chatSection}>
|
||||
<div style={{ display: "flex", gap: "1rem", alignItems: "flex-start" }}>
|
||||
{showSidebar && (
|
||||
<div style={s.sidebar}>
|
||||
<div style={s.sidebarHeader}>
|
||||
<span style={s.sidebarTitle}>All Conversations</span>
|
||||
<button style={s.sidebarClose} onClick={() => setShowSidebar(false)}>✕</button>
|
||||
</div>
|
||||
{convsLoading && <p style={s.sidebarEmpty}>Loading...</p>}
|
||||
{!convsLoading && conversations.length === 0 && (
|
||||
@@ -422,12 +438,11 @@ function ChatPage() {
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<button style={s.newConvSidebarBtn} onClick={() => { setShowSidebar(false); handleNewConversation(); }}>
|
||||
<button style={s.newConvSidebarBtn} onClick={() => handleNewConversation()}>
|
||||
+ New Conversation
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<div style={{ flex: 1, minWidth: 0 }}>
|
||||
<div style={{ flex: 1, minWidth: 0 }}>
|
||||
{!conversation ? (
|
||||
<div style={s.noConvCard}>
|
||||
<div style={s.noConvIcon}>💬</div>
|
||||
@@ -437,9 +452,6 @@ function ChatPage() {
|
||||
<button style={s.startBtn} onClick={handleNewConversation}>
|
||||
Start a Conversation
|
||||
</button>
|
||||
<button style={s.backBtn} onClick={() => setShowSidebar(true)}>
|
||||
View Past Conversations
|
||||
</button>
|
||||
<button style={s.backBtn} onClick={() => router.push("/ai-chat")}>
|
||||
Back to AI Assistant
|
||||
</button>
|
||||
@@ -460,12 +472,15 @@ function ChatPage() {
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ display: "flex", gap: "0.5rem" }}>
|
||||
<button
|
||||
style={{ ...s.historyBtn, ...(showSidebar ? s.historyBtnActive : {}) }}
|
||||
onClick={() => setShowSidebar((v) => !v)}
|
||||
>
|
||||
History
|
||||
</button>
|
||||
{!isClosed && (
|
||||
<button
|
||||
style={s.closeConvBtn}
|
||||
onClick={handleCloseConversation}
|
||||
title="Close this conversation"
|
||||
>
|
||||
Close Chat
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
style={s.aiBtn}
|
||||
onClick={() => router.push("/ai-chat")}
|
||||
@@ -992,10 +1007,10 @@ const s = {
|
||||
padding: "0 0.15rem",
|
||||
flexShrink: 0,
|
||||
},
|
||||
historyBtn: {
|
||||
closeConvBtn: {
|
||||
background: "white",
|
||||
border: "2px solid #555",
|
||||
color: "#555",
|
||||
border: "2px solid #c0392b",
|
||||
color: "#c0392b",
|
||||
borderRadius: 8,
|
||||
padding: "0.45rem 0.9rem",
|
||||
fontSize: "0.82rem",
|
||||
@@ -1003,10 +1018,6 @@ const s = {
|
||||
cursor: "pointer",
|
||||
whiteSpace: "nowrap",
|
||||
},
|
||||
historyBtnActive: {
|
||||
background: "#555",
|
||||
color: "white",
|
||||
},
|
||||
sidebar: {
|
||||
width: 230,
|
||||
flexShrink: 0,
|
||||
@@ -1028,14 +1039,6 @@ const s = {
|
||||
flexShrink: 0,
|
||||
},
|
||||
sidebarTitle: { fontWeight: 700, fontSize: "0.88rem", color: "#333" },
|
||||
sidebarClose: {
|
||||
background: "none",
|
||||
border: "none",
|
||||
cursor: "pointer",
|
||||
fontSize: "0.85rem",
|
||||
color: "#999",
|
||||
padding: "0.1rem 0.25rem",
|
||||
},
|
||||
sidebarEmpty: {
|
||||
color: "#aaa",
|
||||
fontSize: "0.82rem",
|
||||
|
||||
Reference in New Issue
Block a user