const { Card, Button, Icon, Select, Input, DataTable, Badge, Tabs, ProgressBar, Avatar, StatCard, EmptyState, SectorTag } = window.ACRFlowDesignSystem_ba1e9c; const iso = (d) => d.toISOString().slice(0, 10); const brToISO = (s) => { if (!s) return ""; const [d, m, y] = String(s).split("/"); return y && m && d ? `${y}-${m.padStart(2, "0")}-${d.padStart(2, "0")}` : ""; }; const MESES_CURTOS = ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"]; function ReportsScreen() { const D = window.ACRData; const hoje = new Date(); const [rep, setRep] = React.useState("produtividade"); const [de, setDe] = React.useState(iso(new Date(hoje.getFullYear(), hoje.getMonth(), 1))); const [ate, setAte] = React.useState(iso(hoje)); const [setor, setSetor] = React.useState("Todos"); const [resp, setResp] = React.useState("Todos"); const [status, setStatus] = React.useState("Todos"); const [prio, setPrio] = React.useState("Todas"); const sectors = D.sectorsCfg || []; const statuses = D.statuses || []; const priorities = D.priorities || []; const team = D.team || []; const nomeSetor = (id) => (sectors.find((s) => s.id === id) || {}).name || ""; const nomeStatus = (id) => (statuses.find((s) => s.id === id) || {}).name || id; const dentroPeriodo = (d) => { const o = brToISO(d.opened); if (!o) return true; return (!de || o >= de) && (!ate || o <= ate); }; const filtradas = (D.demands || []).filter((d) => dentroPeriodo(d) && (setor === "Todos" || nomeSetor(d.sector) === setor) && (status === "Todos" || nomeStatus(d.status) === status) && (prio === "Todas" || ((priorities.find((p) => p.id === d.priority) || {}).name === prio)) && (resp === "Todos" || (d.people || []).some((p) => p.name === resp))); const encerradas = filtradas.filter((d) => d.status === "encerrada"); const fora = encerradas.filter((d) => typeof d.daysLeft === "number" && d.daysLeft < 0).length; const taxa = encerradas.length ? Math.round(((encerradas.length - fora) / encerradas.length) * 100) : 0; const atrasadas = filtradas.filter((d) => d.status !== "encerrada" && typeof d.daysLeft === "number" && d.daysLeft < 0).length; const vazio = filtradas.length === 0; const pessoas = team.map((u) => { const suas = filtradas.filter((d) => (d.people || []).some((p) => p.name === u.name)); const enc = suas.filter((d) => d.status === "encerrada"); const foraP = enc.filter((d) => typeof d.daysLeft === "number" && d.daysLeft < 0).length; return { id: u.id, name: u.name, sector: u.role || "", atendidas: enc.length, andamento: suas.filter((d) => d.status !== "encerrada").length, atrasadas: suas.filter((d) => d.status !== "encerrada" && typeof d.daysLeft === "number" && d.daysLeft < 0).length, prazo: enc.length ? Math.round(((enc.length - foraP) / enc.length) * 100) : 0, total: suas.length, }; }).filter((p) => p.total > 0); const porStatus = statuses.map((s) => ({ label: s.name, value: filtradas.filter((d) => d.status === s.id).length, tone: "var(--st-" + String(s.id).split("_")[0] + ")" })).filter((x) => x.value > 0); const porPrioridade = priorities.map((p) => ({ label: p.name, value: filtradas.filter((d) => d.priority === p.id).length, tone: "var(--prio-" + p.id + ")" })).filter((x) => x.value > 0); const meses = Array.from({ length: 6 }, (_, i) => { const d = new Date(hoje.getFullYear(), hoje.getMonth() - (5 - i), 1); const pref = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}`; return { label: MESES_CURTOS[d.getMonth()], value: (D.demands || []).filter((x) => brToISO(x.opened).startsWith(pref)).length, atual: i === 5 }; }); const maxMes = Math.max(1, ...meses.map((m) => m.value)); const sla = sectors.map((s) => { const suas = filtradas.filter((d) => d.sector === s.id); const enc = suas.filter((d) => d.status === "encerrada"); return { id: s.id, k: s.id, dentro: enc.filter((d) => !(typeof d.daysLeft === "number" && d.daysLeft < 0)).length, fora: enc.filter((d) => typeof d.daysLeft === "number" && d.daysLeft < 0).length, atr: suas.filter((d) => d.status !== "encerrada" && typeof d.daysLeft === "number" && d.daysLeft < 0).length, total: suas.length, }; }).filter((r) => r.total > 0); const etapas = (D.demands || []).reduce((a, d) => a + (d.checklistDone || 0), 0); const consolidado = [ ["Demandas abertas no período", String(filtradas.length)], ["Encerradas", String(encerradas.length)], ["Em andamento", String(filtradas.filter((d) => d.status === "andamento").length)], ["Aguardando aprovação", String(filtradas.filter((d) => d.status === "aguardando_aprovacao").length)], ["Atrasadas hoje", String(atrasadas)], ["Etapas de checklist concluídas", etapas + (etapas === 1 ? " etapa" : " etapas")], ]; const semDados = (texto) => } title="Sem dados no período" description={texto} />; const periodoLabel = de && ate ? de.split("-").reverse().join("/") + " a " + ate.split("-").reverse().join("/") : "Todo o histórico"; return (

Relatórios

{"Período: " + periodoLabel}
setDe(e.target.value)} /> setAte(e.target.value)} /> setResp(e.target.value)} options={["Todos"].concat(team.map((u) => u.name))} /> setPrio(e.target.value)} options={["Todas"].concat(priorities.map((p) => p.name))} />
} /> } /> } /> } /> } hint={encerradas.length ? null : "Sem encerramentos"} />
{rep === "produtividade" ? ( {pessoas.length === 0 ? semDados("Nenhuma demanda atribuída aos colaboradores neste período.") : ( }, { key: "atendidas", label: "Encerradas", width: 110, align: "right" }, { key: "andamento", label: "Em aberto", width: 110, align: "right" }, { key: "atrasadas", label: "Atrasadas", width: 100, align: "right", render: (r) => {r.atrasadas} }, { key: "prazo", label: "No prazo", width: 170, render: (r) => = 90 ? "success" : "warning"} /> }, ]} rows={pessoas} /> )} ) : null} {rep === "demandas" ? ( vazio ? {semDados("Nenhuma demanda aberta no período selecionado.")} : (
{porStatus.length ? : semDados("Sem registros.")} {porPrioridade.length ? : semDados("Sem registros.")}
{meses.map((m) => (
{m.value}
{m.label}
))}
) ) : null} {rep === "sla" ? ( {sla.length === 0 ? semDados("Nenhuma demanda no período para calcular o SLA.") : ( }, { key: "dentro", label: "Dentro do prazo", width: 150, align: "right" }, { key: "fora", label: "Fora do prazo", width: 140, align: "right" }, { key: "atr", label: "Atrasadas hoje", width: 140, align: "right", render: (r) => {r.atr} }, { key: "total", label: "Total", width: 100, align: "right" }, ]} rows={sla} /> )} ) : null} {rep === "mensal" ? ( {vazio ? semDados("Nenhuma demanda aberta no período selecionado.") : (
{consolidado.map(([l, v]) => (
{l.toUpperCase()} {v}
))}
)}
) : null}
); } Object.assign(window, { ReportsScreen });