// ====== MOCK DATA — Bar/Restaurant procurement ====== const BRL = (n) => 'R$ ' + (n ?? 0).toLocaleString('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); const BRLk = (n) => { if (Math.abs(n) >= 1000) return 'R$ ' + (n / 1000).toLocaleString('pt-BR', { maximumFractionDigits: 1 }) + 'k'; return 'R$ ' + n.toLocaleString('pt-BR', { maximumFractionDigits: 0 }); }; const pad = (n, w = 3) => String(n).padStart(w, '0'); const COMPANY = { name: 'Restaurante Casa do José', cnpj: '32.481.902/0001-55', owner: 'José Alberto', role: 'Administrador', email: 'jose@casadojose.com.br', city: 'São José do Rio Preto · SP', }; const CATEGORIES = [ { key: 'hortifruti', label: 'Hortifruti', tone: 'emerald' }, { key: 'bebidas', label: 'Bebidas', tone: 'sky' }, { key: 'carnes', label: 'Carnes', tone: 'coral' }, { key: 'secos', label: 'Secos e Molhados', tone: 'amber' }, { key: 'limpeza', label: 'Limpeza', tone: 'violet' }, { key: 'descartaveis', label: 'Descartáveis', tone: 'sky' }, { key: 'laticinios', label: 'Laticínios', tone: 'amber' }, { key: 'paes', label: 'Pães e Confeitaria', tone: 'amber' }, ]; const PRODUCTS = [ { id: 'P-001', code: '7891000', name: 'Filé Mignon Bovino kg', cat: 'carnes', unit: 'kg', brand: 'Friboi', stock: 12, min: 20, lastPrice: 78.90, avgPrice: 82.40, supplier: 'Friboi Distribuidora' }, { id: 'P-002', code: '7891001', name: 'Picanha Maturada kg', cat: 'carnes', unit: 'kg', brand: 'JBS', stock: 8, min: 15, lastPrice: 96.50, avgPrice: 99.20, supplier: 'JBS Premium' }, { id: 'P-003', code: '7891002', name: 'Frango Inteiro Resfriado', cat: 'carnes', unit: 'kg', brand: 'Sadia', stock: 28, min: 25, lastPrice: 13.40, avgPrice: 14.10, supplier: 'Sadia Atacado' }, { id: 'P-004', code: '7891003', name: 'Tomate Italiano', cat: 'hortifruti', unit: 'kg', brand: 'In natura', stock: 18, min: 30, lastPrice: 6.80, avgPrice: 7.60, supplier: 'CEAGESP Box 12' }, { id: 'P-005', code: '7891004', name: 'Alface Crespa', cat: 'hortifruti', unit: 'pé', brand: 'Orgânico', stock: 14, min: 24, lastPrice: 2.50, avgPrice: 2.90, supplier: 'Sítio Verde' }, { id: 'P-006', code: '7891005', name: 'Cebola Branca', cat: 'hortifruti', unit: 'kg', brand: 'In natura', stock: 32, min: 20, lastPrice: 4.20, avgPrice: 4.80, supplier: 'CEAGESP Box 12' }, { id: 'P-007', code: '7891006', name: 'Batata Inglesa', cat: 'hortifruti', unit: 'kg', brand: 'In natura', stock: 65, min: 50, lastPrice: 4.90, avgPrice: 5.40, supplier: 'Hortifruti Norte' }, { id: 'P-008', code: '7894900', name: 'Cerveja Heineken 600ml', cat: 'bebidas', unit: 'cx 12', brand: 'Heineken', stock: 22, min: 30, lastPrice: 78.00, avgPrice: 82.50, supplier: 'AmBev Distrib' }, { id: 'P-009', code: '7894901', name: 'Cerveja Original 600ml', cat: 'bebidas', unit: 'cx 12', brand: 'Antarctica', stock: 18, min: 20, lastPrice: 65.40, avgPrice: 68.90, supplier: 'AmBev Distrib' }, { id: 'P-010', code: '7894902', name: 'Refrigerante Coca 2L', cat: 'bebidas', unit: 'cx 6', brand: 'Coca-Cola', stock: 28, min: 40, lastPrice: 48.00, avgPrice: 51.20, supplier: 'Coca-Cola FEMSA' }, { id: 'P-011', code: '7894903', name: 'Água Mineral 500ml', cat: 'bebidas', unit: 'cx 12', brand: 'Crystal', stock: 12, min: 30, lastPrice: 14.50, avgPrice: 16.20, supplier: 'Crystal Águas' }, { id: 'P-012', code: '7894904', name: 'Vinho Tinto Casa Valduga', cat: 'bebidas', unit: 'un', brand: 'Casa Valduga', stock: 9, min: 12, lastPrice: 89.90, avgPrice: 94.00, supplier: 'Decanter Wines' }, { id: 'P-013', code: '7896500', name: 'Azeite Extra Virgem 500ml', cat: 'secos', unit: 'un', brand: 'Andorinha', stock: 11, min: 18, lastPrice: 32.80, avgPrice: 36.20, supplier: 'Andorinha Brasil' }, { id: 'P-014', code: '7896501', name: 'Arroz Tio João 5kg', cat: 'secos', unit: 'pct', brand: 'Tio João', stock: 26, min: 20, lastPrice: 28.40, avgPrice: 30.50, supplier: 'Camil Atacado' }, { id: 'P-015', code: '7896502', name: 'Feijão Carioca 1kg', cat: 'secos', unit: 'pct', brand: 'Camil', stock: 34, min: 40, lastPrice: 8.20, avgPrice: 9.10, supplier: 'Camil Atacado' }, { id: 'P-016', code: '7896503', name: 'Sal Refinado 1kg', cat: 'secos', unit: 'pct', brand: 'Cisne', stock: 19, min: 15, lastPrice: 3.80, avgPrice: 4.10, supplier: 'Cisne Sais' }, { id: 'P-017', code: '7896504', name: 'Açúcar Cristal 5kg', cat: 'secos', unit: 'pct', brand: 'União', stock: 14, min: 20, lastPrice: 22.50, avgPrice: 24.80, supplier: 'União Atacado' }, { id: 'P-018', code: '7897700', name: 'Queijo Mussarela kg', cat: 'laticinios', unit: 'kg', brand: 'Tirolez', stock: 17, min: 25, lastPrice: 34.20, avgPrice: 37.80, supplier: 'Tirolez Direto' }, { id: 'P-019', code: '7897701', name: 'Leite Integral 1L', cat: 'laticinios', unit: 'cx 12', brand: 'Itambé', stock: 13, min: 20, lastPrice: 58.00, avgPrice: 62.40, supplier: 'Itambé Atacado' }, { id: 'P-020', code: '7897702', name: 'Manteiga com Sal 200g', cat: 'laticinios', unit: 'un', brand: 'Aviação', stock: 22, min: 18, lastPrice: 12.40, avgPrice: 13.20, supplier: 'Aviação Premium' }, { id: 'P-021', code: '7898800', name: 'Detergente Neutro 5L', cat: 'limpeza', unit: 'gl', brand: 'Ypê', stock: 6, min: 12, lastPrice: 28.40, avgPrice: 31.20, supplier: 'Limpar Já' }, { id: 'P-022', code: '7898801', name: 'Álcool 70º 5L', cat: 'limpeza', unit: 'gl', brand: 'Itajá', stock: 10, min: 15, lastPrice: 38.00, avgPrice: 41.50, supplier: 'Limpar Já' }, { id: 'P-023', code: '7899900', name: 'Guardanapo Folha Dupla', cat: 'descartaveis', unit: 'fdo 50', brand: 'Mili', stock: 11, min: 20, lastPrice: 18.20, avgPrice: 19.80, supplier: 'Embalux SP' }, { id: 'P-024', code: '7899901', name: 'Copo Descartável 200ml', cat: 'descartaveis', unit: 'pct 100', brand: 'Copobras', stock: 8, min: 15, lastPrice: 6.20, avgPrice: 7.10, supplier: 'Embalux SP' }, { id: 'P-025', code: '7895500', name: 'Pão Francês Congelado', cat: 'paes', unit: 'kg', brand: 'Panco', stock: 24, min: 20, lastPrice: 14.50, avgPrice: 15.20, supplier: 'Panificadora Real' }, ]; const SUPPLIERS = [ { id: 'F-01', name: 'Friboi Distribuidora', cnpj: '02.916.265/0001-60', city: 'São Paulo · SP', cats: ['carnes'], score: 92, wins: 48, response: 96, status: 'Ativo', avgDelivery: '24h', contact: 'Carlos M.', whats: '(11) 9 8821-4499', email: 'comercial@friboi.com.br', address: 'Av. Marginal Tietê, 1500 · Vila Maria · São Paulo · SP · CEP 02112-000' }, { id: 'F-02', name: 'JBS Premium', cnpj: '02.916.265/0001-61', city: 'Barueri · SP', cats: ['carnes'], score: 88, wins: 32, response: 91, status: 'Ativo', avgDelivery: '24h', contact: 'Renato P.', whats: '(11) 9 8542-1027', email: 'pedidos@jbspremium.com', address: 'Rod. Castelo Branco, km 27 · Barueri · SP · CEP 06420-000' }, { id: 'F-03', name: 'Sadia Atacado', cnpj: '20.730.099/0001-94', city: 'São Paulo · SP', cats: ['carnes', 'laticinios'], score: 85, wins: 21, response: 88, status: 'Ativo', avgDelivery: '48h', contact: 'Beatriz L.', whats: '(11) 9 9112-8800', email: 'b.lima@sadia.com.br', address: 'R. Joaquim Floriano, 920 · Itaim Bibi · São Paulo · SP · CEP 04534-002' }, { id: 'F-04', name: 'CEAGESP Box 12', cnpj: '14.829.471/0001-08', city: 'São Paulo · SP', cats: ['hortifruti'], score: 76, wins: 38, response: 82, status: 'Ativo', avgDelivery: '12h', contact: 'Sr. Antônio', whats: '(11) 9 7421-3088', email: 'box12@ceagesp.gov.br', address: 'Av. Dr. Gastão Vidigal, 1946 · Vila Leopoldina · São Paulo · SP · CEP 05316-900' }, { id: 'F-05', name: 'Sítio Verde', cnpj: '21.554.872/0001-10', city: 'Mogi das Cruzes · SP', cats: ['hortifruti'], score: 81, wins: 16, response: 94, status: 'Ativo', avgDelivery: '12h', contact: 'Dona Helena', whats: '(11) 9 8830-7122', email: 'helena@sitioverde.com.br', address: 'Estrada do Taboão, s/n · Zona Rural · Mogi das Cruzes · SP · CEP 08725-000' }, { id: 'F-06', name: 'Hortifruti Norte', cnpj: '11.448.221/0001-44', city: 'Guarulhos · SP', cats: ['hortifruti'], score: 68, wins: 12, response: 74, status: 'Em Avaliação', avgDelivery: '24h', contact: 'José A.', whats: '(11) 9 9221-4400', email: 'contato@hortifrutinorte.com', address: 'R. das Hortências, 88 · Cumbica · Guarulhos · SP · CEP 07182-110' }, { id: 'F-07', name: 'AmBev Distrib', cnpj: '07.526.557/0001-00', city: 'Jundiaí · SP', cats: ['bebidas'], score: 95, wins: 54, response: 98, status: 'Ativo', avgDelivery: '48h', contact: 'Equipe AmBev', whats: '(11) 4 0040-7700', email: 'b2b@ambev.com.br', address: 'R. Dr. Renato Paes de Barros, 1017 · Itaim Bibi · São Paulo · SP · CEP 04530-001' }, { id: 'F-08', name: 'Coca-Cola FEMSA', cnpj: '47.866.934/0001-74', city: 'Itapecerica · SP', cats: ['bebidas'], score: 90, wins: 27, response: 95, status: 'Ativo', avgDelivery: '48h', contact: 'Atendimento', whats: '0800 770 2622', email: 'sac@kof.com.mx', address: 'Av. Pres. Juscelino Kubitschek, 1455 · Vila Nova Conceição · São Paulo · SP · CEP 04543-011' }, { id: 'F-09', name: 'Crystal Águas', cnpj: '60.409.075/0001-52', city: 'Caçapava · SP', cats: ['bebidas'], score: 79, wins: 14, response: 86, status: 'Ativo', avgDelivery: '24h', contact: 'Lúcia S.', whats: '(12) 9 8001-2244', email: 'comercial@crystal.com.br', address: 'Rod. Pres. Dutra, km 132 · Caçapava · SP · CEP 12281-000' }, { id: 'F-10', name: 'Decanter Wines', cnpj: '88.121.745/0001-22', city: 'São Paulo · SP', cats: ['bebidas'], score: 87, wins: 9, response: 92, status: 'Ativo', avgDelivery: '72h', contact: 'Marcelo V.', whats: '(11) 9 7700-3120', email: 'marcelo@decanterwines.com.br', address: 'R. Pamplona, 1325 · Jardim Paulista · São Paulo · SP · CEP 01405-002' }, { id: 'F-11', name: 'Andorinha Brasil', cnpj: '47.123.890/0001-35', city: 'Santos · SP', cats: ['secos'], score: 84, wins: 22, response: 90, status: 'Ativo', avgDelivery: '48h', contact: 'Importadora AB', whats: '(13) 3 233-9090', email: 'vendas@andorinha.com.br', address: 'R. Visconde de São Leopoldo, 540 · Vila Belmiro · Santos · SP · CEP 11075-440' }, { id: 'F-12', name: 'Camil Atacado', cnpj: '64.904.295/0001-03', city: 'Itaquaquecetuba · SP', cats: ['secos'], score: 89, wins: 29, response: 93, status: 'Ativo', avgDelivery: '48h', contact: 'Equipe Camil', whats: '(11) 4 770-9900', email: 'atacado@camil.com.br', address: 'Av. Itaquaquecetuba, 2000 · Distrito Industrial · Itaquaquecetuba · SP · CEP 08572-280' }, { id: 'F-13', name: 'Cisne Sais', cnpj: '92.110.554/0001-89', city: 'Cabo Frio · RJ', cats: ['secos'], score: 72, wins: 8, response: 80, status: 'Ativo', avgDelivery: '72h', contact: 'Cisne S.A.', whats: '(22) 2 644-7700', email: 'contato@cisnesais.com.br', address: 'Av. Salinas, 1200 · Salinas · Cabo Frio · RJ · CEP 28909-000' }, { id: 'F-14', name: 'União Atacado', cnpj: '60.523.211/0001-12', city: 'Limeira · SP', cats: ['secos'], score: 83, wins: 19, response: 88, status: 'Ativo', avgDelivery: '48h', contact: 'União Cosan', whats: '(19) 3 555-7800', email: 'atacado@uniaocosan.com.br', address: 'Av. Brasil, 880 · Centro · Limeira · SP · CEP 13480-200' }, { id: 'F-15', name: 'Tirolez Direto', cnpj: '44.118.776/0001-50', city: 'Tiete · SP', cats: ['laticinios'], score: 91, wins: 24, response: 96, status: 'Ativo', avgDelivery: '48h', contact: 'Pedro T.', whats: '(15) 9 8800-4422', email: 'pedro@tirolez.com.br', address: 'Estrada Tirolez, 100 · Zona Rural · Tietê · SP · CEP 18530-000' }, { id: 'F-16', name: 'Itambé Atacado', cnpj: '17.211.339/0001-66', city: 'Pará de Minas · MG', cats: ['laticinios'], score: 86, wins: 18, response: 89, status: 'Ativo', avgDelivery: '72h', contact: 'Equipe Itambé', whats: '(31) 3 233-2200', email: 'b2b@itambe.com.br', address: 'Av. dos Lácteos, 2500 · Distrito Industrial · Pará de Minas · MG · CEP 35660-000' }, { id: 'F-17', name: 'Aviação Premium', cnpj: '52.330.097/0001-18', city: 'Patrocínio · MG', cats: ['laticinios'], score: 80, wins: 11, response: 85, status: 'Ativo', avgDelivery: '72h', contact: 'Sandra M.', whats: '(34) 9 8442-6611', email: 'sandra@aviacaopremium.com.br', address: 'Fazenda Aviação · Zona Rural · Patrocínio · MG · CEP 38740-000' }, { id: 'F-18', name: 'Limpar Já', cnpj: '67.881.220/0001-09', city: 'Diadema · SP', cats: ['limpeza'], score: 74, wins: 13, response: 81, status: 'Ativo', avgDelivery: '48h', contact: 'Roberto F.', whats: '(11) 9 8221-7700', email: 'pedidos@limparja.com.br', address: 'R. das Indústrias, 1450 · Centro · Diadema · SP · CEP 09910-410' }, { id: 'F-19', name: 'Embalux SP', cnpj: '33.220.991/0001-77', city: 'São Bernardo · SP', cats: ['descartaveis'], score: 78, wins: 17, response: 84, status: 'Ativo', avgDelivery: '48h', contact: 'Comercial EB', whats: '(11) 4 332-8800', email: 'vendas@embalux.com.br', address: 'Av. Faria Lima, 4500 · Itaim Bibi · São Paulo · SP · CEP 04538-132' }, { id: 'F-20', name: 'Panificadora Real', cnpj: '21.119.802/0001-44', city: 'Mogi das Cruzes · SP', cats: ['paes'], score: 88, wins: 15, response: 94, status: 'Ativo', avgDelivery: '24h', contact: 'João R.', whats: '(11) 9 7330-2299', email: 'joao@panreal.com.br', address: 'R. Coronel Almeida, 220 · Centro · Mogi das Cruzes · SP · CEP 08710-000' }, { id: 'F-21', name: 'Mercado Premium Vix', cnpj: '09.443.221/0001-31', city: 'Vitória · ES', cats: ['hortifruti', 'secos'], score: 65, wins: 4, response: 70, status: 'Em Avaliação', avgDelivery: '96h', contact: 'Marcos V.', whats: '(27) 9 8721-3300', email: 'marcos@premiumvix.com.br', address: 'Av. Beira-Mar, 1800 · Praia do Canto · Vitória · ES · CEP 29055-110' }, { id: 'F-22', name: 'Frigorífico Sul', cnpj: '78.221.443/0001-25', city: 'Pelotas · RS', cats: ['carnes'], score: 55, wins: 2, response: 60, status: 'Bloqueado', avgDelivery: '120h', contact: 'Frigo Sul', whats: '(53) 3 222-7700', email: 'comercial@frigosul.com.br', address: 'Av. Bento Gonçalves, 4500 · Centro · Pelotas · RS · CEP 96015-560' }, ]; // Bids for the active quotation (the showcase) const ACTIVE_QUOTATION = { id: 'COT-2026-0148', title: 'Cotação Semanal · Bebidas e Hortifruti', status: 'aberta', // aberta · analise · fechada createdAt: '13/05/2026 09:14', deadline: '15/05/2026 18:00', buyer: 'José Alberto', obs: 'Pagamento 28 dias · Entrega na Rua Carlos Gomes, 1244 · Receber entre 8h e 11h', items: [ { id: 'P-008', name: 'Cerveja Heineken 600ml', unit: 'cx 12', qty: 30, lastPrice: 78.00 }, { id: 'P-009', name: 'Cerveja Original 600ml', unit: 'cx 12', qty: 20, lastPrice: 65.40 }, { id: 'P-010', name: 'Refrigerante Coca 2L', unit: 'cx 6', qty: 40, lastPrice: 48.00 }, { id: 'P-011', name: 'Água Mineral 500ml', unit: 'cx 12', qty: 30, lastPrice: 14.50 }, { id: 'P-004', name: 'Tomate Italiano', unit: 'kg', qty: 30, lastPrice: 6.80 }, { id: 'P-005', name: 'Alface Crespa', unit: 'pé', qty: 24, lastPrice: 2.50 }, { id: 'P-006', name: 'Cebola Branca', unit: 'kg', qty: 20, lastPrice: 4.20 }, { id: 'P-007', name: 'Batata Inglesa', unit: 'kg', qty: 50, lastPrice: 4.90 }, ], suppliers: ['F-07', 'F-08', 'F-09', 'F-10', 'F-04', 'F-05', 'F-06'], bids: { // sup-id -> { product-id: { price, alt, notes, status } } 'F-07': { // AmBev — bebidas _status: 'respondida', _at: '13/05 14:22', 'P-008': { price: 75.40 }, 'P-009': { price: 63.20 }, 'P-010': { price: null, skip: true }, 'P-011': { price: 13.80 }, }, 'F-08': { // Coca-Cola FEMSA — bebidas _status: 'respondida', _at: '13/05 16:08', 'P-008': { price: null, skip: true }, 'P-009': { price: null, skip: true }, 'P-010': { price: 45.20 }, 'P-011': { price: null, skip: true }, }, 'F-09': { // Crystal — bebidas _status: 'respondida', _at: '14/05 09:55', 'P-008': { price: null, skip: true }, 'P-009': { price: null, skip: true }, 'P-010': { price: 49.50 }, 'P-011': { price: 12.90 }, }, 'F-10': { // Decanter — bebidas premium (cervejas premium) _status: 'respondida', _at: '14/05 11:12', 'P-008': { price: 77.20, alt: 'Heineken Long Neck 330ml cx 24' }, 'P-009': { price: 64.90 }, 'P-010': { price: null, skip: true }, 'P-011': { price: null, skip: true }, }, 'F-04': { // CEAGESP — hortifruti _status: 'respondida', _at: '13/05 11:40', 'P-004': { price: 6.20 }, 'P-005': { price: 2.30 }, 'P-006': { price: 3.80 }, 'P-007': { price: 4.70 }, }, 'F-05': { // Sítio Verde — hortifruti _status: 'respondida', _at: '13/05 18:30', 'P-004': { price: 5.90 }, 'P-005': { price: 2.10 }, 'P-006': { price: 4.10 }, 'P-007': { price: 4.95 }, }, 'F-06': { // Hortifruti Norte — pendente _status: 'pendente', _at: null, }, }, }; // Other quotations (list page) const QUOTATIONS = [ { id: 'COT-2026-0148', title: 'Cotação Semanal · Bebidas e Hortifruti', status: 'analise', items: 8, suppliers: 7, responded: 6, total: 7820.50, saving: 422.30, deadline: '15/05/2026', createdAt: '13/05/2026' }, { id: 'COT-2026-0147', title: 'Reposição Carnes — Final de Semana', status: 'fechada', items: 5, suppliers: 4, responded: 4, total: 12480.00, saving: 1148.00, deadline: '12/05/2026', createdAt: '10/05/2026' }, { id: 'COT-2026-0146', title: 'Limpeza e Descartáveis · Mensal', status: 'fechada', items: 12, suppliers: 5, responded: 4, total: 3220.40, saving: 488.20, deadline: '08/05/2026', createdAt: '05/05/2026' }, { id: 'COT-2026-0145', title: 'Laticínios — Reposição Semanal', status: 'fechada', items: 6, suppliers: 4, responded: 4, total: 4180.90, saving: 312.50, deadline: '06/05/2026', createdAt: '04/05/2026' }, { id: 'COT-2026-0144', title: 'Cotação Express · Frutas', status: 'aberta', items: 4, suppliers: 3, responded: 1, total: null, saving: null, deadline: '16/05/2026', createdAt: '13/05/2026' }, { id: 'COT-2026-0143', title: 'Secos e Molhados · Estoque Geral', status: 'fechada', items: 14, suppliers: 6, responded: 5, total: 6840.10, saving: 924.80, deadline: '02/05/2026', createdAt: '29/04/2026' }, { id: 'COT-2026-0142', title: 'Bebidas Premium · Carta de Vinhos', status: 'fechada', items: 9, suppliers: 4, responded: 3, total: 8990.00, saving: 380.00, deadline: '28/04/2026', createdAt: '26/04/2026' }, { id: 'COT-2026-0141', title: 'Cerveja · Reposição Urgente', status: 'cancelada', items: 3, suppliers: 2, responded: 1, total: null, saving: null, deadline: '25/04/2026', createdAt: '24/04/2026' }, ]; const ORDERS = [ { id: 'PC-2026-0312', supplier: 'AmBev Distrib', items: 4, total: 4530.00, status: 'Em Trânsito', eta: '15/05/2026', emitido: '13/05/2026', cotacao: 'COT-2026-0148' }, { id: 'PC-2026-0311', supplier: 'Sítio Verde', items: 3, total: 322.80, status: 'Confirmado', eta: '14/05/2026', emitido: '13/05/2026', cotacao: 'COT-2026-0148' }, { id: 'PC-2026-0310', supplier: 'CEAGESP Box 12', items: 4, total: 568.40, status: 'Entregue', eta: '13/05/2026', emitido: '12/05/2026', cotacao: 'COT-2026-0148' }, { id: 'PC-2026-0309', supplier: 'Friboi Distribuidora', items: 3, total: 5288.20, status: 'Entregue', eta: '12/05/2026', emitido: '10/05/2026', cotacao: 'COT-2026-0147' }, { id: 'PC-2026-0308', supplier: 'JBS Premium', items: 2, total: 7191.80, status: 'Entregue', eta: '12/05/2026', emitido: '10/05/2026', cotacao: 'COT-2026-0147' }, { id: 'PC-2026-0307', supplier: 'Limpar Já', items: 6, total: 1822.40, status: 'Entregue', eta: '09/05/2026', emitido: '05/05/2026', cotacao: 'COT-2026-0146' }, { id: 'PC-2026-0306', supplier: 'Embalux SP', items: 6, total: 1398.00, status: 'Cancelado', eta: '—', emitido: '05/05/2026', cotacao: 'COT-2026-0146' }, { id: 'PC-2026-0305', supplier: 'Tirolez Direto', items: 3, total: 2480.00, status: 'Entregue', eta: '07/05/2026', emitido: '04/05/2026', cotacao: 'COT-2026-0145' }, { id: 'PC-2026-0304', supplier: 'Itambé Atacado', items: 2, total: 1100.90, status: 'Entregue', eta: '07/05/2026', emitido: '04/05/2026', cotacao: 'COT-2026-0145' }, { id: 'PC-2026-0303', supplier: 'Aviação Premium', items: 1, total: 600.00, status: 'Entregue', eta: '07/05/2026', emitido: '04/05/2026', cotacao: 'COT-2026-0145' }, ]; // Monthly savings (last 6 months) const SAVINGS_HISTORY = [ { m: 'Dez/25', value: 2890, quotes: 18 }, { m: 'Jan/26', value: 3210, quotes: 22 }, { m: 'Fev/26', value: 4150, quotes: 24 }, { m: 'Mar/26', value: 3680, quotes: 21 }, { m: 'Abr/26', value: 5240, quotes: 28 }, { m: 'Mai/26', value: 4422, quotes: 19 }, ]; const SAVINGS_HISTORY_12M = [ { m: 'Jun/25', value: 1820, quotes: 12 }, { m: 'Jul/25', value: 2110, quotes: 14 }, { m: 'Ago/25', value: 2480, quotes: 16 }, { m: 'Set/25', value: 2740, quotes: 17 }, { m: 'Out/25', value: 3050, quotes: 19 }, { m: 'Nov/25', value: 2630, quotes: 16 }, { m: 'Dez/25', value: 2890, quotes: 18 }, { m: 'Jan/26', value: 3210, quotes: 22 }, { m: 'Fev/26', value: 4150, quotes: 24 }, { m: 'Mar/26', value: 3680, quotes: 21 }, { m: 'Abr/26', value: 5240, quotes: 28 }, { m: 'Mai/26', value: 4422, quotes: 19 }, ]; const SAVINGS_HISTORY_YEAR = [ { m: '2023', value: 18420, quotes: 142 }, { m: '2024', value: 24890, quotes: 188 }, { m: '2025', value: 31420, quotes: 224 }, { m: '2026 YTD', value: 20702, quotes: 114 }, ]; // Distribution by category (last 30 days) const CATEGORY_SHARE = [ { cat: 'carnes', label: 'Carnes', value: 18420, tone: 'coral' }, { cat: 'bebidas', label: 'Bebidas', value: 14820, tone: 'sky' }, { cat: 'hortifruti', label: 'Hortifruti', value: 6420, tone: 'emerald' }, { cat: 'secos', label: 'Secos', value: 5210, tone: 'amber' }, { cat: 'laticinios', label: 'Laticínios', value: 4720, tone: 'amber' }, { cat: 'limpeza', label: 'Limpeza', value: 2280, tone: 'violet' }, { cat: 'descartaveis', label: 'Descartáveis', value: 1410, tone: 'sky' }, ]; // Top winners + most quoted const TOP_SUPPLIERS = [ { name: 'AmBev Distrib', wins: 54, share: 100 }, { name: 'Friboi Distribuidora', wins: 48, share: 89 }, { name: 'CEAGESP Box 12', wins: 38, share: 70 }, { name: 'JBS Premium', wins: 32, share: 59 }, { name: 'Camil Atacado', wins: 29, share: 54 }, { name: 'Coca-Cola FEMSA', wins: 27, share: 50 }, { name: 'Tirolez Direto', wins: 24, share: 44 }, { name: 'Andorinha Brasil', wins: 22, share: 41 }, { name: 'Sadia Atacado', wins: 21, share: 39 }, { name: 'União Atacado', wins: 19, share: 35 }, ]; const TOP_PRODUCTS = [ { name: 'Cerveja Heineken 600ml', quotes: 18, vol: 540 }, { name: 'Filé Mignon Bovino', quotes: 16, vol: 320 }, { name: 'Tomate Italiano', quotes: 15, vol: 460 }, { name: 'Queijo Mussarela', quotes: 14, vol: 280 }, { name: 'Refrigerante Coca 2L', quotes: 13, vol: 380 }, { name: 'Cerveja Original 600ml', quotes: 12, vol: 420 }, { name: 'Frango Inteiro', quotes: 11, vol: 310 }, { name: 'Arroz Tio João 5kg', quotes: 10, vol: 240 }, { name: 'Picanha Maturada', quotes: 9, vol: 180 }, { name: 'Azeite Extra Virgem', quotes: 9, vol: 210 }, ]; // Distribution by supplier (last 30 days) const SUPPLIER_SHARE = [ { sid: 'F-07', label: 'AmBev Distrib', value: 12480, tone: 'sky' }, { sid: 'F-01', label: 'Friboi Distribuidora', value: 10220, tone: 'coral' }, { sid: 'F-04', label: 'CEAGESP Box 12', value: 5240, tone: 'emerald' }, { sid: 'F-02', label: 'JBS Premium', value: 7388, tone: 'coral' }, { sid: 'F-12', label: 'Camil Atacado', value: 3120, tone: 'amber' }, { sid: 'F-15', label: 'Tirolez Direto', value: 2480, tone: 'amber' }, { sid: 'F-08', label: 'Coca-Cola FEMSA', value: 2340, tone: 'sky' }, { sid: 'F-18', label: 'Limpar Já', value: 1822, tone: 'violet' }, ]; // Price evolution for "Filé Mignon" — line chart const PRICE_HISTORY = [ { d: '12 sem', v: 86.40 }, { d: '10 sem', v: 84.20 }, { d: '8 sem', v: 88.10 }, { d: '6 sem', v: 85.50 }, { d: '4 sem', v: 81.20 }, { d: '2 sem', v: 79.80 }, { d: 'agora', v: 78.90 }, ]; // Alerts feed const ALERTS = [ { id: 1, kind: 'estoque', text: 'Detergente Neutro 5L abaixo do mínimo (6 / 12)', at: 'há 5 min', tone: 'amber' }, { id: 2, kind: 'cotacao', text: 'COT-2026-0144 sem resposta de 2 fornecedores', at: 'há 1h', tone: 'amber' }, { id: 3, kind: 'pedido', text: 'PC-2026-0312 entregue parcialmente — 2 itens em divergência', at: 'há 2h', tone: 'coral' }, { id: 4, kind: 'ia', text: 'IA sugere fechar COT-2026-0148 com economia de R$ 422,30', at: 'há 3h', tone: 'emerald' }, { id: 5, kind: 'fornec', text: 'Hortifruti Norte ainda não respondeu — lembrete enviado', at: 'há 4h', tone: 'amber' }, ]; // Notifications feed const NOTIFICATIONS = [ { id: 1, icon: 'sparkle', title: 'IA finalizou análise de COT-2026-0148', sub: 'Economia projetada: R$ 422,30 (5,4%)', at: '14:08', tone: 'emerald', unread: true }, { id: 2, icon: 'truck', title: 'PC-2026-0312 em trânsito', sub: 'AmBev Distrib · previsão 15/05 às 09h', at: '13:42', tone: 'sky', unread: true }, { id: 3, icon: 'reply', title: 'Sítio Verde respondeu COT-2026-0148', sub: '4 itens preenchidos', at: '13:30', tone: 'emerald', unread: true }, { id: 4, icon: 'warn', title: 'Estoque crítico: 3 produtos', sub: 'Sugerimos abrir nova cotação', at: '11:15', tone: 'amber', unread: false }, { id: 5, icon: 'check', title: 'PC-2026-0310 entregue', sub: 'CEAGESP Box 12 · conferência ok', at: 'ontem', tone: 'emerald', unread: false }, ]; // === Stock receivings === const RECEIVINGS = [ { id: 'REC-0118', order: 'PC-2026-0310', supplier: 'CEAGESP Box 12', items: 4, status: 'Aprovado', div: 0, at: '13/05 09:40' }, { id: 'REC-0117', order: 'PC-2026-0312', supplier: 'AmBev Distrib', items: 4, status: 'Pendente', div: 2, at: '—' }, { id: 'REC-0116', order: 'PC-2026-0309', supplier: 'Friboi Distrib.', items: 3, status: 'Aprovado', div: 1, at: '12/05 07:55' }, { id: 'REC-0115', order: 'PC-2026-0308', supplier: 'JBS Premium', items: 2, status: 'Aprovado', div: 0, at: '12/05 08:10' }, { id: 'REC-0114', order: 'PC-2026-0307', supplier: 'Limpar Já', items: 6, status: 'Aprovado', div: 0, at: '09/05 14:22' }, ]; // === Period filter (dashboard) === // Reference "today" for relative date filtering on the dashboard. const TODAY = new Date(2026, 4, 15); // Maio = month 4 (0-indexed) // Parse "DD/MM/YYYY" -> Date const parseBR = (s) => { if (!s) return null; const [d, m, y] = s.split('/').map(Number); return new Date(y, m - 1, d); }; const daysBetween = (a, b) => Math.floor((a - b) / 86400000); const PERIODS = { hoje: { label: 'Hoje', mult: 0.04, days: 1, sub: 'Hoje', short: 'hoje', compare: '0%' }, '7d': { label: '7 dias', mult: 0.22, days: 7, sub: 'Últimos 7 dias', short: '7d', compare: '-2% vs. anterior' }, '30d': { label: '30 dias', mult: 1, days: 30, sub: 'Últimos 30 dias', short: '30d', compare: '+18% vs. anterior' }, '90d': { label: '90 dias', mult: 3.1, days: 90, sub: 'Últimos 90 dias', short: '90d', compare: '+27% vs. anterior' }, }; // Filter the quotations table rows by createdAt within N days from TODAY. const filterQuotationsByDays = (rows, days) => { return rows.filter(q => { const d = parseBR(q.createdAt); if (!d) return true; const diff = daysBetween(TODAY, d); return diff >= 0 && diff <= days; }); }; // "kind" of alert -> destination route on the SPA const ALERT_ROUTE = { estoque: 'stock', cotacao: 'quotations', pedido: 'orders', ia: 'quotationDetail', // routed via openQuotation fornec: 'suppliers', }; // "cat" key (donut) -> products screen category context const CATEGORY_ROUTE = 'reports'; window.SCP = { BRL, BRLk, pad, COMPANY, CATEGORIES, PRODUCTS, SUPPLIERS, ACTIVE_QUOTATION, QUOTATIONS, ORDERS, RECEIVINGS, SAVINGS_HISTORY, SAVINGS_HISTORY_12M, SAVINGS_HISTORY_YEAR, CATEGORY_SHARE, SUPPLIER_SHARE, TOP_SUPPLIERS, TOP_PRODUCTS, PRICE_HISTORY, ALERTS, NOTIFICATIONS, PERIODS, TODAY, filterQuotationsByDays, parseBR, daysBetween, ALERT_ROUTE, CATEGORY_ROUTE, };