-
Notifications
You must be signed in to change notification settings - Fork 325
Description
import { useState, useEffect } from "react";
const MATERIAIS = [
{ id: "ferro", nome: "Ferro", cor: "#6B7280", unidade: "kg" },
{ id: "cobre", nome: "Cobre", cor: "#D97706", unidade: "kg" },
{ id: "aluminio", nome: "Alumínio", cor: "#60A5FA", unidade: "kg" },
{ id: "bronze", nome: "Bronze", cor: "#B45309", unidade: "kg" },
{ id: "latao", nome: "Latão", cor: "#F59E0B", unidade: "kg" },
{ id: "inox", nome: "Inox", cor: "#9CA3AF", unidade: "kg" },
{ id: "radiador", nome: "Radiador", cor: "#EF4444", unidade: "kg" },
{ id: "bateria", nome: "Bateria", cor: "#7C3AED", unidade: "kg" },
{ id: "fio", nome: "Fios/Cabos", cor: "#EC4899", unidade: "kg" },
{ id: "catalisador", nome: "Catalisador", cor: "#10B981", unidade: "und" },
];
const ESTADOS = ["AC","AL","AP","AM","BA","CE","DF","ES","GO","MA","MT","MS","MG","PA","PB","PR","PE","PI","RJ","RN","RS","RO","RR","SC","SP","SE","TO"];
const formatBRL = (v) => new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(v || 0);
const hoje = () => new Date().toISOString().split("T")[0];
const fmtDate = (d) => d ? new Date(d + "T00:00").toLocaleDateString("pt-BR") : "-";
const initialPrecos = {
ferro: { compra: 0.45, venda: 0.60 }, cobre: { compra: 28.0, venda: 35.0 },
aluminio: { compra: 5.5, venda: 7.0 }, bronze: { compra: 18.0, venda: 23.0 },
latao: { compra: 15.0, venda: 20.0 }, inox: { compra: 4.5, venda: 6.0 },
radiador: { compra: 3.5, venda: 5.0 }, bateria: { compra: 3.0, venda: 4.5 },
fio: { compra: 8.0, venda: 12.0 }, catalisador: { compra: 120.0, venda: 180.0 },
};
const FORN_VAZIO = {
nome: "", telefone: "", whatsapp: "", email: "",
endereco: "", numero: "", bairro: "", cidade: "Belo Horizonte", estado: "MG",
cpfCnpj: "", tipo: "pessoa_fisica", tipoFornecedor: "oficina",
materiaisPrincipais: [], obs: "", ativo: true,
};
const S = {
app: { fontFamily: "'Segoe UI', sans-serif", background: "#0F172A", minHeight: "100vh", color: "#E2E8F0" },
header: { background: "linear-gradient(135deg, #1E3A5F 0%, #0F2744 100%)", padding: "16px 24px", display: "flex", alignItems: "center", gap: 12, borderBottom: "1px solid #1E40AF" },
logo: { fontSize: 26, fontWeight: 800, background: "linear-gradient(90deg, #34D399, #60A5FA)", WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent" },
nav: { display: "flex", gap: 4, padding: "10px 24px", background: "#1E293B", overflowX: "auto" },
page: { padding: "24px", maxWidth: 1200, margin: "0 auto" },
card: { background: "#1E293B", borderRadius: 12, padding: 20, border: "1px solid #334155" },
cardG: { background: "linear-gradient(135deg,#064E3B,#065F46)", borderRadius: 12, padding: 20, border: "1px solid #10B981" },
cardB: { background: "linear-gradient(135deg,#1E3A8A,#1D4ED8)", borderRadius: 12, padding: 20, border: "1px solid #3B82F6" },
cardR: { background: "linear-gradient(135deg,#7F1D1D,#991B1B)", borderRadius: 12, padding: 20, border: "1px solid #EF4444" },
grid2: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 16 },
grid3: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(170px,1fr))", gap: 12 },
grid4: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 16 },
label: { fontSize: 11, color: "#94A3B8", marginBottom: 4, display: "block", textTransform: "uppercase", letterSpacing: "0.5px" },
bigNum: { fontSize: 26, fontWeight: 800 },
sub: { fontSize: 12, color: "#94A3B8", marginTop: 4 },
input: { width: "100%", background: "#0F172A", border: "1px solid #334155", borderRadius: 8, padding: "9px 12px", color: "#E2E8F0", fontSize: 14, boxSizing: "border-box" },
select: { width: "100%", background: "#0F172A", border: "1px solid #334155", borderRadius: 8, padding: "9px 12px", color: "#E2E8F0", fontSize: 14, boxSizing: "border-box" },
textarea: { width: "100%", background: "#0F172A", border: "1px solid #334155", borderRadius: 8, padding: "9px 12px", color: "#E2E8F0", fontSize: 13, boxSizing: "border-box", resize: "vertical", minHeight: 70 },
btn: (c) => ({ background: c || "#2563EB", color: "#fff", border: "none", borderRadius: 8, padding: "9px 18px", cursor: "pointer", fontWeight: 700, fontSize: 13 }),
btnSm: (c) => ({ background: c || "#334155", color: "#fff", border: "none", borderRadius: 6, padding: "5px 12px", cursor: "pointer", fontWeight: 600, fontSize: 12 }),
table: { width: "100%", borderCollapse: "collapse" },
th: { background: "#0F172A", color: "#64748B", padding: "10px 12px", textAlign: "left", fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.5px" },
td: { padding: "10px 12px", fontSize: 13, borderBottom: "1px solid #1E293B" },
h2: { fontSize: 18, fontWeight: 700, marginBottom: 16, color: "#F1F5F9" },
h3: { fontSize: 12, fontWeight: 700, color: "#64748B", marginBottom: 10, textTransform: "uppercase", letterSpacing: "0.8px", borderBottom: "1px solid #334155", paddingBottom: 8 },
row: { display: "flex", gap: 12, flexWrap: "wrap" },
fg: { flex: 1, minWidth: 140 },
badge: (c) => ({ background: c + "25", color: c, padding: "2px 10px", borderRadius: 20, fontSize: 11, fontWeight: 700, display: "inline-block" }),
};
export default function App() {
const [aba, setAba] = useState("dashboard");
const [precos, setPrecos] = useState(initialPrecos);
const [compras, setCompras] = useState([]);
const [vendas, setVendas] = useState([]);
const [despesas, setDespesas] = useState([]);
const [estoque, setEstoque] = useState({});
const [fornecedores, setFornecedores] = useState([]);
const [formForn, setFormForn] = useState(FORN_VAZIO);
const [editFornId, setEditFornId] = useState(null);
const [buscaForn, setBuscaForn] = useState("");
const [filtroAtivo, setFiltroAtivo] = useState("todos");
const [detalhe, setDetalhe] = useState(null);
const [formCompra, setFormCompra] = useState({ data: hoje(), material: "ferro", quantidade: "", fornecedorId: "", obs: "" });
const [formVenda, setFormVenda] = useState({ data: hoje(), material: "ferro", quantidade: "", cliente: "", obs: "" });
const [formDespesa, setFormDespesa] = useState({ data: hoje(), descricao: "", valor: "", categoria: "operacional" });
useEffect(() => {
const est = {};
MATERIAIS.forEach(m => { est[m.id] = 0; });
compras.forEach(c => { est[c.material] = (est[c.material] || 0) + Number(c.quantidade); });
vendas.forEach(v => { est[v.material] = (est[v.material] || 0) - Number(v.quantidade); });
setEstoque(est);
}, [compras, vendas]);
const toggleMat = (mid) => {
const a = formForn.materiaisPrincipais || [];
setFormForn({ ...formForn, materiaisPrincipais: a.includes(mid) ? a.filter(x => x !== mid) : [...a, mid] });
};
const saveForn = () => {
if (!formForn.nome.trim()) return alert("Informe o nome!");
if (editFornId) {
setFornecedores(fornecedores.map(f => f.id === editFornId ? { ...formForn, id: editFornId } : f));
setEditFornId(null);
} else {
setFornecedores([...fornecedores, { ...formForn, id: Date.now(), cadastradoEm: hoje() }]);
}
setFormForn(FORN_VAZIO);
};
const editarForn = (f) => { setFormForn({ ...f }); setEditFornId(f.id); setDetalhe(null); };
const cancelarEdicao = () => { setFormForn(FORN_VAZIO); setEditFornId(null); };
const deletarForn = (id) => { if (!window.confirm("Excluir fornecedor?")) return; setFornecedores(fornecedores.filter(f => f.id !== id)); if (detalhe?.id === id) setDetalhe(null); };
const toggleAtivoForn = (id) => setFornecedores(fornecedores.map(f => f.id === id ? { ...f, ativo: !f.ativo } : f));
const comprasDeForn = (id) => compras.filter(c => Number(c.fornecedorId) === id);
const totalDeForn = (id) => comprasDeForn(id).reduce((s, c) => s + c.total, 0);
const fornFiltrados = fornecedores.filter(f => {
const ok = f.nome.toLowerCase().includes(buscaForn.toLowerCase()) ||
(f.telefone || "").includes(buscaForn) ||
(f.cidade || "").toLowerCase().includes(buscaForn.toLowerCase()) ||
(f.cpfCnpj || "").includes(buscaForn);
if (filtroAtivo === "ativos") return ok && f.ativo;
if (filtroAtivo === "inativos") return ok && !f.ativo;
return ok;
});
const addCompra = () => {
if (!formCompra.quantidade || Number(formCompra.quantidade) <= 0) return alert("Informe a quantidade!");
const preco = precos[formCompra.material]?.compra || 0;
const forn = fornecedores.find(f => f.id === Number(formCompra.fornecedorId));
setCompras([...compras, { ...formCompra, id: Date.now(), preco, total: preco * Number(formCompra.quantidade), fornecedorNome: forn?.nome || "Avulso" }]);
setFormCompra({ data: hoje(), material: "ferro", quantidade: "", fornecedorId: "", obs: "" });
};
const addVenda = () => {
if (!formVenda.quantidade || Number(formVenda.quantidade) <= 0) return alert("Informe a quantidade!");
const disp = estoque[formVenda.material] || 0;
if (Number(formVenda.quantidade) > disp) return alert("Estoque insuficiente! Disponível: " + disp.toFixed(2));
const preco = precos[formVenda.material]?.venda || 0;
setVendas([...vendas, { ...formVenda, id: Date.now(), preco, total: preco * Number(formVenda.quantidade) }]);
setFormVenda({ data: hoje(), material: "ferro", quantidade: "", cliente: "", obs: "" });
};
const addDespesa = () => {
if (!formDespesa.valor || !formDespesa.descricao) return alert("Preencha todos os campos!");
setDespesas([...despesas, { ...formDespesa, id: Date.now(), valor: Number(formDespesa.valor) }]);
setFormDespesa({ data: hoje(), descricao: "", valor: "", categoria: "operacional" });
};
const filtrarHoje = (arr) => arr.filter(i => i.data === hoje());
const filtrarMes = (arr) => arr.filter(i => i.data?.startsWith(hoje().slice(0, 7)));
const tch = filtrarHoje(compras).reduce((s, c) => s + c.total, 0);
const tvh = filtrarHoje(vendas).reduce((s, v) => s + v.total, 0);
const tdh = filtrarHoje(despesas).reduce((s, d) => s + d.valor, 0);
const lh = tvh - tch - tdh;
const tcm = filtrarMes(compras).reduce((s, c) => s + c.total, 0);
const tvm = filtrarMes(vendas).reduce((s, v) => s + v.total, 0);
const tdm = filtrarMes(despesas).reduce((s, d) => s + d.valor, 0);
const lm = tvm - tcm - tdm;
const diasNoMes = new Date(new Date().getFullYear(), new Date().getMonth() + 1, 0).getDate();
const diaAtual = new Date().getDate();
const fator = diasNoMes / Math.max(diaAtual, 1);
const ganhoMaterial = MATERIAIS.map(m => {
const vm = filtrarMes(vendas).filter(v => v.material === m.id);
const cm = filtrarMes(compras).filter(c => c.material === m.id);
const tv = vm.reduce((s, v) => s + v.total, 0);
const tc = cm.reduce((s, c) => s + c.total, 0);
return { ...m, tv, tc, lucro: tv - tc, qtyV: vm.reduce((s, v) => s + Number(v.quantidade), 0), qtyC: cm.reduce((s, c) => s + Number(c.quantidade), 0) };
}).filter(m => m.tv > 0 || m.tc > 0);
const matLabel = (id) => MATERIAIS.find(m => m.id === id);
const navBtn = (a) => ({ padding: "8px 14px", borderRadius: 8, border: "none", cursor: "pointer", fontWeight: 600, fontSize: 12, background: aba === a ? "#2563EB" : "transparent", color: aba === a ? "#fff" : "#94A3B8", whiteSpace: "nowrap" });
const TIPO_LABEL = { oficina: "🔧 Oficina", desmanche: "🏭 Desmanche", particular: "👤 Particular", empresa: "🏢 Empresa", coletor: "🚛 Coletor", outro: "📦 Outro" };
const abas = [
{ id: "dashboard", label: "📊 Dashboard" },
{ id: "fornecedores", label: 🏭 Fornecedores (${fornecedores.length}) },
{ id: "compras", label: "📥 Compras" },
{ id: "vendas", label: "📤 Vendas" },
{ id: "estoque", label: "📦 Estoque" },
{ id: "despesas", label: "💸 Despesas" },
{ id: "projecao", label: "📈 Projeção" },
{ id: "precos", label: "⚙️ Preços" },
];
return (
♻ LDA
<div style={{ fontWeight: 700, fontSize: 15 }}>Sistema de Controle — Reciclagem
<div style={{ fontSize: 11, color: "#94A3B8" }}>LDA Reciclagem • CNPJ 61.846.483/0001-34 • {new Date().toLocaleDateString("pt-BR", { weekday: "long", day: "2-digit", month: "long", year: "numeric" })}
{/* DASHBOARD */}
{aba === "dashboard" && (
<div>
<h2 style={S.h2}>Resumo do Dia — {new Date().toLocaleDateString("pt-BR")}</h2>
<div style={S.grid2}>
<div style={S.cardB}><span style={S.label}>💰 Compras Hoje</span><div style={S.bigNum}>{formatBRL(tch)}</div><div style={S.sub}>{filtrarHoje(compras).length} operações</div></div>
<div style={S.cardG}><span style={S.label}>🤑 Vendas Hoje</span><div style={S.bigNum}>{formatBRL(tvh)}</div><div style={S.sub}>{filtrarHoje(vendas).length} operações</div></div>
<div style={S.cardR}><span style={S.label}>💸 Despesas Hoje</span><div style={S.bigNum}>{formatBRL(tdh)}</div><div style={S.sub}>{filtrarHoje(despesas).length} lançamentos</div></div>
<div style={{ ...S.card, border: "1px solid " + (lh >= 0 ? "#10B981" : "#EF4444") }}>
<span style={S.label}>📊 Lucro Hoje</span>
<div style={{ ...S.bigNum, color: lh >= 0 ? "#34D399" : "#F87171" }}>{formatBRL(lh)}</div>
<div style={S.sub}>Margem: {tvh > 0 ? ((lh / tvh) * 100).toFixed(1) : 0}%</div>
</div>
</div>
<h2 style={{ ...S.h2, marginTop: 28 }}>Resumo do Mês</h2>
<div style={S.grid2}>
<div style={S.card}><span style={S.label}>📥 Compras Mês</span><div style={{ fontSize: 22, fontWeight: 700, color: "#60A5FA" }}>{formatBRL(tcm)}</div></div>
<div style={S.card}><span style={S.label}>📤 Vendas Mês</span><div style={{ fontSize: 22, fontWeight: 700, color: "#34D399" }}>{formatBRL(tvm)}</div></div>
<div style={S.card}><span style={S.label}>💸 Despesas Mês</span><div style={{ fontSize: 22, fontWeight: 700, color: "#F87171" }}>{formatBRL(tdm)}</div></div>
<div style={S.card}><span style={S.label}>📊 Lucro Líquido Mês</span><div style={{ fontSize: 22, fontWeight: 700, color: lm >= 0 ? "#34D399" : "#F87171" }}>{formatBRL(lm)}</div></div>
</div>
{ganhoMaterial.length > 0 && (
<><h2 style={{ ...S.h2, marginTop: 28 }}>Ganho por Material (Mês)</h2>
<div style={S.card}><table style={S.table}><thead><tr>{["Material","Kg Comprado","Kg Vendido","Custo","Receita","Lucro"].map(h => <th key={h} style={S.th}>{h}</th>)}</tr></thead>
<tbody>{ganhoMaterial.map(m => (
<tr key={m.id}>
<td style={{ ...S.td, fontWeight: 700, color: m.cor }}>{m.nome}</td>
<td style={S.td}>{m.qtyC.toFixed(2)} {m.unidade}</td>
<td style={S.td}>{m.qtyV.toFixed(2)} {m.unidade}</td>
<td style={{ ...S.td, color: "#F87171" }}>{formatBRL(m.tc)}</td>
<td style={{ ...S.td, color: "#34D399" }}>{formatBRL(m.tv)}</td>
<td style={{ ...S.td, fontWeight: 700, color: m.lucro >= 0 ? "#34D399" : "#F87171" }}>{formatBRL(m.lucro)}</td>
</tr>
))}</tbody>
</table></div></>
)}
{ganhoMaterial.length === 0 && <div style={{ ...S.card, textAlign: "center", padding: 40, color: "#64748B", marginTop: 24 }}><div style={{ fontSize: 48 }}>♻️</div><div style={{ marginTop: 8 }}>Nenhuma movimentação ainda. Cadastre fornecedores e registre compras!</div></div>}
</div>
)}
{/* FORNECEDORES */}
{aba === "fornecedores" && (
<div>
{/* FORMULÁRIO CADASTRO */}
<div style={{ ...S.card, marginBottom: 24, borderColor: editFornId ? "#F59E0B" : "#334155" }}>
<h2 style={{ ...S.h2, color: editFornId ? "#F59E0B" : "#F1F5F9", marginBottom: 20 }}>
{editFornId ? "✏️ Editando Fornecedor" : "➕ Novo Fornecedor"}
</h2>
<div style={S.h3}>📋 Identificação</div>
<div style={{ ...S.row, marginBottom: 16 }}>
<div style={{ ...S.fg, flex: 3 }}>
<label style={S.label}>Nome / Razão Social *</label>
<input type="text" style={S.input} placeholder="Nome completo ou razão social..." value={formForn.nome} onChange={e => setFormForn({ ...formForn, nome: e.target.value })} />
</div>
<div style={S.fg}>
<label style={S.label}>Tipo de Pessoa</label>
<select style={S.select} value={formForn.tipo} onChange={e => setFormForn({ ...formForn, tipo: e.target.value })}>
<option value="pessoa_fisica">Pessoa Física</option>
<option value="pessoa_juridica">Pessoa Jurídica</option>
</select>
</div>
<div style={S.fg}>
<label style={S.label}>{formForn.tipo === "pessoa_juridica" ? "CNPJ" : "CPF"}</label>
<input type="text" style={S.input} placeholder={formForn.tipo === "pessoa_juridica" ? "00.000.000/0001-00" : "000.000.000-00"} value={formForn.cpfCnpj} onChange={e => setFormForn({ ...formForn, cpfCnpj: e.target.value })} />
</div>
<div style={S.fg}>
<label style={S.label}>Tipo de Fornecedor</label>
<select style={S.select} value={formForn.tipoFornecedor} onChange={e => setFormForn({ ...formForn, tipoFornecedor: e.target.value })}>
<option value="oficina">🔧 Oficina Mecânica</option>
<option value="desmanche">🏭 Desmanche</option>
<option value="particular">👤 Particular</option>
<option value="empresa">🏢 Empresa</option>
<option value="coletor">🚛 Coletor Independente</option>
<option value="outro">📦 Outro</option>
</select>
</div>
</div>
<div style={S.h3}>📞 Contato</div>
<div style={{ ...S.row, marginBottom: 16 }}>
<div style={S.fg}>
<label style={S.label}>Telefone</label>
<input type="text" style={S.input} placeholder="(31) 99999-9999" value={formForn.telefone} onChange={e => setFormForn({ ...formForn, telefone: e.target.value })} />
</div>
<div style={S.fg}>
<label style={S.label}>WhatsApp</label>
<input type="text" style={S.input} placeholder="(31) 99999-9999" value={formForn.whatsapp} onChange={e => setFormForn({ ...formForn, whatsapp: e.target.value })} />
</div>
<div style={{ ...S.fg, flex: 2 }}>
<label style={S.label}>E-mail</label>
<input type="email" style={S.input} placeholder="email@exemplo.com" value={formForn.email} onChange={e => setFormForn({ ...formForn, email: e.target.value })} />
</div>
</div>
<div style={S.h3}>📍 Endereço</div>
<div style={{ ...S.row, marginBottom: 16 }}>
<div style={{ ...S.fg, flex: 3 }}>
<label style={S.label}>Logradouro</label>
<input type="text" style={S.input} placeholder="Rua, Avenida..." value={formForn.endereco} onChange={e => setFormForn({ ...formForn, endereco: e.target.value })} />
</div>
<div style={{ minWidth: 80 }}>
<label style={S.label}>Número</label>
<input type="text" style={S.input} placeholder="Nº" value={formForn.numero} onChange={e => setFormForn({ ...formForn, numero: e.target.value })} />
</div>
<div style={{ ...S.fg, flex: 2 }}>
<label style={S.label}>Bairro</label>
<input type="text" style={S.input} placeholder="Bairro" value={formForn.bairro} onChange={e => setFormForn({ ...formForn, bairro: e.target.value })} />
</div>
<div style={{ ...S.fg, flex: 2 }}>
<label style={S.label}>Cidade</label>
<input type="text" style={S.input} placeholder="Cidade" value={formForn.cidade} onChange={e => setFormForn({ ...formForn, cidade: e.target.value })} />
</div>
<div style={{ minWidth: 80 }}>
<label style={S.label}>UF</label>
<select style={S.select} value={formForn.estado} onChange={e => setFormForn({ ...formForn, estado: e.target.value })}>
{ESTADOS.map(e => <option key={e} value={e}>{e}</option>)}
</select>
</div>
</div>
<div style={S.h3}>♻️ Materiais que Fornece</div>
<div style={{ display: "flex", flexWrap: "wrap", gap: 8, marginBottom: 16 }}>
{MATERIAIS.map(m => {
const sel = formForn.materiaisPrincipais?.includes(m.id);
return (
<button key={m.id} onClick={() => toggleMat(m.id)} style={{
padding: "6px 14px", borderRadius: 20, border: "2px solid " + (sel ? m.cor : "#334155"),
background: sel ? m.cor + "30" : "transparent", color: sel ? m.cor : "#64748B",
cursor: "pointer", fontSize: 12, fontWeight: 600, transition: "all 0.15s"
}}>{m.nome}</button>
);
})}
</div>
<div style={S.h3}>📝 Observações e Status</div>
<div style={{ ...S.row, marginBottom: 16 }}>
<div style={{ ...S.fg, flex: 4 }}>
<label style={S.label}>Observações</label>
<textarea style={S.textarea} placeholder="Horário de atendimento, localização de referência, observações importantes..." value={formForn.obs} onChange={e => setFormForn({ ...formForn, obs: e.target.value })} />
</div>
<div style={S.fg}>
<label style={S.label}>Status</label>
<select style={S.select} value={formForn.ativo ? "ativo" : "inativo"} onChange={e => setFormForn({ ...formForn, ativo: e.target.value === "ativo" })}>
<option value="ativo">✅ Ativo</option>
<option value="inativo">⛔ Inativo</option>
</select>
</div>
</div>
<div style={{ display: "flex", gap: 10 }}>
<button style={S.btn(editFornId ? "#D97706" : "#059669")} onClick={saveForn}>
{editFornId ? "💾 Salvar Alterações" : "✅ Cadastrar Fornecedor"}
</button>
{editFornId && <button style={S.btn("#475569")} onClick={cancelarEdicao}>✕ Cancelar</button>}
</div>
</div>
{/* BUSCA */}
<div style={{ display: "flex", gap: 12, marginBottom: 16, flexWrap: "wrap", alignItems: "center" }}>
<div style={{ flex: 1, minWidth: 240 }}>
<input type="text" style={S.input} placeholder="🔍 Buscar nome, telefone, cidade, CPF/CNPJ..." value={buscaForn} onChange={e => setBuscaForn(e.target.value)} />
</div>
<div style={{ display: "flex", gap: 6 }}>
{["todos", "ativos", "inativos"].map(f => (
<button key={f} style={S.btnSm(filtroAtivo === f ? "#2563EB" : "#334155")} onClick={() => setFiltroAtivo(f)}>
{f.charAt(0).toUpperCase() + f.slice(1)}
</button>
))}
</div>
<div style={{ fontSize: 13, color: "#64748B" }}>{fornFiltrados.length} fornecedor(es)</div>
</div>
{/* CARDS FORNECEDORES */}
{fornFiltrados.length === 0 ? (
<div style={{ ...S.card, textAlign: "center", padding: 48, color: "#64748B" }}>
<div style={{ fontSize: 44, marginBottom: 12 }}>🏭</div>
<div style={{ fontSize: 16, marginBottom: 4 }}>{buscaForn ? "Nenhum resultado encontrado." : "Nenhum fornecedor cadastrado."}</div>
<div style={{ fontSize: 13 }}>Use o formulário acima para cadastrar fornecedores.</div>
</div>
) : (
<div style={S.grid4}>
{fornFiltrados.map(f => {
const total = totalDeForn(f.id);
const nComp = comprasDeForn(f.id).length;
const isOpen = detalhe?.id === f.id;
return (
<div key={f.id} style={{ ...S.card, cursor: "pointer", borderColor: isOpen ? "#3B82F6" : f.ativo ? "#334155" : "#7F1D1D", opacity: f.ativo ? 1 : 0.65, transition: "border-color 0.2s" }} onClick={() => setDetalhe(isOpen ? null : f)}>
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: 10 }}>
<div style={{ flex: 1 }}>
<div style={{ fontWeight: 700, fontSize: 15, color: "#F1F5F9", lineHeight: 1.3, marginBottom: 3 }}>{f.nome}</div>
<div style={{ fontSize: 12, color: "#64748B" }}>{TIPO_LABEL[f.tipoFornecedor] || f.tipoFornecedor}</div>
</div>
<span style={S.badge(f.ativo ? "#10B981" : "#EF4444")}>{f.ativo ? "Ativo" : "Inativo"}</span>
</div>
{f.telefone && <div style={{ fontSize: 12, color: "#94A3B8", marginBottom: 3 }}>📞 {f.telefone}</div>}
{f.whatsapp && f.whatsapp !== f.telefone && <div style={{ fontSize: 12, color: "#94A3B8", marginBottom: 3 }}>💬 {f.whatsapp}</div>}
{(f.cidade || f.estado) && <div style={{ fontSize: 12, color: "#94A3B8", marginBottom: 3 }}>📍 {[f.bairro, f.cidade, f.estado].filter(Boolean).join(", ")}</div>}
{f.cpfCnpj && <div style={{ fontSize: 12, color: "#64748B", marginBottom: 3 }}>🪪 {f.cpfCnpj}</div>}
{f.materiaisPrincipais?.length > 0 && (
<div style={{ display: "flex", flexWrap: "wrap", gap: 4, marginTop: 8 }}>
{f.materiaisPrincipais.map(mid => {
const m = MATERIAIS.find(x => x.id === mid);
return m ? <span key={mid} style={{ ...S.badge(m.cor), fontSize: 10 }}>{m.nome}</span> : null;
})}
</div>
)}
<div style={{ borderTop: "1px solid #334155", paddingTop: 10, marginTop: 10, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
<div style={{ textAlign: "center" }}>
<div style={{ fontSize: 18, fontWeight: 800, color: "#60A5FA" }}>{nComp}</div>
<div style={{ fontSize: 10, color: "#64748B" }}>compras</div>
</div>
<div style={{ textAlign: "center" }}>
<div style={{ fontSize: 15, fontWeight: 700, color: "#34D399" }}>{formatBRL(total)}</div>
<div style={{ fontSize: 10, color: "#64748B" }}>total fornecido</div>
</div>
{f.cadastradoEm && <div style={{ textAlign: "center" }}>
<div style={{ fontSize: 12, color: "#94A3B8" }}>{fmtDate(f.cadastradoEm)}</div>
<div style={{ fontSize: 10, color: "#64748B" }}>cadastrado</div>
</div>}
</div>
<div style={{ display: "flex", gap: 6, marginTop: 12, flexWrap: "wrap" }} onClick={e => e.stopPropagation()}>
<button style={S.btnSm("#2563EB")} onClick={() => editarForn(f)}>✏️ Editar</button>
<button style={S.btnSm(f.ativo ? "#7F1D1D" : "#064E3B")} onClick={() => toggleAtivoForn(f.id)}>{f.ativo ? "⛔ Inativar" : "✅ Ativar"}</button>
{nComp === 0 && <button style={S.btnSm("#7F1D1D")} onClick={() => deletarForn(f.id)}>🗑️</button>}
<button style={S.btnSm("#1E40AF")} onClick={() => { setAba("compras"); setFormCompra({ ...formCompra, fornecedorId: String(f.id) }); }}>+ Compra</button>
</div>
{isOpen && (
<div style={{ marginTop: 14, borderTop: "1px solid #334155", paddingTop: 14 }}>
{f.endereco && <div style={{ fontSize: 12, color: "#94A3B8", marginBottom: 4 }}>🏠 {[f.endereco, f.numero, f.bairro, f.cidade + "/" + f.estado].filter(Boolean).join(", ")}</div>}
{f.email && <div style={{ fontSize: 12, color: "#94A3B8", marginBottom: 4 }}>✉️ {f.email}</div>}
{f.obs && <div style={{ fontSize: 12, background: "#0F172A", padding: "8px 10px", borderRadius: 8, color: "#94A3B8", marginTop: 6 }}>💬 {f.obs}</div>}
{nComp > 0 && (
<div style={{ marginTop: 12 }}>
<div style={{ fontSize: 11, fontWeight: 700, color: "#64748B", marginBottom: 8 }}>ÚLTIMAS COMPRAS</div>
{comprasDeForn(f.id).slice(-4).reverse().map(c => (
<div key={c.id} style={{ display: "flex", justifyContent: "space-between", fontSize: 12, padding: "5px 0", borderBottom: "1px solid #1E293B" }}>
<span style={{ color: matLabel(c.material)?.cor, fontWeight: 600 }}>{matLabel(c.material)?.nome}</span>
<span style={{ color: "#94A3B8" }}>{Number(c.quantidade).toFixed(1)} {matLabel(c.material)?.unidade}</span>
<span style={{ color: "#34D399", fontWeight: 700 }}>{formatBRL(c.total)}</span>
<span style={{ color: "#64748B" }}>{fmtDate(c.data)}</span>
</div>
))}
</div>
)}
</div>
)}
</div>
);
})}
</div>
)}
</div>
)}
{/* COMPRAS */}
{aba === "compras" && (
<div>
<h2 style={S.h2}>Registrar Compra</h2>
<div style={S.card}>
<div style={S.row}>
<div style={S.fg}><label style={S.label}>Data</label><input type="date" style={S.input} value={formCompra.data} onChange={e => setFormCompra({ ...formCompra, data: e.target.value })} /></div>
<div style={S.fg}><label style={S.label}>Material</label>
<select style={S.select} value={formCompra.material} onChange={e => setFormCompra({ ...formCompra, material: e.target.value })}>
{MATERIAIS.map(m => <option key={m.id} value={m.id}>{m.nome}</option>)}
</select>
</div>
<div style={S.fg}><label style={S.label}>Qtd ({matLabel(formCompra.material)?.unidade})</label><input type="number" style={S.input} placeholder="0,00" value={formCompra.quantidade} onChange={e => setFormCompra({ ...formCompra, quantidade: e.target.value })} /></div>
<div style={S.fg}><label style={S.label}>R$/unit</label><input style={{ ...S.input, background: "#1E293B" }} value={formatBRL(precos[formCompra.material]?.compra || 0)} readOnly /></div>
<div style={S.fg}><label style={S.label}>Total</label><input style={{ ...S.input, background: "#1E293B", color: "#60A5FA" }} value={formatBRL((precos[formCompra.material]?.compra || 0) * (formCompra.quantidade || 0))} readOnly /></div>
</div>
<div style={{ ...S.row, marginTop: 12 }}>
<div style={{ ...S.fg, flex: 2 }}><label style={S.label}>Fornecedor</label>
<select style={S.select} value={formCompra.fornecedorId} onChange={e => setFormCompra({ ...formCompra, fornecedorId: e.target.value })}>
<option value="">— Avulso / Sem cadastro —</option>
{fornecedores.filter(f => f.ativo).map(f => <option key={f.id} value={f.id}>{f.nome}{f.cidade ? " (" + f.cidade + ")" : ""}</option>)}
</select>
</div>
<div style={{ ...S.fg, flex: 2 }}><label style={S.label}>Observação</label><input type="text" style={S.input} placeholder="Obs..." value={formCompra.obs} onChange={e => setFormCompra({ ...formCompra, obs: e.target.value })} /></div>
<div style={{ display: "flex", alignItems: "flex-end" }}><button style={S.btn("#059669")} onClick={addCompra}>+ Registrar</button></div>
</div>
</div>
<h2 style={{ ...S.h2, marginTop: 24 }}>Histórico de Compras</h2>
<div style={S.card}>
{compras.length === 0 ? <div style={{ textAlign: "center", color: "#64748B", padding: 32 }}>Nenhuma compra registrada.</div> :
<table style={S.table}><thead><tr>{["Data", "Material", "Qtd", "R$/unit", "Total", "Fornecedor", "Obs", ""].map(h => <th key={h} style={S.th}>{h}</th>)}</tr></thead>
<tbody>{[...compras].reverse().map(c => (
<tr key={c.id}>
<td style={S.td}>{fmtDate(c.data)}</td>
<td style={{ ...S.td, color: matLabel(c.material)?.cor, fontWeight: 600 }}>{matLabel(c.material)?.nome}</td>
<td style={S.td}>{Number(c.quantidade).toFixed(2)} {matLabel(c.material)?.unidade}</td>
<td style={S.td}>{formatBRL(c.preco)}</td>
<td style={{ ...S.td, color: "#F87171", fontWeight: 700 }}>{formatBRL(c.total)}</td>
<td style={S.td}>{c.fornecedorNome || "Avulso"}</td>
<td style={S.td}>{c.obs || "-"}</td>
<td style={S.td}><button style={{ ...S.btn("#991B1B"), padding: "4px 10px", fontSize: 12 }} onClick={() => setCompras(compras.filter(x => x.id !== c.id))}>✕</button></td>
</tr>
))}</tbody>
</table>}
</div>
</div>
)}
{/* VENDAS */}
{aba === "vendas" && (
<div>
<h2 style={S.h2}>Registrar Venda</h2>
<div style={S.card}>
<div style={S.row}>
<div style={S.fg}><label style={S.label}>Data</label><input type="date" style={S.input} value={formVenda.data} onChange={e => setFormVenda({ ...formVenda, data: e.target.value })} /></div>
<div style={S.fg}><label style={S.label}>Material</label>
<select style={S.select} value={formVenda.material} onChange={e => setFormVenda({ ...formVenda, material: e.target.value })}>
{MATERIAIS.map(m => <option key={m.id} value={m.id}>{m.nome} (est: {(estoque[m.id] || 0).toFixed(2)} {m.unidade})</option>)}
</select>
</div>
<div style={S.fg}><label style={S.label}>Qtd ({matLabel(formVenda.material)?.unidade})</label><input type="number" style={S.input} placeholder="0,00" value={formVenda.quantidade} onChange={e => setFormVenda({ ...formVenda, quantidade: e.target.value })} /></div>
<div style={S.fg}><label style={S.label}>R$/unit</label><input style={{ ...S.input, background: "#1E293B" }} value={formatBRL(precos[formVenda.material]?.venda || 0)} readOnly /></div>
<div style={S.fg}><label style={S.label}>Total</label><input style={{ ...S.input, background: "#1E293B", color: "#34D399" }} value={formatBRL((precos[formVenda.material]?.venda || 0) * (formVenda.quantidade || 0))} readOnly /></div>
</div>
<div style={{ ...S.row, marginTop: 12 }}>
<div style={{ ...S.fg, flex: 2 }}><label style={S.label}>Cliente</label><input type="text" style={S.input} placeholder="Nome do cliente..." value={formVenda.cliente} onChange={e => setFormVenda({ ...formVenda, cliente: e.target.value })} /></div>
<div style={{ ...S.fg, flex: 2 }}><label style={S.label}>Observação</label><input type="text" style={S.input} placeholder="Obs..." value={formVenda.obs} onChange={e => setFormVenda({ ...formVenda, obs: e.target.value })} /></div>
<div style={{ display: "flex", alignItems: "flex-end" }}><button style={S.btn("#2563EB")} onClick={addVenda}>+ Registrar</button></div>
</div>
</div>
<h2 style={{ ...S.h2, marginTop: 24 }}>Histórico de Vendas</h2>
<div style={S.card}>
{vendas.length === 0 ? <div style={{ textAlign: "center", color: "#64748B", padding: 32 }}>Nenhuma venda registrada.</div> :
<table style={S.table}><thead><tr>{["Data", "Material", "Qtd", "R$/unit", "Total", "Cliente", "Obs", ""].map(h => <th key={h} style={S.th}>{h}</th>)}</tr></thead>
<tbody>{[...vendas].reverse().map(v => (
<tr key={v.id}>
<td style={S.td}>{fmtDate(v.data)}</td>
<td style={{ ...S.td, color: matLabel(v.material)?.cor, fontWeight: 600 }}>{matLabel(v.material)?.nome}</td>
<td style={S.td}>{Number(v.quantidade).toFixed(2)} {matLabel(v.material)?.unidade}</td>
<td style={S.td}>{formatBRL(v.preco)}</td>
<td style={{ ...S.td, color: "#34D399", fontWeight: 700 }}>{formatBRL(v.total)}</td>
<td style={S.td}>{v.cliente || "-"}</td>
<td style={S.td}>{v.obs || "-"}</td>
<td style={S.td}><button style={{ ...S.btn("#991B1B"), padding: "4px 10px", fontSize: 12 }} onClick={() => setVendas(vendas.filter(x => x.id !== v.id))}>✕</button></td>
</tr>
))}</tbody>
</table>}
</div>
</div>
)}
{/* ESTOQUE */}
{aba === "estoque" && (
<div>
<h2 style={S.h2}>Estoque Atual</h2>
<div style={S.grid3}>
{MATERIAIS.map(m => {
const qty = estoque[m.id] || 0;
const vc = qty * (precos[m.id]?.compra || 0);
const vv = qty * (precos[m.id]?.venda || 0);
return (
<div key={m.id} style={{ ...S.card, borderLeft: "4px solid " + m.cor }}>
<div style={{ fontWeight: 700, color: m.cor, fontSize: 15, marginBottom: 8 }}>{m.nome}</div>
<div style={{ fontSize: 22, fontWeight: 800, color: qty > 0 ? "#F1F5F9" : "#64748B" }}>{qty.toFixed(2)} <span style={{ fontSize: 12, fontWeight: 400 }}>{m.unidade}</span></div>
<div style={{ marginTop: 8, fontSize: 12, color: "#94A3B8" }}>
<div>Custo: {formatBRL(vc)}</div>
<div style={{ color: "#34D399" }}>Venda: {formatBRL(vv)}</div>
{qty > 0 && <div style={{ color: "#F59E0B", fontWeight: 600 }}>Margem: {formatBRL(vv - vc)}</div>}
</div>
</div>
);
})}
</div>
<div style={{ ...S.card, marginTop: 20 }}>
<div style={{ display: "flex", justifyContent: "space-between", flexWrap: "wrap", gap: 16 }}>
<div><span style={S.label}>Total em Custo</span><div style={{ fontSize: 22, fontWeight: 700, color: "#F87171" }}>{formatBRL(MATERIAIS.reduce((s, m) => s + (estoque[m.id] || 0) * (precos[m.id]?.compra || 0), 0))}</div></div>
<div><span style={S.label}>Total Valor Venda</span><div style={{ fontSize: 22, fontWeight: 700, color: "#34D399" }}>{formatBRL(MATERIAIS.reduce((s, m) => s + (estoque[m.id] || 0) * (precos[m.id]?.venda || 0), 0))}</div></div>
<div><span style={S.label}>Margem Potencial</span><div style={{ fontSize: 22, fontWeight: 700, color: "#F59E0B" }}>{formatBRL(MATERIAIS.reduce((s, m) => s + (estoque[m.id] || 0) * ((precos[m.id]?.venda || 0) - (precos[m.id]?.compra || 0)), 0))}</div></div>
</div>
</div>
</div>
)}
{/* DESPESAS */}
{aba === "despesas" && (
<div>
<h2 style={S.h2}>Lançar Despesa</h2>
<div style={S.card}>
<div style={S.row}>
<div style={S.fg}><label style={S.label}>Data</label><input type="date" style={S.input} value={formDespesa.data} onChange={e => setFormDespesa({ ...formDespesa, data: e.target.value })} /></div>
<div style={{ ...S.fg, flex: 3 }}><label style={S.label}>Descrição</label><input type="text" style={S.input} placeholder="Ex: combustível, aluguel container..." value={formDespesa.descricao} onChange={e => setFormDespesa({ ...formDespesa, descricao: e.target.value })} /></div>
<div style={S.fg}><label style={S.label}>Categoria</label>
<select style={S.select} value={formDespesa.categoria} onChange={e => setFormDespesa({ ...formDespesa, categoria: e.target.value })}>
<option value="operacional">Operacional</option>
<option value="transporte">Transporte</option>
<option value="pessoal">Pessoal</option>
<option value="administrativo">Administrativo</option>
<option value="outros">Outros</option>
</select>
</div>
<div style={S.fg}><label style={S.label}>Valor (R$)</label><input type="number" style={S.input} placeholder="0,00" value={formDespesa.valor} onChange={e => setFormDespesa({ ...formDespesa, valor: e.target.value })} /></div>
<div style={{ display: "flex", alignItems: "flex-end" }}><button style={S.btn("#DC2626")} onClick={addDespesa}>+ Lançar</button></div>
</div>
</div>
<h2 style={{ ...S.h2, marginTop: 24 }}>Histórico de Despesas</h2>
<div style={S.card}>
{despesas.length === 0 ? <div style={{ textAlign: "center", color: "#64748B", padding: 32 }}>Nenhuma despesa lançada.</div> :
<table style={S.table}><thead><tr>{["Data", "Descrição", "Categoria", "Valor", ""].map(h => <th key={h} style={S.th}>{h}</th>)}</tr></thead>
<tbody>{[...despesas].reverse().map(d => (
<tr key={d.id}>
<td style={S.td}>{fmtDate(d.data)}</td>
<td style={S.td}>{d.descricao}</td>
<td style={S.td}><span style={{ background: "#0F172A", padding: "2px 8px", borderRadius: 12, fontSize: 11 }}>{d.categoria}</span></td>
<td style={{ ...S.td, color: "#F87171", fontWeight: 700 }}>{formatBRL(d.valor)}</td>
<td style={S.td}><button style={{ ...S.btn("#991B1B"), padding: "4px 10px", fontSize: 12 }} onClick={() => setDespesas(despesas.filter(x => x.id !== d.id))}>✕</button></td>
</tr>
))}</tbody>
</table>}
</div>
</div>
)}
{/* PROJEÇÃO */}
{aba === "projecao" && (
<div>
<h2 style={S.h2}>Projeção — {new Date().toLocaleDateString("pt-BR", { month: "long", year: "numeric" })}</h2>
<div style={{ ...S.card, background: "linear-gradient(135deg,#0F2744,#1E3A5F)", marginBottom: 24, borderColor: "#1D4ED8" }}>
<div style={{ fontSize: 13, color: "#94A3B8", marginBottom: 16 }}>📅 Dia {diaAtual} de {diasNoMes} | Projeção proporcional ao mês completo</div>
<div style={S.grid2}>
<div><span style={S.label}>📤 Projeção Vendas</span><div style={{ fontSize: 26, fontWeight: 800, color: "#34D399" }}>{formatBRL(tvm * fator)}</div><div style={S.sub}>Real até hoje: {formatBRL(tvm)}</div></div>
<div><span style={S.label}>📊 Projeção Lucro</span><div style={{ fontSize: 26, fontWeight: 800, color: lm * fator >= 0 ? "#F59E0B" : "#F87171" }}>{formatBRL(lm * fator)}</div><div style={S.sub}>Real até hoje: {formatBRL(lm)}</div></div>
<div><span style={S.label}>💰 Projeção Compras</span><div style={{ fontSize: 26, fontWeight: 800, color: "#60A5FA" }}>{formatBRL(tcm * fator)}</div><div style={S.sub}>Real até hoje: {formatBRL(tcm)}</div></div>
<div><span style={S.label}>💸 Projeção Despesas</span><div style={{ fontSize: 26, fontWeight: 800, color: "#F87171" }}>{formatBRL(tdm * fator)}</div><div style={S.sub}>Real até hoje: {formatBRL(tdm)}</div></div>
</div>
</div>
<h2 style={S.h2}>Por Material</h2>
<div style={S.card}>
{ganhoMaterial.length === 0 ? <div style={{ textAlign: "center", color: "#64748B", padding: 32 }}>Registre movimentações para ver a projeção por material.</div> :
<table style={S.table}><thead><tr>{["Material", "Lucro Real", "Projeção Mês", "Média/dia"].map(h => <th key={h} style={S.th}>{h}</th>)}</tr></thead>
<tbody>{ganhoMaterial.map(m => (
<tr key={m.id}>
<td style={{ ...S.td, color: m.cor, fontWeight: 600 }}>{m.nome}</td>
<td style={{ ...S.td, color: m.lucro >= 0 ? "#34D399" : "#F87171" }}>{formatBRL(m.lucro)}</td>
<td style={{ ...S.td, color: "#F59E0B", fontWeight: 700 }}>{formatBRL(m.lucro * fator)}</td>
<td style={S.td}>{formatBRL(m.lucro / diaAtual)}/dia</td>
</tr>
))}</tbody>
</table>}
</div>
</div>
)}
{/* PREÇOS */}
{aba === "precos" && (
<div>
<h2 style={S.h2}>⚙️ Configurar Preços</h2>
<div style={{ ...S.card, marginBottom: 12, fontSize: 13, color: "#94A3B8" }}>Os preços são aplicados automaticamente nas compras e vendas.</div>
<div style={S.card}>
<table style={S.table}><thead><tr>{["Material", "Preço Compra", "Preço Venda", "Margem R$", "% Margem"].map(h => <th key={h} style={S.th}>{h}</th>)}</tr></thead>
<tbody>{MATERIAIS.map(m => {
const pc = precos[m.id]?.compra || 0;
const pv = precos[m.id]?.venda || 0;
const mg = pv - pc;
const pct = pc > 0 ? ((mg / pc) * 100).toFixed(1) : 0;
return (
<tr key={m.id}>
<td style={{ ...S.td, color: m.cor, fontWeight: 600 }}>{m.nome} ({m.unidade})</td>
<td style={S.td}><input type="number" step="0.01" style={{ ...S.input, width: 120 }} value={pc} onChange={e => setPrecos({ ...precos, [m.id]: { ...precos[m.id], compra: parseFloat(e.target.value) || 0 } })} /></td>
<td style={S.td}><input type="number" step="0.01" style={{ ...S.input, width: 120 }} value={pv} onChange={e => setPrecos({ ...precos, [m.id]: { ...precos[m.id], venda: parseFloat(e.target.value) || 0 } })} /></td>
<td style={{ ...S.td, color: mg >= 0 ? "#34D399" : "#F87171" }}>{formatBRL(mg)}</td>
<td style={{ ...S.td, color: "#F59E0B", fontWeight: 600 }}>{pct}%</td>
</tr>
);
})}</tbody>
</table>
</div>
</div>
)}
</div>
</div>
);
}