aki-008
commited on
Commit
·
4a0902b
1
Parent(s):
feafade
chore: notes ui update
Browse files- Frontend/src/pages/note.tsx +83 -59
Frontend/src/pages/note.tsx
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
| 13 |
Trash2,
|
| 14 |
Edit2,
|
| 15 |
Check,
|
|
|
|
| 16 |
} from "lucide-react";
|
| 17 |
import {
|
| 18 |
fetchNotes,
|
|
@@ -61,10 +62,8 @@ const Notes: React.FC = () => {
|
|
| 61 |
loadNotes();
|
| 62 |
}, []);
|
| 63 |
|
| 64 |
-
// ---
|
| 65 |
const scrollToBottom = () => {
|
| 66 |
-
// "smooth" gets interrupted by rapid streaming updates.
|
| 67 |
-
// "instant" ensures it snaps to bottom every time a token arrives.
|
| 68 |
messagesEndRef.current?.scrollIntoView({
|
| 69 |
behavior: "instant",
|
| 70 |
block: "end",
|
|
@@ -78,6 +77,7 @@ const Notes: React.FC = () => {
|
|
| 78 |
// --- Resizing Logic ---
|
| 79 |
const startResizing = useCallback(() => setIsResizing(true), []);
|
| 80 |
const stopResizing = useCallback(() => setIsResizing(false), []);
|
|
|
|
| 81 |
const resize = useCallback(
|
| 82 |
(mouseMoveEvent: MouseEvent) => {
|
| 83 |
if (isResizing) {
|
|
@@ -158,6 +158,7 @@ const Notes: React.FC = () => {
|
|
| 158 |
const saveRename = async (e: React.MouseEvent) => {
|
| 159 |
e.stopPropagation();
|
| 160 |
if (!editingNoteId || !editName.trim()) return;
|
|
|
|
| 161 |
try {
|
| 162 |
await renameNote(editingNoteId, editName);
|
| 163 |
setNotes((prev) =>
|
|
@@ -259,18 +260,23 @@ const Notes: React.FC = () => {
|
|
| 259 |
};
|
| 260 |
|
| 261 |
return (
|
| 262 |
-
|
| 263 |
-
|
|
|
|
| 264 |
<div
|
| 265 |
-
className={`h-screen shrink-0 transition-all duration-300 bg-
|
| 266 |
-
isSidebarOpen ? "w-
|
| 267 |
}`}
|
| 268 |
>
|
| 269 |
{isSidebarOpen && (
|
| 270 |
<>
|
| 271 |
-
<
|
| 272 |
-
|
| 273 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 274 |
<input
|
| 275 |
type="file"
|
| 276 |
ref={fileInputRef}
|
|
@@ -278,10 +284,12 @@ const Notes: React.FC = () => {
|
|
| 278 |
accept="application/pdf"
|
| 279 |
onChange={handleFileChange}
|
| 280 |
/>
|
|
|
|
|
|
|
| 281 |
<button
|
| 282 |
onClick={handleUploadClick}
|
| 283 |
disabled={isUploading}
|
| 284 |
-
className="flex items-center gap-
|
| 285 |
>
|
| 286 |
{isUploading ? (
|
| 287 |
<Loader2 className="animate-spin" size={20} />
|
|
@@ -291,8 +299,8 @@ const Notes: React.FC = () => {
|
|
| 291 |
{isUploading ? "Uploading..." : "Upload New PDF"}
|
| 292 |
</button>
|
| 293 |
|
| 294 |
-
<div className="mt-
|
| 295 |
-
<p className="text-
|
| 296 |
History
|
| 297 |
</p>
|
| 298 |
|
|
@@ -300,10 +308,10 @@ const Notes: React.FC = () => {
|
|
| 300 |
<div
|
| 301 |
key={note.id}
|
| 302 |
onClick={() => handleNoteSelect(note)}
|
| 303 |
-
className={`group relative
|
| 304 |
currentNote?.id === note.id
|
| 305 |
-
? "bg-
|
| 306 |
-
: ""
|
| 307 |
}`}
|
| 308 |
>
|
| 309 |
{editingNoteId === note.id ? (
|
|
@@ -313,44 +321,54 @@ const Notes: React.FC = () => {
|
|
| 313 |
value={editName}
|
| 314 |
onChange={(e) => setEditName(e.target.value)}
|
| 315 |
onClick={(e) => e.stopPropagation()}
|
| 316 |
-
className="flex-1 bg-
|
| 317 |
autoFocus
|
| 318 |
/>
|
| 319 |
<button
|
| 320 |
onClick={saveRename}
|
| 321 |
-
className="text-green-
|
| 322 |
>
|
| 323 |
<Check size={14} />
|
| 324 |
</button>
|
| 325 |
<button
|
| 326 |
onClick={cancelRename}
|
| 327 |
-
className="text-red-
|
| 328 |
>
|
| 329 |
<X size={14} />
|
| 330 |
</button>
|
| 331 |
</div>
|
| 332 |
) : (
|
| 333 |
<>
|
| 334 |
-
<div className="flex items-center gap-
|
| 335 |
<FileText
|
| 336 |
size={16}
|
| 337 |
-
className=
|
|
|
|
|
|
|
|
|
|
|
|
|
| 338 |
/>
|
| 339 |
-
<span
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 340 |
{note.filename}
|
| 341 |
</span>
|
| 342 |
</div>
|
| 343 |
<div className="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
|
| 344 |
<button
|
| 345 |
onClick={(e) => startEditing(e, note)}
|
| 346 |
-
className="p-1.5 hover:bg-
|
| 347 |
title="Rename"
|
| 348 |
>
|
| 349 |
<Edit2 size={14} />
|
| 350 |
</button>
|
| 351 |
<button
|
| 352 |
onClick={(e) => handleDeleteNote(e, note.id)}
|
| 353 |
-
className="p-1.5 hover:bg-red-
|
| 354 |
title="Delete"
|
| 355 |
>
|
| 356 |
<Trash2 size={14} />
|
|
@@ -365,85 +383,90 @@ const Notes: React.FC = () => {
|
|
| 365 |
)}
|
| 366 |
</div>
|
| 367 |
|
| 368 |
-
{/* --- Center: PDF Viewer --- */}
|
| 369 |
-
<div className="flex flex-1 overflow-hidden relative flex-col">
|
| 370 |
-
<header className="flex justify-between items-center p-4
|
| 371 |
<div className="flex items-center gap-3">
|
| 372 |
<button
|
| 373 |
onClick={() => setIsSidebarOpen(!isSidebarOpen)}
|
| 374 |
-
className="p-2 rounded-lg
|
| 375 |
>
|
| 376 |
<Menu size={20} />
|
| 377 |
</button>
|
| 378 |
-
<h2 className="text-lg font-
|
| 379 |
{currentNote ? currentNote.filename : "Select a Note"}
|
| 380 |
</h2>
|
| 381 |
</div>
|
| 382 |
{!isChatOpen && currentNote && (
|
| 383 |
<button
|
| 384 |
onClick={() => setIsChatOpen(true)}
|
| 385 |
-
className="flex items-center gap-2 bg-
|
| 386 |
>
|
| 387 |
<MessageSquare size={18} /> Open Chat
|
| 388 |
</button>
|
| 389 |
)}
|
| 390 |
</header>
|
| 391 |
|
| 392 |
-
<div className="flex-1 w-full h-full
|
| 393 |
{pdfUrl ? (
|
| 394 |
-
<
|
| 395 |
-
|
| 396 |
-
|
| 397 |
-
|
| 398 |
-
|
| 399 |
-
|
| 400 |
-
|
|
|
|
|
|
|
| 401 |
) : (
|
| 402 |
-
<div className="flex flex-col items-center justify-center h-full text-gray-400">
|
| 403 |
-
<FileText size={
|
| 404 |
-
<p
|
|
|
|
|
|
|
| 405 |
</div>
|
| 406 |
)}
|
| 407 |
</div>
|
| 408 |
</div>
|
| 409 |
|
| 410 |
-
{/* --- Resizable Chat Panel --- */}
|
| 411 |
{isChatOpen && (
|
| 412 |
<div
|
| 413 |
-
className="w-1
|
| 414 |
onMouseDown={startResizing}
|
| 415 |
>
|
| 416 |
-
<GripVertical size={16} className="text-
|
| 417 |
</div>
|
| 418 |
)}
|
| 419 |
|
| 420 |
<div
|
| 421 |
style={{ width: isChatOpen ? chatWidth : 0 }}
|
| 422 |
-
className={`flex flex-col bg-
|
| 423 |
>
|
| 424 |
{isChatOpen && (
|
| 425 |
<>
|
| 426 |
-
<header className="flex justify-between items-center p-4 border-b border-
|
| 427 |
<div className="flex items-center gap-2">
|
| 428 |
-
<
|
| 429 |
-
<h3 className="text-lg font-bold text-white whitespace-nowrap">
|
| 430 |
AI Chat
|
| 431 |
</h3>
|
| 432 |
</div>
|
| 433 |
<button
|
| 434 |
onClick={() => setIsChatOpen(false)}
|
| 435 |
-
className="p-2 rounded-lg text-gray-
|
| 436 |
>
|
| 437 |
<X size={20} />
|
| 438 |
</button>
|
| 439 |
</header>
|
| 440 |
|
| 441 |
-
<div className="flex-1 overflow-y-auto p-4 space-y-4">
|
| 442 |
{messages.length === 0 && (
|
| 443 |
-
<div className="text-center text-gray-
|
| 444 |
<p>Ask a question about this document...</p>
|
| 445 |
</div>
|
| 446 |
)}
|
|
|
|
| 447 |
{messages.map((msg, i) => (
|
| 448 |
<div
|
| 449 |
key={i}
|
|
@@ -452,10 +475,10 @@ const Notes: React.FC = () => {
|
|
| 452 |
}`}
|
| 453 |
>
|
| 454 |
<div
|
| 455 |
-
className={`max-w-[85%] p-
|
| 456 |
msg.role === "user"
|
| 457 |
-
? "bg-
|
| 458 |
-
: "bg-
|
| 459 |
}`}
|
| 460 |
>
|
| 461 |
{msg.role === "assistant" ? (
|
|
@@ -470,8 +493,8 @@ const Notes: React.FC = () => {
|
|
| 470 |
))}
|
| 471 |
{isChatLoading && (
|
| 472 |
<div className="flex justify-start">
|
| 473 |
-
<div className="bg-
|
| 474 |
-
<Loader2 className="animate-spin w-4 h-4 text-
|
| 475 |
</div>
|
| 476 |
</div>
|
| 477 |
)}
|
|
@@ -479,7 +502,7 @@ const Notes: React.FC = () => {
|
|
| 479 |
<div ref={messagesEndRef} />
|
| 480 |
</div>
|
| 481 |
|
| 482 |
-
<div className="p-4 border-t border-
|
| 483 |
<div className="flex gap-2">
|
| 484 |
<input
|
| 485 |
type="text"
|
|
@@ -487,13 +510,14 @@ const Notes: React.FC = () => {
|
|
| 487 |
onChange={(e) => setInputMessage(e.target.value)}
|
| 488 |
onKeyDown={(e) => e.key === "Enter" && handleSendMessage()}
|
| 489 |
placeholder="Type your question..."
|
| 490 |
-
|
|
|
|
| 491 |
disabled={!sessionId || isChatLoading}
|
| 492 |
/>
|
| 493 |
<button
|
| 494 |
onClick={handleSendMessage}
|
| 495 |
disabled={!sessionId || isChatLoading}
|
| 496 |
-
className="bg-
|
| 497 |
>
|
| 498 |
<Send size={20} />
|
| 499 |
</button>
|
|
|
|
| 13 |
Trash2,
|
| 14 |
Edit2,
|
| 15 |
Check,
|
| 16 |
+
Brain,
|
| 17 |
} from "lucide-react";
|
| 18 |
import {
|
| 19 |
fetchNotes,
|
|
|
|
| 62 |
loadNotes();
|
| 63 |
}, []);
|
| 64 |
|
| 65 |
+
// --- Robust Auto-Scroll ---
|
| 66 |
const scrollToBottom = () => {
|
|
|
|
|
|
|
| 67 |
messagesEndRef.current?.scrollIntoView({
|
| 68 |
behavior: "instant",
|
| 69 |
block: "end",
|
|
|
|
| 77 |
// --- Resizing Logic ---
|
| 78 |
const startResizing = useCallback(() => setIsResizing(true), []);
|
| 79 |
const stopResizing = useCallback(() => setIsResizing(false), []);
|
| 80 |
+
|
| 81 |
const resize = useCallback(
|
| 82 |
(mouseMoveEvent: MouseEvent) => {
|
| 83 |
if (isResizing) {
|
|
|
|
| 158 |
const saveRename = async (e: React.MouseEvent) => {
|
| 159 |
e.stopPropagation();
|
| 160 |
if (!editingNoteId || !editName.trim()) return;
|
| 161 |
+
|
| 162 |
try {
|
| 163 |
await renameNote(editingNoteId, editName);
|
| 164 |
setNotes((prev) =>
|
|
|
|
| 260 |
};
|
| 261 |
|
| 262 |
return (
|
| 263 |
+
// 1. Root Container: #434E78 Background, No Scrollbars
|
| 264 |
+
<div className="flex h-screen w-full overflow-hidden bg-[#434E78] font-sans text-white">
|
| 265 |
+
{/* --- Left Sidebar (#607B8F) --- */}
|
| 266 |
<div
|
| 267 |
+
className={`h-screen shrink-0 transition-all duration-300 bg-[#607B8F] border-r border-white/10 flex flex-col gap-4 ${
|
| 268 |
+
isSidebarOpen ? "w-72 p-4" : "w-0 p-0 overflow-hidden"
|
| 269 |
}`}
|
| 270 |
>
|
| 271 |
{isSidebarOpen && (
|
| 272 |
<>
|
| 273 |
+
<div className="flex items-center gap-2 mb-2 border-b border-white/10 pb-4">
|
| 274 |
+
<FileText className="text-[#F7E396] w-6 h-6" />
|
| 275 |
+
<h3 className="text-xl font-bold text-white font-handwriting">
|
| 276 |
+
My Notes
|
| 277 |
+
</h3>
|
| 278 |
+
</div>
|
| 279 |
+
|
| 280 |
<input
|
| 281 |
type="file"
|
| 282 |
ref={fileInputRef}
|
|
|
|
| 284 |
accept="application/pdf"
|
| 285 |
onChange={handleFileChange}
|
| 286 |
/>
|
| 287 |
+
|
| 288 |
+
{/* Upload Button: #F7E396 (Highlight) */}
|
| 289 |
<button
|
| 290 |
onClick={handleUploadClick}
|
| 291 |
disabled={isUploading}
|
| 292 |
+
className="flex items-center justify-center gap-2 w-full bg-[#F7E396] text-[#434E78] px-4 py-3 rounded-xl hover:bg-[#E97F4A] hover:text-white transition font-bold shadow-md"
|
| 293 |
>
|
| 294 |
{isUploading ? (
|
| 295 |
<Loader2 className="animate-spin" size={20} />
|
|
|
|
| 299 |
{isUploading ? "Uploading..." : "Upload New PDF"}
|
| 300 |
</button>
|
| 301 |
|
| 302 |
+
<div className="mt-2 flex-1 overflow-y-auto space-y-2 pr-1 custom-scrollbar">
|
| 303 |
+
<p className="text-xs text-gray-200 uppercase tracking-widest font-semibold mb-2">
|
| 304 |
History
|
| 305 |
</p>
|
| 306 |
|
|
|
|
| 308 |
<div
|
| 309 |
key={note.id}
|
| 310 |
onClick={() => handleNoteSelect(note)}
|
| 311 |
+
className={`group relative p-3 rounded-lg cursor-pointer flex items-center justify-between transition-all border border-transparent ${
|
| 312 |
currentNote?.id === note.id
|
| 313 |
+
? "bg-[#434E78] border-[#F7E396] shadow-md"
|
| 314 |
+
: "hover:bg-[#434E78]/50 text-gray-100"
|
| 315 |
}`}
|
| 316 |
>
|
| 317 |
{editingNoteId === note.id ? (
|
|
|
|
| 321 |
value={editName}
|
| 322 |
onChange={(e) => setEditName(e.target.value)}
|
| 323 |
onClick={(e) => e.stopPropagation()}
|
| 324 |
+
className="flex-1 bg-[#434E78] text-white text-xs px-2 py-1 rounded border border-[#F7E396] outline-none"
|
| 325 |
autoFocus
|
| 326 |
/>
|
| 327 |
<button
|
| 328 |
onClick={saveRename}
|
| 329 |
+
className="text-green-300 hover:text-green-200 p-1"
|
| 330 |
>
|
| 331 |
<Check size={14} />
|
| 332 |
</button>
|
| 333 |
<button
|
| 334 |
onClick={cancelRename}
|
| 335 |
+
className="text-red-300 hover:text-red-200 p-1"
|
| 336 |
>
|
| 337 |
<X size={14} />
|
| 338 |
</button>
|
| 339 |
</div>
|
| 340 |
) : (
|
| 341 |
<>
|
| 342 |
+
<div className="flex items-center gap-3 overflow-hidden">
|
| 343 |
<FileText
|
| 344 |
size={16}
|
| 345 |
+
className={`${
|
| 346 |
+
currentNote?.id === note.id
|
| 347 |
+
? "text-[#F7E396]"
|
| 348 |
+
: "text-gray-300"
|
| 349 |
+
} shrink-0`}
|
| 350 |
/>
|
| 351 |
+
<span
|
| 352 |
+
className={`truncate text-sm font-medium ${
|
| 353 |
+
currentNote?.id === note.id
|
| 354 |
+
? "text-white"
|
| 355 |
+
: "text-gray-200"
|
| 356 |
+
}`}
|
| 357 |
+
>
|
| 358 |
{note.filename}
|
| 359 |
</span>
|
| 360 |
</div>
|
| 361 |
<div className="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
|
| 362 |
<button
|
| 363 |
onClick={(e) => startEditing(e, note)}
|
| 364 |
+
className="p-1.5 hover:bg-white/10 rounded text-gray-300 hover:text-[#F7E396]"
|
| 365 |
title="Rename"
|
| 366 |
>
|
| 367 |
<Edit2 size={14} />
|
| 368 |
</button>
|
| 369 |
<button
|
| 370 |
onClick={(e) => handleDeleteNote(e, note.id)}
|
| 371 |
+
className="p-1.5 hover:bg-red-500/20 rounded text-gray-300 hover:text-red-300"
|
| 372 |
title="Delete"
|
| 373 |
>
|
| 374 |
<Trash2 size={14} />
|
|
|
|
| 383 |
)}
|
| 384 |
</div>
|
| 385 |
|
| 386 |
+
{/* --- Center: PDF Viewer (#434E78 Background) --- */}
|
| 387 |
+
<div className="flex flex-1 overflow-hidden relative flex-col bg-[#434E78]">
|
| 388 |
+
<header className="flex justify-between items-center p-4 border-b border-white/10 shrink-0 z-10 bg-[#434E78]">
|
| 389 |
<div className="flex items-center gap-3">
|
| 390 |
<button
|
| 391 |
onClick={() => setIsSidebarOpen(!isSidebarOpen)}
|
| 392 |
+
className="p-2 rounded-lg hover:bg-white/10 text-white transition"
|
| 393 |
>
|
| 394 |
<Menu size={20} />
|
| 395 |
</button>
|
| 396 |
+
<h2 className="text-lg font-bold text-white truncate max-w-md">
|
| 397 |
{currentNote ? currentNote.filename : "Select a Note"}
|
| 398 |
</h2>
|
| 399 |
</div>
|
| 400 |
{!isChatOpen && currentNote && (
|
| 401 |
<button
|
| 402 |
onClick={() => setIsChatOpen(true)}
|
| 403 |
+
className="flex items-center gap-2 bg-[#F7E396] text-[#434E78] hover:bg-[#E97F4A] hover:text-white px-4 py-2 rounded-lg text-sm font-bold transition shadow-md"
|
| 404 |
>
|
| 405 |
<MessageSquare size={18} /> Open Chat
|
| 406 |
</button>
|
| 407 |
)}
|
| 408 |
</header>
|
| 409 |
|
| 410 |
+
<div className="flex-1 w-full h-full relative p-4">
|
| 411 |
{pdfUrl ? (
|
| 412 |
+
<div className="w-full h-full rounded-xl overflow-hidden shadow-2xl border border-white/10 bg-white/5 backdrop-blur-sm">
|
| 413 |
+
<iframe
|
| 414 |
+
src={pdfUrl}
|
| 415 |
+
className={`w-full h-full border-none ${
|
| 416 |
+
isResizing ? "pointer-events-none" : ""
|
| 417 |
+
}`}
|
| 418 |
+
title="PDF Viewer"
|
| 419 |
+
/>
|
| 420 |
+
</div>
|
| 421 |
) : (
|
| 422 |
+
<div className="flex flex-col items-center justify-center h-full text-gray-400/50">
|
| 423 |
+
<FileText size={80} className="mb-4 opacity-30" />
|
| 424 |
+
<p className="text-lg font-medium">
|
| 425 |
+
Select a PDF from the sidebar to view
|
| 426 |
+
</p>
|
| 427 |
</div>
|
| 428 |
)}
|
| 429 |
</div>
|
| 430 |
</div>
|
| 431 |
|
| 432 |
+
{/* --- Resizable Chat Panel (#607B8F) --- */}
|
| 433 |
{isChatOpen && (
|
| 434 |
<div
|
| 435 |
+
className="w-1 hover:w-2 cursor-col-resize bg-[#434E78] hover:bg-[#F7E396] transition-all z-20 flex items-center justify-center shrink-0"
|
| 436 |
onMouseDown={startResizing}
|
| 437 |
>
|
| 438 |
+
<GripVertical size={16} className="text-white/30" />
|
| 439 |
</div>
|
| 440 |
)}
|
| 441 |
|
| 442 |
<div
|
| 443 |
style={{ width: isChatOpen ? chatWidth : 0 }}
|
| 444 |
+
className={`flex flex-col bg-[#607B8F] border-l border-white/10 shrink-0 transition-all duration-100 ease-linear overflow-hidden`}
|
| 445 |
>
|
| 446 |
{isChatOpen && (
|
| 447 |
<>
|
| 448 |
+
<header className="flex justify-between items-center p-4 border-b border-white/10 bg-[#607B8F] shrink-0">
|
| 449 |
<div className="flex items-center gap-2">
|
| 450 |
+
<Brain size={20} className="text-[#F7E396]" />
|
| 451 |
+
<h3 className="text-lg font-bold text-white whitespace-nowrap font-handwriting">
|
| 452 |
AI Chat
|
| 453 |
</h3>
|
| 454 |
</div>
|
| 455 |
<button
|
| 456 |
onClick={() => setIsChatOpen(false)}
|
| 457 |
+
className="p-2 rounded-lg text-gray-200 hover:bg-white/10 hover:text-white transition-colors"
|
| 458 |
>
|
| 459 |
<X size={20} />
|
| 460 |
</button>
|
| 461 |
</header>
|
| 462 |
|
| 463 |
+
<div className="flex-1 overflow-y-auto p-4 space-y-4 custom-scrollbar">
|
| 464 |
{messages.length === 0 && (
|
| 465 |
+
<div className="text-center text-gray-200 mt-10 opacity-70">
|
| 466 |
<p>Ask a question about this document...</p>
|
| 467 |
</div>
|
| 468 |
)}
|
| 469 |
+
|
| 470 |
{messages.map((msg, i) => (
|
| 471 |
<div
|
| 472 |
key={i}
|
|
|
|
| 475 |
}`}
|
| 476 |
>
|
| 477 |
<div
|
| 478 |
+
className={`max-w-[85%] p-4 rounded-xl text-sm shadow-sm ${
|
| 479 |
msg.role === "user"
|
| 480 |
+
? "bg-[#F7E396] text-[#434E78] font-medium rounded-tr-none"
|
| 481 |
+
: "bg-[#434E78] text-white border border-white/10 rounded-tl-none prose prose-invert prose-sm max-w-none"
|
| 482 |
}`}
|
| 483 |
>
|
| 484 |
{msg.role === "assistant" ? (
|
|
|
|
| 493 |
))}
|
| 494 |
{isChatLoading && (
|
| 495 |
<div className="flex justify-start">
|
| 496 |
+
<div className="bg-[#434E78] p-3 rounded-lg border border-white/10">
|
| 497 |
+
<Loader2 className="animate-spin w-4 h-4 text-[#F7E396]" />
|
| 498 |
</div>
|
| 499 |
</div>
|
| 500 |
)}
|
|
|
|
| 502 |
<div ref={messagesEndRef} />
|
| 503 |
</div>
|
| 504 |
|
| 505 |
+
<div className="p-4 border-t border-white/10 shrink-0 bg-[#607B8F]">
|
| 506 |
<div className="flex gap-2">
|
| 507 |
<input
|
| 508 |
type="text"
|
|
|
|
| 510 |
onChange={(e) => setInputMessage(e.target.value)}
|
| 511 |
onKeyDown={(e) => e.key === "Enter" && handleSendMessage()}
|
| 512 |
placeholder="Type your question..."
|
| 513 |
+
// Input: Dark Blue (#434E78) for contrast on Light Blue (#607B8F) panel
|
| 514 |
+
className="flex-1 bg-[#434E78] text-white rounded-xl px-4 py-3 border border-transparent focus:border-[#F7E396] focus:ring-0 outline-none placeholder-gray-400 shadow-inner"
|
| 515 |
disabled={!sessionId || isChatLoading}
|
| 516 |
/>
|
| 517 |
<button
|
| 518 |
onClick={handleSendMessage}
|
| 519 |
disabled={!sessionId || isChatLoading}
|
| 520 |
+
className="bg-[#F7E396] p-3 rounded-xl text-[#434E78] hover:bg-[#E97F4A] hover:text-white disabled:opacity-50 disabled:cursor-not-allowed transition-colors shadow-md"
|
| 521 |
>
|
| 522 |
<Send size={20} />
|
| 523 |
</button>
|