import { useState, useEffect, useCallback } from 'react'; import { adminData } from '@/lib/adminApi'; import { auditedAdminData } from '@/hooks/useAuditedAdminData'; import { useEntityForm } from '@/hooks/useEntityForm'; import { Button } from '@/components/ui/button'; import { Label } from '@/components/ui/label'; import { Input } from '@/components/ui/input'; import { Textarea } from '@/components/ui/textarea'; import { Badge } from '@/components/ui/badge'; import { Switch } from '@/components/ui/switch'; import { Skeleton } from '@/components/ui/skeleton'; import { PaginationControls } from '@/components/ui/pagination'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from '@/components/ui/dialog'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Card } from '@/components/ui/card'; import { Plus, Pencil, Loader2, HelpCircle, X, Eye, EyeOff } from 'lucide-react'; import { toast } from 'sonner'; import { MAX_QUIZ_OPTIONS, MIN_QUIZ_OPTIONS, sanitizeQuizOptions, validateQuizQuestionForm } from '@/lib/quizQuestions'; // ============================================================================= // Types // ============================================================================= interface QuizQuestion { id: string; prompt_self: string; prompt_guess: string; options: string[]; sort_order: number; is_active: boolean; created_at: string | null; } interface QuizQuestionFormData { prompt_self: string; prompt_guess: string; options: string[]; sort_order: string; is_active: boolean; } type ActiveFilter = 'all' | 'active' | 'inactive'; const emptyOptions = () => ['', '']; // ============================================================================= // Component // ============================================================================= export function QuizQuestionsPage() { const [questions, setQuestions] = useState([]); const [loading, setLoading] = useState(true); const [page, setPage] = useState(1); const [pageSize, setPageSize] = useState(25); const [totalCount, setTotalCount] = useState(0); const [activeFilter, setActiveFilter] = useState('all'); const form = useEntityForm( { prompt_self: '', prompt_guess: '', options: emptyOptions(), sort_order: '0', is_active: true, }, (question) => ({ prompt_self: question.prompt_self, prompt_guess: question.prompt_guess, options: question.options.length ? [...question.options] : emptyOptions(), sort_order: String(question.sort_order), is_active: question.is_active, }) ); const fetchData = useCallback(async () => { setLoading(true); try { const from = (page - 1) * pageSize; const to = from + pageSize - 1; let query = adminData .from('quiz_questions') .select('*', { count: 'exact' }) .order('sort_order', { ascending: true }) .range(from, to); if (activeFilter === 'active') { query = query.eq('is_active', true); } else if (activeFilter === 'inactive') { query = query.eq('is_active', false); } const { data, error, count } = await query; if (error) throw error; setTotalCount(count || 0); setQuestions((data as QuizQuestion[]) || []); } catch (error) { toast.error('Failed to load quiz questions'); console.error(error); } finally { setLoading(false); } }, [page, pageSize, activeFilter]); useEffect(() => { fetchData(); }, [fetchData]); useEffect(() => { const totalPages = Math.max(1, Math.ceil(totalCount / pageSize)); if (page > totalPages) { setPage(totalPages); } }, [page, pageSize, totalCount]); useEffect(() => { setPage(1); }, [activeFilter]); // ============================================================================= // Option helpers // ============================================================================= const setOption = (index: number, value: string) => { form.setFields({ options: form.formData.options.map((opt, i) => (i === index ? value : opt)), }); }; const addOption = () => { if (form.formData.options.length >= MAX_QUIZ_OPTIONS) return; form.setFields({ options: [...form.formData.options, ''] }); }; const removeOption = (index: number) => { if (form.formData.options.length <= MIN_QUIZ_OPTIONS) return; form.setFields({ options: form.formData.options.filter((_, i) => i !== index) }); }; // ============================================================================= // Handlers // ============================================================================= const handleSave = async () => { const validationError = validateQuizQuestionForm(form.formData); if (validationError) { toast.error(validationError); return; } const cleanedOptions = sanitizeQuizOptions(form.formData.options); const parsedSortOrder = Number(form.formData.sort_order); const sortOrder = Number.isFinite(parsedSortOrder) ? parsedSortOrder : 0; const payload = { prompt_self: form.formData.prompt_self.trim(), prompt_guess: form.formData.prompt_guess.trim(), options: cleanedOptions, sort_order: sortOrder, is_active: form.formData.is_active, }; form.setSaving(true); try { if (form.editingItem) { const { error } = await auditedAdminData.update('quiz_questions', form.editingItem.id, payload); if (error) throw error; toast.success('Quiz question updated'); } else { const { error } = await auditedAdminData.insert('quiz_questions', payload); if (error) throw error; toast.success('Quiz question created'); } form.close(); fetchData(); } catch (error) { toast.error('Failed to save quiz question'); console.error(error); } finally { form.setSaving(false); } }; const handleToggleActive = async (question: QuizQuestion) => { try { const { error } = await auditedAdminData.update('quiz_questions', question.id, { is_active: !question.is_active, }); if (error) throw error; toast.success(question.is_active ? 'Quiz question deactivated' : 'Quiz question activated'); fetchData(); } catch (error) { toast.error('Failed to update quiz question'); console.error(error); } }; if (loading) { return (
); } return (
{/* Header */}

Quiz Questions

{totalCount} question{totalCount !== 1 ? 's' : ''} in the couples quiz pool

{form.isEditing ? 'Edit Quiz Question' : 'Add Quiz Question'} {form.isEditing ? 'Update the quiz question details below.' : 'Add a new question to the couples quiz pool.'}