From 7c4d7a4a5ea21f8bbe40f5fd68ce6e8cf14a858e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Fri, 17 Apr 2026 21:21:05 -0400 Subject: [PATCH] refactor(hiring): delete three redundant sections (pending-panel + summary cards + department headcount) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HiringPipeline carried three panels that restated information already shown — one with more emphasis — on the Team page or in the stage filter directly above them: 1. "Pending approval" mini-Panel (lines 121-187): listed the same candidates that the user reaches by clicking the `pending_approval` chip in the stage filter at the top of the page. The mini-Panel also carried its own Approve / Reject buttons, but those approvals are resolvable from Approvals section too. Doubling the approval path increases the chance of racing clicks between the two surfaces. Deleted. 2. 4-card summary row at the bottom (lines 246-267): Total agents / Pending hires / Departments / Monthly payroll. The first two are rendered on the Team page by TeamHeaderSummary (commit 36bed1b). Payroll can return via a Team-page dedicated surface when there is a business reason; until then it is clutter. Deleted. 3. "Department headcount" Panel (lines 269-293): grid of active+ pending count per department. OrgChart already shows this through the department colour on each agent card, and TeamHeaderSummary covers the aggregate. Two places describing the same fact is one too many. Deleted. Also: - `onRefresh` prop removed from HiringPipeline + OrganizationSections caller — only the (now-deleted) approve/reject buttons used it. - `Card`, `UserPlus`, `Check`, `unwrap` imports dropped because the deletions made them unused. - Unused `i` index in Dashboard.tsx activeWork map callback cleaned up (left over from the previous commit that removed the arbitrary animation gate). File size: HiringPipeline.tsx 296 LOC → 175 LOC (net −121). Typecheck + lint pass. --- .../components/dashboard/Dashboard.tsx | 2 +- .../components/hiring/HiringPipeline.tsx | 125 +----------------- .../views/sections/OrganizationSections.tsx | 1 - 3 files changed, 3 insertions(+), 125 deletions(-) diff --git a/src/renderer/components/dashboard/Dashboard.tsx b/src/renderer/components/dashboard/Dashboard.tsx index fce32c99..f6318b73 100644 --- a/src/renderer/components/dashboard/Dashboard.tsx +++ b/src/renderer/components/dashboard/Dashboard.tsx @@ -187,7 +187,7 @@ export function Dashboard(props: DashboardProps) { {activeWork.length > 0 ? (
- {activeWork.map(({ run, agent, task }, i) => ( + {activeWork.map(({ run, agent, task }) => (
- {pendingCount > 0 && ( - -
- {allCandidates - .filter(c => c.stage === "requisition" || c.stage === "pending_approval") - .map((candidate) => { - const a = candidate.approval; - const ag = candidate.agent; - return ( -
-
- -
-
-
- {ag?.name ?? t("hiring.pendingHires")} - - {stageLabelMap[candidate.stage]} - -
-
- {ag ? `${ag.role} — ${ag.title}` : a?.payloadSummary} -
- {ag?.capabilities && ( -
{ag.capabilities}
- )} -
-
- {a && a.state === "pending" && ( - <> - { - unwrap(await window.agentCompany.decideApproval({ - companyId: a.companyId, - approvalId: a.id, - state: "approved", - decisionNote: t("hiring.approvedNote"), - })); - await onRefresh(); - }} - /> - { - unwrap(await window.agentCompany.decideApproval({ - companyId: a.companyId, - approvalId: a.id, - state: "rejected", - decisionNote: t("hiring.rejectedNote"), - })); - await onRefresh(); - }} - /> - - )} -
-
- ); - })} -
-
- )} - -
- -
{t("hiring.totalAgents")}
-
{agents.filter(a => a.status !== "terminated").length}
-
- -
{t("hiring.pendingHires")}
-
{agents.filter(a => a.status === "pending_approval").length}
-
- -
{t("hiring.departments")}
-
- {new Set(agents.filter(a => a.department && a.status !== "terminated").map(a => a.department)).size} -
-
- -
{t("hiring.monthlyPayroll")}
-
- ${agents.filter(a => a.status !== "terminated" && a.status !== "pending_approval").reduce((s, a) => s + a.budgetMonthlyUsd, 0).toLocaleString()} -
-
-
- - -
- {(["executive", "engineering", "product", "design", "marketing", "sales", "hr", "finance", "legal", "customer_support", "operations", "research"] as const).map(dept => { - const deptAgents = agents.filter(a => a.department === dept && a.status !== "terminated"); - const pending = deptAgents.filter(a => a.status === "pending_approval").length; - const active = deptAgents.filter(a => a.status !== "pending_approval").length; - if (active === 0 && pending === 0) return null; - return ( -
-
{dept.replace("_", " ")}
-
- {active} - {t("hiring.active")} - {pending > 0 && ( - <> - +{pending} - {t("hiring.pendingApproval")} - - )} -
-
- ); - })} -
-
); } diff --git a/src/renderer/views/sections/OrganizationSections.tsx b/src/renderer/views/sections/OrganizationSections.tsx index 6f136747..d5100c65 100644 --- a/src/renderer/views/sections/OrganizationSections.tsx +++ b/src/renderer/views/sections/OrganizationSections.tsx @@ -117,7 +117,6 @@ export function OrganizationSections({ section }: OrganizationSectionsProps) { a.companyId === currentCompany.id)} - onRefresh={refresh} onNavigateToAgent={(id) => { setSelectedAgentId(id); setSection("agents"); }} /> ) : null}