import React, { useState, useRef, useEffect } from 'react'; import { Button } from './ui/button'; import { Textarea } from './ui/textarea'; import { Send, ArrowDown, AlertCircle, Trash2, Share2 } from 'lucide-react'; import { Message } from './Message'; import { FileUploadArea } from './FileUploadArea'; import { MemoryLine } from './MemoryLine'; import { Alert, AlertDescription } from './ui/alert'; import { Badge } from './ui/badge'; import type { Message as MessageType, LearningMode, UploadedFile, FileType, SpaceType } from '../App'; import { toast } from 'sonner'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from './ui/dropdown-menu'; interface ChatAreaProps { messages: MessageType[]; onSendMessage: (content: string) => void; uploadedFiles: UploadedFile[]; onFileUpload: (files: File[]) => void; onRemoveFile: (index: number) => void; onFileTypeChange: (index: number, type: FileType) => void; memoryProgress: number; isLoggedIn: boolean; learningMode: LearningMode; onClearConversation: () => void; onLearningModeChange: (mode: LearningMode) => void; spaceType: SpaceType; } export function ChatArea({ messages, onSendMessage, uploadedFiles, onFileUpload, onRemoveFile, onFileTypeChange, memoryProgress, isLoggedIn, learningMode, onClearConversation, onLearningModeChange, spaceType, }: ChatAreaProps) { const [input, setInput] = useState(''); const [isTyping, setIsTyping] = useState(false); const [showScrollButton, setShowScrollButton] = useState(false); const messagesEndRef = useRef(null); const scrollContainerRef = useRef(null); const scrollToBottom = () => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }; useEffect(() => { scrollToBottom(); }, [messages]); useEffect(() => { const handleScroll = () => { if (scrollContainerRef.current) { const { scrollTop, scrollHeight, clientHeight } = scrollContainerRef.current; setShowScrollButton(scrollHeight - scrollTop - clientHeight > 100); } }; const container = scrollContainerRef.current; container?.addEventListener('scroll', handleScroll); return () => container?.removeEventListener('scroll', handleScroll); }, []); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!input.trim() || !isLoggedIn) return; onSendMessage(input); setInput(''); setIsTyping(true); setTimeout(() => setIsTyping(false), 1500); }; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSubmit(e); } }; const modeLabels: Record = { concept: 'Concept Explainer', socratic: 'Socratic Tutor', exam: 'Exam Prep', assignment: 'Assignment Helper', summary: 'Quick Summary', }; const handleClearClick = () => { if (messages.length <= 1) { toast.info('No conversation to clear'); return; } if (window.confirm('Are you sure you want to clear the conversation? This cannot be undone.')) { onClearConversation(); toast.success('Conversation cleared'); } }; const handleShareClick = () => { if (messages.length <= 1) { toast.info('No conversation to share'); return; } // Create a shareable text version of the conversation const conversationText = messages .map(msg => `${msg.sender === 'user' ? 'You' : 'Clare'}: ${msg.content}`) .join('\n\n'); // Copy to clipboard navigator.clipboard.writeText(conversationText).then(() => { toast.success('Conversation copied to clipboard!'); }).catch(() => { toast.error('Failed to copy conversation'); }); }; return (
{/* Chat Area with Floating Input */}
{/* Action Buttons - Fixed at top right */} {messages.length > 1 && (
)} {/* Messages Area */}
{messages.map((message) => ( ))} {isTyping && (
C
)}
{/* Scroll to Bottom Button - Floating above input */} {showScrollButton && (
)} {/* Floating Input Area */}
{/* Mode Selector - ChatGPT style at bottom left */} onLearningModeChange('concept')} className={learningMode === 'concept' ? 'bg-accent' : ''} >
Concept Explainer Get detailed explanations of concepts
onLearningModeChange('socratic')} className={learningMode === 'socratic' ? 'bg-accent' : ''} >
Socratic Tutor Learn through guided questions
onLearningModeChange('exam')} className={learningMode === 'exam' ? 'bg-accent' : ''} >
Exam Prep Practice with quiz questions
onLearningModeChange('assignment')} className={learningMode === 'assignment' ? 'bg-accent' : ''} >
Assignment Helper Get help with assignments
onLearningModeChange('summary')} className={learningMode === 'summary' ? 'bg-accent' : ''} >
Quick Summary Get concise summaries