Files
AgentCompany/src/renderer/views/sections/OrganizationSections.tsx
T
ZacharyZhang-NY 7c4d7a4a5e refactor(hiring): delete three redundant sections (pending-panel + summary cards + department headcount)
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.
2026-04-17 21:21:05 -04:00

174 lines
7.7 KiB
TypeScript

import type { SectionId } from "@shared/types";
import { NEW_ENTITY_ID } from "../../lib/constants";
import {
Target,
UserPlus,
Kanban,
} from "../../components/ui/icons";
import { AgentCreator } from "../../components/organization/AgentCreator";
import { AgentEditor } from "../../components/organization/AgentEditor";
import { AgentRoster } from "../../components/organization/AgentRoster";
import { GoalCreator } from "../../components/organization/GoalCreator";
import { GoalEditor } from "../../components/organization/GoalEditor";
import { GoalList } from "../../components/organization/GoalList";
import { OrgChart } from "../../components/organization/OrgChart";
import { TeamHeaderSummary } from "../../components/organization/TeamHeaderSummary";
import { ProjectCreator } from "../../components/organization/ProjectCreator";
import { ProjectEditor } from "../../components/organization/ProjectEditor";
import { ProjectList } from "../../components/organization/ProjectList";
import { HiringPipeline } from "../../components/hiring/HiringPipeline";
import { ActionButton, Modal, Panel } from "../../components/ui";
import { useT } from "../../i18n";
import { useAppStore } from "../../state/store";
import { useSectionContext } from "../../hooks/useSectionContext";
import { useAppActions } from "../../hooks/useAppActions";
interface OrganizationSectionsProps {
section: SectionId;
}
export function OrganizationSections({ section }: OrganizationSectionsProps) {
const t = useT();
const {
snapshot,
currentCompany,
companyAgents,
companyGoals,
companyProjects,
companyWorkspaces,
pendingApprovals,
editingAgent,
selectedGoal,
selectedProject,
} = useSectionContext();
const { refresh } = useAppActions();
const selectedAgentId = useAppStore((s) => s.selectedAgentId);
const setSelectedAgentId = useAppStore((s) => s.setSelectedAgentId);
const editingAgentId = useAppStore((s) => s.editingAgentId);
const setEditingAgentId = useAppStore((s) => s.setEditingAgentId);
const selectedGoalId = useAppStore((s) => s.selectedGoalId);
const setSelectedGoalId = useAppStore((s) => s.setSelectedGoalId);
const selectedProjectId = useAppStore((s) => s.selectedProjectId);
const setSelectedProjectId = useAppStore((s) => s.setSelectedProjectId);
const setSection = useAppStore((s) => s.setSection);
// Open the Edit modal on row / card click. `selectedAgentId` is updated
// alongside so the roster highlight follows the user's last interaction
// even after the modal closes.
const openAgentEditor = (id: string) => {
setSelectedAgentId(id);
setEditingAgentId(id);
};
if (!snapshot || !currentCompany) return null;
return (
<>
{section === "agents" ? (
<>
<TeamHeaderSummary agents={companyAgents} pendingApprovals={pendingApprovals} />
<OrgChart agents={companyAgents} connectors={snapshot.connectors} onSelectAgent={openAgentEditor} />
<Panel title={t("org.agentRoster")} action={<ActionButton label={t("org.newHireRequest")} icon={UserPlus} tone="accent" onClick={() => setEditingAgentId(NEW_ENTITY_ID)} />}>
<AgentRoster
agents={companyAgents}
connectors={snapshot.connectors}
workspaces={companyWorkspaces}
selectedAgentId={selectedAgentId}
onSelect={openAgentEditor}
/>
</Panel>
<Modal open={editingAgentId === NEW_ENTITY_ID} title={t("org.requestNewHire")} onClose={() => setEditingAgentId(null)}>
<AgentCreator
companyId={currentCompany.id}
connectors={snapshot.connectors}
workspaces={companyWorkspaces}
agents={companyAgents}
onSaved={async () => {
setEditingAgentId(null);
setSection("hiring");
await refresh();
}}
/>
</Modal>
<Modal
open={!!editingAgent}
title={editingAgent ? t("org.editAgentTitle").replace("{name}", editingAgent.name).replace("{role}", editingAgent.role) : ""}
onClose={() => setEditingAgentId(null)}
>
{editingAgent ? (
<AgentEditor
key={editingAgent.id}
agent={editingAgent}
connectors={snapshot.connectors}
workspaces={companyWorkspaces}
agents={companyAgents}
companyId={currentCompany.id}
onSaved={refresh}
onCancel={() => setEditingAgentId(null)}
onDeleted={async () => { setEditingAgentId(null); await refresh(); }}
/>
) : null}
</Modal>
</>
) : null}
{section === "hiring" && currentCompany ? (
<HiringPipeline
agents={companyAgents}
approvals={(snapshot?.approvals ?? []).filter(a => a.companyId === currentCompany.id)}
onNavigateToAgent={(id) => { setSelectedAgentId(id); setSection("agents"); }}
/>
) : null}
{section === "goals" ? (
<>
<Panel title={t("org.goalStack")} action={<ActionButton label={t("org.newGoal")} icon={Target} tone="accent" onClick={() => setSelectedGoalId(NEW_ENTITY_ID)} />}>
<GoalList goals={companyGoals} agents={companyAgents} selectedGoalId={selectedGoalId} onSelect={setSelectedGoalId} />
</Panel>
<Modal open={selectedGoalId === NEW_ENTITY_ID} title={t("org.newGoal")} onClose={() => setSelectedGoalId(null)}>
<GoalCreator companyId={currentCompany.id} agents={companyAgents} goals={companyGoals} onSaved={async () => { setSelectedGoalId(null); await refresh(); }} />
</Modal>
<Modal open={!!selectedGoal} title={selectedGoal ? `Edit: ${selectedGoal.title}` : ""} onClose={() => setSelectedGoalId(null)}>
{selectedGoal ? (
<GoalEditor
key={selectedGoalId}
goal={selectedGoal}
goals={companyGoals}
agents={companyAgents}
companyId={currentCompany.id}
onSaved={async () => { setSelectedGoalId(null); await refresh(); }}
onDeleted={async () => { setSelectedGoalId(null); await refresh(); }}
/>
) : null}
</Modal>
</>
) : null}
{section === "projects" ? (
<>
<Panel title={t("nav.projects")} action={<ActionButton label={t("org.newProject")} icon={Kanban} tone="accent" onClick={() => setSelectedProjectId(NEW_ENTITY_ID)} />}>
<ProjectList projects={companyProjects} goals={companyGoals} agents={companyAgents} workspaces={companyWorkspaces} selectedProjectId={selectedProjectId} onSelect={setSelectedProjectId} />
</Panel>
<Modal open={selectedProjectId === NEW_ENTITY_ID} title={t("org.newProject")} onClose={() => setSelectedProjectId(null)}>
<ProjectCreator companyId={currentCompany.id} goals={companyGoals} agents={companyAgents} onSaved={async () => { setSelectedProjectId(null); await refresh(); }} />
</Modal>
<Modal open={!!selectedProject} title={selectedProject ? `Edit: ${selectedProject.name}` : ""} onClose={() => setSelectedProjectId(null)}>
{selectedProject ? (
<ProjectEditor
key={selectedProjectId}
project={selectedProject}
goals={companyGoals}
agents={companyAgents}
companyId={currentCompany.id}
onSaved={async () => { setSelectedProjectId(null); await refresh(); }}
onDeleted={async () => { setSelectedProjectId(null); await refresh(); }}
/>
) : null}
</Modal>
</>
) : null}
</>
);
}