/* global React, Icon, BRL, Ticker, Drawer */ // ============ INTEGRATIONS CATALOG ============ const INTEGRACOES = [ { id: 'openai', nome: 'OpenAI', cat: 'IA', cor: '#10a37f', logo: 'OAI', desc: 'ChatGPT/GPT-4 para análise de e-mails, geração de pareceres e diagnóstico da IA Gerente.', campos: [ { id: 'apiKey', label: 'API Key', tipo: 'secret', serverManaged: true, req: false, hint: 'A chave fica nos Secrets do Supabase (servidor). Nunca é salva no navegador.' }, { id: 'modelo', label: 'Modelo padrão', tipo: 'select', opcoes: ['gpt-4-turbo', 'gpt-4o', 'gpt-4o-mini', 'gpt-3.5-turbo'], default: 'gpt-4o', req: true }, { id: 'temperatura', label: 'Temperatura', tipo: 'number', min: 0, max: 2, step: 0.1, default: 0.3, req: false, hint: '0 = determinístico · 2 = criativo' }, { id: 'maxTokens', label: 'Máx. tokens por resposta', tipo: 'number', default: 2000, req: false }, { id: 'org', label: 'Organization ID (opcional)', tipo: 'text', placeholder: 'org-...', req: false }, ], mapeamentos: [ { de: 'Análise de e-mails (M08)', para: 'gpt-4o + temperatura 0.2', editavel: true }, { de: 'Geração de pareceres (M12)', para: 'gpt-4-turbo + temperatura 0.4', editavel: true }, { de: 'Sugestões IA (M05, M07)', para: 'gpt-4o-mini + temperatura 0.3', editavel: true }, { de: 'Chat conversacional (M08)', para: 'gpt-4o + streaming ativado', editavel: true }, ], docsUrl: 'https://platform.openai.com/docs', }, { id: 'focus', nome: 'Focus NFe', cat: 'FISCAL', cor: '#f5b544', logo: 'FNF', desc: 'Emissão de NFe, NFCe e NFSe diretamente da SEFAZ. Usado em M07 (NF emitida) e M11 (NFC-e do PDV).', campos: [ { id: 'token', label: 'Token de acesso', tipo: 'secret', placeholder: 'Token gerado no painel Focus', req: true }, { id: 'ambiente', label: 'Ambiente', tipo: 'radio', opcoes: ['homologacao', 'producao'], default: 'homologacao', req: true }, { id: 'cnpjEmitente', label: 'CNPJ emitente', tipo: 'text', placeholder: '00.000.000/0000-00', default: '33.804.351/0001-04', req: true }, { id: 'serieNFe', label: 'Série NF-e', tipo: 'number', default: 1, req: true }, { id: 'serieNFCe', label: 'Série NFC-e', tipo: 'number', default: 1, req: true }, { id: 'naturezaPadrao', label: 'Natureza operação padrão', tipo: 'text', default: 'Venda de mercadoria', req: false }, ], mapeamentos: [ { de: 'NFe de venda (Empenho)', para: 'CFOP 5102/6102 · NCM por SKU', editavel: true }, { de: 'NFCe do PDV', para: 'CFOP 5102 · ICMS 18%', editavel: true }, { de: 'NFe de devolução', para: 'CFOP 5202/6202 · referenciada', editavel: true }, ], docsUrl: 'https://focusnfe.com.br/doc', }, { id: 'pncp', nome: 'PNCP', cat: 'LICITAÇÃO', cor: '#1e6091', logo: 'PNC', desc: 'Portal Nacional de Contratações Públicas. Captura automática de editais em todo o Brasil.', campos: [ { id: 'token', label: 'Token PNCP', tipo: 'secret', placeholder: 'Token obtido em painel.pncp.gov.br', req: true }, { id: 'cnpjMonitor', label: 'CNPJ para monitoramento', tipo: 'text', default: '33.804.351/0001-04', req: true }, { id: 'ufs', label: 'UFs monitoradas (vírgula)', tipo: 'text', default: 'RJ,SP,ES,MG,SC,PR,RS', req: true }, { id: 'frequencia', label: 'Frequência de varredura', tipo: 'select', opcoes: ['1 min', '5 min', '15 min', '30 min', '1 hora'], default: '5 min', req: true }, ], mapeamentos: [ { de: 'Edital novo no PNCP', para: 'M01 Prospecção · cruzar NCMs', editavel: true }, { de: 'Esclarecimento publicado', para: 'M08 IA · alerta no card do edital', editavel: true }, { de: 'Convocação amostras', para: 'M06 Logística · gerar postagem', editavel: true }, ], docsUrl: 'https://www.gov.br/pncp/pt-br/acesso-a-informacao/manuais', }, { id: 'sefaz', nome: 'SEFAZ Nacional', cat: 'FISCAL', cor: '#003366', logo: 'SFZ', desc: 'Captura automática de NFs emitidas contra a BTM (para criação de CAP) + consulta de status NFe.', campos: [ { id: 'certPath', label: 'Caminho do certificado A1/A3', tipo: 'text', placeholder: '/path/cert.pfx ou identificador A3', req: true }, { id: 'certSenha', label: 'Senha do certificado', tipo: 'secret', req: true }, { id: 'uf', label: 'UF principal', tipo: 'select', opcoes: ['RJ', 'SP', 'ES', 'MG', 'SC', 'PR', 'RS', 'BA', 'CE', 'DF', 'GO', 'PE', 'MT', 'MS'], default: 'RJ', req: true }, { id: 'cnpj', label: 'CNPJ', tipo: 'text', default: '33.804.351/0001-04', req: true }, { id: 'pollIntervalo', label: 'Intervalo de captura (min)', tipo: 'number', default: 30, req: false }, ], mapeamentos: [ { de: 'NF de fornecedor capturada', para: 'M07 · NF contra BTM (aprovação manual)', editavel: false }, { de: 'NFe própria emitida', para: 'M07 · CAR criado automaticamente', editavel: false }, ], docsUrl: 'https://www.nfe.fazenda.gov.br', }, { id: 'bb', nome: 'Banco do Brasil', cat: 'BANCO', cor: '#f9b233', logo: 'BB', desc: 'Open Banking BB · consulta de extrato, geração de PIX cobrança, conciliação automática.', campos: [ { id: 'clientId', label: 'Client ID', tipo: 'text', placeholder: 'Client ID do app BB', req: true }, { id: 'clientSecret', label: 'Client Secret', tipo: 'secret', req: true }, { id: 'agencia', label: 'Agência', tipo: 'text', default: '1234', req: true }, { id: 'conta', label: 'Conta corrente', tipo: 'text', default: '12.847-3', req: true }, { id: 'ambiente', label: 'Ambiente OAuth2', tipo: 'radio', opcoes: ['homologacao', 'producao'], default: 'homologacao', req: true }, { id: 'pixChave', label: 'Chave PIX padrão', tipo: 'text', placeholder: 'CNPJ ou aleatória', default: '33804351000104', req: false }, ], mapeamentos: [ { de: 'Extrato diário', para: 'M07 Conciliação automática', editavel: false }, { de: 'PIX recebido', para: 'M07 · baixar CAR correspondente', editavel: true }, { de: 'Boleto pago', para: 'M07 · baixar CAP correspondente', editavel: true }, ], docsUrl: 'https://developers.bb.com.br', }, { id: 'correios', nome: 'Correios', cat: 'LOGÍSTICA', cor: '#003399', logo: 'COR', desc: 'Cotação de frete, geração de etiquetas SEDEX/PAC e rastreio automático.', campos: [ { id: 'usuario', label: 'Usuário SIGEP', tipo: 'text', req: true }, { id: 'senha', label: 'Senha SIGEP', tipo: 'secret', req: true }, { id: 'codAdmin', label: 'Código administrativo', tipo: 'text', placeholder: '00000000', req: true }, { id: 'contrato', label: 'Número do contrato', tipo: 'text', placeholder: '0000000000', req: true }, { id: 'cartao', label: 'Cartão de postagem', tipo: 'text', placeholder: '0000000000', req: true }, { id: 'cepOrigem', label: 'CEP de origem', tipo: 'text', default: '20021-130', req: true }, ], mapeamentos: [ { de: 'Pedido despachado (M06)', para: 'Gera etiqueta + rastreio automático', editavel: false }, { de: 'Rastreio atualizado', para: 'M06 · timeline da postagem', editavel: false }, { de: 'Cotação de frete (M03)', para: 'Tabela frete por região (M03 aba Frete)', editavel: true }, ], docsUrl: 'https://cws.correios.com.br', }, { id: 'google', nome: 'Google Workspace', cat: 'COMUNICAÇÃO', cor: '#4285f4', logo: 'GWS', desc: 'Drive como espelho de processos · Gmail como fonte de e-mails para o M08 · Calendar para Agenda IA.', campos: [ { id: 'clientId', label: 'OAuth Client ID', tipo: 'text', placeholder: '0000000000-xxxx.apps.googleusercontent.com', req: true }, { id: 'clientSecret', label: 'OAuth Client Secret', tipo: 'secret', req: true }, { id: 'dominio', label: 'Domínio Workspace', tipo: 'text', placeholder: 'btmsigma.com', default: 'btmsigma.com', req: true }, { id: 'escopos', label: 'Escopos solicitados', tipo: 'tags', default: ['drive', 'gmail.readonly', 'calendar'], req: true }, { id: 'pastaRaiz', label: 'Pasta raiz no Drive', tipo: 'text', default: 'BTM-SGL', req: false }, ], mapeamentos: [ { de: 'E-mail recebido', para: 'M08 IA · classificação automática', editavel: false }, { de: 'Edital capturado', para: 'Drive · criar pasta espelho do edital', editavel: false }, { de: 'Prazo detectado pela IA', para: 'Calendar · criar evento', editavel: true }, ], docsUrl: 'https://developers.google.com/workspace', }, { id: 'whatsapp', nome: 'WhatsApp Business API', cat: 'COMUNICAÇÃO', cor: '#25d366', logo: 'WAB', desc: 'Mensagens com pregoeiros, fornecedores e clientes via WhatsApp Cloud API (Meta).', campos: [ { id: 'phoneNumberId', label: 'Phone Number ID', tipo: 'text', placeholder: '1234567890', req: true }, { id: 'token', label: 'Token permanente Meta', tipo: 'secret', placeholder: 'EAAxxxxx...', req: true }, { id: 'businessAccountId', label: 'WhatsApp Business Account ID', tipo: 'text', req: true }, { id: 'webhookUrl', label: 'Webhook URL (entrada)', tipo: 'text', default: 'https://sgl.btmsigma.com/webhook/whatsapp', req: false }, { id: 'webhookToken', label: 'Verify token webhook', tipo: 'secret', req: false }, ], mapeamentos: [ { de: 'Mensagem recebida', para: 'M09 Comunicação · auto-categoriza', editavel: false }, { de: 'Empenho aprovado (M05)', para: 'WhatsApp · notifica cliente', editavel: true }, { de: 'Entrega confirmada (M06)', para: 'WhatsApp · agradece cliente', editavel: true }, ], docsUrl: 'https://developers.facebook.com/docs/whatsapp', }, { id: 'telefonia', nome: 'Telefonia / VoIP', cat: 'COMUNICAÇÃO', cor: '#9b59b6', logo: 'VOP', desc: 'Disque corporativo com gravação de chamadas e ata automática pela IA. Suporta Twilio/3CX/Asterisk.', campos: [ { id: 'provedor', label: 'Provedor', tipo: 'select', opcoes: ['Twilio', '3CX', 'Asterisk', 'TotalVoice', 'outro'], default: 'Twilio', req: true }, { id: 'apiKey', label: 'API Key', tipo: 'secret', req: true }, { id: 'apiSecret', label: 'API Secret', tipo: 'secret', req: false }, { id: 'numeroPrincipal', label: 'Número principal', tipo: 'text', placeholder: '+55 21 0000-0000', default: '+55 21 2620-1500', req: true }, { id: 'gravarChamadas', label: 'Gravar chamadas', tipo: 'toggle', default: true, req: false, hint: 'LGPD: aviso sonoro obrigatório' }, { id: 'transcrever', label: 'Transcrição automática IA', tipo: 'toggle', default: true, req: false }, ], mapeamentos: [ { de: 'Chamada finalizada', para: 'M09 Telefonia · histórico + ata IA', editavel: false }, { de: 'Áudio gravado', para: 'Drive · pasta /chamadas/{ano-mes}', editavel: true }, ], docsUrl: 'https://www.twilio.com/docs', }, { id: 'smtp', nome: 'SMTP / IMAP customizado', cat: 'COMUNICAÇÃO', cor: '#7a7770', logo: 'EML', desc: 'Servidor de e-mail próprio (alternativa ao Gmail) para captura de e-mails do M08.', campos: [ { id: 'imapHost', label: 'IMAP Host', tipo: 'text', placeholder: 'imap.btmsigma.com', req: true }, { id: 'imapPort', label: 'IMAP Porta', tipo: 'number', default: 993, req: true }, { id: 'smtpHost', label: 'SMTP Host', tipo: 'text', placeholder: 'smtp.btmsigma.com', req: true }, { id: 'smtpPort', label: 'SMTP Porta', tipo: 'number', default: 587, req: true }, { id: 'usuario', label: 'Usuário', tipo: 'text', placeholder: 'sgl@btmsigma.com', req: true }, { id: 'senha', label: 'Senha', tipo: 'secret', req: true }, { id: 'ssl', label: 'Usar SSL/TLS', tipo: 'toggle', default: true, req: false }, ], mapeamentos: [ { de: 'E-mail recebido (IMAP)', para: 'M08 IA · classificação automática', editavel: false }, { de: 'Resposta automática IA', para: 'SMTP · envio com timbre BTM', editavel: true }, ], docsUrl: '', }, ]; const CAT_COLORS = { 'IA': 'badge-cyan', 'FISCAL': 'badge-amber', 'LICITAÇÃO': 'badge-lime', 'BANCO': 'badge-lime', 'LOGÍSTICA': 'badge-cyan', 'COMUNICAÇÃO': 'badge-violet', }; // ============ STORAGE ============ const STORAGE_KEY = 'sgl_config_v1'; function loadConfig() { try { return JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}'); } catch { return {}; } } function saveConfig(c) { localStorage.setItem(STORAGE_KEY, JSON.stringify(c)); } const DEFAULT_EMPRESA = { cnpj: '33.804.351/0001-04', razao: 'BTM Serviços e Comércio LTDA', fantasia: 'BTM', ie: '12.345.678-9', im: '0000000-0', atividade: '4647-8/01 — Comércio atacadista de artigos de escritório e papelaria', cep: '20021-130', logradouro: 'Rua São Bento, 248', numero: '248', complemento: 'Sala 1402', bairro: 'Centro', cidade: 'Rio de Janeiro', uf: 'RJ', telefone: '(21) 2620-1500', email: 'contato@btmsigma.com', regime: 'lucro-real', anexoSimples: '', rbt12: '4800000', certVencimento: '2027-03-14', certEmissor: 'AC Certisign Mult. G7', certTipo: 'A3 · Token físico', contas: [ { id: 'c1', banco: 'Banco do Brasil', agencia: '1234-5', conta: '12.847-3', tipo: 'CC', pix: '33804351000104', principal: true }, { id: 'c2', banco: 'Itaú', agencia: '0291', conta: '38201-1', tipo: 'CC', pix: '', principal: false }, { id: 'c3', banco: 'Sicredi', agencia: '4710', conta: '5210-X', tipo: 'CC', pix: '', principal: false }, ], }; // ============ MODULE ============ function MConfig({ onNav }) { const [tab, setTab] = React.useState('integracoes'); const [config, setConfig] = React.useState(loadConfig); const [drawer, setDrawer] = React.useState(null); const [drawerTab, setDrawerTab] = React.useState('conexao'); const empresa = { ...DEFAULT_EMPRESA, ...(config.empresa || {}) }; const updateIntegracao = (id, valores) => { const novo = { ...config, integracoes: { ...(config.integracoes || {}), [id]: valores } }; setConfig(novo); saveConfig(novo); }; const updateEmpresa = (campo, valor) => { const novo = { ...config, empresa: { ...empresa, [campo]: valor } }; setConfig(novo); saveConfig(novo); }; const updateContas = (contas) => { const novo = { ...config, empresa: { ...empresa, contas } }; setConfig(novo); saveConfig(novo); }; const totalConfiguradas = INTEGRACOES.filter(i => { const c = config.integracoes?.[i.id]; return c && i.campos.filter(f => f.req).every(f => c[f.id]); }).length; return ( <>
Configurações do SistemaM13

Integrações API · Dados da Empresa

Centro de configurações da BTM SGL. Conexões com APIs externas (OpenAI, Focus NFe, PNCP, etc.) e dados cadastrais que alimentam todos os módulos.

{totalConfiguradas}/{INTEGRACOES.length} INTEGRAÇÕES PRONTAS
setTab('integracoes')}> Integrações API {INTEGRACOES.length}
setTab('empresa')}> Dados da Empresa
{tab === 'integracoes' && { setDrawer(int); setDrawerTab('conexao'); }} />} {tab === 'empresa' && }
{drawer && ( updateIntegracao(drawer.id, v)} onClose={() => setDrawer(null)} tab={drawerTab} onTab={setDrawerTab} /> )} ); } // ============ INTEGRAÇÕES GRID ============ function IntegracoesGrid({ config, onOpen }) { return (
Configurações pré-API
Os campos abaixo serão preenchidos com as credenciais reais quando as conexões forem habilitadas. Hoje, todas as integrações estão em modo simulado (mock). Os dados configurados persistem localmente (localStorage).
{INTEGRACOES.map(int => { const valores = config.integracoes?.[int.id] || {}; const reqCampos = int.campos.filter(c => c.req); // Campo obrigatório com valor padrão já conta como preenchido. const preenchidos = reqCampos.filter(c => valores[c.id] || c.default !== undefined).length; const status = preenchidos === 0 ? { label: 'NÃO CONFIGURADO', cls: '', dot: 'var(--fg-3)' } : preenchidos < reqCampos.length ? { label: 'INCOMPLETO', cls: 'badge-amber', dot: 'var(--amber)' } : { label: 'CONFIGURADO', cls: 'badge-lime', dot: 'var(--lime)' }; return (
onOpen(int)} style={{ padding: 16 }}>
{int.logo}
{int.nome} {int.cat}
{status.label} {preenchidos}/{reqCampos.length} campos req.
{int.desc}
{int.campos.length} parâmetros · {int.mapeamentos.length} mapeamentos Configurar →
); })}
); } // ============ INTEGRAÇÃO DRAWER ============ function IntegracaoDrawer({ integracao, valores, onSave, onClose, tab, onTab }) { const [edited, setEdited] = React.useState({}); const [testing, setTesting] = React.useState(false); const [testResult, setTestResult] = React.useState(null); const merged = { ...valores, ...edited }; const reqCampos = integracao.campos.filter(c => c.req); // Campo obrigatório com valor padrão já conta como preenchido. const preenchidos = reqCampos.filter(c => merged[c.id] || c.default !== undefined).length; const completo = preenchidos === reqCampos.length; const isOpenAI = integracao.id === 'openai'; const handleSave = () => { onSave(merged); setEdited({}); }; const handleTest = async () => { setTesting(true); setTestResult(null); try { const r = await window.testOpenAI(); setTestResult(r); } catch (e) { setTestResult({ ok: false, error: (e && e.message) || 'Erro inesperado ao testar.' }); } finally { setTesting(false); } }; return ( Integração · {integracao.cat}M13{completo ? 'CONFIGURADO' : preenchidos === 0 ? 'NÃO CONFIGURADO' : 'INCOMPLETO'}} title={
{integracao.logo}
{integracao.nome}
} subtitle={integracao.desc} tabs={[ { id: 'conexao', label: 'Conexão', count: preenchidos + '/' + reqCampos.length }, { id: 'map', label: 'Mapeamentos', count: integracao.mapeamentos.length }, { id: 'logs', label: 'Logs' }, ]} activeTab={tab} onTabChange={onTab} footer={ <> {integracao.docsUrl && ( Documentação )} } > {tab === 'conexao' && } {tab === 'map' && } {tab === 'logs' && }
); } function ServerManagedField({ campo }) { return (
{campo.label}
Gerenciada no servidor (Supabase Secrets) SEGURO
{campo.hint &&
{campo.hint}
}
); } function TestResultBanner({ result }) { if (!result) return null; if (result.ok) { return (
Conexão OK
{result.modelos} modelos disponíveis · resposta em {result.latencia}ms.
); } return (
Falha na conexão
{result.error}
); } function TabConexao({ integracao, merged, setEdited, edited, valores, isOpenAI, testResult, testing }) { const setCampo = (id, v) => setEdited({ ...edited, [id]: v }); return (
{isOpenAI && testing && (
Testando conexão com a OpenAI…
)} {isOpenAI && !testing && }
PARÂMETROS DE CONEXÃO
{integracao.campos.map(c => ( c.serverManaged ? : setCampo(c.id, v)} /> ))}
Credenciais sensíveis
Em produção, as chaves/tokens serão armazenadas criptografadas no servidor (AES-256). Hoje, persistem no localStorage do navegador apenas para testes da interface.
{Object.keys(edited).length > 0 && (
{Object.keys(edited).length} campo(s) modificado(s) — clique em Salvar no rodapé para persistir.
)}
); } function CampoInput({ campo, valor, onChange }) { if (campo.tipo === 'select') { return (
{campo.label}{campo.req && *}
{campo.hint &&
{campo.hint}
}
); } if (campo.tipo === 'radio') { return (
{campo.label}{campo.req && *}
{campo.opcoes.map(o => (
onChange(o)}>{o.toUpperCase()}
))}
{campo.hint &&
{campo.hint}
}
); } if (campo.tipo === 'toggle') { const v = valor !== undefined ? valor : campo.default; return (
{campo.label}
{campo.hint &&
{campo.hint}
}
onChange(!v)}>
); } if (campo.tipo === 'tags') { const tags = valor || campo.default || []; return (
{campo.label}{campo.req && *}
{tags.map(t => ( {t} onChange(tags.filter(x => x !== t))} /> ))} { if (e.key === 'Enter' && e.target.value) { onChange([...tags, e.target.value]); e.target.value = ''; } }} />
); } // text, secret, number return (
{campo.label}{campo.req && *}
onChange(campo.tipo === 'number' ? parseFloat(e.target.value) : e.target.value)} /> {campo.hint &&
{campo.hint}
} {campo.exemplo && !valor &&
Exemplo: {campo.exemplo}
}
); } function TabMapeamentos({ integracao }) { return (
FLUXOS MAPEADOS DESTA INTEGRAÇÃO
{integracao.mapeamentos.map((m, i) => (
EVENTO / FONTE
{m.de}
AÇÃO NO SISTEMA
{m.para}
{m.editavel ? ( ) : ( SISTEMA )}
))}
Mapeamentos marcados como SISTEMA são automáticos e não podem ser desabilitados (são parte do contrato da integração). Os editáveis permitem personalização do fluxo.
); } function TabLogs({ integracao }) { // Mock logs - in real system would come from server const logs = [ { ts: '12/05 14:32:18', endpoint: '/v1/chat/completions', method: 'POST', status: 200, dur: '1.24s', preview: '{"messages":[...], "model":"gpt-4o"}' }, { ts: '12/05 14:18:42', endpoint: '/v1/chat/completions', method: 'POST', status: 200, dur: '0.89s', preview: '{"messages":[...], "model":"gpt-4o-mini"}' }, { ts: '12/05 11:42:08', endpoint: '/v1/chat/completions', method: 'POST', status: 429, dur: '0.12s', preview: 'rate_limit_exceeded · tentar em 60s' }, { ts: '12/05 10:14:55', endpoint: '/v1/embeddings', method: 'POST', status: 200, dur: '0.42s', preview: '{"input":"...", "model":"text-embedding-3-small"}' }, { ts: '12/05 09:22:14', endpoint: '/v1/chat/completions', method: 'POST', status: 200, dur: '2.18s', preview: '{"messages":[...], "stream":true}' }, ]; return (
5 chamadas nas últimas 24h · 1 erro (rate limit)
{logs.map((l, i) => ( ))}
Timestamp Endpoint Method Status Duração Preview
{l.ts} {l.endpoint} {l.method} = 200 && l.status < 300 ? 'badge-lime' : l.status >= 400 && l.status < 500 ? 'badge-amber' : 'badge-red'}`}> {l.status} {l.dur} {l.preview}
Logs simulados · em produção virão do servidor com retenção de 30 dias
); } // ============ EMPRESA TAB ============ function EmpresaTab({ empresa, onUpdate, onUpdateContas }) { return (
Dados Básicos
onUpdate('cnpj', v)} placeholder="00.000.000/0000-00" req /> onUpdate('razao', v)} req /> onUpdate('fantasia', v)} />
onUpdate('ie', v)} /> onUpdate('im', v)} />
onUpdate('atividade', v)} />
onUpdate('telefone', v)} /> onUpdate('email', v)} />
Endereço Fiscal
onUpdate('cep', v)} placeholder="00000-000" /> onUpdate('uf', v)} />
onUpdate('logradouro', v)} />
onUpdate('numero', v)} /> onUpdate('complemento', v)} />
onUpdate('bairro', v)} /> onUpdate('cidade', v)} />
Regime Tributário
REGIME ATIVO
{[ { id: 'lucro-real', l: 'LUCRO REAL' }, { id: 'presumido', l: 'PRESUMIDO' }, { id: 'simples', l: 'SIMPLES' }, ].map(r => (
onUpdate('regime', r.id)}>{r.l}
))}
{empresa.regime === 'simples' && ( <>
ANEXO DO SIMPLES
{['ANEXO I', 'ANEXO II', 'ANEXO III', 'ANEXO IV', 'ANEXO V'].map(a => (
onUpdate('anexoSimples', a)}>{a.replace('ANEXO ', '')}
))}
)} onUpdate('rbt12', v)} hint="Receita bruta dos últimos 12 meses" /> {empresa.regime === 'lucro-real' && (
Cargas tributárias do regime Lucro Real são configuradas no M03 Precificação por edital.
)}
Certificado Digital ICP-Brasil
{empresa.certTipo}
{empresa.certEmissor}
VÁLIDO
Vencimento: {empresa.certVencimento}
Contas Bancárias
{empresa.contas.map(c => (
{c.banco} {c.principal && PRINCIPAL}
AG {c.agencia} · CC {c.conta} {c.pix && '· PIX ' + c.pix}
))}
); } function FormRow({ label, value, onChange, placeholder, hint, req }) { return (
{label}{req && *}
onChange(e.target.value)} /> {hint &&
{hint}
}
); } window.MConfig = MConfig;