task-d.6.2

This commit is contained in:
phaichayon
2026-07-01 13:57:16 +07:00
parent 0a144f0f9e
commit ed28ff6b50
71 changed files with 4137 additions and 51727 deletions

View File

@@ -0,0 +1,63 @@
import { addMonths, endOfDay, isValid, parse } from 'date-fns';
const DATE_ONLY_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
export interface HotProjectResolutionInput {
projectCloseDate?: string | null;
isHotProject?: boolean | null;
hotProjectManuallyOverridden?: boolean | null;
}
export interface HotProjectResolution {
isHotProject: boolean;
hotProjectAutoSuggested: boolean;
hotProjectManuallyOverridden: boolean;
}
export function isValidDateOnlyString(value: string | null | undefined): value is string {
if (!value || !DATE_ONLY_PATTERN.test(value)) {
return false;
}
const parsed = parse(value, 'yyyy-MM-dd', new Date());
return isValid(parsed);
}
export function isHotProjectSuggested(projectCloseDate: string | null | undefined, now = new Date()) {
if (!isValidDateOnlyString(projectCloseDate)) {
return false;
}
const parsed = parse(projectCloseDate, 'yyyy-MM-dd', now);
return parsed.getTime() <= endOfDay(addMonths(now, 3)).getTime();
}
export function resolveHotProjectState(
input: HotProjectResolutionInput,
now = new Date()
): HotProjectResolution {
const hotProjectAutoSuggested = isHotProjectSuggested(input.projectCloseDate, now);
const hotProjectManuallyOverridden = Boolean(input.hotProjectManuallyOverridden);
if (hotProjectManuallyOverridden) {
return {
isHotProject: Boolean(input.isHotProject),
hotProjectAutoSuggested,
hotProjectManuallyOverridden: true
};
}
if (hotProjectAutoSuggested) {
return {
isHotProject: true,
hotProjectAutoSuggested: true,
hotProjectManuallyOverridden: false
};
}
return {
isHotProject: Boolean(input.isHotProject),
hotProjectAutoSuggested: false,
hotProjectManuallyOverridden: false
};
}