// Fornecedores Module function Fornecedores() { const [fornecedores, setFornecedores] = React.useState([]); const [loading, setLoading] = React.useState(true); const [selected, setSelected] = React.useState(null); const [addModal, setAddModal] = React.useState(false); const [editModal, setEditModal] = React.useState(false); const [delConfirm, setDelConfirm] = React.useState(false); const [saving, setSaving] = React.useState(false); const [note, setNote] = React.useState(''); const [detailNotes, setDetailNotes] = React.useState([]); const [toast, setToast] = React.useState(null); const showToast = (msg, type = 'success') => { setToast({ msg, type }); setTimeout(() => setToast(null), 3000); }; const emptyForm = { nome: '', contato: '', email: '', telefone: '', cidade: '', categoria: 'Audiovisual', website: '', status: 'Ativo' }; const [form, setForm] = React.useState(emptyForm); const [editForm, setEditForm] = React.useState(emptyForm); const CATEGORIAS = [ { value: 'Audiovisual', label: 'Audiovisual' }, { value: 'Alimentação', label: 'Alimentação' }, { value: 'Decoração', label: 'Decoração' }, { value: 'Segurança', label: 'Segurança' }, { value: 'Transporte', label: 'Transporte' }, { value: 'Limpeza', label: 'Limpeza' }, { value: 'Tecnologia', label: 'Tecnologia' }, { value: 'Gráfica', label: 'Gráfica' }, { value: 'Brindes', label: 'Brindes' }, { value: 'Fotografia', label: 'Fotografia' }, { value: 'Outro', label: 'Outro' }, ]; const catColor = { 'Audiovisual': 'primary', 'Alimentação': 'success', 'Decoração': 'purple', 'Segurança': 'danger', 'Transporte': 'warning', 'Limpeza': 'default', 'Tecnologia': 'primary', 'Gráfica': 'default', 'Brindes': 'warning', 'Fotografia': 'default', 'Outro': 'default' }; const statusColor = { 'Ativo': 'success', 'Inativo': 'default' }; React.useEffect(() => { sb.from('fornecedores').select('*').order('nome').then(({ data }) => { if (data) setFornecedores(data); setLoading(false); }); }, []); const openFornecedor = (f) => { setSelected(f); setDetailNotes(f.notas || []); setNote(''); }; const saveNote = async () => { if (!note.trim() || !selected) return; const updated = [...detailNotes, note]; setDetailNotes(updated); setNote(''); await sb.from('fornecedores').update({ notas: updated }).eq('id', selected.id); setFornecedores(prev => prev.map(f => f.id === selected.id ? { ...f, notas: updated } : f)); showToast('Anotação salva!'); }; const openEdit = () => { setEditForm({ nome: selected.nome || '', contato: selected.contato || '', email: selected.email || '', telefone: selected.telefone || '', cidade: selected.cidade || '', categoria: selected.categoria || 'Audiovisual', website: selected.website || '', status: selected.status || 'Ativo' }); setEditModal(true); }; const handleCreate = async () => { if (!form.nome.trim()) { showToast('Preencha o nome do fornecedor.', 'danger'); return; } setSaving(true); const { data, error } = await sb.from('fornecedores').insert({ nome: form.nome, contato: form.contato, email: form.email, telefone: form.telefone, cidade: form.cidade, categoria: form.categoria, website: form.website, status: form.status, notas: [], }).select().single(); setSaving(false); if (error) { console.error('[Fornecedores.handleCreate] Supabase error:', error); showToast('Erro ao adicionar fornecedor: ' + (error.message || 'desconhecido'), 'danger'); return; } setFornecedores(prev => [...prev, data].sort((a, b) => a.nome.localeCompare(b.nome))); setAddModal(false); setForm(emptyForm); showToast(`${data.nome} adicionado com sucesso!`); }; const handleEditSave = async () => { if (!editForm.nome.trim()) { showToast('Preencha o nome.', 'danger'); return; } setSaving(true); const { data, error } = await sb.from('fornecedores').update({ nome: editForm.nome, contato: editForm.contato, email: editForm.email, telefone: editForm.telefone, cidade: editForm.cidade, categoria: editForm.categoria, website: editForm.website, status: editForm.status, }).eq('id', selected.id).select().single(); setSaving(false); if (error) { showToast('Erro ao salvar.', 'danger'); return; } setFornecedores(prev => prev.map(f => f.id === data.id ? data : f).sort((a, b) => a.nome.localeCompare(b.nome))); setSelected(data); setEditModal(false); showToast('Fornecedor atualizado!'); }; const handleDelete = async () => { const id = selected.id; const nome = selected.nome; await sb.from('fornecedores').delete().eq('id', id); setFornecedores(prev => prev.filter(f => f.id !== id)); setDelConfirm(false); setSelected(null); showToast(`${nome} excluído.`); }; return (

Fornecedores

Gerencie seus parceiros e prestadores de serviço

setAddModal(true)}>Novo fornecedor
{/* Stats */}
{[ { label: 'Total de fornecedores', value: fornecedores.length, color: DS.colors.primary }, { label: 'Ativos', value: fornecedores.filter(f => f.status === 'Ativo').length, color: DS.colors.success }, { label: 'Categorias', value: new Set(fornecedores.map(f => f.categoria)).size, color: DS.colors.warning }, ].map(s => (
{s.label}
{s.value}
))}
{/* Table */} {loading ? : ( <>
FornecedorContatoCategoriaCidadeStatusAções
{fornecedores.length === 0 ? : fornecedores.map((f, i) => (
openFornecedor(f)} onMouseEnter={e => e.currentTarget.style.background = '#F8FAFC'} onMouseLeave={e => e.currentTarget.style.background = 'transparent'} >
{f.nome}
{f.website &&
{f.website}
}
{f.contato || '—'} {f.categoria} {f.cidade || '—'} {f.status}
{ e.stopPropagation(); f.email ? window.open(`mailto:${f.email}`) : showToast('E-mail não cadastrado.', 'danger'); }} /> { e.stopPropagation(); f.telefone ? window.open(`tel:${f.telefone.replace(/\D/g, '')}`) : showToast('Telefone não cadastrado.', 'danger'); }} />
)) } )}
{/* Popup detalhe */} setSelected(null)} title={selected?.nome || ''} width={700} extra={selected && (
Editar setDelConfirm(true)}>Excluir
)}> {selected && (
{/* Notas */}
Anotações
{detailNotes.length === 0 ?
Nenhuma anotação ainda.
: detailNotes.map((n, i) => (
{n}
)) }
setNote(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') saveNote(); }} placeholder="Adicionar anotação..." style={{ flex: 1, border: `1px solid ${DS.colors.border}`, borderRadius: DS.radius.sm, padding: '7px 11px', fontSize: 13, outline: 'none', fontFamily: 'inherit' }} onFocus={e => e.target.style.borderColor = DS.colors.primary} onBlur={e => e.target.style.borderColor = DS.colors.border} /> Salvar
{selected.nome}
{selected.contato || ''}
{selected.categoria} {selected.status}
selected.email ? window.open(`mailto:${selected.email}`) : showToast('E-mail não cadastrado.', 'danger')}>E-mail selected.telefone ? window.open(`tel:${selected.telefone.replace(/\D/g, '')}`) : showToast('Telefone não cadastrado.', 'danger')}>Ligar
Contato
{[ { icon: 'mail', label: selected.email || '—' }, { icon: 'phone', label: selected.telefone || '—' }, { icon: 'map', label: selected.cidade || '—' }, ...(selected.website ? [{ icon: 'grid', label: selected.website }] : []), ].map(r => (
{r.label}
))}
)}
{/* Modal editar */} setEditModal(false)} title="Editar Fornecedor" width={560}>
setEditForm(f => ({ ...f, nome: v }))} placeholder="Ex: Som & Luz Produções" />
setEditForm(f => ({ ...f, contato: v }))} placeholder="Ex: Roberto Lima" /> setEditForm(f => ({ ...f, cidade: v }))} placeholder="Ex: Fortaleza" />
setEditForm(f => ({ ...f, email: v }))} placeholder="Ex: contato@empresa.com" /> setEditForm(f => ({ ...f, telefone: v }))} placeholder="Ex: (85) 99999-0000" />
setEditForm(f => ({ ...f, status: v }))} options={[{ value: 'Ativo', label: 'Ativo' }, { value: 'Inativo', label: 'Inativo' }]} />
setEditForm(f => ({ ...f, website: v }))} placeholder="Ex: www.empresa.com.br" />
setEditModal(false)}>Cancelar {saving ? 'Salvando…' : 'Salvar alterações'}
{/* Modal exclusão */} setDelConfirm(false)} title="Excluir fornecedor" width={400}>

Tem certeza que deseja excluir {selected?.nome}? Esta ação não pode ser desfeita.

setDelConfirm(false)}>Cancelar Excluir
{/* Modal novo */} { setAddModal(false); setForm(emptyForm); }} title="Novo Fornecedor" width={560}>
setForm(f => ({ ...f, nome: v }))} placeholder="Ex: Som & Luz Produções" />
setForm(f => ({ ...f, contato: v }))} placeholder="Ex: Roberto Lima" /> setForm(f => ({ ...f, cidade: v }))} placeholder="Ex: Fortaleza" />
setForm(f => ({ ...f, email: v }))} placeholder="Ex: contato@empresa.com" /> setForm(f => ({ ...f, telefone: v }))} placeholder="Ex: (85) 99999-0000" />
setForm(f => ({ ...f, status: v }))} options={[{ value: 'Ativo', label: 'Ativo' }, { value: 'Inativo', label: 'Inativo' }]} />
setForm(f => ({ ...f, website: v }))} placeholder="Ex: www.empresa.com.br" />
{ setAddModal(false); setForm(emptyForm); }}>Cancelar {saving ? 'Salvando…' : 'Adicionar fornecedor'}
{toast && setToast(null)} />}
); } Object.assign(window, { Fornecedores });