74 lines
2.7 KiB
TypeScript
74 lines
2.7 KiB
TypeScript
export type BuildReviewProgressInput = {
|
|
blocking: number;
|
|
individualRequired: number;
|
|
individualReviewed: number;
|
|
groupRequired: number;
|
|
reviewComplete: boolean;
|
|
};
|
|
|
|
export type BuildReviewProgress = {
|
|
blocking: number;
|
|
individualRequired: number;
|
|
individualReviewed: number;
|
|
individualRemaining: number;
|
|
groupRequired: number;
|
|
groupReviewed: number;
|
|
groupRemaining: number;
|
|
required: number;
|
|
reviewed: number;
|
|
remaining: number;
|
|
};
|
|
|
|
function count(value: number): number {
|
|
return Number.isFinite(value) ? Math.max(0, Math.trunc(value)) : 0;
|
|
}
|
|
|
|
export function calculateBuildReviewProgress(input: BuildReviewProgressInput): BuildReviewProgress {
|
|
const blocking = count(input.blocking);
|
|
const individualRequired = count(input.individualRequired);
|
|
const groupRequired = count(input.groupRequired);
|
|
const individualReviewed = input.reviewComplete
|
|
? individualRequired
|
|
: Math.min(individualRequired, count(input.individualReviewed));
|
|
const groupReviewed = input.reviewComplete ? groupRequired : 0;
|
|
const individualRemaining = individualRequired - individualReviewed;
|
|
const groupRemaining = groupRequired - groupReviewed;
|
|
|
|
return {
|
|
blocking,
|
|
individualRequired,
|
|
individualReviewed,
|
|
individualRemaining,
|
|
groupRequired,
|
|
groupReviewed,
|
|
groupRemaining,
|
|
required: individualRequired + groupRequired,
|
|
reviewed: individualReviewed + groupReviewed,
|
|
remaining: individualRemaining + groupRemaining
|
|
};
|
|
}
|
|
|
|
/** Summary match counts describe inputs; they are not fresh review gates. */
|
|
export function attachmentDeliveryPreflight(input: {
|
|
migrationRequired: boolean;
|
|
hasBuild: boolean;
|
|
reviewLoaded: boolean;
|
|
blocking: number;
|
|
remaining: number;
|
|
inspectionComplete: boolean;
|
|
missing: number;
|
|
ambiguous: number;
|
|
}): { state: "ready" | "warning" | "blocked" | "info"; detail: string } {
|
|
if (input.migrationRequired) return { state: "blocked", detail: "i18n:govoplan-campaign.attachment_checks_await_mail_migration" };
|
|
if (!input.hasBuild) return { state: "info", detail: "i18n:govoplan-campaign.attachment_preflight_build_first" };
|
|
if (!input.reviewLoaded) return { state: "info", detail: "i18n:govoplan-campaign.attachment_preflight_loading" };
|
|
if (input.blocking > 0) return { state: "blocked", detail: "i18n:govoplan-campaign.attachment_preflight_blocked" };
|
|
if (input.inspectionComplete || input.remaining === 0) {
|
|
return { state: "ready", detail: "i18n:govoplan-campaign.attachment_preflight_satisfied" };
|
|
}
|
|
if (input.missing + input.ambiguous > 0) {
|
|
return { state: "warning", detail: "i18n:govoplan-campaign.attachment_preflight_review" };
|
|
}
|
|
return { state: "info", detail: "i18n:govoplan-campaign.attachment_preflight_pending" };
|
|
}
|