import React, { useState, useEffect, useCallback } from 'react'; import { SchoolData, PreMatriculaCampo, PreMatriculaConfig, PreMatriculaInscricao } from '../types'; import { Plus, Trash2, Save, Eye, EyeOff, Download, GripVertical, Link2, ClipboardPen, Copy, Check, ChevronDown, ChevronRight, Users, RefreshCw, FileText, X, Settings2, ArrowLeft, ExternalLink, AlertCircle, UserCheck } from 'lucide-react'; interface Props { data: SchoolData; updateData: (d: Partial) => void; onConvert?: (preData: any) => void; } const FIELD_TYPES: Record = { text: 'Texto', email: 'Email', phone: 'Telefone', cpf: 'CPF', date: 'Data', select: 'Seleção', textarea: 'Texto Longo', number: 'Número' }; const PreMatricula: React.FC = ({ data, onConvert }) => { const [config, setConfig] = useState(null); const [campos, setCampos] = useState([]); const [inscricoes, setInscricoes] = useState([]); const [turmas, setTurmas] = useState([]); const [activeTab, setActiveTab] = useState<'editor' | 'inscricoes'>('editor'); const [isSaving, setIsSaving] = useState(false); const [isLoading, setIsLoading] = useState(true); const [copied, setCopied] = useState(false); const [selectedTurma, setSelectedTurma] = useState('all'); const [editingCampo, setEditingCampo] = useState(null); const [showNewField, setShowNewField] = useState(false); const [newField, setNewField] = useState({ label: '', tipo: 'text', placeholder: '', obrigatorio: false, opcoes: '' }); const loadData = useCallback(async () => { setIsLoading(true); try { const [cfgRes, camposRes, inscRes, turmasRes] = await Promise.all([ fetch('/api/prematricula/config'), fetch('/api/prematricula/campos'), fetch('/api/prematricula/inscricoes'), fetch('/api/turmas') ]); if (cfgRes.ok) { const j = await cfgRes.json(); setConfig(j.config); } if (camposRes.ok) { const j = await camposRes.json(); setCampos(j.campos || []); } if (inscRes.ok) { const j = await inscRes.json(); setInscricoes(j.inscricoes || []); } if (turmasRes.ok) { const j = await turmasRes.json(); setTurmas(j.turmas || []); } } catch (e) { console.error(e); } finally { setIsLoading(false); } }, []); useEffect(() => { loadData(); }, [loadData]); const saveConfig = async () => { if (!config) return; setIsSaving(true); try { await fetch('/api/prematricula/config', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(config) }); } catch (e) { console.error(e); } finally { setIsSaving(false); } }; const togglePublish = async () => { if (!config) return; const newStatus = config.status === 'published' ? 'draft' : 'published'; const updated = { ...config, status: newStatus as 'draft' | 'published' }; setConfig(updated); await fetch('/api/prematricula/config', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(updated) }); }; const addField = async () => { if (!newField.label.trim()) return; const campo = { id: crypto.randomUUID(), label: newField.label, tipo: newField.tipo, placeholder: newField.placeholder, obrigatorio: newField.obrigatorio, opcoes: newField.tipo === 'select' ? newField.opcoes.split(',').map(o => o.trim()).filter(Boolean) : [], ordem: campos.length, ativo: true }; try { const res = await fetch('/api/prematricula/campos', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(campo) }); if (res.ok) { setCampos(prev => [...prev, campo as PreMatriculaCampo]); setNewField({ label: '', tipo: 'text', placeholder: '', obrigatorio: false, opcoes: '' }); setShowNewField(false); } } catch (e) { console.error(e); } }; const deleteField = async (id: string) => { try { const res = await fetch(`/api/prematricula/campos/${id}`, { method: 'DELETE' }); if (res.ok) setCampos(prev => prev.filter(c => c.id !== id)); } catch (e) { console.error(e); } }; const updateField = async (campo: PreMatriculaCampo) => { try { await fetch(`/api/prematricula/campos/${campo.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(campo) }); setCampos(prev => prev.map(c => c.id === campo.id ? campo : c)); setEditingCampo(null); } catch (e) { console.error(e); } }; const deleteInscricao = async (id: string) => { try { const res = await fetch(`/api/prematricula/inscricoes/${id}`, { method: 'DELETE' }); if (res.ok) setInscricoes(prev => prev.filter(i => i.id !== id)); } catch (e) { console.error(e); } }; const exportCSV = (turmaId: string) => { const filtered = turmaId === 'all' ? inscricoes : inscricoes.filter(i => i.turmaId === turmaId); if (filtered.length === 0) return; const allKeys = new Set(); filtered.forEach(i => Object.keys(i.respostas || {}).forEach(k => allKeys.add(k))); const headers = ['Nome', 'Email', 'Telefone', 'Turma', 'Status', 'Data', ...Array.from(allKeys)]; const rows = filtered.map(i => [ i.nome, i.email, i.telefone, i.turmaNome, i.status, new Date(i.createdAt).toLocaleDateString('pt-BR'), ...Array.from(allKeys).map(k => (i.respostas || {})[k] || '') ]); const csv = [headers.join(';'), ...rows.map(r => r.join(';'))].join('\n'); const blob = new Blob(['\uFEFF' + csv], { type: 'text/csv;charset=utf-8;' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; const turmaName = turmaId === 'all' ? 'todas' : turmas.find(t => t.id === turmaId)?.nome || turmaId; a.download = `pre-matriculas-${turmaName}.csv`; a.click(); URL.revokeObjectURL(url); }; const copyLink = () => { if (!config) return; const url = `${window.location.origin}/${config.slug}`; navigator.clipboard.writeText(url); setCopied(true); setTimeout(() => setCopied(false), 2000); }; const filteredInscricoes = selectedTurma === 'all' ? inscricoes : inscricoes.filter(i => i.turmaId === selectedTurma); const turmasComInscritos = turmas.map(t => ({ ...t, count: inscricoes.filter(i => i.turmaId === t.id).length })); if (isLoading) { return (
); } return (
{/* Header */}

Pré-Matrícula

Gerencie o formulário público de pré-matrícula e visualize inscrições.

{/* Tab Switcher */}
{activeTab === 'editor' ? (
{/* Left: Config */}

Configurações

setConfig(prev => prev ? { ...prev, titulo: e.target.value } : prev)} />