kaboot/hooks/useQuizLibrary.ts

103 lines
2.8 KiB
TypeScript

import { useState, useCallback } from 'react';
import { useAuthenticatedFetch } from './useAuthenticatedFetch';
import type { Quiz, QuizSource, SavedQuiz, QuizListItem } from '../types';
interface UseQuizLibraryReturn {
quizzes: QuizListItem[];
loading: boolean;
error: string | null;
fetchQuizzes: () => Promise<void>;
loadQuiz: (id: string) => Promise<SavedQuiz>;
saveQuiz: (quiz: Quiz, source: QuizSource, aiTopic?: string) => Promise<string>;
deleteQuiz: (id: string) => Promise<void>;
}
export const useQuizLibrary = (): UseQuizLibraryReturn => {
const { authFetch, isAuthenticated } = useAuthenticatedFetch();
const [quizzes, setQuizzes] = useState<QuizListItem[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const fetchQuizzes = useCallback(async () => {
if (!isAuthenticated) return;
setLoading(true);
setError(null);
try {
const response = await authFetch('/api/quizzes');
if (!response.ok) {
throw new Error('Failed to fetch quizzes');
}
const data = await response.json();
setQuizzes(data);
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to fetch quizzes');
} finally {
setLoading(false);
}
}, [authFetch, isAuthenticated]);
const loadQuiz = useCallback(async (id: string): Promise<SavedQuiz> => {
const response = await authFetch(`/api/quizzes/${id}`);
if (!response.ok) {
throw new Error('Failed to load quiz');
}
return response.json();
}, [authFetch]);
const saveQuiz = useCallback(async (
quiz: Quiz,
source: QuizSource,
aiTopic?: string
): Promise<string> => {
const response = await authFetch('/api/quizzes', {
method: 'POST',
body: JSON.stringify({
title: quiz.title,
source,
aiTopic,
questions: quiz.questions.map(q => ({
text: q.text,
timeLimit: q.timeLimit,
options: q.options.map(o => ({
text: o.text,
isCorrect: o.isCorrect,
shape: o.shape,
color: o.color,
reason: o.reason,
})),
})),
}),
});
if (!response.ok) {
throw new Error('Failed to save quiz');
}
const data = await response.json();
return data.id;
}, [authFetch]);
const deleteQuiz = useCallback(async (id: string): Promise<void> => {
const response = await authFetch(`/api/quizzes/${id}`, {
method: 'DELETE',
});
if (!response.ok && response.status !== 204) {
throw new Error('Failed to delete quiz');
}
setQuizzes(prev => prev.filter(q => q.id !== id));
}, [authFetch]);
return {
quizzes,
loading,
error,
fetchQuizzes,
loadQuiz,
saveQuiz,
deleteQuiz,
};
};