export interface CandidateInput { id: number; weightGrams: number | null; priceCents: number | null; } export interface SetupItemInput { categoryId: number; weightGrams: number | null; priceCents: number | null; name: string; } export type DeltaMode = "replace" | "add" | "none"; export interface CandidateDelta { candidateId: number; mode: DeltaMode; weightDelta: number | null; priceDelta: number | null; replacedItemName: string | null; } export interface ImpactDeltas { mode: DeltaMode; deltas: Record; } export function computeImpactDeltas( candidates: CandidateInput[], setupItems: SetupItemInput[] | undefined, threadCategoryId: number, ): ImpactDeltas { if (!setupItems) return { mode: "none", deltas: {} }; const replacedItem = setupItems.find((item) => item.categoryId === threadCategoryId) ?? null; const mode: DeltaMode = replacedItem ? "replace" : "add"; const deltas: Record = {}; for (const candidate of candidates) { let weightDelta: number | null = null; let priceDelta: number | null = null; if (candidate.weightGrams != null) { weightDelta = replacedItem?.weightGrams != null ? candidate.weightGrams - replacedItem.weightGrams : candidate.weightGrams; } if (candidate.priceCents != null) { priceDelta = replacedItem?.priceCents != null ? candidate.priceCents - replacedItem.priceCents : candidate.priceCents; } deltas[candidate.id] = { candidateId: candidate.id, mode, weightDelta, priceDelta, replacedItemName: replacedItem?.name ?? null, }; } return { mode, deltas }; }