| import "./WorkflowTimeline.css"; |
|
|
| |
| |
| |
| |
| |
| export function WorkflowTimeline({ workflow, proposals = [] }) { |
| const events = []; |
|
|
| |
| if (workflow.started_at) { |
| events.push({ |
| time: new Date(workflow.started_at), |
| icon: "βΆ", |
| label: "Workflow started", |
| tone: "default", |
| }); |
| } |
|
|
| |
| if (workflow.status !== "PENDING") { |
| events.push({ |
| time: new Date(new Date(workflow.started_at).getTime() + 1000), |
| icon: "π", |
| label: "Document extracted and processed", |
| tone: "default", |
| }); |
| } |
|
|
| |
| if (proposals.length > 0) { |
| const earliest = proposals.reduce( |
| (min, p) => (p.created_at && new Date(p.created_at) < min ? new Date(p.created_at) : min), |
| new Date() |
| ); |
| events.push({ |
| time: earliest, |
| icon: "π", |
| label: `${proposals.length} proposal(s) generated`, |
| tone: "default", |
| }); |
| } |
|
|
| |
| if (workflow.status === "WAITING_FOR_REVIEW" || workflow.validation_results?.some((r) => r.status === "FAIL" || r.status === "WARNING")) { |
| events.push({ |
| time: new Date(new Date(workflow.started_at).getTime() + 3000), |
| icon: "β οΈ", |
| label: "Validation triggered human review", |
| tone: "warning", |
| }); |
| } |
|
|
| |
| for (const p of proposals) { |
| if (p.status === "APPROVED" && p.reviewed_at) { |
| events.push({ |
| time: new Date(p.reviewed_at), |
| icon: "β", |
| label: `Approved: ${p.summary?.slice(0, 50) || "proposal"}`, |
| tone: "success", |
| }); |
| } |
| if (p.status === "REJECTED" && p.reviewed_at) { |
| events.push({ |
| time: new Date(p.reviewed_at), |
| icon: "β", |
| label: `Rejected: ${p.summary?.slice(0, 50) || "proposal"}`, |
| tone: "danger", |
| }); |
| } |
| } |
|
|
| |
| if (workflow.completed_at) { |
| events.push({ |
| time: new Date(workflow.completed_at), |
| icon: "β
", |
| label: "Workflow completed", |
| tone: "success", |
| }); |
| } |
|
|
| |
| events.sort((a, b) => a.time - b.time); |
|
|
| if (events.length === 0) return null; |
|
|
| return ( |
| <div className="dw-timeline"> |
| {events.map((event, i) => ( |
| <div key={i} className={`dw-timeline__item dw-timeline__item--${event.tone}`}> |
| <span className="dw-timeline__time"> |
| {event.time.toLocaleTimeString()} |
| </span> |
| <span className="dw-timeline__icon">{event.icon}</span> |
| <span className="dw-timeline__label">{event.label}</span> |
| </div> |
| ))} |
| </div> |
| ); |
| } |
|
|