diff --git a/components/Landing.tsx b/components/Landing.tsx
index 5b81058..8e69678 100644
--- a/components/Landing.tsx
+++ b/components/Landing.tsx
@@ -1,20 +1,46 @@
-import React, { useState } from 'react';
+import React, { useState, useEffect } from 'react';
import { motion } from 'framer-motion';
-import { BrainCircuit, Loader2, Users, Play, PenTool } from 'lucide-react';
+import { BrainCircuit, Loader2, Play, PenTool, BookOpen } from 'lucide-react';
+import { useAuth } from 'react-oidc-context';
+import { AuthButton } from './AuthButton';
+import { QuizLibrary } from './QuizLibrary';
+import { useQuizLibrary } from '../hooks/useQuizLibrary';
+import type { Quiz } from '../types';
interface LandingProps {
onGenerate: (topic: string) => void;
onCreateManual: () => void;
+ onLoadQuiz: (quiz: Quiz) => void;
onJoin: (pin: string, name: string) => void;
isLoading: boolean;
error: string | null;
}
-export const Landing: React.FC
= ({ onGenerate, onCreateManual, onJoin, isLoading, error }) => {
+export const Landing: React.FC = ({ onGenerate, onCreateManual, onLoadQuiz, onJoin, isLoading, error }) => {
+ const auth = useAuth();
const [mode, setMode] = useState<'HOST' | 'JOIN'>('HOST');
const [topic, setTopic] = useState('');
const [pin, setPin] = useState('');
const [name, setName] = useState('');
+ const [libraryOpen, setLibraryOpen] = useState(false);
+
+ const {
+ quizzes,
+ loading: libraryLoading,
+ loadingQuizId,
+ deletingQuizId,
+ error: libraryError,
+ fetchQuizzes,
+ loadQuiz,
+ deleteQuiz,
+ retry: retryLibrary
+ } = useQuizLibrary();
+
+ useEffect(() => {
+ if (libraryOpen && auth.isAuthenticated) {
+ fetchQuizzes();
+ }
+ }, [libraryOpen, auth.isAuthenticated, fetchQuizzes]);
const handleHostSubmit = (e: React.FormEvent) => {
e.preventDefault();
@@ -26,8 +52,24 @@ export const Landing: React.FC = ({ onGenerate, onCreateManual, on
if (pin.trim() && name.trim()) onJoin(pin, name);
};
+ const handleLoadQuiz = async (id: string) => {
+ try {
+ const quiz = await loadQuiz(id);
+ setLibraryOpen(false);
+ onLoadQuiz(quiz);
+ } catch (err) {
+ if (err instanceof Error && err.message.includes('redirecting')) {
+ return;
+ }
+ console.error('Failed to load quiz:', err);
+ }
+ };
+
return (
-
+
+
= ({ onGenerate, onCreateManual, on
>
Create Manually
+
+ {auth.isAuthenticated && (
+
+ )}
) : (
);
};
diff --git a/components/QuizCreator.tsx b/components/QuizCreator.tsx
index 726e527..7260cd1 100644
--- a/components/QuizCreator.tsx
+++ b/components/QuizCreator.tsx
@@ -1,21 +1,24 @@
import React, { useState } from 'react';
+import { useAuth } from 'react-oidc-context';
import { Quiz, Question, AnswerOption } from '../types';
import { v4 as uuidv4 } from 'uuid';
-import { Plus, Save, Trash2, CheckCircle, Circle, X } from 'lucide-react';
+import { Plus, Save, Trash2, CheckCircle, Circle, X, BookOpen } from 'lucide-react';
import { COLORS, SHAPES } from '../constants';
interface QuizCreatorProps {
- onFinalize: (quiz: Quiz) => void;
+ onFinalize: (quiz: Quiz, saveToLibrary: boolean) => void;
onCancel: () => void;
}
export const QuizCreator: React.FC = ({ onFinalize, onCancel }) => {
+ const auth = useAuth();
const [title, setTitle] = useState('');
const [questions, setQuestions] = useState([]);
const [qText, setQText] = useState('');
const [options, setOptions] = useState(['', '', '', '']);
const [reasons, setReasons] = useState(['', '', '', '']);
const [correctIdx, setCorrectIdx] = useState(0);
+ const [saveToLibrary, setSaveToLibrary] = useState(false);
const handleAddQuestion = () => {
if (!qText.trim() || options.some(o => !o.trim())) {
@@ -53,7 +56,7 @@ export const QuizCreator: React.FC = ({ onFinalize, onCancel }
const handleFinalize = () => {
if (!title.trim() || questions.length === 0) return;
- onFinalize({ title, questions });
+ onFinalize({ title, questions }, saveToLibrary);
};
return (
@@ -176,7 +179,25 @@ export const QuizCreator: React.FC = ({ onFinalize, onCancel }
-