Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | 1x 1x 8x 8x 8x 1x 4x 1x 4x 1x 5x 1x 4x 4x 5x 5x 5x 1x 4x 1x | export type TimeSlotValue = "all_day" | "morning" | "afternoon";
export interface DateLikeRange {
startDate: Date | null;
endDate: Date | null;
}
interface SlotBoundary {
hours: number;
minutes: number;
}
const RANGE_TIME_BOUNDARY = {
WORK_START: { hours: 8, minutes: 0 },
MORNING_END: { hours: 12, minutes: 0 },
AFTERNOON_START: { hours: 13, minutes: 30 },
WORK_END: { hours: 17, minutes: 30 },
} as const;
const withBoundaryTime = (
date: Date,
{ hours, minutes }: SlotBoundary,
): Date => {
const nextDate = new Date(date);
nextDate.setHours(hours, minutes, 0, 0);
return nextDate;
};
const getRangeStartBoundary = (slot: TimeSlotValue): SlotBoundary =>
slot === "afternoon"
? RANGE_TIME_BOUNDARY.AFTERNOON_START
: RANGE_TIME_BOUNDARY.WORK_START;
const getRangeEndBoundary = (slot: TimeSlotValue): SlotBoundary =>
slot === "morning"
? RANGE_TIME_BOUNDARY.MORNING_END
: RANGE_TIME_BOUNDARY.WORK_END;
const resolveRangeBounds = (
range: DateLikeRange,
): { startDate: Date | null; endDate: Date | null } => {
if (!range.startDate && !range.endDate) {
return {
startDate: null,
endDate: null,
};
}
Eif (range.startDate && range.endDate) {
return {
startDate: range.startDate,
endDate: range.endDate,
};
}
const date = range.startDate || range.endDate;
return {
startDate: date,
endDate: date,
};
};
export const applyTimeSlotsToRange = (
range: DateLikeRange,
startSlot: TimeSlotValue,
endSlot: TimeSlotValue,
): DateLikeRange => {
const { startDate, endDate } = resolveRangeBounds(range);
if (!startDate || !endDate) {
return {
startDate: null,
endDate: null,
};
}
return {
startDate: withBoundaryTime(startDate, getRangeStartBoundary(startSlot)),
endDate: withBoundaryTime(endDate, getRangeEndBoundary(endSlot)),
};
};
/**
* Normalizes a range where both start and end dates use the same time slot.
* Useful for single-day shift normalization or quick selection presets.
*/
export const normalizeRangeBySlot = (
startDate: Date | null,
endDate: Date | null,
slot: TimeSlotValue,
): DateLikeRange => {
return applyTimeSlotsToRange({ startDate, endDate }, slot, slot);
};
|