All files / packages/ui/src/components/DatePicker/hooks useDatePickerDisabledDates.ts

87.17% Statements 34/39
86.2% Branches 25/29
83.33% Functions 5/6
87.17% Lines 34/39

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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110                                  5x             206x 108x 108x     206x   118x 118x       118x 10x       108x 2x     106x 106x                   206x   155x   155x 114x     41x   8x   10x   23x       206x   16x 2x     14x 7x     7x 7x       7x 7x   7x   3x   4x               206x          
import { useCallback, useMemo } from "react";
import type { DateType } from "react-native-ui-datepicker";
 
import { DATE_PICKER_MODE, DATE_PICKER_TIME_SLOT } from "../constants";
import type { DatePickerDisabledDates, DatePickerMode, DatePickerTimeSlot } from "../types";
import { getStartOfDayTime, isSameDay, normalizeDate } from "../utils";
 
interface UseDatePickerDisabledDatesArgs {
  disabledDates?: DatePickerDisabledDates;
  mode: DatePickerMode;
  normalizedRangeStartDate: Date | null;
  rangeStartTimeSlot: DatePickerTimeSlot;
  selectedDays: number;
}
 
type RangeEndConstraint = "disable_before_start" | "disable_after_start" | null;
 
export const useDatePickerDisabledDates = ({
  disabledDates,
  mode,
  normalizedRangeStartDate,
  rangeStartTimeSlot,
  selectedDays,
}: UseDatePickerDisabledDatesArgs) => {
  const isWeekend = useCallback((date: Date) => {
    const dayOfWeek = date.getDay();
    return dayOfWeek === 0 || dayOfWeek === 6;
  }, []);
 
  const isDateDisabledByProp = useCallback(
    (date: DateType) => {
      const normalizedDate = normalizeDate(date);
      Iif (!normalizedDate) {
        return false;
      }
 
      if (typeof disabledDates === "function") {
        return disabledDates(date);
      }
 
      // By default, weekends are disabled unless the caller provides a function.
      if (isWeekend(normalizedDate)) {
        return true;
      }
 
      Eif (!disabledDates) {
        return false;
      }
 
      return disabledDates.some((blockedDate) =>
        isSameDay(normalizeDate(blockedDate), normalizedDate),
      );
    },
    [disabledDates, isWeekend],
  );
 
  const rangeEndConstraint = useMemo<RangeEndConstraint>(() => {
    const canConstrainRangeEnd =
      mode === DATE_PICKER_MODE.RANGE && selectedDays <= 1 && !!normalizedRangeStartDate;
 
    if (!canConstrainRangeEnd) {
      return null;
    }
 
    switch (rangeStartTimeSlot) {
      case DATE_PICKER_TIME_SLOT.MORNING:
        return "disable_after_start";
      case DATE_PICKER_TIME_SLOT.AFTERNOON:
        return "disable_before_start";
      default:
        return null;
    }
  }, [mode, normalizedRangeStartDate, rangeStartTimeSlot, selectedDays]);
 
  const rangeDisabledDates = useCallback(
    (date: DateType) => {
      if (isDateDisabledByProp(date)) {
        return true;
      }
 
      if (!rangeEndConstraint || !normalizedRangeStartDate) {
        return false;
      }
 
      const normalizedDate = normalizeDate(date);
      Iif (!normalizedDate) {
        return false;
      }
 
      const selectedDateStartOfDay = getStartOfDayTime(normalizedDate);
      const startDateStartOfDay = getStartOfDayTime(normalizedRangeStartDate);
 
      switch (rangeEndConstraint) {
        case "disable_after_start":
          return selectedDateStartOfDay > startDateStartOfDay;
        case "disable_before_start":
          return selectedDateStartOfDay < startDateStartOfDay;
        default:
          return false;
      }
    },
    [isDateDisabledByProp, normalizedRangeStartDate, rangeEndConstraint],
  );
 
  return {
    isDateDisabledByProp,
    rangeDisabledDates,
  };
};