src/lib/reach.ts
Rama main · réplica de lectura del repositorio original.
import type { Stage } from "@prisma/client";
/**
* How far one application ever got: sent, interviewed, offered.
*
* The one rule behind every per-resume outcome. list_resumes' grid counts and
* resume_performance used to carry a copy each, with their own stage lists and
* slightly different offer rules (one counted a move into ACCEPTED, the other
* did not), and both tools said they answered "which resume is working".
*
* An offer proves the interviews happened even when no move to a screen was
* recorded, so `offered` implies `interviewed`, always. A wishlist row was
* never sent and reaches nothing.
*/
export const INTERVIEWED_STAGES: Stage[] = ["INTERVIEWING", "OFFER", "ACCEPTED"];
export const OFFER_STAGES: Stage[] = ["OFFER", "ACCEPTED"];
export type Reach = { sent: boolean; interviewed: boolean; offered: boolean };
export function reachOf(application: {
stage: Stage;
activities: { type: string; toStage: Stage | null }[];
}): Reach {
if (application.stage === "WISHLIST") return { sent: false, interviewed: false, offered: false };
const reached = (stages: Stage[], type: "INTERVIEW" | "OFFER") =>
stages.includes(application.stage) ||
application.activities.some(
(activity) => activity.type === type || (activity.toStage !== null && stages.includes(activity.toStage)),
);
const offered = reached(OFFER_STAGES, "OFFER");
return { sent: true, interviewed: offered || reached(INTERVIEWED_STAGES, "INTERVIEW"), offered };
}