react-date-range icon indicating copy to clipboard operation
react-date-range copied to clipboard

Maximum days restriction

Open Yashas0796 opened this issue 3 years ago • 5 comments

Subject of the issue

Max days restriction

[BUG] Bug Reproduce Steps

How to add max. no. of days restriction. Ex. I should be able to select only max of one day.

[BUG] Expected behaviour

Environment

Package Version: React version: Node version: Browser:

Yashas0796 avatar Feb 25 '21 17:02 Yashas0796

I should be able to select only max of one day.

I am confused what you intend to do, is it:

  1. Maximum date user can select is is before a specific date lik 2023-04-01
  2. Range user can select can not include more than a numbers of days
    • e.g. 14 days, so (2021-05-01, 2021-05-15) is acceptable ✅ but not (2021-05-01, 2021-05-30) is not ❌

kamyar avatar Jun 10 '21 22:06 kamyar

I should be able to select only max of one day.

I am confused what you intend to do, is it:

  1. Maximum date user can select is is before a specific date lik 2023-04-01

  2. Range user can select can not include more than a numbers of days

    • e.g. 14 days, so (2021-05-01, 2021-05-15) is acceptable ✅ but not (2021-05-01, 2021-05-30) is not ❌

@kamyar I think he has the same problem as me. We need to restrict the selected date range to 30 days. Min and max date are not applicable because you should be allowed to choose, for example, the last month, not only 30 days in the past. An option would be to update the min and max date dynamically, but I found no prop to detect a running selection.

lhimstedt avatar Nov 24 '21 09:11 lhimstedt

@kamyar @lhimstedt I am also having the same problem. I want to restrict the number of days for the range starting from any date.

PetrisorIustin avatar Dec 09 '21 10:12 PetrisorIustin

Exactly for the same please check my post with full code at https://stackoverflow.com/a/70403423/3574669

This will restrict to selection before and after from the range startDate by a maxDays.

However, reproducing the code below as well,

import React, {useState, useEffect} from "react"
import {makeStyles} from "@material-ui/core/styles";
import { DateRangePicker } from 'react-date-range';
import 'react-date-range/dist/styles.css'; // main style file
import 'react-date-range/dist/theme/default.css';
import { addDays, subDays } from "date-fns"; // theme css file


const useStyles = makeStyles(theme => ({
  root:{
    // padding: 16
  }
}))

const selectionRange = {
  startDate: new Date(),
  endDate: new Date(),
  key: 'dateRange',
}

const DateRange = (props) => {
  const classes = useStyles();
  const {
    dateRange, 
    onSelectPeriod, 
    hides, 
    minDate, 
    maxDate,
    maxDays
  } = props
  const [period, setPeriod] = useState(selectionRange)
  const [miDate, setMiDate] = useState(new Date(1970, 1, 1))
  const [maDate, setMaDate] = useState(new Date(2100, 1, 1))
 
  useEffect(()=>{
    if(dateRange) {
      setPeriod(dateRange)
    } 
    
    if(hides)
      hides.map((num, index) => {
        (document.getElementsByClassName('rdrStaticRanges')[0]).childNodes[num-index].remove();
      })

    if(minDate != null) setMiDate(minDate)
    if(maxDate != null) setMaDate(maxDate)
  },[])

  useEffect(()=>{
    onSelectPeriod(period)
  },[period])

  const handleSelect = (ranges) => {
    if(ranges === undefined) return
    // console.log("DateRangePicker: ", ranges)    
    setPeriod(ranges.dateRange)

    // set to restrict only maxDays range selection; post selection it reset to as initial for further selection
    if(maxDays != null) {
      if(ranges.dateRange.startDate.getTime() === ranges.dateRange.endDate.getTime()){
        // REstrict maxDays before or after for selection
        setMiDate(subDays(ranges.dateRange.startDate, maxDays-1))
        const mDate = addDays(ranges.dateRange.startDate, maxDays-1)
        if(mDate.getTime() <= maxDate.getTime()) setMaDate(mDate)
      } else {
        // RESET as INITIAL
        if(minDate != null) {
          setMiDate(minDate) 
        } else {
          setMiDate(new Date(1970, 1, 1))
        }

        if(maxDate != null) {
          setMaDate(maxDate)
        } else {
          setMaDate(new Date(2100, 1, 1))
        }
      }
    }
  }

  return (
    <div className={classes.root}>
      <DateRangePicker
        ranges={[period]}
        onChange={handleSelect}
        minDate={miDate}
        maxDate={maDate}
      />
    </div>
  )
}

export default DateRange

ghost avatar Dec 18 '21 12:12 ghost

To achieve this, we can easily set minDate and maxDate when user select date. Just need to check if the startDate and endDate of the selected is the same. Example:


const [tempDateLimit, setTempDateLimit] = useState<
  | {
      minDate: Date;
      maxDate: Date;
    }
  | undefined
>();

const handleOnChange = (keyDict: RangeKeyDict) => {
  const selected = keyDict.selection;
  const isSameDate =
    selected.startDate?.getTime() === selected.endDate?.getTime();
  setSelectedDate({ ...selected });
  if (isSameDate && selected.startDate && selected.startDate) {
    const tempMinDate = moment(selected.startDate)
      .subtract(30, 'days')
      .toDate();
    const tempMaxDate = moment(selected.startDate)
      .add(30, 'days')
      .toDate();
    setTempDateLimit({
      minDate: tempMinDate,
      maxDate: tempMaxDate,
    });
  } else {
    setTempDateLimit(undefined);
  }
};

return ( <DateRangePicker
              {...props}
              onChange={handleOnChange}
              minDate={tempDateLimit?.minDate}
              maxDate={tempDateLimit?.maxDate}
            />)

danny-dang avatar Dec 11 '23 08:12 danny-dang