const { StatCard, Card, Icon, Button, DemandCard, ProgressBar, Badge, Avatar, DataTable, StatusPill, PriorityBadge, SectorTag, DeadlineIndicator, EmptyState } = window.ACRFlowDesignSystem_ba1e9c; function SectionTitle({ children, action }) { return (

{children}

{action}
); } function BarChart({ data, tone = "var(--accent-primary)" }) { const max = Math.max(...data.map((d) => d.value)); return (
{data.map((d) => (
{d.label}
{d.value}
))}
); } const LAYOUT_KEY = "flowtix.dash.layout.v2"; const SPAN_OPTS = [{ value: 4, label: "1/3 da largura" }, { value: 6, label: "Metade" }, { value: 8, label: "2/3 da largura" }, { value: 12, label: "Largura total" }]; const DEFAULT_LAYOUT = [ { id: "demandas", span: 12 }, { id: "acao", span: 8 }, { id: "setor", span: 4 }, { id: "prazo", span: 4 }, { id: "recorrentes", span: 4 }, ]; function useLayout() { const [layout, setLayout] = React.useState(() => { try { const raw = localStorage.getItem(LAYOUT_KEY); if (raw) { const saved = JSON.parse(raw); if (Array.isArray(saved) && saved.length) return saved; } } catch (e) { /* ignora */ } return DEFAULT_LAYOUT; }); const persist = (next) => { setLayout(next); try { localStorage.setItem(LAYOUT_KEY, JSON.stringify(next)); } catch (e) { /* ignora */ } }; return [layout, persist]; } function Panel({ item, children, onSpan, onMove, drag, setDrag, over, setOver }) { const NSp = window.ACRFlowDesignSystem_ba1e9c; const [hover, setHover] = React.useState(false); return (
setHover(true)} onMouseLeave={() => setHover(false)} onDragOver={(e) => { e.preventDefault(); setOver(item.id); }} onDragLeave={() => setOver((o) => (o === item.id ? null : o))} onDrop={(e) => { e.preventDefault(); onMove(drag, item.id); setDrag(null); setOver(null); }} style={{ gridColumn: "span " + item.span, display: "flex", flexDirection: "column", position: "relative", opacity: drag === item.id ? 0.45 : 1, outline: over === item.id && drag && drag !== item.id ? "2px dashed var(--border-focus)" : "none", outlineOffset: 4, borderRadius: "var(--radius-card)" }}>
{ setDrag(item.id); e.dataTransfer.effectAllowed = "move"; }} onDragEnd={() => { setDrag(null); setOver(null); }} title="Arraste para mudar de lugar" style={{ display: "inline-flex", padding: 3, borderRadius: "var(--radius-sm)", color: "var(--text-subtle)", cursor: "grab" }}> } />} items={SPAN_OPTS.map((o) => ({ label: o.label, icon: , onSelect: () => onSpan(item.id, o.value) }))} />
{children}
); } function DashboardScreen({ user, onOpenDemand, onNavigate }) { const D = window.ACRData; const supervisor = user.profile === "supervisor"; const [layout, setLayout] = useLayout(); const [drag, setDrag] = React.useState(null); const [newBoard, setNewBoard] = React.useState(false); const addBoard = (cfg) => { setLayout([...layout, { id: "c" + Date.now(), span: cfg.span, custom: cfg }]); setNewBoard(false); }; const setChart = (id, chart) => setLayout(layout.map((i) => (i.id === id ? { ...i, custom: { ...i.custom, chart } } : i))); const removeBoard = (id) => setLayout(layout.filter((i) => i.id !== id)); const [over, setOver] = React.useState(null); const setSpan = (id, span) => setLayout(layout.map((i) => (i.id === id ? { ...i, span } : i))); const move = (fromId, toId) => { if (!fromId || !toId || fromId === toId) return; const next = [...layout]; const fi = next.findIndex((i) => i.id === fromId); const ti = next.findIndex((i) => i.id === toId); if (fi < 0 || ti < 0) return; next.splice(ti, 0, next.splice(fi, 1)[0]); setLayout(next); }; const mine = D.demands.filter((d) => d.status !== "encerrada"); const rows = mine.slice(0, 5); const count = (s) => D.demands.filter((d) => d.status === s).length; const abertas = mine.length; const atrasadas = mine.filter((d) => d.daysLeft < 0).length; const hoje = mine.filter((d) => d.daysLeft === 0).length; const amanha = mine.filter((d) => d.daysLeft === 1).length; const emAndamento = count("andamento"); const aprovacao = count("aguardando_aprovacao"); const encerradas = count("encerrada"); const encerradasAll = D.demands.filter((d) => d.status === "encerrada"); const noPrazo = encerradasAll.filter((d) => (d.daysLeft ?? 0) >= 0).length; const foraPrazo = encerradasAll.length - noPrazo; const pctPrazo = encerradasAll.length ? Math.round((noPrazo / encerradasAll.length) * 100) : 0; const pendentesAprovacao = D.demands.filter((d) => d.status === "aguardando_aprovacao"); const recorrentes = D.demands.filter((d) => d.recurrence && d.recurrence !== "nao"); const checklistHoje = (D.checklist || []).filter((c) => !c.done).slice(0, 3); const porSetor = D.sectorsCfg.map((s) => ({ label: s.name, value: D.demands.filter((d) => d.sector === s.id).length, tone: "var(--setor-" + (s.id === "gestao-condominial" ? "condominial" : s.id === "departamento-pessoal" ? "pessoal" : "contabilidade") + ")" })); return (

{(new Date().getHours() < 12 ? "Bom dia, " : new Date().getHours() < 18 ? "Boa tarde, " : "Boa noite, ") + user.name.split(" ")[0]}

{supervisor ? (abertas === 0 && aprovacao === 0 ? "Nenhuma demanda em aberto no momento." : "Sua equipe tem " + abertas + " demanda" + (abertas === 1 ? "" : "s") + " em aberto e " + aprovacao + " aguardando sua aprovação.") : (abertas === 0 ? "Você não tem demandas pendentes." : "Você possui " + abertas + " demanda" + (abertas === 1 ? "" : "s") + " pendente" + (abertas === 1 ? "" : "s") + " — " + atrasadas + " atrasada" + (atrasadas === 1 ? "" : "s") + " e " + hoje + " vence hoje.")}
{JSON.stringify(layout) !== JSON.stringify(DEFAULT_LAYOUT) ? : null}
} hint="Ação imediata" onClick={() => onNavigate("fila")} /> } onClick={() => onNavigate("fila")} /> } onClick={() => onNavigate("fila")} /> } /> {supervisor ? } hint="Somente você aprova" onClick={() => pendentesAprovacao[0] ? onOpenDemand(pendentesAprovacao[0].id) : onNavigate("demandas")} /> : } />}
{layout.map((item) => ( {item.custom ? ( ) : null} {item.id === "demandas" ? ( onNavigate("demandas")}>Ver todas} padding="0"> {r.id} }, { key: "title", label: "Demanda", render: (r) => (
{r.title}
) }, { key: "status", label: "Status", width: 150, render: (r) => }, { key: "priority", label: "Prioridade", width: 92, render: (r) => }, { key: "daysLeft", label: "Prazo", width: 128, render: (r) => }, { key: "progress", label: "Conclusão", width: 100, render: (r) => }, ]} rows={rows} onRowClick={(r) => onOpenDemand(r.id)} dense />
) : null} {item.id === "acao" ? (supervisor ? ( {pendentesAprovacao.length === 0 ?
Nenhuma demanda aguardando aprovação.
: pendentesAprovacao.map((d) => (
{d.id} {d.title} {(d.people && d.people[0] ? d.people[0].name + " solicitou o encerramento" : "Encerramento solicitado") + " · checklist " + d.progress + "%"}
))}
) : ( {checklistHoje.length === 0 ?
Nenhuma etapa com prazo para hoje.
: null} {checklistHoje.map((c) => (
{c.text} {c.demandId || ""}
))}
)) : null} {item.id === "setor" ? ( ) : null} {item.id === "prazo" ? (
{pctPrazo + "%"}
{"Dentro do prazo · " + noPrazo} {"Fora do prazo · " + foraPrazo} {encerradasAll.length ? encerradasAll.length + " demanda" + (encerradasAll.length === 1 ? "" : "s") + " encerrada" + (encerradasAll.length === 1 ? "" : "s") : "Sem demandas encerradas ainda"}
) : null} {item.id === "recorrentes" ? ( {recorrentes.length === 0 ?
Nenhuma demanda recorrente configurada.
: recorrentes.map((d) => (
onOpenDemand(d.id)}> {d.title} {d.recurrenceLabel || "Recorrente"}
))}
) : null}
))}
{newBoard ? setNewBoard(false)} onCreate={addBoard} /> : null}
); } Object.assign(window, { DashboardScreen, BarChart, SectionTitle });