(() => { const { Modal, Badge, Icon, Avatar, Button, StatusPill } = window.TaskFlowDesignSystem_dd53c2; /* Riwayat satu task, disusun dari data task yang sudah ada (tidak ada request tambahan, tidak ada state — murni turunan) agar halaman tetap ringan. */ const EV = { assign: { icon: "clipboard-list", color: "var(--teal-600)", bg: "var(--teal-50)" }, start: { icon: "play", color: "var(--mint-600)", bg: "var(--mint-50)" }, submit: { icon: "upload", color: "var(--gold-600)", bg: "var(--gold-50)" }, revision: { icon: "rotate-ccw", color: "var(--coral-600)", bg: "var(--coral-50)" }, delegate: { icon: "users", color: "var(--coral-600)", bg: "var(--coral-50)" }, accept: { icon: "check", color: "var(--leaf-600)", bg: "var(--leaf-50)" }, sign: { icon: "signature", color: "var(--leaf-600)", bg: "var(--leaf-50)" }, comment: { icon: "message-circle", color: "var(--text-muted)", bg: "var(--neutral-100)" }, }; function timelineOf(task, messages) { const u = userById(task.user); const ev = []; ev.push({ k: "assign", at: task.assigned, title: "Task diberikan", by: "Direktur Klinik", detail: `Untuk ${u.name} · target ${task.target}` }); if (task.progress > 0 || task.status !== "todo") ev.push({ k: "start", at: task.assigned, title: "Mulai dikerjakan", by: u.name, detail: checklistLabel ? checklistLabel(task) : null }); (task.versions || []).forEach((v) => { ev.push({ k: "submit", at: v.at, title: `Kirim hasil v${v.round}`, by: u.name, detail: v.files.map((f) => f.name).join(", ") + (v.note ? " · " + v.note : "") }); ev.push({ k: "revision", at: v.at, title: "Diminta revisi", by: "Direktur Klinik", detail: v.note || "Poin revisi dikirim ke user" }); }); if (task.submitted) ev.push({ k: "submit", at: task.submitted, title: "Kirim hasil final", by: u.name, detail: task.userNote || (task.evidence ? task.evidence.name : null) }); if (task.status === "revision" && !(task.versions || []).length) ev.push({ k: "revision", at: task.submitted || task.assigned, title: "Diminta revisi", by: "Direktur Klinik", detail: task.revision || "Poin revisi dikirim ke user" }); if (task.delegate != null) ev.push({ k: "delegate", at: task.submitted || task.assigned, title: "Revisi didelegasikan", by: "Direktur Klinik", detail: `Dibantu ${userById(task.delegate).name}${task.delegateNote ? " · " + task.delegateNote : ""}` }); if (task.done) ev.push({ k: "accept", at: task.done, title: "Diterima Direktur", by: "Direktur Klinik", detail: task.delay ? "Selesai melewati target · " + task.delay : "Status task menjadi Done" }); if (task.signature) ev.push({ k: "sign", at: task.signature.at || task.done, title: "Dokumen ditandatangani", by: task.signature.by || "Direktur Klinik", detail: `Halaman ${task.signature.page}` }); (messages || []).forEach((m) => ev.push({ k: "comment", at: m.at, title: "Komentar di diskusi", by: m.name, detail: m.text ? String(m.text).slice(0, 110) : m.file ? m.file.name : null })); return ev; } function TaskTimelineModal({ task, messages, onClose, onOpenDiscussion, onViewEvidence }) { if (!task) return null; const u = userById(task.user); const events = React.useMemo(() => timelineOf(task, messages), [task, messages]); return ( {task.evidence && onViewEvidence && } {onOpenDiscussion && }}>
{events.length} kejadian {task.needSign && {task.signature ? "Sudah di-TTD" : "Perlu TTD"}}
{events.map((e, i) => { const s = EV[e.k] || EV.comment; const last = i === events.length - 1; return (
{!last && } {e.title} {e.at || "-"} · {e.by} {e.detail && {e.detail}}
); })}
); } Object.assign(window, { TaskTimelineModal, timelineOf }); })();