import { useState } from 'react'; import './App.css'; import { parseDocument, generateQuiz, submitQuiz } from './api'; import DropZone from './components/DropZone'; import StepHeader from './components/StepHeader'; import QuestionCard from './components/QuestionCard'; import ResultsView from './components/ResultsView'; import Alert from './components/Alert'; // ── small helpers ────────────────────────────────────────────── function NumberInput({ label, value, onChange, min = 1, max = 20 }) { return (
{ const v = Math.min(max, Math.max(min, Number(e.target.value))); onChange(v); }} />
); } function SelectInput({ label, id, value, onChange, options }) { return (
); } function LoadingBlock({ text }) { return (
{text}
); } // ── progress strip ──────────────────────────────────────────── function QuizProgress({ answered, total }) { const pct = total ? (answered / total) * 100 : 0; return (
Progress {answered}/{total} answered
); } // ── main app ────────────────────────────────────────────────── export default function App() { // wizard state const [file, setFile] = useState(null); const [docReady, setDocReady] = useState(false); const [quiz, setQuiz] = useState(null); // { quiz_id, questions } const [answers, setAnswers] = useState({}); // { [i]: string } const [result, setResult] = useState(null); // settings const [numQ, setNumQ] = useState(5); const [difficulty, setDifficulty] = useState('Medium'); const [qType, setQType] = useState('MCQ'); // async state const [parsing, setParsing] = useState(false); const [generating, setGenerating] = useState(false); const [submitting, setSubmitting] = useState(false); // errors const [parseErr, setParseErr] = useState(''); const [genErr, setGenErr] = useState(''); const [submitErr, setSubmitErr] = useState(''); const [warnMsg, setWarnMsg] = useState(''); // ── handlers ── const handleParse = async () => { if (!file) return; setParseErr(''); setParsing(true); try { await parseDocument(file); setDocReady(true); } catch { setParseErr('Failed to connect to backend. Is the server running?'); } finally { setParsing(false); } }; const handleGenerate = async () => { setGenErr(''); setGenerating(true); setAnswers({}); setResult(null); try { const data = await generateQuiz({ topic: 'full document', num_questions: numQ, difficulty, question_type: qType, }); setQuiz(data); } catch { setGenErr('Quiz generation failed. Please try again.'); } finally { setGenerating(false); } }; const handleAnswer = (idx, val) => { setAnswers((prev) => ({ ...prev, [idx]: val })); setWarnMsg(''); }; const handleSubmit = async () => { if (!quiz) return; setWarnMsg(''); setSubmitErr(''); // validation const unanswered = quiz.questions.reduce((acc, _, i) => { if (!answers[i]?.trim()) acc.push(i + 1); return acc; }, []); if (unanswered.length) { setWarnMsg( `Please answer all questions before submitting. (${unanswered.length} remaining: Q${unanswered.join(', Q')})` ); return; } const payload = quiz.questions.map((_, i) => ({ question_index: i, user_answer: answers[i] || '', })); setSubmitting(true); try { const res = await submitQuiz(quiz.quiz_id, payload); setResult(res); } catch (e) { if (e.message === 'Quiz expired') { setSubmitErr('Quiz session expired. Please generate a new quiz.'); } else { setSubmitErr('Submission failed. Please try again.'); } } finally { setSubmitting(false); } }; const handleReset = () => { setQuiz(null); setAnswers({}); setResult(null); setGenErr(''); setSubmitErr(''); setWarnMsg(''); }; const handleFullReset = () => { handleReset(); setDocReady(false); setFile(null); setParseErr(''); }; const answeredCount = quiz ? quiz.questions.filter((_, i) => answers[i]?.trim()).length : 0; // ── render ── return (
{/* HERO */}

Quizify

AI-Powered Knowledge Assessment

{/* ══ LEFT PANEL ══ */} {/* ══ RIGHT PANEL ══ */}
{/* Loading states */} {generating && } {submitting && } {/* QUIZ QUESTIONS */} {!generating && !submitting && quiz && !result && (
{quiz.questions.map((q, i) => ( handleAnswer(i, val)} /> ))} {warnMsg && {warnMsg}} {submitErr && {submitErr}}
)} {/* RESULTS */} {!submitting && result && ( )} {/* EMPTY — no document */} {!quiz && !result && !generating && !docReady && (
📄
Upload a document to begin your session
Supports PDF · DOCX · PPTX · TXT · MD
)} {/* EMPTY — document ready, not generated */} {!quiz && !result && !generating && docReady && (
Configure your quiz settings and generate
Choose difficulty, type & question count
)}
); }