stephy / CalendarPicker

CalendarPicker Component for React Native
787 stars 369 forks source link

Able to select date ranges that include disabled dates #318

Open adrienclay36 opened 2 years ago

adrienclay36 commented 2 years ago

Hey there. I'm trying to write some scheduling functionality that reaches into a database and finds existing start and end dates to disable these dates on CalendarPicker.

This is working just fine, however, I am able to select date ranges that include dates that are disabled. I cannot select disabled dates individually, but if I select an available date before a range of disabled ones, and then select an available date that exists after the disabled dates, I am able to select a range that includes disabled dates.

Does anyone have any logic or methods that can handle this situation so that I am not able to select that date range, or maybe reset the selections if the user selects a date range that includes disabled dates?

Here is an example:

const [fakeReserveration, setFakeReservation] = useState({
    start: '2022-04-22',
    end: '2022-04-25',
  })

 <CalendarPicker
            startFromMonday={true}
            nextTitleStyle={styles.calendarTitleStyle}
            previousTitleStyle={styles.calendarTitleStyle}
            monthTitleStyle={styles.calendarTitleStyle}
            yearTitleStyle={styles.calendarTitleStyle}
            selectedRangeStartTextStyle={{ fontFamily: primaryFont.bold }}
            selectedRangeEndTextStyle={{ fontFamily: primaryFont.bold }}
            previousTitle={"Back"}
            selectedDayColor={Colors.pink600}
            selectedDayTextColor="#fff"
            textStyle={{ fontFamily: primaryFont.regular }}
            allowRangeSelection
            onDateChange={(date, type) => setDates(date, type)}

            disabledDates={(date) => {
              if(date.isBetween(fakeReserveration.start, fakeReserveration.end)) return true;
            }}

          />

Results:

22 - 24 are disabled dates, and I cannot select them individually

Photo Apr 19, 12 39 04 PM

But I am able to select this range:

Photo Apr 19, 12 39 11 PM

dstiglr commented 1 year ago

First, you need to store the disabled days as range, using an json object like this: imagen

Then, set the onDateChange funtion, and detect the event type.

<CalendarPicker
    selectedStartDate={selectedStartDate}
    selectedEndDate={selectedEndDate}
    onDateChange={(date, type) => {

        if(date == null) {
            return;
        }

        const { selectedStartDate, bookingRanges } = this.state;

        if (type === 'END_DATE') {
            let selectedEndDate = date;

            // detect if range contains disabled  days
            let disabledDaysSelected = false;
            for(let range of bookingRanges) {
                let startAt =  moment(range.start_at);
                let endAt = moment(range.end_at);
                if(selectedStartDate.isBefore(startAt) && selectedEndDate.isAfter(endAt)){
                    disabledDaysSelected = true;
                    break;
                }
            }

            if(disabledDaysSelected) {
                // your code goes here
            }          
          } else {
            this.setState({
              selectedStartDate: date,
              selectedEndDate: null,
            });
          }
    }}
/>

In my case, I just set the selectedStartDate equal to selectedEndDate when user select a range that contains disabled dates :).

ezgif-4-2ad5448cde