1- import React , { FC , useState } from "react" ;
2- import dayjs , { Dayjs } from "dayjs" ;
3- import Calendar from "@atlaskit/calendar" ;
4- import { WeekDay } from "@atlaskit/calendar/types" ;
1+ import React , { FC , useState } from "react"
2+ import dayjs , { Dayjs } from "dayjs"
3+ import Calendar from "@atlaskit/calendar"
4+ import { WeekDay } from "@atlaskit/calendar/types"
55
6- export class EndDateBeforeStartDateError extends Error {
7-
8- }
6+ export class EndDateBeforeStartDateError extends Error { }
97
108export interface DateTimeRangeProps {
119 minDate ?: string
1210 maxDate ?: string
13- disabledDates : Array < string >
11+ disabledDates : string [ ]
1412 startDate ?: string
1513 endDate ?: string
1614 locale : string
1715 weekStartDate : WeekDay
18- onChange : ( start : string , end : string ) => void
19- onCollision : ( ) => void
16+ onChange : ( start : string , end : string ) => void
17+ onCollision : ( dateString : string ) => void
2018}
2119
22- export const DateTimeRange : FC < DateTimeRangeProps > = ( { ...props } ) => {
23-
24- const [ dateSelectCounter , setDateSelectCounter ] = useState ( 0 )
25- const [ startDate , setStartDate ] = useState ( props . startDate )
26- const [ endDate , setEndDate ] = useState ( props . endDate )
20+ function toDateString ( date : Dayjs ) {
21+ return date . format ( "YYYY-MM-DD" )
22+ }
2723
28- function getDatesBetweenStartEnd ( startDate : Dayjs , endDate : Dayjs ) {
29- if ( endDate . isBefore ( startDate ) ) {
30- throw new EndDateBeforeStartDateError ( )
31- }
32- const daysDiff = endDate . diff ( startDate , "day" ) + 1
33- return [ ...Array ( daysDiff ) ] . map ( ( item , index ) => {
34- return dayjs ( startDate ) . add ( index , "days" )
35- } )
24+ function getDatesBetweenStartEnd ( startDate : Dayjs , endDate : Dayjs ) {
25+ if ( endDate . isBefore ( startDate ) ) {
26+ throw new EndDateBeforeStartDateError ( )
3627 }
28+ const daysDiff = endDate . diff ( startDate , "day" ) + 1
29+ return [ ...Array ( daysDiff ) ] . map ( ( item , index ) => {
30+ return startDate . add ( index , "days" )
31+ } )
32+ }
3733
38- function toDateString ( date : Dayjs ) {
39- return date . format ( "yyyy-MM-DD" )
34+ function getSelectedDates (
35+ startDate : Dayjs | undefined ,
36+ endDate : Dayjs | undefined ,
37+ ) {
38+ if ( startDate != undefined && endDate == undefined ) {
39+ return [ toDateString ( startDate ) ]
40+ } else if ( startDate != undefined && endDate != undefined ) {
41+ return getDatesBetweenStartEnd ( startDate , endDate ) . map ( ( item ) => {
42+ return toDateString ( item )
43+ } )
44+ } else {
45+ return [ ]
4046 }
47+ }
4148
42- function getSelectedDates ( ) {
43- if ( startDate != undefined && endDate == undefined ) {
44- return [ startDate ]
45- } else if ( startDate != undefined && endDate != undefined ) {
46- return getDatesBetweenStartEnd ( dayjs ( startDate ) , dayjs ( endDate ) ) . map ( ( item ) => { return toDateString ( item ) } )
47- } else {
48- return [ ]
49- }
50- }
49+ function checkCollisions ( to : Dayjs , disabledDates : Dayjs [ ] ) {
50+ const intersection = disabledDates . find ( ( it ) => it . isSame ( to , "day" ) )
51+ return intersection
52+ }
5153
52- function checkCollisions ( to : string ) {
53- const range = getDatesBetweenStartEnd ( dayjs ( startDate ) , dayjs ( to ) ) . map ( ( item ) => toDateString ( item ) )
54- const intersections = range . filter ( ( item ) => props . disabledDates . includes ( item ) )
55- return intersections . length > 0
56- }
54+ export const DateTimeRange : FC < DateTimeRangeProps > = ( { ...props } ) => {
55+ const [ startDate , setStartDate ] = useState (
56+ props . startDate ? dayjs ( props . startDate ) : undefined ,
57+ )
58+ const [ endDate , setEndDate ] = useState (
59+ props . endDate ? dayjs ( props . endDate ) : undefined ,
60+ )
61+
62+ const disabledDates = props . disabledDates . map ( ( item ) => dayjs ( item ) )
63+
64+ function onDateSelect ( value : string ) {
65+ const pickedDate = dayjs ( value )
66+ const collision = checkCollisions ( pickedDate , disabledDates )
67+ if ( collision ) {
68+ props . onCollision ( collision . format ( "YYYY-MM-DD" ) )
69+ return
70+ }
5771
58- function onDateSelect ( value : string ) {
59- if ( dateSelectCounter == 1 ) {
60- // select to
61- if ( checkCollisions ( value ) ) {
62- setDateSelectCounter ( 0 )
63- props . onCollision ( )
64- } else if ( dayjs ( value ) . isBefore ( dayjs ( startDate ) ) ) {
65- setDateSelectCounter ( 0 )
66- props . onCollision ( )
72+ if ( startDate && endDate ) {
73+ setStartDate ( pickedDate )
74+ setEndDate ( undefined )
75+ } else if ( startDate && ! endDate ) {
76+ if ( pickedDate . isBefore ( startDate ) ) {
77+ setStartDate ( pickedDate )
78+ setEndDate ( undefined )
6779 } else {
68- setDateSelectCounter ( 2 )
69- setEndDate ( value )
70- props . onChange ( startDate as string , value )
80+ setEndDate ( pickedDate )
81+ props . onChange (
82+ startDate . format ( "YYYY-MM-DD" ) ,
83+ pickedDate . format ( "YYYY-MM-DD" ) ,
84+ )
7185 }
7286 } else {
73- // select from
74- setStartDate ( value )
75- setEndDate ( undefined )
76- setDateSelectCounter ( 1 )
87+ setStartDate ( pickedDate )
7788 }
7889 }
7990
91+ const selectedDates = getSelectedDates ( startDate , endDate )
92+
8093 return (
8194 < Calendar
82- minDate = { props . minDate }
83- maxDate = { props . maxDate }
84- disabled = { props . disabledDates }
85- selected = { getSelectedDates ( ) }
86- onSelect = { ( event ) => {
95+ minDate = { props . minDate }
96+ maxDate = { props . maxDate }
97+ disabled = { props . disabledDates }
98+ previouslySelected = { [ ] }
99+ selected = { selectedDates }
100+ onSelect = { ( event ) => {
87101 const selectedDate = event . iso
88- onDateSelect ( selectedDate )
89- }
90- }
91- locale = { props . locale }
92- weekStartDay = { props . weekStartDate }
102+ onDateSelect ( selectedDate )
103+ } }
104+ locale = { props . locale }
105+ weekStartDay = { props . weekStartDate }
93106 />
94107 )
95- }
108+ }
0 commit comments