const IXC={MODE:'mock',BASE_URL:'https://SEU_DOMINIO/webservice/v1',PROXY:'/wp-json/rnet/v1',};
const SEED={kpis:{mrr_total:241738.81,novas_ativacoes:33,cancelamentos:11,churn_rate:0.045779,cac_medio:120.30,arpu:112.53,ltv:2254.43,ltv_cac:18.74,payback:2.12,margem_media:0.5038,lifespan:1.82,meta_churn:0.01,meta_cac:180,meta_arpu:110,meta_ltv:2200,meta_ltv_cac:8,meta_mrr_growth:0.02},planos:[{nome:"COMBO BASIC 150MEGA",vel:300,mens:89.9,custo:60,ativos:65,mrr:5843.5},{nome:"COMBO HOME 250MEGA",vel:500,mens:99.9,custo:60,ativos:462,mrr:46153.8},{nome:"COMBO HOME 300MEGA",vel:600,mens:119.9,custo:60,ativos:420,mrr:50358},{nome:"COMBO HOME 350MEGA",vel:700,mens:129.9,custo:60,ativos:122,mrr:15847.8},{nome:"COMBO GAMER 450MEGA",vel:900,mens:149.9,custo:60,ativos:56,mrr:8394.4},{nome:"COMBO GAMER 500MEGA",vel:1000,mens:189.9,custo:60,ativos:7,mrr:1329.3},{nome:"RURAL BASIC 50MEGA",vel:100,mens:109.9,custo:90,ativos:23,mrr:2527.7},{nome:"RURAL BASIC 100MEGA",vel:200,mens:119.9,custo:90,ativos:75,mrr:8992.5},{nome:"RURAL HOME 150MEGA",vel:300,mens:129.9,custo:90,ativos:101,mrr:13119.9},{nome:"RURAL HOME 250MEGA",vel:500,mens:159.9,custo:90,ativos:41,mrr:6555.9},{nome:"RURAL GAMER 350MEGA",vel:700,mens:189.9,custo:90,ativos:8,mrr:1519.2},{nome:"RADIO 5MEGA",vel:10,mens:99.9,custo:60,ativos:350,mrr:34965},{nome:"RADIO 8MEGA",vel:16,mens:119.9,custo:60,ativos:177,mrr:21222.3},{nome:"RADIO 10MEGA",vel:20,mens:149.9,custo:60,ativos:74,mrr:11092.6},{nome:"EMPRESARIAL 50MEGA",vel:100,mens:129.9,custo:90,ativos:17,mrr:2208.3},{nome:"EMPRESARIAL 150MEGA",vel:300,mens:159.9,custo:90,ativos:25,mrr:3997.5},{nome:"EMPRESARIAL 250MEGA",vel:500,mens:199.9,custo:90,ativos:10,mrr:1999},{nome:"EMPRESARIAL 300MEGA",vel:600,mens:299,custo:90,ativos:1,mrr:299},],comissoes:[{plano:"COMBO BASIC 150MEGA",mens:89.9,c50:14.95,cmax:29.9},{plano:"COMBO HOME 250MEGA",mens:99.9,c50:19.95,cmax:39.9},{plano:"COMBO HOME 300MEGA",mens:119.9,c50:29.95,cmax:59.9},{plano:"COMBO HOME 350MEGA",mens:129.9,c50:34.95,cmax:69.9},{plano:"COMBO GAMER 450MEGA",mens:149.9,c50:44.95,cmax:89.9},{plano:"COMBO GAMER 500MEGA",mens:189.9,c50:64.95,cmax:129.9},{plano:"RADIO 5MEGA",mens:99.9,c50:19.95,cmax:39.9},{plano:"EMPRESARIAL 250MEGA",mens:199.9,c50:54.95,cmax:109.9},],custos:[{tec:"FTTH",loc:"Rural",custo:90},{tec:"FTTH",loc:"Urbano",custo:60},{tec:"RADIO",loc:"Rural",custo:60}],canais:[{canal:"📱 Meta Ads",invest:6000,leads:42,visitas:18,ativacoes:14,kpi:"CPL < R$30"},{canal:"🔍 Google Ads",invest:4500,leads:33,visitas:15,ativacoes:11,kpi:"CPC < R$5"},{canal:"🚶 Porta a Porta",invest:1500,leads:20,visitas:20,ativacoes:9,kpi:"Ativ/vendedor/dia"},{canal:"💬 Indique e ganhe",invest:0,leads:14,visitas:12,ativacoes:7,kpi:"CAC quase zero"},{canal:"📻 Rádio",invest:3000,leads:9,visitas:0,ativacoes:2,kpi:"Ligações rastreadas"},{canal:"🤝 Influenciadores",invest:2000,leads:11,visitas:4,ativacoes:3,kpi:"Ativações via código"},],pipeline:[{etapa:"Leads Recebidos",qtd:129},{etapa:"Contato Realizado",qtd:104},{etapa:"Proposta Enviada",qtd:71},{etapa:"Em Negociação",qtd:38},{etapa:"Fechamentos",qtd:33},],vendedoras:[{nome:"Mayara Quadros",ativ:13,mrr:1410,cancel:1,canal:"Porta a Porta",meta:12},{nome:"Alessandra F.",ativ:9,mrr:1080,cancel:0,canal:"Meta Ads",meta:12},{nome:"Patrícia Arantes",ativ:7,mrr:790,cancel:2,canal:"Indicação",meta:12},{nome:"Vivien Stersa",ativ:4,mrr:430,cancel:1,canal:"Google Ads",meta:12},],metas_equipe:[{nome:"Ativações da equipe / mês",atual:33,meta:48,un:"ativações"},{nome:"MRR novo gerado / mês",atual:3710,meta:5200,un:"R$",money:!0},{nome:"Conversão lead→cliente",atual:0.256,meta:0.30,un:"%",pct:!0},{nome:"Cancelamentos (teto)",atual:11,meta:6,un:"cancel.",invert:!0},],};const SEED_PROCESSOS=[{n:"01",area:"Lead",resp:"Marketing/CRM",sla:"Imediato",titulo:"Lead chega",txt:"Lead entra via formulário (Meta), ligação (rádio), WhatsApp ou indicação. O CRM cria o card automaticamente. Dados mínimos: nome, telefone e endereço."},{n:"02",area:"Cobertura",resp:"SDR/Sistema",sla:"< 3 min",titulo:"Verificação de cobertura",txt:"Conferir se o endereço tem CTO disponível e capacidade. Sem cobertura, registrar como 'Aguardando Expansão' e notificar quando liberar."},{n:"03",area:"Contato",resp:"SDR",sla:"< 5 min",titulo:"Contato inicial",txt:"Ligar/WhatsApp em menos de 5 minutos. Confirmar interesse e endereço, apresentar planos e qualificar (quem usa, quantos dispositivos, uso atual)."},{n:"04",area:"Proposta",resp:"SDR/Closer",sla:"< 30 min",titulo:"Proposta",txt:"Enviar proposta por WhatsApp (plano, preço, bônus de instalação). Mencionar oferta especial com prazo para criar urgência real."},{n:"05",area:"Agenda",resp:"Closer + Agenda",sla:"< 24h",titulo:"Agendamento técnico",txt:"Agendar visita para instalação em até 48h úteis. Confirmar janela de 2h (manhã/tarde) e enviar lembrete automático."},{n:"06",area:"Instalação",resp:"Técnico",sla:"≤ 48h",titulo:"Instalação",txt:"Técnico instala ONU/roteador, testa velocidade com o cliente e apresenta o app de suporte. Ativação no sistema + speedtest aprovado."},{n:"07",area:"Onboarding",resp:"CS/Automação",sla:"D+0 a D+7",titulo:"Boas-vindas",txt:"WhatsApp D+0 com app de suporte, D+3 tutorial de uso, D+7 checagem. Meta: nenhum chamado de suporte nos primeiros 7 dias."},{n:"08",area:"Retenção",resp:"CS/Retenção",sla:"Mensal",titulo:"Prevenção de churn",txt:"Monitorar assinantes com chamados repetidos, inadimplentes e plano básico há mais de 6 meses. Oferta proativa de upgrade antes do cancelamento."},];function buildSeries(){const base=SEED.kpis;const meses=['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'];const seedrand=(s)=>{let x=Math.sin(s)*10000;return x-Math.floor(x)};const mensal=meses.map((m,i)=>{const growth=Math.pow(1.021,i-3);const mrr=base.mrr_total*growth*(0.97+seedrand(i+1)*0.06);const ativ=Math.round(28+seedrand(i*3)*16);const cancel=Math.round(7+seedrand(i*5)*8);return{label:m,mrr:Math.round(mrr),ativacoes:ativ,cancelamentos:cancel,churn:+(cancel/(3400+i*30)).toFixed(4),cac:Math.round(105+seedrand(i*7)*55),arpu:+(108+seedrand(i*9)*10).toFixed(1),budget:Math.round(14000+seedrand(i*11)*4000),nps:Math.round(60+seedrand(i*13)*18),}});const diario=[];for(let d=1;d<=22;d++){const ativ=Math.round(seedrand(d*1.7)*4);diario.push({label:String(d).padStart(2,'0')+'/06',leads:Math.round(2+seedrand(d*2.1)*6),visitas:Math.round(seedrand(d*2.6)*4),ativacoes:ativ,cancelamentos:Math.round(seedrand(d*3.3)*2),mrr:Math.round(ativ*112),invest:Math.round(400+seedrand(d*3.9)*300),chamados:Math.round(seedrand(d*4.4)*5),})} const semanal=[1,2,3,4].map(w=>{const slice=diario.slice((w-1)*5,w*5);const sum=(k)=>slice.reduce((a,b)=>a+b[k],0);return{label:'Sem '+w,leads:sum('leads'),ativacoes:sum('ativacoes'),cancelamentos:sum('cancelamentos'),mrr:sum('mrr'),nps:Math.round(62+seedrand(w*6)*16)}});return{mensal,diario,semanal,meses}}
const SERIES=buildSeries();
function periodAggregate(period){const M=SERIES.mensal;const cur=M[5];let serie,comparaLabel,prev;switch(period){case 'semanal':serie=SERIES.semanal;return wrap(serie,'vs. semana anterior',SERIES.semanal[2]?.mrr,serie.at(-1).mrr);case 'mensal':serie=M.slice(0,6);prev=M[4];return wrap(serie,'vs. mês anterior',prev.mrr,cur.mrr);case 'trimestral':{const tris=chunkSum(M,3).slice(0,4).map((t,i)=>({...t,label:'T'+(i+1)}));serie=tris;prev=tris[0];return wrap(serie,'vs. trimestre anterior',tris.at(-2)?.mrr,tris.at(-1).mrr)}
case 'semestral':{const sem=chunkSum(M,6).map((s,i)=>({...s,label:(i+1)+'º Sem'}));serie=sem;return wrap(serie,'vs. semestre anterior',sem[0]?.mrr,sem.at(-1).mrr)}
case 'anual':default:serie=M;return wrap(serie,'acumulado 12 meses',M[0].mrr,M.at(-1).mrr)}}
function chunkSum(arr,size){const out=[];for(let i=0;i
const RNET={ixc:IXC,data:{kpis:()=>SEED.kpis,planos:()=>SEED.planos,comissoes:()=>SEED.comissoes,custos:()=>SEED.custos,canais:()=>SEED.canais,pipeline:()=>SEED.pipeline,vendedoras:()=>SEED.vendedoras,metasEquipe:()=>SEED.metas_equipe,processos:()=>JSON.parse(localStorage.getItem('rnet_proc')||'null')||SEED_PROCESSOS,saveProcessos:(arr)=>localStorage.setItem('rnet_proc',JSON.stringify(arr)),period:periodAggregate,series:()=>SERIES,},
async ixcListar(table,body){if(IXC.MODE!=='live')return{registros:[],mock:!0};const r=await fetch(`${IXC.PROXY}/listar/${table}`,{method:'POST',headers:{'Content-Type':'application/json','X-WP-Nonce':window.rnetNonce||''},body:JSON.stringify(body)});if(!r.ok)throw new Error('IXC erro '+r.status);return r.json()}};window.RNET=RNET;
const USERS=[{id:'anderson',nome:'Anderson Françolle',role:'admin',pin:'1234'},{id:'gerente',nome:'Gerente Comercial',role:'gerente',pin:'1234'},{id:'mayara',nome:'Mayara Quadros',role:'vendedora',pin:'1234',vendedora:'Mayara Quadros'},];
const ROLE_LABEL={admin:'Administrador',gerente:'Gerente Comercial',vendedora:'Vendedora'};
const PERMISSIONS={admin:{hub:['comercial','aceite','calculadora','simulador'],tabs:['dashboard','tracker','planos','metas','vendedoras','comissao','processos','config'],},gerente:{hub:['comercial','aceite'],tabs:['dashboard','tracker','planos','metas','vendedoras','processos'],},vendedora:{hub:['comercial','aceite'],tabs:['dashboard','tracker','processos'],},};
const Auth={current:null,init(){const saved=sessionStorage.getItem('rnet_user');if(saved){this.current=JSON.parse(saved)}},login(id,pin){const u=USERS.find(x=>x.id===id);if(!u||u.pin!==pin)return!1;this.current=u;sessionStorage.setItem('rnet_user',JSON.stringify(u));return!0},logout(){this.current=null;sessionStorage.removeItem('rnet_user')},can(tab){return PERMISSIONS[this.current.role].tabs.includes(tab)},hubApps(){return PERMISSIONS[this.current.role].hub},role(){return this.current.role},isAdmin(){return this.current.role==='admin'},};window.Auth=Auth;
const $=(s,el=document)=>el.querySelector(s);const $$=(s,el=document)=>[...el.querySelectorAll(s)];const app=$('#app');
const fmtBRL=(n)=>'R$ '+(n||0).toLocaleString('pt-BR',{minimumFractionDigits:0,maximumFractionDigits:0});const fmtBRL2=(n)=>'R$ '+(n||0).toLocaleString('pt-BR',{minimumFractionDigits:2,maximumFractionDigits:2});const fmtPct=(n,d=1)=>(n*100).toFixed(d).replace('.',',')+'%';const fmtNum=(n)=>(n||0).toLocaleString('pt-BR');const initials=(s)=>s.split(' ').slice(0,2).map(w=>w[0]).join('').toUpperCase();function toast(msg){const t=document.createElement('div');t.className='toast';t.textContent=msg;document.body.appendChild(t);setTimeout(()=>t.remove(),2200)}
let STATE={view:'hub',tab:'dashboard',period:'mensal'};window.STATE=STATE;window.render=render;window.renderComercial=renderComercial;
function render(){if(!Auth.current){return renderLogin()} if(STATE.view==='hub'){return renderHub()} if(STATE.view==='comercial'){return renderComercial()} return renderPlaceholderApp(STATE.view)}
function renderLogin(){app.innerHTML=`
RNET • Acesso
${USERS.map(u=>`
`).join('')}
`;
const tryLogin=(id,pin)=>{if(Auth.login(id,pin)){STATE.view='hub';render()}else $('#lg-err').textContent='Usuário ou senha inválidos.'};$('#lg-btn').onclick=()=>tryLogin($('#lg-user').value.trim(),$('#lg-pin').value);$('#lg-pin').onkeydown=(e)=>{if(e.key==='Enter')$('#lg-btn').click();};$$('.demo-user').forEach(b=>b.onclick=()=>tryLogin(b.dataset.u,'1234'))}
const HUB_APPS={comercial:{ico:'📊',bg:'linear-gradient(135deg,#19c3e6,#0e9cbb)',nome:'Sistema Comercial',desc:'Dashboard, metas, tracker diário, planos e performance da equipe.',soon:!1},aceite:{ico:'✍️',bg:'linear-gradient(135deg,#1fb877,#0f7a52)',nome:'Aceite Digital',desc:'Assinatura digital de contratos e termos dos clientes.',soon:!1,ext:!0},calculadora:{ico:'🧮',bg:'linear-gradient(135deg,#f5a623,#c47e10)',nome:'Calculadora de Projetos',desc:'Custos de extensão de rede, viabilidade e payback de projetos.',soon:!0},simulador:{ico:'🎚️',bg:'linear-gradient(135deg,#8b6cf0,#5b3fc0)',nome:'Simulador de Planos',desc:'Monta combos, simula desconto, fidelidade e comissão na hora.',soon:!0},};function renderHub(){const u=Auth.current;const apps=Auth.hubApps();app.innerHTML=`
RNET • Central de Sistemas
Tudo em um lugar só. Escolha por onde começar.
${a.nome}
${a.desc}
`;}).join('')}
`;$('#hub-logout').onclick=()=>{Auth.logout();render()};$$('.hub-card').forEach(c=>{const k=c.dataset.app;if(HUB_APPS[k].soon)return;c.onclick=()=>{if(k==='comercial'){STATE.view='comercial';STATE.tab='dashboard';render()}else{STATE.view=k;render()}}})}
function renderPlaceholderApp(key){const a=HUB_APPS[key]||{nome:key,ico:'📦'};app.innerHTML=`
${a.nome}
Este módulo é um projeto à parte. O botão fica aqui pronto e, quando o sistema existir, basta apontar a URL real (ex.: outra página do WordPress).
`;$('#back-hub').onclick=()=>{STATE.view='hub';render()}}
const TABS=[{id:'dashboard',ico:'📊',label:'Dashboard'},{id:'tracker',ico:'📅',label:'Tracker Diário'},{id:'metas',ico:'🎯',label:'Metas'},{id:'vendedoras',ico:'🏅',label:'Equipe'},{id:'planos',ico:'📶',label:'Planos & Preços'},{id:'comissao',ico:'💵',label:'Comissões'},{id:'processos',ico:'📋',label:'Processos'},{id:'config',ico:'⚙️',label:'Configurações'},];function renderComercial(){if(!Auth.can(STATE.tab))STATE.tab='dashboard';const u=Auth.current;app.innerHTML=`
`;
const nav=$('#nav');nav.innerHTML=TABS.filter(t=>Auth.can(t.id)).map(t=>` `).join('');$$('#nav .nav-item').forEach(b=>b.onclick=()=>{STATE.tab=b.dataset.tab;renderComercial()});$('#to-hub').onclick=()=>{STATE.view='hub';render()};$('#logout').onclick=()=>{Auth.logout();render()};$('#mtoggle').onclick=()=>$('#sb').classList.toggle('open');
const tab=TABS.find(t=>t.id===STATE.tab);$('#page-title').textContent=tab.label;
const c=$('#content');({dashboard:renderDashboard,tracker:renderTracker,metas:renderMetas,vendedoras:renderEquipe,planos:renderPlanos,comissao:renderComissao,processos:renderProcessos,config:renderConfig,})[STATE.tab](c)}
function ixcBanner(){const live=RNET.ixc.MODE==='live';return `
`}
function periodSwitcher(){const opts=[['semanal','Semanal'],['mensal','Mensal'],['trimestral','Trimestral'],['semestral','Semestral'],['anual','Anual']];return `
`} function bindPeriod(reRender){$$('.period-bar button').forEach(b=>b.onclick=()=>{STATE.period=b.dataset.p;reRender()})}
function lineChart(serie,key,{color='var(--cyan-400)',h=180,fmt=fmtNum,area=!0}={}){if(!serie.length)return'';const vals=serie.map(d=>d[key]||0);const max=Math.max(...vals)*1.12||1,min=Math.min(...vals,0);const W=620,H=h,pad=34;const x=i=>pad+i*(W-pad*1.4)/(serie.length-1||1);const y=v=>H-pad-((v-min)/(max-min||1))*(H-pad*1.6);const pts=serie.map((d,i)=>[x(i),y(d[key]||0)]);const path=pts.map((p,i)=>(i?'L':'M')+p[0].toFixed(1)+' '+p[1].toFixed(1)).join(' ');const areaPath=`${path} L${x(serie.length-1)} ${H-pad} L${pad} ${H-pad} Z`;const grid=[0,.25,.5,.75,1].map(t=>{const yy=pad*0.6+t*(H-pad*1.6);return `
function renderDashboard(c){const k=RNET.data.kpis();const p=RNET.data.period(STATE.period);const canais=RNET.data.canais();const pipe=RNET.data.pipeline();const isVend=Auth.role()==='vendedora';
const deltaCls=p.deltaMRR>=0?'up':'down';const deltaArr=p.deltaMRR>=0?'▲':'▼';
const kpiCards=`
`;
const finCards=isVend?'':`
`;
c.innerHTML=` ${ixcBanner()}
${periodSwitcher()}
${finCards?`
`:''}
Evolução de MRR
Receita recorrente — ${STATE.period}
${lineChart(p.serie,'mrr',{fmt:fmtBRL})}
Ativações × Cancelamentos
${barChart(p.serie,'ativacoes',{fmt:fmtNum})}
Pipeline comercial
`;}).join('')}
Ativações & receita por canal
${canais.map(ch=>{const cac=ch.ativacoes?Math.round(ch.invest/ch.ativacoes):0; const mx=Math.max(...canais.map(x=>x.ativacoes)); return `
`;}).join('')}
`;
bindPeriod(()=>renderComercial());if(window.innerWidth<880)$('#dash-2col').style.gridTemplateColumns='1fr'} function renderTracker(c){const S=RNET.data.series();const dia=S.diario,sem=S.semanal;const tot=(k)=>dia.reduce((a,b)=>a+b[k],0);c.innerHTML=` ${ixcBanner()}
Resumo do mês (acumulado diário)
Instalações por dia útil
${barChart(dia,'ativacoes',{fmt:fmtNum,h:170})}
Lançamento diário
| Data | Leads | Visitas Téc. | Ativações | Cancel. | MRR R$ | Invest. | CAC | Chamados |
|---|---|---|---|---|---|---|---|---|
| ${d.label} | ${d.leads} | ${d.visitas} | ${d.ativacoes} | ${d.cancelamentos} | ${fmtBRL(d.mrr)} | ${fmtBRL(d.invest)} | ${cac?fmtBRL(cac):'—'} | ${d.chamados} |
Consolidado semanal
| Semana | Leads | Ativações | Cancel. | MRR novo | NPS |
|---|---|---|---|---|---|
| ${w.label} | ${w.leads} | ${w.ativacoes} | ${w.cancelamentos} | ${fmtBRL(w.mrr)} | ${w.nps} |
`;
$('#add-dia').onclick=()=>openDiaModal()} function openDiaModal(){const m=document.createElement('div');m.className='modal-bg';m.innerHTML=`
Lançar dia
`;document.body.appendChild(m);$('#d-cancelar').onclick=()=>m.remove();m.onclick=(e)=>{if(e.target===m)m.remove();};$('#d-salvar').onclick=()=>{m.remove();toast('Lançamento registrado (modo teste)')}}
function renderMetas(c){const k=RNET.data.kpis();const eq=RNET.data.metasEquipe();const isAdmin=Auth.isAdmin();
const empresa=[{nome:'Crescimento de MRR',atual:0.0111,meta:k.meta_mrr_growth,pct:!0},{nome:'Churn mensal',atual:k.churn_rate,meta:k.meta_churn,pct:!0,invert:!0},{nome:'CAC médio',atual:k.cac_medio,meta:k.meta_cac,money:!0,invert:!0},{nome:'LTV',atual:k.ltv,meta:k.meta_ltv,money:!0},{nome:'LTV : CAC',atual:k.ltv_cac,meta:k.meta_ltv_cac,suf:'x'},{nome:'ARPU',atual:k.arpu,meta:k.meta_arpu,money:!0},];
const goalCard=(g)=>{let pct=g.invert?Math.min(g.meta/(g.atual||1),1):Math.min((g.atual||0)/(g.meta||1),1);const cls=pct>=1?'ok':pct>=0.7?'warn':'bad';const fmtv=(v)=>g.money?fmtBRL2(v):g.pct?fmtPct(v,2):g.un==='R$'?fmtBRL(v):(v+(g.suf||(g.un&&!g.money&&!g.pct?' '+g.un:'')));const atualTxt=g.money?fmtBRL(g.atual):g.pct?fmtPct(g.atual,2):(g.atual+(g.suf||''));const metaTxt=g.money?fmtBRL(g.meta):g.pct?fmtPct(g.meta,2):(g.meta+(g.suf||''));return `
`};
c.innerHTML=` ${ixcBanner()} ${isAdmin?`
Metas daempresa
Responsável:Anderson
`:''}
Metas da equipe comercial
Como a meta da equipe vira meta da empresa
`;
const em=$('#edit-metas');if(em)em.onclick=()=>openMetaModal();} function openMetaModal(){const eq=RNET.data.metasEquipe();const m=document.createElement('div');m.className='modal-bg';m.innerHTML=`
Ajustar metas da equipe
${eq.map((g,i)=>`
`).join('')}
`;document.body.appendChild(m);$('#mt-cancel').onclick=()=>m.remove();m.onclick=(e)=>{if(e.target===m)m.remove();};$('#mt-save').onclick=()=>{m.remove();toast('Metas atualizadas (modo teste)')}}
function renderEquipe(c){const v=RNET.data.vendedoras();const maxAtiv=Math.max(...v.map(x=>x.ativ));c.innerHTML=` ${ixcBanner()}
Ranking de vendedoras · mês
`;}).join('')}
Tabela comparativa
| Vendedora | Ativações | Meta | % Meta | MRR gerado | Cancel. | Status |
|---|---|---|---|---|---|---|
| ${x.nome} | ${x.ativ} | ${x.meta} | ${Math.round(pct*100)}% | ${fmtBRL(x.mrr)} | ${x.cancel} | ${ok?'No alvo':warn?'Atenção':'Abaixo'} |
`}
function renderPlanos(c){const planos=RNET.data.planos();const totAtivos=planos.reduce((a,b)=>a+b.ativos,0);const totMRR=planos.reduce((a,b)=>a+b.mrr,0);const podeEditar=Auth.isAdmin();c.innerHTML=` ${ixcBanner()}
Carteira por plano
${podeEditar?'':''}
| Plano | Mbps | Mensalidade | Custo Op. | Margem | Assinantes | MRR | % carteira |
|---|---|---|---|---|---|---|---|
| ${p.nome} | ${p.vel} | ${fmtBRL2(p.mens)} | ${fmtBRL(p.custo)} | ${fmtPct(marg,0)} | ${fmtNum(p.ativos)} | ${fmtBRL(p.mrr)} | ${fmtPct(p.mrr/totMRR,1)} |
`;const ap=$('#add-plano');if(ap)ap.onclick=()=>toast('Cadastro de plano disponível na integração IXC');}
function renderComissao(c){const com=RNET.data.comissoes();c.innerHTML=` ${ixcBanner()}
Modelo de comissionamento · por ativação
| Plano | Mensalidade | Comissão base (50%) | Comissão máxima | % da mensalidade |
|---|---|---|---|---|
| ${x.plano} | ${fmtBRL2(x.mens)} | ${fmtBRL2(x.c50)} | ${fmtBRL2(x.cmax)} | ${fmtPct(x.cmax/x.mens,0)} |
Simulação rápida
`;const calc=()=>{const i=+$('#sim-plano').value,q=+$('#sim-qtd').value||0;const x=com[i];$('#sim-out').innerHTML=`Com ${q} ativações no plano selecionado, a comissão varia de ${fmtBRL2(x.c50*q)} (base) até ${fmtBRL2(x.cmax*q)} (máxima ao bater meta).`};$('#sim-plano').onchange=calc;$('#sim-qtd').oninput=calc;calc()}
function renderProcessos(c){const procs=RNET.data.processos();const podeEditar=Auth.role()!=='vendedora';c.innerHTML=`
Processo comercial — do lead à ativação
${podeEditar?'':''}
`;if(podeEditar){$('#add-proc').onclick=()=>{const arr=RNET.data.processos();arr.push({n:String(arr.length+1).padStart(2,'0'),area:'Nova',resp:'—',sla:'—',titulo:'Nova etapa',txt:'Descreva o processo aqui.'});RNET.data.saveProcessos(arr);renderProcessos(c)};bindProcEdit(c)}} function procCard(p,i,editable){return `
${p.titulo}
${p.txt}
`} function bindProcEdit(c){$$('#proc-grid .pedit').forEach(b=>b.onclick=()=>{const i=+b.dataset.edit;const arr=RNET.data.processos();const p=arr[i];const card=b.closest('.proc');card.innerHTML=`
`;$('#pe-cancel',card).onclick=()=>renderProcessos(c);$('#pe-save',card).onclick=()=>{arr[i]={...p,titulo:$('#pe-t',card).value,area:$('#pe-a',card).value,resp:$('#pe-r',card).value,sla:$('#pe-s',card).value,txt:$('#pe-x',card).value};RNET.data.saveProcessos(arr);renderProcessos(c);toast('Processo atualizado')};$('#pe-del',card).onclick=()=>{arr.splice(i,1);RNET.data.saveProcessos(arr);renderProcessos(c);toast('Etapa removida')}})}
function renderConfig(c){const live=RNET.ixc.MODE==='live';c.innerHTML=`
Integração IXC Soft
${ixcBanner()}
Mapeamento de tabelas IXC
| Indicador no painel | Tabela IXC | Campos-chave |
|---|---|---|
| Assinantes / clientes | cliente |
razao, cnpj_cpf, cidade, ativo |
| Contratos / ativações | cliente_contrato |
id_cliente, status, status_internet, data_ativacao, fidelidade |
| Planos & valores | vd_contratos |
nome, valor_contrato, fidelidade, id_cidade |
| Cancelamentos / churn | cliente_contrato |
status='I', status_internet='D' |
`;$('#cfg-test').onclick=()=>toast(live?'Conexão IXC OK':'Em modo teste — nada é chamado');$('#cfg-save').onclick=()=>toast('Configuração salva (aplicar no plugin do WordPress)')}
Auth.init();render();window.addEventListener('resize',()=>{if(STATE.view==='comercial'&&STATE.tab==='dashboard'){}});