import { useState, useEffect } from 'react'; import { Link, useParams } from 'react-router-dom'; import { supabase } from '@/config'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; import { Switch } from '@/components/ui/switch'; import { Badge } from '@/components/ui/badge'; import { Skeleton } from '@/components/ui/skeleton'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from '@/components/ui/dialog'; import { Plus, MessageCircle, Pencil, Trash2, Sparkles, Loader2, Crown, Eye, EyeOff } from 'lucide-react'; import { toast } from 'sonner'; import { AiGeneratorDialog } from '@/components/ai/AiGeneratorDialog'; import { AIPolishButton } from '@/components/ai/AIPolishButton'; interface Category { id: string; name: string; icon: string | null; } interface QuestionPack { id: string; name: string; description: string | null; icon: string | null; is_premium: boolean; is_public: boolean; sort_order: number | null; category_id: string | null; created_at: string | null; question_count?: number; } export function PacksPage() { const { categoryId } = useParams<{ categoryId: string }>(); const [category, setCategory] = useState(null); const [packs, setPacks] = useState([]); const [loading, setLoading] = useState(true); const [dialogOpen, setDialogOpen] = useState(false); const [aiDialogOpen, setAiDialogOpen] = useState(false); const [editingPack, setEditingPack] = useState(null); const [saving, setSaving] = useState(false); // Form state const [formData, setFormData] = useState({ name: '', description: '', icon: '💕', is_premium: false, is_public: true, }); const fetchData = async () => { setLoading(true); try { // Fetch category info if (categoryId) { const { data: cat } = await supabase .from('categories') .select('id, name, icon') .eq('id', categoryId) .single(); setCategory(cat); } // Fetch packs let query = supabase .from('question_packs') .select('*') .order('sort_order', { ascending: true }); if (categoryId) { query = query.eq('category_id', categoryId); } const { data: packData, error } = await query; if (error) throw error; // Fetch question counts const packIds = (packData || []).map(p => p.id); const { data: questions } = await supabase .from('questions') .select('pack_id') .in('pack_id', packIds); const questionCounts: Record = {}; questions?.forEach(q => { questionCounts[q.pack_id] = (questionCounts[q.pack_id] || 0) + 1; }); setPacks( (packData || []).map(p => ({ ...p, question_count: questionCounts[p.id] || 0, })) ); } catch (error) { toast.error('Failed to load packs'); console.error(error); } finally { setLoading(false); } }; useEffect(() => { fetchData(); }, [categoryId]); const openCreateDialog = () => { setEditingPack(null); setFormData({ name: '', description: '', icon: '💕', is_premium: false, is_public: true, }); setDialogOpen(true); }; const openEditDialog = (pack: QuestionPack) => { setEditingPack(pack); setFormData({ name: pack.name, description: pack.description || '', icon: pack.icon || '💕', is_premium: pack.is_premium, is_public: pack.is_public, }); setDialogOpen(true); }; const handleSave = async () => { if (!formData.name.trim()) { toast.error('Name is required'); return; } setSaving(true); try { if (editingPack) { const { error } = await supabase .from('question_packs') .update({ name: formData.name, description: formData.description || null, icon: formData.icon || null, is_premium: formData.is_premium, is_public: formData.is_public, }) .eq('id', editingPack.id); if (error) throw error; toast.success('Pack updated'); } else { const { error } = await supabase .from('question_packs') .insert({ name: formData.name, description: formData.description || null, icon: formData.icon || null, is_premium: formData.is_premium, is_public: formData.is_public, category_id: categoryId || null, sort_order: packs.length, }); if (error) throw error; toast.success('Pack created'); } setDialogOpen(false); fetchData(); } catch (error) { toast.error('Failed to save pack'); console.error(error); } finally { setSaving(false); } }; const handleDelete = async (pack: QuestionPack) => { if (!confirm(`Delete pack "${pack.name}"? This will delete all questions in this pack.`)) { return; } try { const { error } = await supabase .from('question_packs') .delete() .eq('id', pack.id); if (error) throw error; toast.success('Pack deleted'); fetchData(); } catch (error) { toast.error('Failed to delete pack'); console.error(error); } }; const handleAiGenerated = (result: any) => { // Handle pack generation if (result.description) { setFormData({ ...formData, name: result.name, description: result.description, icon: result.icon || '💕', }); setAiDialogOpen(false); setDialogOpen(true); } }; if (loading) { return (
{[1, 2, 3].map(i => ( ))}
); } return (
{/* Header */}

{category && ( <> {category.icon} {category.name}: )} Question Packs

{category ? `Manage packs in the ${category.name} category` : 'Manage all question packs'}

{editingPack ? 'Edit Pack' : 'Create Pack'} {editingPack ? 'Update the pack details below.' : 'Add a new question pack to this category.'}
setFormData(d => ({ ...d, icon: e.target.value }))} placeholder="💕" className="w-20 text-center text-2xl" />
setFormData(d => ({ ...d, name: val }))} />
setFormData(d => ({ ...d, name: e.target.value }))} placeholder="e.g., 36 Questions to Fall in Love" />
setFormData(d => ({ ...d, description: val }))} />