Skip to content

Commit 542f1b7

Browse files
committed
fixed DateTimeRange selector
1 parent c733096 commit 542f1b7

File tree

3 files changed

+284
-285
lines changed

3 files changed

+284
-285
lines changed
Lines changed: 79 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,108 @@
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

108
export 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

Comments
 (0)