Rank held applies to every candidate, not just ex-hands; it auto-updates for returning crew on sign-off. Ex-hand designation is decoupled from the Source dropdown and owned by the office: - Candidate form: drop the EX_HAND source option, relabel "Rank held (ex-hands)" to "Rank held". addCandidate always intakes NEW/CANDIDATE (ex-hand recognition still reuses an existing EX_HAND row); updateCandidate no longer rewrites type/status, so an admin-set EX_HAND or onboarded EMPLOYEE is never clobbered by a candidate edit. - Admin crew form: the type NEW/EX_HAND select becomes an "Ex-hand (returning crew)" checkbox -- the only place ex-hand is tagged. - List/detail ex-hand indicators key on type === EX_HAND (not source). - Sign-off preserves the original recruitment source when flipping to EX_HAND. - Tests seed EX_HAND rows directly; assert candidate intake stays NEW. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
43 lines
1.4 KiB
TypeScript
43 lines
1.4 KiB
TypeScript
import type { CandidateSource, CrewStatus } from "@prisma/client";
|
|
import type { BadgeProps } from "@/components/ui/badge";
|
|
|
|
type Variant = NonNullable<BadgeProps["variant"]>;
|
|
|
|
export const SOURCE_LABEL: Record<CandidateSource, string> = {
|
|
CAREERS: "Careers",
|
|
EX_HAND: "Ex-hand",
|
|
WALK_IN: "Walk-in",
|
|
REFERRAL: "Referral",
|
|
OTHER: "Other",
|
|
};
|
|
|
|
export const SOURCE_OPTIONS: CandidateSource[] = ["CAREERS", "EX_HAND", "WALK_IN", "REFERRAL", "OTHER"];
|
|
|
|
// Ex-hand is now its own checkbox (not a source) — the Add/Edit form offers only
|
|
// the real origins. EX_HAND stays in the enum/label for legacy rows created
|
|
// before the split.
|
|
export const FORM_SOURCE_OPTIONS: CandidateSource[] = ["CAREERS", "WALK_IN", "REFERRAL", "OTHER"];
|
|
|
|
export const STATUS_LABEL: Record<CrewStatus, string> = {
|
|
PROSPECT: "Prospect",
|
|
CANDIDATE: "Candidate",
|
|
EMPLOYEE: "Employee",
|
|
EX_HAND: "Ex-hand",
|
|
BLACKLISTED: "Blacklisted",
|
|
};
|
|
|
|
export const STATUS_VARIANT: Record<CrewStatus, Variant> = {
|
|
PROSPECT: "outline",
|
|
CANDIDATE: "default",
|
|
EMPLOYEE: "success",
|
|
EX_HAND: "secondary",
|
|
BLACKLISTED: "danger",
|
|
};
|
|
|
|
// Compact experience label, e.g. "3y 6m", "8m", "—".
|
|
export function experienceLabel(months: number): string {
|
|
if (!months) return "—";
|
|
const y = Math.floor(months / 12);
|
|
const m = months % 12;
|
|
return [y ? `${y}y` : "", m ? `${m}m` : ""].filter(Boolean).join(" ") || "0m";
|
|
}
|