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