`;
const pa=projAg(s),pr=projRe(s),mp=margemProj(s),fp=fatProj(s);
const rows=[
{lbl:'Leads', v:s.leads, color:'#30a88c', hl:false,isBrl:false,isPct:false,pfx:''},
{lbl:'Consumidos', v:s.consumido,color:'#3a9e88', hl:false,isBrl:false,isPct:false,pfx:''},
{lbl:'Ganhos', v:s.ganhos, color:'#2d9476', hl:false,isBrl:false,isPct:false,pfx:''},
{lbl:'R. Agendada', v:s.agendada, color:'#257d64', hl:false,isBrl:false,isPct:false,pfx:''},
{lbl:'R. Realizada', v:s.realizada,color:'#1dc077', hl:true, isBrl:false,isPct:false,pfx:''},
{lbl:'Bolo', v:s.bolo, color:'#1a6b52', hl:false,isBrl:false,isPct:false,pfx:''},
null,
{lbl:'R. Ag. Proj.', v:pa, color:'rgba(48,168,140,.5)',hl:false,isBrl:false,isPct:false,pfx:'proj.'},
{lbl:'R. Re. Proj.', v:pr, color:'rgba(48,168,140,.5)',hl:false,isBrl:false,isPct:false,pfx:'proj.'},
{lbl:'Margem Proj.', v:mp, color:'rgba(48,168,140,.4)',hl:false,isBrl:false,isPct:true, pfx:'proj.'},
null,
{lbl:'Fat. Planej.', v:s.fat||null,color:'rgba(48,168,140,.6)',hl:false,isBrl:true, isPct:false,pfx:'fat.'},
{lbl:'Fat.+Cross-sell',v:fp, color:'rgba(48,168,140,.35)',hl:false,isBrl:true,isPct:false,pfx:'proj.'},
];
return`
${rows.map(r=>{
if(r===null)return`
`;
const p=r.isPct?Math.min(r.v||0,100):r.isBrl?(r.v?r.v/300000*100:0):r.v?Math.min(r.v/s.leads*100,100):0;
const pc=Math.min(p,100);
const pfxHtml=r.pfx?`
${r.pfx}`:'';
const dispVal=r.v==null?'–':r.isPct?pct(r.v):r.isBrl?brl(r.v,true):n(r.v);
return`
${pfxHtml}${r.lbl}
${!r.isBrl&&!r.isPct&&pc>10?pct(p):''}
${dispVal}
${!r.isBrl&&!r.isPct&&pc0?pct(p):''}
`;
}).join('')}
`;
}
function safraTable(s){
const c=cpl(s),cr=consRate(s),cv=convRate(s),pa=projAg(s),pr=projRe(s),fp=fatProj(s),mp=margemProj(s);
const rows=[
{lbl:'Investimento', val:brl(s.inv), obs:'', hl:false,t:''},
{lbl:'Leads Gerados', val:n(s.leads), obs:'', hl:false,t:''},
{lbl:'CPL', val:brl(c), obs:c&&c
| Métrica | Valor | Obs. |
${rows.map(r=>{
const pfx=r.t?`${r.t==='tr-proj'?'proj.':'fat.'}`:'';
return`| ${pfx}${r.lbl} | ${r.val} | ${r.obs} |
`;
}).join('')}
`;
}
function renderSafra(){
const s=S.find(x=>x.id===curSafra);
document.getElementById('tabs').innerHTML=S.map(x=>`
${x.label}${x.partial?'Em andamento':''}
`).join('');
const c=cpl(s),cr=consRate(s),cv=convRate(s),pa=projAg(s),pr=projRe(s),fp=fatProj(s),mp=margemProj(s);
document.getElementById('kpi-safra').innerHTML=`
Realizado
Investimento
${brl(s.inv)}
R. Agendada
${n(s.agendada)}
R. Realizadas
${n(s.realizada)}
${pct(cv)} conv. ag.
Fat. Planejamento
${s.fat?brl(s.fat):'–'}
Projetado
proj.
R. Ag. Projetada
${pa!=null?n(pa):'–'}
leads×60%×(ag./cons.)
proj.
R. Re. Projetada
${pr!=null?n(pr):'–'}
conv.×R.Ag.Proj.
proj.
Margem Projetada
${mp!=null?pct(mp):'–'}
inv÷(R.Re.Proj×20%×11k)
proj.
Fat.+Cross-sell
${fp?brl(fp):'–'}
fat. planej. × 2,2
`;
document.getElementById('content-safra').innerHTML=`
Funil de Conversão — ${s.label}
${funnel(s)}
Métricas Completas
${safraTable(s)}
`;
}
function renderAcum(){
const full=S.filter(x=>x.leads>0);
const noFat=S.filter(x=>x.leads>0&&x.fat>0);
const tot={
inv:S.reduce((a,x)=>a+x.inv,0),
leads:full.reduce((a,x)=>a+x.leads,0),
consumido:full.reduce((a,x)=>a+x.consumido,0),
agendada:full.reduce((a,x)=>a+x.agendada,0),
realizada:full.reduce((a,x)=>a+x.realizada,0),
bolo:full.reduce((a,x)=>a+x.bolo,0),
ganhos:full.reduce((a,x)=>a+x.ganhos,0),
fat:noFat.reduce((a,x)=>a+x.fat,0),
};
const tPA=projAg(tot)||0,tPR=projRe(tot)||0,tFP=tot.fat*2.2,tMP=margemProj(tot);
document.getElementById('content-acum').innerHTML=`
Realizado
Invest. Total
${brl(tot.inv,true)}
Total Leads
${n(tot.leads)}
Dez–Abr
CPL Médio
${brl(tot.inv/tot.leads)}
Consumidos
${pct(tot.consumido/tot.leads*100)}
${n(tot.consumido)} leads
R. Agendada
${n(tot.agendada)}
R. Realizadas
${n(tot.realizada)}
${pct(tot.realizada/tot.agendada*100)} conv.
Fat. Planejamento
${brl(tot.fat,true)}
Dez–Mar
Projetado
proj.
R. Ag. Projetada
${n(tPA)}
proj.
R. Re. Projetada
${n(tPR)}
proj.
Margem Projetada
${tMP!=null?pct(tMP):'–'}
inv÷(R.Re.Proj×20%×11k)
proj.
Fat.+Cross-sell
${brl(tFP,true)}
fat. planej. × 2,2
Faturamento: Realizado vs Projetado+Cross-sell
Fat. Planejamento
Fat.+Cross-sell (×2,2)
Margem Projetada por Safra
Leads · Consumidos · R. Realizadas por Safra
Leads
Consumidos
R. Realizadas
Comparativo por Safra
| Safra | Leads | R.Re.Proj. | Margem Proj. | Fat.Plan. | Fat.+Cross |
${full.map((s,i)=>`
| ${s.short}${s.partial?'parcial':''} |
${n(s.leads)} |
${n(projRe(s))} |
${margemProj(s)!=null?pct(margemProj(s)):'–'} |
${s.fat?brl(s.fat,true):'–'} |
${fatProj(s)?brl(fatProj(s),true):'–'} |
`).join('')}
| Total |
${n(tot.leads)} |
${n(tPR)} |
${tMP!=null?pct(tMP):'–'} |
${brl(tot.fat,true)} |
${brl(tFP,true)} |
Funil Acumulado (Dez–Abr)
${funnel({...tot,fat:tot.fat,partial:false})}
`;
setTimeout(()=>{
destroyChart('c1');destroyChart('c2');destroyChart('c3');
const ctx1=document.getElementById('c1'),ctx2=document.getElementById('c2'),ctx3=document.getElementById('c3');
const fatFull=full.filter(s=>s.fat>0);
const ax={ticks:{color:'rgba(235,235,245,.35)',font:{size:11},autoSkip:false},grid:{color:'rgba(84,84,88,.15)'},border:{color:'rgba(84,84,88,.2)'}};
if(ctx1){charts['c1']=new Chart(ctx1,{type:'bar',data:{
labels:fatFull.map(s=>s.short),
datasets:[
{label:'Fat. Planejamento',data:fatFull.map(s=>s.fat),backgroundColor:'rgba(29,192,119,.75)',borderColor:'#1dc077',borderWidth:1.5,borderRadius:5},
{label:'Fat.+Cross-sell', data:fatFull.map(s=>s.fat*2.2),backgroundColor:'rgba(29,192,119,.2)',borderColor:'rgba(29,192,119,.45)',borderWidth:1,borderRadius:5},
]
},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{display:false}},scales:{
x:{...ax},y:{...ax,ticks:{...ax.ticks,callback:v=>'R$'+(v>=1000?(v/1000).toFixed(0)+'k':v)}}
}}})}
if(ctx2){charts['c2']=new Chart(ctx2,{type:'bar',data:{
labels:full.map(s=>s.short),
datasets:[
{label:'Leads', data:full.map(s=>s.leads), backgroundColor:C_FILL, borderColor:C_SOLID,borderWidth:1.5,borderRadius:5},
{label:'Consumidos',data:full.map(s=>s.consumido), backgroundColor:'rgba(84,84,88,.35)',borderColor:'rgba(84,84,88,.55)',borderWidth:1,borderRadius:5},
{label:'Realizadas',data:full.map(s=>s.realizada), backgroundColor:'rgba(29,192,119,.75)',borderColor:'#1dc077',borderWidth:1.5,borderRadius:5},
]
},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{display:false}},scales:{
x:{...ax},y:{...ax,ticks:{...ax.ticks,callback:v=>v>=1000?(v/1000).toFixed(1)+'k':v}}
}}})}
if(ctx3){charts['c3']=new Chart(ctx3,{type:'bar',data:{
labels:full.map(s=>s.short),
datasets:[{label:'Margem Projetada',data:full.map(s=>{const m=margemProj(s);return m!=null?parseFloat(m.toFixed(2)):null;}),backgroundColor:'rgba(29,192,119,.65)',borderColor:'#1dc077',borderWidth:1.5,borderRadius:5}]
},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{display:false}},scales:{
x:{...ax},y:{...ax,ticks:{...ax.ticks,callback:v=>v+'%'}}
}}})}
},60);
}
function selectSafra(id){curSafra=id;renderSafra();}
function setView(v){
document.querySelectorAll('.vt-btn').forEach(b=>b.classList.toggle('active',b.textContent.trim().toLowerCase().includes(v==='safra'?'safra':'acum')));
document.getElementById('view-safra').style.display=v==='safra'?'block':'none';
document.getElementById('view-acumulada').style.display=v==='acumulada'?'block':'none';
if(v==='acumulada')renderAcum();
}
renderSafra();