import React, { useState, useEffect, useRef } from 'react'; import ReactMarkdown from 'react-markdown'; import { Send, Bot, User, ChevronLeft, LayoutGrid, GraduationCap as CapIcon, BookOpen, Upload, Settings, RefreshCw } from 'lucide-react'; const API_BASE = window.location.port === "5173" ? "http://localhost:8000/api" : "/api"; function App() { const [page, setPage] = useState('welcome'); const [curriculum, setCurriculum] = useState({}); const [selection, setSelection] = useState({ grade: '', subject: '', topic: '' }); const [messages, setMessages] = useState([]); const [inputText, setInputText] = useState(''); const [loading, setLoading] = useState(false); const [hintLevel, setHintLevel] = useState(1); const [status, setStatus] = useState('ACTIVE'); const [ingestStatus, setIngestStatus] = useState(''); const [uploadData, setUploadData] = useState({ grade: '', subject: '', file: null }); const messagesEndRef = useRef(null); useEffect(() => { fetchCurriculum(); }, []); useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); }, [messages]); const fetchCurriculum = async () => { try { const res = await fetch(`${API_BASE}/curriculum`); const data = await res.json(); setCurriculum(data); } catch (err) { console.error("Failed to fetch curriculum:", err); } }; const startSession = (grade, subject, topic) => { setSelection({ grade, subject, topic }); setMessages([{ role: 'assistant', content: `Hello! I'm your AI Learner for **${grade} ${subject}**. What would you like to explore today?` }]); setPage('chat'); }; const sendMessage = async (e) => { e.preventDefault(); if (!inputText.trim() || loading) return; const userMsg = { role: 'user', content: inputText }; const newMessages = [...messages, userMsg]; setMessages(newMessages); setInputText(''); setLoading(true); try { const res = await fetch(`${API_BASE}/chat`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ messages: newMessages, grade: selection.grade, subject: selection.subject, topic: selection.topic, hint_level: hintLevel, status: status }) }); if (!res.ok) { const errorData = await res.json().catch(() => ({})); throw new Error(errorData.detail || `Server error: ${res.status}`); } const data = await res.json(); setMessages([...newMessages, data.message]); setHintLevel(data.hint_level); setStatus(data.status); } catch (err) { console.error("Chat error:", err); setMessages([...newMessages, { role: 'assistant', content: `⚠️ **Error:** ${err.message}. Please check if the backend server is running and try again.` }]); } finally { setLoading(false); } }; const handleUpload = async (e) => { e.preventDefault(); if (!uploadData.file || !uploadData.grade || !uploadData.subject) return; setIngestStatus('Uploading...'); const formData = new FormData(); formData.append('file', uploadData.file); try { await fetch(`${API_BASE}/upload?grade=${uploadData.grade}&subject=${uploadData.subject}`, { method: 'POST', body: formData }); setIngestStatus('Processing...'); const res = await fetch(`${API_BASE}/ingest`, { method: 'POST' }); const result = await res.json(); setIngestStatus(result.message); fetchCurriculum(); } catch (err) { setIngestStatus('Error: ' + err.message); } }; // --- RENDERERS --- if (page === 'ingest') { return (