/* global React */ /* Cosidata Portal — shared primitives + sample data. Loaded first; exposes components on window for client.jsx / admin.jsx. */ const { useState, useEffect, useRef } = React; const MARK = "assets/cosidata-mark.svg"; function useLucide(){ useEffect(() => { if (window.lucide) window.lucide.createIcons(); }); } const Icon = ({ name, style, cls }) => ; function Wordmark({ size = 22, dark = false }){ return ( cosidata ); } function Avatar({ name, bg = "linear-gradient(135deg,var(--primary),var(--accent))", size = 38 }){ const initials = name.split(" ").map(w => w[0]).slice(0,2).join("").toUpperCase(); return
{initials}
; } function Badge({ kind = "primary", children }){ return {children}; } // ============================ SIDEBAR ============================ function Sidebar({ nav, view, onNav, user, accentLabel, open, onClose, footer }){ useLucide(); return ( ); } // ============================ TOPBAR ============================ function Topbar({ title, sub, onMenu, actions, crumb }){ useLucide(); return (
cosidata
{crumb &&
{crumb}
}

{title}

{sub &&
{sub}
}
{actions}
); } // ============================ KPI ============================ function KpiTile({ label, value, delta, dir = "up", icon }){ return (
{label}
{icon && }
{value}
{delta && {dir === "up" ? "▲" : "▼"} {delta}}
); } // ============================ BAR CHART (forked) ============================ function BarChart({ title, sub, data, unit = "" }){ const max = Math.max(...data.map(d => d[1])) * 1.12; return (

{title}

{sub &&
{sub}
}
{data.map(([m, v], i) => (
{m}
))}
); } // ============================ KANBAN ============================ const KAN_COLS = [ { id: "todo", label: "A fazer", color: "var(--muted)" }, { id: "doing", label: "Em andamento", color: "var(--amber)" }, { id: "done", label: "Concluído", color: "var(--green)" }, ]; function Kanban({ tasks, setTasks, readOnly }){ useLucide(); const [dragId, setDragId] = useState(null); const [overCol, setOverCol] = useState(null); const [adding, setAdding] = useState(false); const [draft, setDraft] = useState(""); const move = (id, col) => setTasks(ts => ts.map(t => t.id === id ? { ...t, col } : t)); const addTask = () => { const txt = draft.trim(); if (!txt) { setAdding(false); return; } setTasks(ts => [...ts, { id: "t" + Date.now(), title: txt, col: "todo", tag: null }]); setDraft(""); setAdding(false); }; return (
{KAN_COLS.map(col => { const items = tasks.filter(t => t.col === col.id); return (
{ if (readOnly) return; e.preventDefault(); setOverCol(col.id); }} onDragLeave={() => setOverCol(o => o === col.id ? null : o)} onDrop={e => { e.preventDefault(); if (dragId) move(dragId, col.id); setDragId(null); setOverCol(null); }}>
{col.label} {items.length}
{items.map(t => (
setDragId(t.id)} onDragEnd={() => { setDragId(null); setOverCol(null); }}>
{t.title}
{t.tag &&
{t.tag.label}
}
))} {col.id === "todo" && !readOnly && ( adding ? (