1
0
Fork 0
polaris-task-force/src/components/frontend/baseManagement/EmploymentCard.tsx
Z8MB1E 9e44b69714 feat(base): add structure staffing and upgrade management UI
Adds hire/terminate staff actions and an upgradeStructure server action plus baseManagement components (employment card, hire dialog, staff roster, upgrade card) wired into the structure detail page.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-09-06 01:24:14 -04:00

84 lines
3 KiB
TypeScript

"use client";
import { BadgeCheckIcon } from "lucide-react";
import { formatAmount, type CurrencyConfig } from "@/lib/banking/format";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { HireStaffDialog } from "@/components/frontend/baseManagement/HireStaffDialog";
import type { LaborClassificationOption, StructureStaffingOption } from "@/lib/base";
interface EmploymentCardProps {
readonly employment: {
readonly positionTitle: string;
readonly positionType: string;
readonly structureName: string;
readonly salary: number;
} | null;
readonly structures: readonly StructureStaffingOption[];
readonly canManage: boolean;
readonly npcId: number;
readonly npcName?: string;
readonly classifications?: readonly LaborClassificationOption[];
readonly hiringEnabled: boolean;
readonly hiringDisabledMessage?: string;
readonly currencyConfig: CurrencyConfig;
}
export function EmploymentCard({
employment,
structures,
canManage,
npcId,
npcName,
classifications,
hiringEnabled,
hiringDisabledMessage,
currencyConfig,
}: EmploymentCardProps) {
return (
<Card>
<CardHeader className="gap-2">
<CardTitle className="flex items-center gap-2">
<BadgeCheckIcon className="size-4 text-muted-foreground" />
Employment
</CardTitle>
<CardDescription>Current base assignment and compensation.</CardDescription>
</CardHeader>
<CardContent>
{employment ? (
<div className="flex flex-col gap-2">
<p className="font-medium">{employment.positionTitle}</p>
<p className="text-sm text-muted-foreground">
{employment.positionType} · {employment.structureName}
</p>
<p className="font-mono text-sm tabular-nums">
{formatAmount(employment.salary, currencyConfig)}/tick
</p>
</div>
) : canManage && hiringEnabled ? (
<div className="flex flex-wrap items-center justify-between gap-3">
<p className="text-sm text-muted-foreground">Not currently employed.</p>
<HireStaffDialog
structures={structures}
npcs={[{ id: npcId, name: npcName ?? `NPC #${npcId}` }]}
fixedNpcId={npcId}
canManage={canManage}
classifications={classifications}
hiringEnabled={hiringEnabled}
hiringDisabledMessage={hiringDisabledMessage}
currencyConfig={currencyConfig}
/>
</div>
) : canManage ? (
<div className="flex flex-col gap-2">
<p className="text-sm text-muted-foreground">Not currently employed.</p>
<p className="text-sm text-muted-foreground">
{hiringDisabledMessage || "Staff hiring is currently disabled."}
</p>
</div>
) : (
<p className="text-sm text-muted-foreground">Not currently employed.</p>
)}
</CardContent>
</Card>
);
}