const { Card, DataTable, Button, Icon, IconButton, Tabs, SearchField, Select, StatusPill, PriorityBadge, SectorTag, DeadlineIndicator, ProgressBar, AvatarGroup, Badge, EmptyState } = window.ACRFlowDesignSystem_ba1e9c; const PRESETS = [ { value: "todos", label: "Todo o histórico" }, { value: "3", label: "Últimos 3 dias" }, { value: "7", label: "Últimos 7 dias" }, { value: "30", label: "Últimos 30 dias" }, { value: "90", label: "Últimos 3 meses" }, { value: "custom", label: "Escolher no calendário" }, ]; const MONTHS = ["janeiro", "fevereiro", "março", "abril", "maio", "junho", "julho", "agosto", "setembro", "outubro", "novembro", "dezembro"]; const WD = ["D", "S", "T", "Q", "Q", "S", "S"]; const TODAY = new Date(2026, 8, 1); const parseBR = (s) => { const [d, m, y] = (s || "").split("/"); return y ? new Date(+y, +m - 1, +d) : null; }; const fmtBR = (d) => d ? String(d.getDate()).padStart(2, "0") + "/" + String(d.getMonth() + 1).padStart(2, "0") + "/" + d.getFullYear() : ""; const sameDay = (a, b) => a && b && a.toDateString() === b.toDateString(); /** Mini-calendário de seleção de intervalo: 1º clique define o início, 2º o fim. */ function RangeCalendar({ from, to, onPick }) { const [view, setView] = React.useState(new Date((to || TODAY).getFullYear(), (to || TODAY).getMonth(), 1)); const first = new Date(view.getFullYear(), view.getMonth(), 1); const days = new Date(view.getFullYear(), view.getMonth() + 1, 0).getDate(); const cells = [...Array(first.getDay()).fill(null), ...Array.from({ length: days }, (_, i) => new Date(view.getFullYear(), view.getMonth(), i + 1))]; const inRange = (d) => from && to && d > from && d < to; const edge = (d) => sameDay(d, from) || sameDay(d, to); return (
} onClick={() => setView(new Date(view.getFullYear(), view.getMonth() - 1, 1))} /> {MONTHS[view.getMonth()]} {view.getFullYear()} } onClick={() => setView(new Date(view.getFullYear(), view.getMonth() + 1, 1))} />
{WD.map((w, i) => {w})} {cells.map((d, i) => d ? ( ) : )}
{from ? fmtBR(from) + (to ? " – " + fmtBR(to) : " – ...") : "Selecione a data inicial"}
); } function DemandsListScreen({ onOpenDemand, onNavigate }) { const D = window.ACRData; const [q, setQ] = React.useState(""); const [sector, setSector] = React.useState("todos"); const [status, setStatus] = React.useState("todos"); const [priority, setPriority] = React.useState("todas"); const [preset, setPreset] = React.useState("todos"); const [from, setFrom] = React.useState(null); const [to, setTo] = React.useState(null); const [calOpen, setCalOpen] = React.useState(false); const [advanced, setAdvanced] = React.useState(false); const all = D.demands; const sectors = D.sectorsCfg; const pick = (d) => { if (!d) { setFrom(null); setTo(null); return; } if (!from || (from && to)) { setFrom(d); setTo(null); return; } if (d < from) { setTo(from); setFrom(d); } else setTo(d); }; const inPeriod = (dem) => { const ref = parseBR(dem.opened) || parseBR(dem.due); if (!ref) return true; if (preset === "custom") { if (from && ref < from) return false; if (to && ref > to) return false; return true; } if (preset === "todos") return true; const limit = new Date(TODAY); limit.setDate(limit.getDate() - Number(preset)); return ref >= limit; }; const rows = all.filter((d) => (sector === "todos" || d.sector === sector) && (status === "todos" || d.status === status) && (priority === "todas" || d.priority === priority) && inPeriod(d) && (d.title + " " + d.id + " " + (d.context || "") + " " + (d.category || "") + " " + (d.people || []).map((p) => p.name).join(" ") + " " + (d.tags || []).join(" ")).toLowerCase().includes(q.toLowerCase())); const periodLabel = preset === "custom" ? (from ? fmtBR(from) + (to ? " – " + fmtBR(to) : " – ...") : "Escolher no calendário") : (PRESETS.find((p) => p.value === preset) || {}).label; const active = [ sector !== "todos" && { k: "sector", label: (sectors.find((s) => s.id === sector) || {}).name, clear: () => setSector("todos") }, status !== "todos" && { k: "status", label: (D.statuses.find((s) => s.id === status) || {}).name, clear: () => setStatus("todos") }, priority !== "todas" && { k: "prio", label: (D.priorities.find((p) => p.id === priority) || {}).name, clear: () => setPriority("todas") }, preset !== "todos" && { k: "per", label: periodLabel, clear: () => { setPreset("todos"); setFrom(null); setTo(null); } }, q && { k: "q", label: '"' + q + '"', clear: () => setQ("") }, ].filter(Boolean); const clearAll = () => { setQ(""); setSector("todos"); setStatus("todos"); setPriority("todas"); setPreset("todos"); setFrom(null); setTo(null); }; return (

Todas as Demandas

Busque em todo o histórico — demandas encerradas há meses ou anos mantêm timeline, evidências e ciclo completo.
setQ(e.target.value)} onClear={() => setQ("")} width="100%" shortcut={null} placeholder="Nº da demanda, título, empresa, responsável ou tag..." />
setStatus(e.target.value)} options={[{ value: "todos", label: "Todos os status" }, ...D.statuses.map((s) => ({ value: s.id, label: s.name }))]} />
Período de abertura
setPriority(e.target.value)} options={[{ value: "todas", label: "Todas as prioridades" }, ...D.priorities.map((p) => ({ value: p.id, label: p.name }))]} /> ) : null} {advanced ? ({ value: c.id, label: c.name }))]} /> : null}
{calOpen ? (
{from ? fmtBR(from) + (to ? " – " + fmtBR(to) : " – selecione a data final") : "Selecione a data inicial"} O primeiro clique define o início do período e o segundo o fim. Sem data final, a busca vai da data escolhida até hoje.
) : null}
{active.length ? active.map((f) => ( {f.label} )) : Nenhum filtro aplicado — mostrando todo o histórico.} {active.length ? : null}
d.status === "aguardando_atendimento").length }, { id: "andamento", label: "Em andamento", count: all.filter((d) => d.status === "andamento").length }, { id: "pendente", label: "Pendentes", count: all.filter((d) => d.status === "pendente").length }, { id: "aguardando_aprovacao", label: "Aguardando aprovação", count: all.filter((d) => d.status === "aguardando_aprovacao").length }, { id: "encerrada", label: "Encerradas", count: all.filter((d) => d.status === "encerrada").length }, ]} /> {rows.length ? ( {r.id} }, { key: "title", label: "Demanda", render: (r) => (
{r.title} {r.context}{r.category ? " · " + r.category : ""}
) }, { key: "sector", label: "Setor", width: 190, render: (r) => }, { key: "status", label: "Status", width: 190, render: (r) => }, { key: "priority", label: "Prioridade", width: 108, render: (r) => }, { key: "people", label: "Responsáveis", width: 118, render: (r) => }, { key: "daysLeft", label: "Prazo", width: 170, render: (r) => r.status === "encerrada" ? Entregue em {r.due} : }, { key: "progress", label: "Conclusão", width: 128, render: (r) => }, ]} rows={rows} onRowClick={(r) => onOpenDemand(r.id)} dense /> ) : ( } title="Nenhuma demanda encontrada." description="Amplie o período ou remova filtros — o histórico completo continua disponível." action={} /> )}
); } Object.assign(window, { DemandsListScreen });