@@ -3,7 +3,13 @@ import React, { useCallback, useContext } from "react";
33
44import { BG_COLOR } from "../../constants" ;
55import DatepickerContext from "../../contexts/DatepickerContext" ;
6- import { formatDate , getTextColorByPrimaryColor , nextMonth , previousMonth } from "../../helpers" ;
6+ import {
7+ formatDate ,
8+ getTextColorByPrimaryColor ,
9+ nextMonth ,
10+ previousMonth ,
11+ classNames as cn
12+ } from "../../helpers" ;
713
814const isBetween = require ( "dayjs/plugin/isBetween" ) ;
915dayjs . extend ( isBetween ) ;
@@ -29,8 +35,16 @@ const Days: React.FC<Props> = ({
2935 onClickNextDays
3036} ) => {
3137 // Contexts
32- const { primaryColor, period, changePeriod, dayHover, changeDayHover } =
33- useContext ( DatepickerContext ) ;
38+ const {
39+ primaryColor,
40+ period,
41+ changePeriod,
42+ dayHover,
43+ changeDayHover,
44+ minDate,
45+ maxDate,
46+ disabledDates
47+ } = useContext ( DatepickerContext ) ;
3448
3549 // Functions
3650 const currentDateClass = useCallback (
@@ -139,16 +153,97 @@ const Days: React.FC<Props> = ({
139153 [ calendarData . date , currentDateClass , dayHover , period . end , period . start , primaryColor ]
140154 ) ;
141155
142- const buttonCass = useCallback (
143- ( day : number ) => {
144- const baseClass = "flex items-center justify-center w-12 h-12 lg:w-10 lg:h-10" ;
145- return `${ baseClass } ${
146- ! activeDateData ( day ) . active
147- ? ` ${ hoverClassByDay ( day ) } `
148- : activeDateData ( day ) . className
156+ const isDateTooEarly = useCallback (
157+ ( day : number , type : string ) => {
158+ if ( ! minDate ) {
159+ return false ;
160+ }
161+ const object = {
162+ previous : previousMonth ( calendarData . date ) ,
163+ current : calendarData . date ,
164+ next : nextMonth ( calendarData . date )
165+ } ;
166+ const newDate = object [ type as keyof typeof object ] ;
167+ const formattedDate = `${ newDate . year ( ) } -${ newDate . month ( ) + 1 } -${
168+ day >= 10 ? day : "0" + day
169+ } `;
170+ return dayjs ( formattedDate ) . isSame ( dayjs ( minDate ) )
171+ ? false
172+ : dayjs ( formattedDate ) . isBefore ( dayjs ( minDate ) ) ;
173+ } ,
174+ [ calendarData . date , minDate ]
175+ ) ;
176+
177+ const isDateTooLate = useCallback (
178+ ( day : number , type : string ) => {
179+ if ( ! maxDate ) {
180+ return false ;
181+ }
182+ const object = {
183+ previous : previousMonth ( calendarData . date ) ,
184+ current : calendarData . date ,
185+ next : nextMonth ( calendarData . date )
186+ } ;
187+ const newDate = object [ type as keyof typeof object ] ;
188+ const formattedDate = `${ newDate . year ( ) } -${ newDate . month ( ) + 1 } -${
189+ day >= 10 ? day : "0" + day
149190 } `;
191+ return dayjs ( formattedDate ) . isSame ( maxDate )
192+ ? false
193+ : dayjs ( formattedDate ) . isAfter ( dayjs ( maxDate ) ) ;
194+ } ,
195+ [ calendarData . date , maxDate ]
196+ ) ;
197+
198+ const isDateDisabled = useCallback (
199+ ( day : number , type : string ) => {
200+ if ( isDateTooEarly ( day , type ) || isDateTooLate ( day , type ) ) {
201+ return true ;
202+ }
203+ const object = {
204+ previous : previousMonth ( calendarData . date ) ,
205+ current : calendarData . date ,
206+ next : nextMonth ( calendarData . date )
207+ } ;
208+ const newDate = object [ type as keyof typeof object ] ;
209+ const formattedDate = `${ newDate . year ( ) } -${ newDate . month ( ) + 1 } -${
210+ day >= 10 ? day : "0" + day
211+ } `;
212+
213+ if ( ! disabledDates || disabledDates ?. length <= 0 ) {
214+ return false ;
215+ }
216+
217+ let matchingCount = 0 ;
218+ disabledDates ?. forEach ( dateRange => {
219+ if (
220+ dayjs ( formattedDate ) . isAfter ( dateRange . startDate ) &&
221+ dayjs ( formattedDate ) . isBefore ( dateRange . endDate )
222+ ) {
223+ matchingCount ++ ;
224+ }
225+ if (
226+ dayjs ( formattedDate ) . isSame ( dateRange . startDate ) ||
227+ dayjs ( formattedDate ) . isSame ( dateRange . endDate )
228+ ) {
229+ matchingCount ++ ;
230+ }
231+ } ) ;
232+ return matchingCount > 0 ;
233+ } ,
234+ [ calendarData . date , isDateTooEarly , isDateTooLate ]
235+ ) ;
236+
237+ const buttonClass = useCallback (
238+ ( day : number , type : string ) => {
239+ const baseClass = "flex items-center justify-center w-12 h-12 lg:w-10 lg:h-10" ;
240+ return cn (
241+ baseClass ,
242+ ! activeDateData ( day ) . active ? hoverClassByDay ( day ) : activeDateData ( day ) . className ,
243+ isDateDisabled ( day , type ) && "line-through"
244+ ) ;
150245 } ,
151- [ activeDateData , hoverClassByDay ]
246+ [ activeDateData , hoverClassByDay , isDateDisabled ]
152247 ) ;
153248
154249 const hoverDay = useCallback (
@@ -192,6 +287,7 @@ const Days: React.FC<Props> = ({
192287 < button
193288 type = "button"
194289 key = { index }
290+ disabled = { isDateDisabled ( item , "previous" ) }
195291 className = "flex items-center justify-center text-gray-400 h-12 w-12 lg:w-10 lg:h-10"
196292 onClick = { ( ) => onClickPreviousDays ( item ) }
197293 onMouseOver = { ( ) => {
@@ -206,7 +302,8 @@ const Days: React.FC<Props> = ({
206302 < button
207303 type = "button"
208304 key = { index }
209- className = { buttonCass ( item ) }
305+ disabled = { isDateDisabled ( item , "current" ) }
306+ className = { `${ buttonClass ( item , "current" ) } ` }
210307 onClick = { ( ) => {
211308 onClickDay ( item ) ;
212309 } }
@@ -222,6 +319,7 @@ const Days: React.FC<Props> = ({
222319 < button
223320 type = "button"
224321 key = { index }
322+ disabled = { isDateDisabled ( index , "previous" ) }
225323 className = "flex items-center justify-center text-gray-400 h-12 w-12 lg:w-10 lg:h-10"
226324 onClick = { ( ) => {
227325 onClickNextDays ( item ) ;
0 commit comments