// Serviços Module — Catálogo de serviços oferecidos function Servicos() { const [servicos, setServicos] = React.useState([]); const [loading, setLoading] = React.useState(true); const [addModal, setAddModal] = React.useState(false); const [editModal, setEditModal] = React.useState(false); const [delConfirm, setDelConfirm] = React.useState(false); const [selected, setSelected] = React.useState(null); const [saving, setSaving] = React.useState(false); const [toast, setToast] = React.useState(null); const [search, setSearch] = React.useState(''); const [catFilter, setCatFilter] = React.useState('all'); const showToast = (msg, type = 'success') => { setToast({ msg, type }); setTimeout(() => setToast(null), 3000); }; const emptyForm = { nome: '', categoria: 'Promotoria', descricao: '', preco: '', unidade: 'diária', status: 'Ativo' }; const [form, setForm] = React.useState(emptyForm); const [editForm, setEditForm] = React.useState(emptyForm); const CATEGORIAS = [ { value: 'Promotoria', label: 'Promotoria' }, { value: 'Recepção', label: 'Recepção' }, { value: 'Sampling', label: 'Sampling' }, { value: 'Panfletagem', label: 'Panfletagem' }, { value: 'DJ/Música', label: 'DJ/Música' }, { value: 'Decoração', label: 'Decoração' }, { value: 'Foto/Vídeo', label: 'Foto/Vídeo' }, { value: 'Segurança', label: 'Segurança' }, { value: 'Transporte', label: 'Transporte' }, { value: 'Audiovisual', label: 'Audiovisual' }, { value: 'Limpeza', label: 'Limpeza' }, { value: 'Outro', label: 'Outro' }, ]; const UNIDADES = [ { value: 'hora', label: 'Hora' }, { value: 'diária', label: 'Diária' }, { value: 'evento', label: 'Por evento' }, { value: 'unidade', label: 'Unidade' }, { value: 'pessoa', label: 'Por pessoa' }, ]; const catColor = { 'Promotoria': 'primary', 'Recepção': 'success', 'Sampling': 'warning', 'Panfletagem': 'default', 'DJ/Música': 'purple', 'Decoração': 'primary', 'Foto/Vídeo': 'default', 'Segurança': 'danger', 'Transporte': 'warning', 'Audiovisual': 'primary', 'Limpeza': 'default', 'Outro': 'default' }; const fmtCurrency = v => 'R$ ' + (parseFloat(v) || 0).toLocaleString('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); React.useEffect(() => { sb.from('servicos').select('*').order('nome').then(({ data }) => { if (data) setServicos(data); setLoading(false); }); }, []); const handleCreate = async () => { if (!form.nome.trim()) { showToast('Preencha o nome do serviço.', 'danger'); return; } setSaving(true); const { data, error } = await sb.from('servicos').insert({ nome: form.nome, categoria: form.categoria, descricao: form.descricao, preco: parseFloat(form.preco) || 0, unidade: form.unidade, status: form.status, }).select().single(); setSaving(false); if (error) { console.error('[Servicos.handleCreate] Supabase error:', error); showToast('Erro ao adicionar serviço: ' + (error.message || 'desconhecido'), 'danger'); return; } setServicos(prev => [...prev, data].sort((a, b) => a.nome.localeCompare(b.nome))); setAddModal(false); setForm(emptyForm); showToast(`Serviço "${data.nome}" adicionado!`); }; const openEdit = (s) => { setSelected(s); setEditForm({ nome: s.nome || '', categoria: s.categoria || 'Promotoria', descricao: s.descricao || '', preco: String(s.preco || ''), unidade: s.unidade || 'diária', status: s.status || 'Ativo' }); setEditModal(true); }; const handleEditSave = async () => { if (!editForm.nome.trim()) { showToast('Preencha o nome.', 'danger'); return; } setSaving(true); const { data, error } = await sb.from('servicos').update({ nome: editForm.nome, categoria: editForm.categoria, descricao: editForm.descricao, preco: parseFloat(editForm.preco) || 0, unidade: editForm.unidade, status: editForm.status, }).eq('id', selected.id).select().single(); setSaving(false); if (error) { showToast('Erro ao salvar.', 'danger'); return; } setServicos(prev => prev.map(s => s.id === data.id ? data : s).sort((a, b) => a.nome.localeCompare(b.nome))); setEditModal(false); setSelected(null); showToast('Serviço atualizado!'); }; const handleDelete = async () => { await sb.from('servicos').delete().eq('id', selected.id); setServicos(prev => prev.filter(s => s.id !== selected.id)); setDelConfirm(false); setSelected(null); showToast('Serviço excluído.'); }; const totalAtivos = servicos.filter(s => s.status === 'Ativo').length; // Filtros: busca + categoria const filteredServicos = React.useMemo(() => { const q = search.trim().toLowerCase(); return servicos.filter(s => { if (catFilter !== 'all' && s.categoria !== catFilter) return false; if (!q) return true; return ( (s.nome || '').toLowerCase().includes(q) || (s.descricao || '').toLowerCase().includes(q) || (s.categoria || '').toLowerCase().includes(q) ); }); }, [servicos, search, catFilter]); const precoMedio = servicos.length > 0 ? servicos.reduce((sum, s) => sum + (parseFloat(s.preco) || 0), 0) / servicos.length : 0; return (
Gerencie os serviços oferecidos pela Promoup
Tem certeza que deseja excluir {selected?.nome}? Esta ação não pode ser desfeita.