From 55842d12a1be66cc901f47574c5caba33d38b250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Sun, 7 Jun 2026 18:08:48 -0400 Subject: [PATCH] Add hiring pipeline with four-stage board view HiringPipeline component shows agents across stages: Pending Approval, Approved, Active, and Rejected. Each stage column shows agent cards with role, department, and approval timing. Stage assignment is derived from the agent's lifecycle and associated hire approval state. --- .../src/renderer/src/pages/TeamPage.tsx | 3 + .../src/pages/team/HiringPipeline.tsx | 75 +++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 AgentCompany-New/src/renderer/src/pages/team/HiringPipeline.tsx diff --git a/AgentCompany-New/src/renderer/src/pages/TeamPage.tsx b/AgentCompany-New/src/renderer/src/pages/TeamPage.tsx index 583d8eb6..d43ed0e0 100644 --- a/AgentCompany-New/src/renderer/src/pages/TeamPage.tsx +++ b/AgentCompany-New/src/renderer/src/pages/TeamPage.tsx @@ -3,6 +3,7 @@ import { Avatar, Button, Field, Icon, IconButton } from "../shared/ui"; import { TopbarActions } from "../shared/TopbarActions"; import { Dialog } from "../shared/Dialog"; import { OrgChartTree } from "./team/OrgChartTree"; +import { HiringPipeline } from "./team/HiringPipeline"; import type { AgentRecord, EmployeeRecord, ProviderRecord } from "../../../shared/domain"; import type { PageProps } from "./types"; import { activeOrgId, money } from "./types"; @@ -112,6 +113,8 @@ export function TeamPage({ snapshot, actions }: PageProps) { + a.orgId === orgId)} /> +
Roster
a.sourceEntityType === "agent" && a.sourceEntityId === agent.id && a.kind === "agent_hire", + ) ?? null; + + if (hireApproval?.state === "pending") return { agent, stage: "pending_approval", approval: hireApproval }; + if (hireApproval?.state === "declined") return { agent, stage: "rejected", approval: hireApproval }; + if (agent.lifecycle === "active") return { agent, stage: "active", approval: hireApproval }; + return { agent, stage: "approved", approval: hireApproval }; +} + +export function HiringPipeline({ agents, approvals }: { agents: AgentRecord[]; approvals: ApprovalRecord[] }) { + const entries = agents.map((a) => resolveStage(a, approvals)); + + return ( +
+
Hiring pipeline
+
+ {STAGES.map((stage) => { + const stageEntries = entries.filter((e) => e.stage === stage.id); + return ( +
+
+ + {stage.label} + {stageEntries.length} +
+
+ {stageEntries.map((entry) => ( +
+
+ +
+
{entry.agent.name}
+
{entry.agent.role} ยท {entry.agent.department}
+
+
+ {entry.approval && ( +
+ {formatRelative(entry.approval.createdAt)} +
+ )} +
+ ))} +
+
+ ); + })} +
+
+ ); +}