/* Growth OS — Modal de indicador (breadcrumb interno) + Pesquisa inteligente */ (function(){ const R=window.React,h=R.createElement,{useState}=R; const G=window.GOS,L=window.GOSlib,Icon=window.GOSIcon; function relatedOf(co,ind){ const rel=new Set(); if(ind.parts)ind.parts.forEach(p=>rel.add(p[1])); co.indicators.forEach(i=>{if(i.key!==ind.key&&i.parts&&i.parts.some(p=>p[1]===ind.key))rel.add(i.key);}); co.indicators.forEach(i=>{if(i.key!==ind.key&&i.cat===ind.cat&&i.star)rel.add(i.key);}); return[...rel].map(k=>co.indicators.find(i=>i.key===k)).filter(Boolean).filter(i=>i.key!==ind.key).slice(0,4); } function breakdown(co,ind,c){ if(c==null)return null; if(ind.cat==="Marketing"||ind.cat==="Comercial"){ const split=[["Meta Ads",.52],["Google Ads",.31],["Orgânico / Indicação",.17]]; return{dim:"Canal",rows:split.map(s=>[s[0],ind.type==="percentual"||ind.type==="indice"?c:c*s[1],s[1]])}; } if(ind.cat==="Receita"){ const split=[["Novos contratos",.46],["Recorrente / renovação",.39],["Expansão / upsell",.15]]; return{dim:"Origem",rows:split.map(s=>[s[0],ind.type==="percentual"||ind.type==="indice"?c:c*s[1],s[1]])}; } return null; } function readingText(co,ind,c,p,d,good,period){ if(c==null)return["Dados insuficientes para este indicador no período selecionado."]; const cmpName=period.cmp?period.cmp.label:"mês anterior"; const lines=[]; if(d.ok&&d.pct!=null){ const dir=good==="up"?"subiu":good==="down"?"caiu":"manteve-se estável"; const pp=L.isPP(ind)?` (${d.pp>0?"+":""}${d.pp} pontos percentuais)`:""; lines.push(`${ind.name} ${dir} ${Math.abs(d.pct)}%${pp} em relação a ${cmpName}, indo de ${L.fmtVal(ind,p,true)} para ${L.fmtVal(ind,c,true)}.`); }else{lines.push(`${ind.name} está em ${L.fmtVal(ind,c,true)}. Sem base comparável confiável no período.`);} if(ind.goal!=null){ const hit=ind.dir==="menor"?c<=ind.goal:c>=ind.goal; lines.push(hit?`O valor está dentro da meta de ${L.fmtVal(ind,ind.goal,true)}.`:`Ainda ${ind.dir==="menor"?"acima":"abaixo"} da meta de ${L.fmtVal(ind,ind.goal,true)}.`); } const t=L.trend(ind,G.keys6); lines.push(`Tendência ${t.cls.toLowerCase()} nos últimos 3 meses comparáveis (janela padrão da análise).`); return lines; } function IndicatorModal(props){ const{company:co,period}=props; const[stack,setStack]=useState([props.metricKey]); const key=stack[stack.length-1]; const ind=co.indicators.find(i=>i.key===key); if(!ind)return null; const cur=period.keys,cmp=period.cmp&&!period.cmp.noData?period.cmp.keys:["2026-05"]; const c=L.agg(ind,cur),p=L.agg(ind,cmp),d=L.delta(ind,c,p),good=L.goodness(ind,c,p); const goToRel=k=>setStack(s=>[...s,k]); const back=()=>setStack(s=>s.slice(0,-1)); const spark=G.keys6.map(k=>ind.series[k]); const cmpSpark=period.cmp&&!period.cmp.noData?null:null; const rel=relatedOf(co,ind); const bd=breakdown(co,ind,c); const tipFmt=v=>L.fmtVal(ind,v,true); const goalHit=ind.goal!=null?(ind.dir==="menor"?c<=ind.goal:c>=ind.goal):null; return h("div",{className:"modal-scrim",onClick:props.onClose}, h("div",{className:"modal",onClick:e=>e.stopPropagation()}, h("div",{className:"modal-hd"}, h("div",{style:{minWidth:0}}, h("div",{className:"modal-bc"}, h("span",null,co.name),h(Icon,{name:"chevronR",size:11}), stack.length>1?h(React.Fragment,null,h("button",{onClick:back},"Indicador"),h(Icon,{name:"chevronR",size:11})):null, h("span",{style:{color:"var(--papel)"}},ind.cat)), h("h2",null,ind.name), h("p",{className:"mh-def"},ind.formula?ind.formula:"Indicador de "+ind.cat.toLowerCase()+"."," · ",co.name," · ",period.label)), h("button",{className:"modal-close",onClick:props.onClose},h(Icon,{name:"close",size:18}))), h("div",{className:"modal-body"}, h("div",{className:"stat-row"}, statCell("Valor atual",L.fmtVal(ind,c),period.label,"var(--papel)"), statCell("Anterior",L.fmtVal(ind,p),period.cmp?period.cmp.label:"mai/26","var(--mist)"), statCell("Variação",d.ok&&d.pct!=null?(L.isPP(ind)?`${d.pp>0?"+":""}${d.pp} p.p.`:`${d.pct>0?"+":""}${d.pct}%`):"—",d.ok&&d.abs!=null?"abs "+L.fmtVal(ind,Math.abs(d.abs),true):"",good==="up"?"var(--up)":good==="down"?"var(--down)":"var(--papel)"), ind.goal!=null?statCell("Meta",L.fmtVal(ind,ind.goal),goalHit?"atingida":"em aberto",goalHit?"var(--up)":"var(--warn)"):statCell("Direção",dirLabel(ind.dir),"objetivo","var(--papel)")), h("div",{className:"reading"}, h("div",{className:"rd-l"},"Leitura do acontecimento"), readingText(co,ind,c,p,d,good,period).map((t,i)=>h("p",{key:i},t))), h("div",{className:"grid-2",style:{alignItems:"start",gap:20}}, h("div",{className:"panel"}, h("div",{className:"panel-hd"},h("h3",null,"Evolução mensal"),h("span",{className:"lbl"},"jan – jun 26")), h(L.LineChart,{months:G.keys6,values:spark,goal:ind.goal,color:co.color,tipFmt}), h("div",{className:"chart-legend"}, h("span",null,h("i",{style:{background:co.color}}),ind.name), ind.goal!=null&&h("span",null,h("i",{style:{background:"#6E7163"}}),"meta"))), h("div",{style:{display:"flex",flexDirection:"column",gap:20}}, ind.formula&&h("div",{className:"panel"}, h("div",{className:"panel-hd"},h("h3",null,"Fórmula")), h("div",{className:"formula"}, h("div",{className:"fx"},ind.formula), ind.parts&&h("div",{className:"formula-parts"}, ind.parts.map((pt,i)=>{const pind=co.indicators.find(x=>x.key===pt[1]);const pv=pind?L.agg(pind,cur):null; return h("div",{className:"fp-row",key:i},h("span",{className:"fp-n"},pt[0]),h("span",{className:"fp-v"},pind?L.fmtVal(pind,pv,true):"—"));}), h("div",{className:"fp-row"},h("span",{className:"fp-n",style:{color:"var(--lume)"}},"Resultado"),h("span",{className:"fp-v",style:{color:"var(--lume)"}},L.fmtVal(ind,c)))))), h("div",{className:"panel"}, h("div",{className:"panel-hd"},h("h3",null,"Fonte e confiança")), h("div",{style:{display:"flex",flexWrap:"wrap",gap:9}}, h("span",{className:"tag-src"},h(Icon,{name:"integracoes",size:13}),ind.source), h("span",{className:"tag-src"},h(Icon,{name:"refresh",size:13}),co.dataQ.updated), h("span",{className:"conf-badge "+ind.conf},h(Icon,{name:ind.conf==="alta"?"check":"alert",size:12}),"confiança "+ind.conf), h("span",{className:"tag-src"},h(Icon,{name:"clientes",size:13}),ind.resp)), h("p",{className:"muted",style:{fontSize:12.5,marginTop:12,lineHeight:1.5}},"Periodicidade mensal. Todo valor mantém referência à fonte original; valores manuais e integrados não se sobrescrevem silenciosamente.")))), bd&&h("div",{className:"panel",style:{marginTop:20}}, h("div",{className:"panel-hd"},h("h3",null,"Quebra por "+bd.dim.toLowerCase()),h("span",{className:"lbl"},"estimativa")), h("table",{className:"dtable"}, h("thead",null,h("tr",null,h("th",null,bd.dim),h("th",null,"Valor"),h("th",null,"Participação"))), h("tbody",null,bd.rows.map((r,i)=>h("tr",{key:i}, h("td",null,h("span",{className:"cell-name"},r[0])), h("td",{className:"num"},L.fmtVal(ind,r[1],true)), h("td",{className:"num"},Math.round(r[2]*100)+"%")))))), rel.length>0&&h("div",{style:{marginTop:22}}, h("div",{className:"section-lbl",style:{margin:"0 0 14px"}},h("h2",{style:{fontSize:15}},"Indicadores relacionados"),h("span",{className:"sl-line"})), h("div",{className:"metric-grid"},rel.map(ri=>h(window.GOSMetricCard,{key:ri.key,ind:ri,period,onOpen:goToRel})))), // context tied to metric category h("div",{className:"panel",style:{marginTop:20}}, h("div",{className:"panel-hd"},h("h3",null,"Contexto associado")), co.context.slice(0,3).map((ce,i)=>h("div",{className:"ctx-item",key:i,style:i===2?{borderBottom:"none"}:null}, h("span",{className:"ci-date"},fmtDate(ce.date)), h("span",{className:"ci-cat"},ce.cat), h("span",{className:"ci-txt"},ce.txt))))), h("div",{className:"modal-foot"}, stack.length>1&&h("button",{className:"btn btn-ghost btn-sm",onClick:back},h(Icon,{name:"chevron",size:14,style:{transform:"rotate(90deg)"}}),"Voltar"), h("button",{className:"btn btn-ghost",onClick:props.onClose},"Fechar"), h("button",{className:"btn btn-lume",onClick:()=>props.onReport(ind)},h(Icon,{name:"download",size:15}),"Gerar relatório do indicador")))); } function statCell(l,v,x,col){return h("div",{className:"stat-cell"},h("div",{className:"sc-l"},l),h("div",{className:"sc-v",style:{color:col}},v),x&&h("div",{className:"sc-x muted"},x));} function dirLabel(d){return{maior:"Maior é melhor",menor:"Menor é melhor",faixa:"Faixa é melhor",monitor:"Monitorar"}[d]||d;} function fmtDate(s){const[y,m,dd]=s.split("-");return`${dd}/${m}`;} /* ============ PESQUISA INTELIGENTE (spec §8) ============ */ const MONTHKW={janeiro:"2026-01",fevereiro:"2026-02","março":"2026-03",marco:"2026-03",abril:"2026-04",maio:"2026-05",junho:"2026-06"}; function findMetric(co,q){ const map=[["cpl","cpl"],["custo por lead","cpl"],["cac","cac"],["roi","roi"],["roas","roas"],["conversão","conversao"],["conversao","conversao"],["receita","rrec"],["faturamento","rfat"],["faturado","rfat"],["ticket","ticket"],["lead","leads"],["reuni","reunioes"],["contrato","contratos"],["cliente","ativos"],["churn","churn"],["retenção","retencao"],["ocupação","ocupacao"],["ocupacao","ocupacao"],["reserva","reserva"],["diária","diarias"],["capacidade","capacidade"],["ctr","ctr"]]; for(const[kw,key]of map){if(q.includes(kw)){const ind=co.indicators.find(i=>i.key===key);if(ind)return ind;}} return null; } function answer(co,period,q){ const ql=q.toLowerCase(); const months=Object.keys(MONTHKW).filter(m=>ql.includes(m)).map(m=>MONTHKW[m]); const ind=findMetric(co,ql); const isCompare=/(compar|versus| vs |diferença|aumentou|subiu|caiu|variou)/.test(ql); const isExtreme=/(melhor|pior|maior|menor)/.test(ql); const isTrend=/(tend|subindo|caindo|aumentando|crescendo)/.test(ql); const isGoal=/(meta|falta)/.test(ql); if(!ind&&!isGoal){ return{type:"insuf",title:"Não identifiquei o indicador",body:"Reformule citando um indicador de "+co.name+", por exemplo: CPL, CAC, ROI, conversão, receita, reservas ou churn.",conf:"—"}; } // extreme if(ind&&isExtreme){ const vals=G.keys6.map(k=>({k,v:ind.series[k]})).filter(x=>x.v!=null); const worst=ind.dir==="menor";const pickBest=/melhor|maior/.test(ql)&&!/pior|menor/.test(ql); const better=(a,b)=>ind.dir==="menor"?ab; let best=vals[0];vals.forEach(x=>{if(pickBest?better(x.v,best.v):!better(x.v,best.v))best=x;}); return{type:"answer",ind,title:`${pickBest?"Melhor":"Pior"} mês de ${ind.name}`, big:L.fmtVal(ind,best.v),bigSub:L.monthLong(best.k), body:`Considerando jan–jun/26, ${L.monthLong(best.k)} foi o ${pickBest?"melhor":"pior"} mês de ${ind.name} (${L.fmtVal(ind,best.v,true)}).`, months:G.keys6,values:G.keys6.map(k=>ind.series[k]),conf:ind.conf}; } // goal if(ind&&isGoal&&ind.goal!=null){ const c=L.agg(ind,period.keys);const gap=ind.goal-c;const proj=c; // simple return{type:"answer",ind,title:`Meta de ${ind.name}`, big:L.fmtVal(ind,c),bigSub:"realizado · "+period.label, body:`A meta é ${L.fmtVal(ind,ind.goal,true)}. Realizado de ${period.label}: ${L.fmtVal(ind,c,true)}. ${ind.dir==="menor"?(c<=ind.goal?"Meta já atingida.":"Faltam "+L.fmtVal(ind,Math.abs(gap),true)+" para chegar ao alvo."):(c>=ind.goal?"Meta já atingida.":"Faltam "+L.fmtVal(ind,Math.abs(gap),true)+" para atingir a meta.")}`, months:G.keys6,values:G.keys6.map(k=>ind.series[k]),conf:ind.conf}; } // specific month or compare if(ind&&months.length>=2){ const a=ind.series[months[0]],b=ind.series[months[1]],d=L.delta(ind,b,a); return{type:"answer",ind,title:`${ind.name}: ${L.monthName(months[0])} → ${L.monthName(months[1])}`, big:d.pct!=null?`${d.pct>0?"+":""}${d.pct}%`:"—",bigSub:"variação", body:`${L.monthLong(months[0])}: ${L.fmtVal(ind,a,true)}. ${L.monthLong(months[1])}: ${L.fmtVal(ind,b,true)}. Diferença de ${L.fmtVal(ind,Math.abs(d.abs),true)} (${d.pct>0?"+":""}${d.pct}%).`, months:G.keys6,values:G.keys6.map(k=>ind.series[k]),conf:ind.conf}; } if(ind&&months.length===1){ const v=ind.series[months[0]]; return{type:"answer",ind,title:`${ind.name} em ${L.monthLong(months[0])}`, big:L.fmtVal(ind,v),bigSub:L.monthLong(months[0]), body:v==null?"Sem dado registrado para este mês.":`${ind.name} em ${L.monthLong(months[0])} foi ${L.fmtVal(ind,v,true)}.${ind.formula?" Fórmula: "+ind.formula+".":""}`, months:G.keys6,values:G.keys6.map(k=>ind.series[k]),conf:ind.conf}; } if(ind&&(isTrend||isCompare)){ const t=L.trend(ind,G.keys6);const c=L.agg(ind,period.keys),p=period.cmp&&!period.cmp.noData?L.agg(ind,period.cmp.keys):L.agg(ind,["2026-05"]);const d=L.delta(ind,c,p); return{type:"answer",ind,title:`Tendência de ${ind.name}`, big:t.cls,bigSub:"últimos 3 meses", body:`${ind.name} está ${t.cls.toLowerCase()} na janela de 3 meses. No período atual (${period.label}): ${L.fmtVal(ind,c,true)}${d.pct!=null?`, ${d.pct>0?"+":""}${d.pct}% frente ao anterior.`:"."}`, months:G.keys6,values:G.keys6.map(k=>ind.series[k]),conf:ind.conf}; } // default: current period value const c=L.agg(ind,period.keys); return{type:"answer",ind,title:ind.name,big:L.fmtVal(ind,c),bigSub:period.label, body:`${ind.name} no período ${period.label}: ${L.fmtVal(ind,c,true)}.${ind.formula?" Fórmula: "+ind.formula+".":""}`, months:G.keys6,values:G.keys6.map(k=>ind.series[k]),conf:ind.conf}; } const EXAMPLES=["Qual foi o CPL de janeiro?","Quanto o CAC aumentou de março para abril?","Qual foi o melhor mês de faturamento?","O ROI está aumentando?","Quanto falta para a meta de contratos?"]; function SearchModal(props){ const{company:co,period}=props; const[q,setQ]=useState(props.initial||""); const[res,setRes]=useState(props.initial?answer(co,period,props.initial):null); const run=v=>{if(!v.trim())return;setRes(answer(co,period,v));}; return h("div",{className:"modal-scrim",onClick:props.onClose}, h("div",{className:"modal",style:{width:"min(820px,94vw)"},onClick:e=>e.stopPropagation()}, h("div",{className:"modal-hd",style:{paddingBottom:18}}, h("div",{style:{flex:1}}, h("div",{className:"modal-bc"},h(Icon,{name:"search",size:13}),h("span",null,"Pesquisa inteligente · "+co.name)), h("form",{onSubmit:e=>{e.preventDefault();run(q);}}, h("div",{className:"gsearch",style:{maxWidth:"none"}}, h(Icon,{name:"search"}), h("input",{autoFocus:true,value:q,onChange:e=>setQ(e.target.value),placeholder:"Pergunte sobre os dados desta empresa…"})))), h("button",{className:"modal-close",onClick:props.onClose},h(Icon,{name:"close",size:18}))), h("div",{className:"modal-body"}, !res&&h("div",null, h("div",{className:"lbl",style:{marginBottom:12}},"Exemplos"), h("div",{style:{display:"flex",flexDirection:"column",gap:8}}, EXAMPLES.map((ex,i)=>h("button",{key:i,className:"btn btn-ghost",style:{justifyContent:"flex-start",width:"100%"},onClick:()=>{setQ(ex);run(ex);}},h(Icon,{name:"search",size:14,style:{color:"var(--mist-2)"}}),ex)))), res&&res.type==="insuf"&&h("div",{className:"empty"},h("div",{className:"em-t"},res.title),res.body), res&&res.type==="answer"&&h("div",{className:"fade-in"}, h("div",{className:"stat-row"}, h("div",{className:"stat-cell",style:{gridColumn:"span 1"}},h("div",{className:"sc-l"},res.title),h("div",{className:"sc-v",style:{color:"var(--lume)"}},res.big),h("div",{className:"sc-x muted"},res.bigSub)), h("div",{className:"stat-cell"},h("div",{className:"sc-l"},"Empresa"),h("div",{className:"sc-v",style:{fontSize:18}},co.name),h("div",{className:"sc-x muted"},period.label)), h("div",{className:"stat-cell"},h("div",{className:"sc-l"},"Confiança"),h("div",{style:{marginTop:8}},h("span",{className:"conf-badge "+res.conf},res.conf)),h("div",{className:"sc-x muted"},"resposta baseada só nesta empresa"))), h("div",{className:"reading",style:{marginBottom:20}},h("div",{className:"rd-l"},"Resposta"),h("p",null,res.body)), res.values&&h("div",{className:"panel"}, h("div",{className:"panel-hd"},h("h3",null,res.ind.name),h("span",{className:"lbl"},"jan – jun 26")), h(L.LineChart,{months:res.months,values:res.values,goal:res.ind.goal,color:co.color,tipFmt:v=>L.fmtVal(res.ind,v,true)})), h("div",{style:{display:"flex",gap:10,marginTop:18,flexWrap:"wrap"}}, res.ind&&h("button",{className:"btn btn-lume btn-sm",onClick:()=>props.onOpenMetric(res.ind.key)},h(Icon,{name:"arrowR",size:14}),"Abrir indicador completo"), h("span",{className:"chip static"},h(Icon,{name:"info",size:13}),"Distingue fato de hipótese · não afirma causalidade"))) ))); } window.GOSIndicatorModal=IndicatorModal; window.GOSSearchModal=SearchModal; })();