1

I have installed these package in my project :-

  • react-datepicker library for from time and to time
  • for date validation date-fns, moment.js,
  • another validations library/package jQuery and lodash
Here is my project link where all code is there but it is not running because of some restriction and VPN
Codesandbox Link
  • here is DatePicker tag for from time and to time.
  • My goal is to achieve these validation inside table.
  • It is dropdown, Users cannot input any time here.
  • Only users can select time from dropdown.
  • I was trying to hide selected day but didn't find the way to do it.
  • Some of the validation are working but if we change randomly some time range from table then that time my validation is failing.
  • If selected time range with validation can be hidden then also it will be fine.
from time to time isValidate
09:00 AM 09:15 AM Yes
09:15 AM 09:45 AM Yes
09:15 AM 09:30 AM No (from time(09:15) is already in second column)
09:30 AM 09:45 AM No (from time(09:30) is coming in between(09:15-09:45) of time in second column
08:15 AM 07:30 AM No (to time is less than from time)
06:15 AM 12:30 AM No (in these time range from time(09:15) and to time(09:45) already entered
11:45 AM 12:30 PM Yes
11:45 PM 12:30 AM No (after(11:59 PM) is next day so entry is restricted)

here is UI of table

 <td>
                        <DatePicker
                          id="fromTime"
                          name="fromTime"
                          value={el.fromTime || ""}
                          onChange={(event) => timeHandler(event, index, "fromTime")}
                          menuPortalTarget={document.body}
                          styles={{ menuPortal: (base) => ({ ...base, zIndex: 99999 }) }}
                          showTimeSelect
                          showTimeSelectOnly
                          timeIntervals={15}
                          dateFormat="h:mm aa"
                          placeholderText="From:"
                          autoComplete="off"
                          dropdownMode="select"
                          onKeyDown={(e) => e.preventDefault()}
                          className={
                            isSubmitButtonCall && ERPUtils.isNullorWhiteSpace(el.fromTime) && (el.totalTime <= 0 || el.totalTime === "00:00")
                              ? "form-control border border-danger rounded"
                              : "form-control"
                          }
                          excludeTimes={excludedTimes}
                          // minTime={setHours(setMinutes(new Date(), 0), 8)}
                          // maxTime={setHours(setMinutes(new Date(), 45), 14)}
                        />
                      </td>
                      <td>
                        <DatePicker
                          id="toTime"
                          name="toTime"
                          disabled={ERPUtils.isNullorWhiteSpace(el.fromTime)}
                          readOnly={ERPUtils.isNullorWhiteSpace(el.fromTime)}
                          value={el.toTime || ""}
                          onChange={(event) => timeHandler(event, index, "toTime")}
                          menuPortalTarget={document.body}
                          styles={{ menuPortal: (base) => ({ ...base, zIndex: 99999 }) }}
                          showTimeSelect
                          showTimeSelectOnly
                          timeIntervals={15}
                          dateFormat="h:mm aa"
                          timeFormat="h:mm aa"
                          placeholderText="To:"
                          autoComplete="off"
                          dropdownMode="select"
                          onKeyDown={(e) => e.preventDefault()}
                          className={
                            isSubmitButtonCall && ERPUtils.isNullorWhiteSpace(el.toTime) && (el.totalTime <= 0 || el.totalTime === "00:00")
                              ? "form-control border border-danger rounded"
                              : "form-control"
                          }
                        />
                      </td>
// DatePicker timeHandler
  const [hour, setHour] = useState({ fromTime: "", toTime: "" });
  const [ISODate, setISODate] = useState({ fromTime: "", toTime: "" });
  const [isBeforeTime, setIsBeforeTime] = useState(false);
  const [isAfterTime, setIsAfterTime] = useState(false);
  const [INDEX, setINDEX] = useState(null);
  const [minFromTime, setMinFromTime] = useState("");
  const [maxTimeTO, setMaxTimeTO] = useState("");

  const callback = useCallback(() => {
    const ISODates = { ...ISODate };
    const newState = { ...secondaryState };
    const hours = { ...hour };
    if (isBeforeTime && isAfterTime) {
      AppContext.alert({
        Text: "Time range is already exist in between time!",
      });
      hours.fromTime = "";
      ISODates.fromTime = "";
      newState.empWorkDiaryEntriesDetails[INDEX].fromTime = "";
      hours.toTime = "";
      ISODates.toTime = "";
      newState.empWorkDiaryEntriesDetails[INDEX].toTime = "";
      newState.empWorkDiaryEntriesDetails[INDEX].totalTime = "";
      setIsBeforeTime(false);
      setIsAfterTime(false);
      setHour(hours);
      setISODate(ISODates);
      setSecondaryState(newState);
    }
  }, [isBeforeTime, isAfterTime]); // memoize callback
  useEffectUpdate(callback);

  const timeHandler = (date, index, name) => {
    setINDEX(index);
    // selcted time for DatePicker - Dec 27 2021 16:15:00 GMT+0530 (India Standard Time)
    const ISODates = { ...ISODate };
    const newState = { ...secondaryState };
    // converted time to hh:mm AA
    const hours = { ...hour };
    const format = "hh:mm A";
    // var time = moment() gives you current time. no format required.
    if (name === "fromTime") {
      hours.fromTime = moment(date).format("hh:mm A");
      newState.empWorkDiaryEntriesDetails[index].fromTime = hours.fromTime;
      newState.empWorkDiaryEntriesDetails[index].toTime = "";
      ISODates[name] = date;
      hours.toTime = "";
      ISODates.toTime = "";
      // newState.empWorkDiaryEntriesDetails.map((item) => {
      //   if (!ERPUtils.isNullorWhiteSpace(item.toTime)) {
      //     if (CommonMethods.hhmmAFormat(date) === item.toTime) {
      //       AppContext.alert({
      //         Text: "From Time cannot be same as To time",
      //       });
      //       hours.fromTime = "";
      //       newState.empWorkDiaryEntriesDetails[index].fromTime = "";
      //       newState.empWorkDiaryEntriesDetails[index].toTime = "";
      //       ISODates[name] = "";
      //       hours.toTime = "";
      //       ISODates.toTime = "";
      //     }
      //   }
      //   return null;
      // });
    }
    if (name === "toTime") {
      const fromTime = moment(hours.fromTime, "hh:mm A");
      const toTime = moment(moment(date).format("hh:mm A"), "hh:mm A");
      if (toTime.isSame(fromTime)) {
        hours.toTime = "";
        AppContext.alert({
          Text: "To Time cannot be same as from time",
        });
      } else if (toTime.isBefore(fromTime)) {
        hours.toTime = "";
        AppContext.alert({
          Text: "To Time cannot be less than from time",
        });
      } else {
        ISODates[name] = date;
        hours.toTime = moment(date).format("hh:mm A");
        console.log(index, "inde");
        newState.empWorkDiaryEntriesDetails[index].toTime = hours.toTime;
      }
    }
    newState.empWorkDiaryEntriesDetails.map((item) => {
      const time = moment(date, format);
      const beforeTime = moment(item.fromTime, format);
      const afterTime = moment(item.toTime, format);

      // converted to 24Hrs
      // const currHr24hr = moment(time, ["hh:mm A"]).format("HH:mm");
      // const fromTime24hr = moment(item.fromTime, ["hh:mm A"]).format("HH:mm");
      // const toTime24hr = moment(item.toTime, ["hh:mm A"]).format("HH:mm");

      // converted to ISO
      // const currHrInISO = new Date(`01-01-2017 ${currHr24hr}:00`);
      // const fromTimeHrInISO = new Date(`01-01-2017 ${fromTime24hr}:00`);
      // const toTimeHrInISO = new Date(`01-01-2017 ${toTime24hr}:00`);

      // converted to miliseconds
      // const currHrInMs = moment(currHrInISO).valueOf();
      // const fromTimeHrInMs = moment(fromTimeHrInISO).valueOf();
      // const toTimeHrInMs = moment(toTimeHrInISO).valueOf();

      // setMinFromTime(fromTimeHrInISO);
      // setMaxTimeTO(toTimeHrInISO);
      // console.log(setHours(setMinutes(new Date(), 0), 8), "df");
      // console.log(fromTimeHrInISO, "m");

      // if (name === "fromTime") {
      //   if (currHrInMs <= fromTimeHrInMs) {
      //     setIsBeforeTime(true);
      //   }
      // }
      // if (name === "toTime") {
      //   if (currHrInMs >= toTimeHrInMs) {
      //     setIsAfterTime(true);
      //   }
      // }
      // if (name === "fromTime") {
      //   if (time.isSameOrBefore(beforeTime)) {
      //     setIsBeforeTime(true);
      //   }
      // }
      // if (name === "toTime") {
      //   if (time.isSameOrAfter(afterTime)) {
      //     setIsAfterTime(true);
      //   }
      // }

      if (time.isBetween(beforeTime, afterTime)) {
        if (name === "fromTime") {
          AppContext.alert({
            Text: "Date range is already exist!",
          });
          hours.fromTime = "";
          ISODates.fromTime = "";
          newState.empWorkDiaryEntriesDetails[index].fromTime = "";
          newState.empWorkDiaryEntriesDetails[index].totalTime = "";
        }
        if (name === "toTime") {
          AppContext.alert({
            Text: "Date range is already exist!",
          });
          hours.toTime = "";
          ISODates.toTime = "";
          newState.empWorkDiaryEntriesDetails[index].toTime = "";
          // hours.fromTime = "";
          // ISODates.fromTime = "";
          // newState.empWorkDiaryEntriesDetails[index].fromTime = "";
          newState.empWorkDiaryEntriesDetails[index].totalTime = "";
        }
      }
      setHour(hours);
      getTotalHoursDifference(hours.fromTime, hours.toTime, index, newState, ISODates);
      return null;
    });
    if (name === "toTime") {
      newState.empWorkDiaryEntriesDetails[index].toTime = hours.toTime;
      // if (newState.empWorkDiaryEntriesDetails[index].totalTime === 0) {
      // AppContext.alert({
      // Text: "Date range is already exist!",
      // });
      // newState.empWorkDiaryEntriesDetails[index].fromTime = "";
      // newState.empWorkDiaryEntriesDetails[index].toTime = "";
      // setSecondaryState(newState);
      // }
    }
    // console.log(newState.empWorkDiaryEntriesDetails[index].totalTime, "tttt");
  };

Vishal
  • 11
  • 1
  • 4

1 Answers1

0

You can try it with the below method.



Firstly make an array of the slots which you want to be disabled like this





let slots = [
{ start: new Date(2022, 8, 8, 13), end: new Date(2022, 8, 8, 14) },
{ start: new Date(2022, 8, 8, 15), end: new Date(2022, 8, 8, 17) },
{ start: new Date(2022, 7, 18, 12), end: new Date(2022, 7, 18, 16) },
{ start: new Date(2022, 8, 1, 9), end: new Date(2022, 8, 2, 13) },
]

You can define a object in any proper format or using Date function like this


// { start: "08/09/2022 13:00", end: "08/09/2022 14:00" }
// OR
// { start: new Date(2022, 8, 8, 3), end: new Date(2022, 8, 8, 5) }

Now use filterTime prop of react-datepicker

filterTime={(time) => {
                  for (let i = 0; i < slots.length; i++) {
                    const e = slots[i];

                    var x = moment(time),
                      beforeTime = moment(e.start),
                      afterTime = moment(e.end);

                    if (
                      x.isBetween(beforeTime, afterTime) ||
                      x.isSame(moment(beforeTime)) ||
                      x.isSame(moment(afterTime))
                    ) {
                      return false;
                    }
                    if (i + 1 == slots.length) {
                      return true;
                    }
                  }
                }}