Files
padhle/frontend/src/components/chat-history/ChatHistory.jsx
T

258 lines
15 KiB
React
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ========================================
ChatHistory Component — padhle (Refined Workspace)
======================================== */
import { useEffect, useRef } from "react";
import Message from "../message/Message";
import SelectorFlow from "../selector-flow/SelectorFlow";
import "./ChatHistory.css";
const ChatHistory = ({
messages,
activeSubject,
activeGrade,
activeChapter,
onPromptClick,
isTyping,
selectorStep,
selectorData,
}) => {
const hasMessages = messages.length > 0;
const isSelector = selectorStep !== "chat";
const suggestions = [
{
id: 1,
icon: "eco",
iconFilled: true,
color: "--color-accent-green",
colorBg: "--color-accent-green-bg",
keywords: ["photosynthesis"],
text: "Explain how ",
textEnd: " works in simple terms",
},
{
id: 2,
icon: "calculate",
iconFilled: false,
color: "--color-accent-blue",
colorBg: "--color-accent-blue-bg",
keywords: ["derivatives"],
text: "Help me understand ",
textEnd: " in calculus",
},
{
id: 3,
icon: "account_balance",
iconFilled: false,
color: "--color-accent-orange",
colorBg: "--color-accent-orange-bg",
keywords: ["Industrial"],
text: "What caused the ",
textEnd: " Revolution?",
},
{
id: 4,
icon: "edit",
iconFilled: true,
color: "--color-accent-purple",
colorBg: "--color-accent-purple-bg",
keywords: ["Romeo and Juliet"],
text: "Help me analyze themes in ",
textEnd: "",
},
];
const fullPromptTexts = suggestions.map(
(s) => s.text + s.keywords.join(" ") + s.textEnd,
);
const streamingMsg = messages.find((m) => m.streaming);
const historyRef = useRef(null);
// Scroll only the chat pane, and only when a message is added. Streaming
// token updates must not move the page or restart a smooth-scroll animation.
useEffect(() => {
const history = historyRef.current;
if (history) history.scrollTop = history.scrollHeight;
}, [messages.length]);
/* ─── Messages mode ─── */
if (hasMessages) {
return (
<div className="chat-history" ref={historyRef}>
<div className="chat-history__list">
{messages.map((message) => (
<Message
key={message.id}
message={message}
/>
))}
{isTyping && !streamingMsg && (
<Message
message={{
id: "typing",
role: "assistant",
text: "",
streaming: true,
}}
/>
)}
</div>
</div>
);
}
/* ─── Selector mode (grade → subject → chapter) ─── */
if (isSelector && selectorData) {
return (
<div className="chat-history">
<SelectorFlow
title={selectorData.title}
subtitle={selectorData.subtitle}
selected={selectorData.selected}
items={selectorData.items}
onSelect={selectorData.onSelect}
step={selectorStep}
/>
</div>
);
}
/* ─── Welcome / suggestions mode ─── */
return (
<div className="chat-history">
<div className="chat-history__focus">
{/* Welcome Header */}
<div className="chat-history__welcome">
<div className="chat-history__welcome-icon">
<span
className="material-symbols-outlined"
style={{
fontWeight: 200,
}}
>
menu_book
</span>
<span className="material-symbols-outlined chat-history__welcome-sparkle">
auto_awesome
</span>
</div>
<h2 className="chat-history__welcome-title">
Welcome to padhle
</h2>
<p className="chat-history__welcome-subtitle">
Your AI tutor for grades 6–12.
Ask anything!
</p>
</div>
{/* Bento Grid Suggestions */}
<div className="chat-history__bento">
{suggestions.map((suggestion) => {
const colorVar =
suggestion.color.replace(
"--",
"var(",
);
const bgColorVar =
suggestion.colorBg.replace(
"--",
"var(",
);
return (
<button
key={
suggestion.id
}
className="chat-history__bento-card"
onClick={() => {
const text =
fullPromptTexts[
suggestion.id -
1
];
onPromptClick(
text,
);
}}
>
<div
className="chat-history__bento-icon-wrap"
style={{
backgroundColor: `var(${bgColorVar})`,
}}
>
<span
className="material-symbols-outlined"
style={{
color: `var(${colorVar})`,
fontWeight: suggestion.iconFilled
? 700
: 200,
}}
>
{
suggestion.icon
}
</span>
</div>
<div className="chat-history__bento-text">
<span className="chat-history__bento-text-main">
{
suggestion.text
}
</span>
<span
className="chat-history__bento-text-highlight"
style={{
color: `var(${colorVar})`,
fontWeight: 600,
}}
>
{
suggestion
.keywords[0]
}
</span>
{
suggestion.textEnd
}
</div>
<span className="material-symbols-outlined chat-history__bento-arrow">
arrow_forward
</span>
</button>
);
})}
</div>
{/* Info Panel */}
<div className="chat-history__info">
<div className="chat-history__info-icon-wrap">
<span className="material-symbols-outlined">
lightbulb
</span>
</div>
<div className="chat-history__info-content">
<h4 className="chat-history__info-title">
Focused on your learning
</h4>
<p className="chat-history__info-text">
I'll answer questions
related to your selected
subject and chapter
<br />
using your textbook
content.
</p>
</div>
</div>
</div>
</div>
);
};
export default ChatHistory;