Skip to content

Commit 16832c3

Browse files
committed
Refactor(DateTimeSection): extract pickers to separate component
1 parent f6bc7dc commit 16832c3

File tree

2 files changed

+213
-168
lines changed

2 files changed

+213
-168
lines changed
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
import React, { FC } from "react";
2+
import dayjs from "dayjs";
3+
import { Key } from "ts-key-enum";
4+
import { darken } from "@core/util/color.utils";
5+
import { MONTH_DAY_YEAR } from "@core/constants/date.constants";
6+
import { DatePicker } from "@web/components/DatePicker";
7+
import { AlignItems } from "@web/components/Flex/styled";
8+
import {
9+
dateIsValid,
10+
shouldAdjustComplimentDate,
11+
} from "@web/common/utils/web.date.util";
12+
13+
import { StyledDateFlex } from "./styled";
14+
15+
const stopPropagation = (e: React.MouseEvent<HTMLDivElement>) => {
16+
e.stopPropagation();
17+
};
18+
19+
interface Props {
20+
bgColor: string;
21+
inputColor?: string;
22+
isEndDatePickerOpen: boolean;
23+
isStartDatePickerOpen: boolean;
24+
selectedEndDate: Date;
25+
selectedStartDate: Date;
26+
setSelectedEndDate: (value: Date) => void;
27+
setSelectedStartDate: (value: Date) => void;
28+
setIsStartDatePickerOpen: (arg0: boolean) => void;
29+
setIsEndDatePickerOpen: (arg0: boolean) => void;
30+
}
31+
32+
export const DatePickers: FC<Props> = ({
33+
bgColor,
34+
inputColor,
35+
isEndDatePickerOpen,
36+
isStartDatePickerOpen,
37+
selectedEndDate,
38+
selectedStartDate,
39+
setIsEndDatePickerOpen,
40+
setIsStartDatePickerOpen,
41+
setSelectedEndDate,
42+
setSelectedStartDate,
43+
}) => {
44+
const adjustComplimentDateIfNeeded = (
45+
changed: "start" | "end",
46+
value: Date
47+
) => {
48+
const start = changed === "start" ? value : selectedStartDate;
49+
const end = changed === "end" ? value : selectedEndDate;
50+
51+
const { shouldAdjust, compliment } = shouldAdjustComplimentDate(changed, {
52+
start,
53+
end,
54+
});
55+
56+
if (shouldAdjust) {
57+
if (changed === "start") {
58+
setSelectedEndDate(compliment);
59+
return;
60+
}
61+
62+
if (changed === "end") {
63+
setSelectedStartDate(compliment);
64+
}
65+
}
66+
};
67+
const closeEndDatePicker = () => {
68+
setIsEndDatePickerOpen(false);
69+
};
70+
71+
const closeStartDatePicker = () => {
72+
setIsStartDatePickerOpen(false);
73+
};
74+
const getDateFromInput = (val: string) => {
75+
const date = dayjs(val, MONTH_DAY_YEAR).toDate();
76+
return date;
77+
};
78+
const onPickerKeyDown = (
79+
picker: "start" | "end",
80+
e: React.KeyboardEvent<HTMLDivElement>
81+
) => {
82+
switch (e.key) {
83+
case Key.Backspace: {
84+
e.stopPropagation();
85+
break;
86+
}
87+
case Key.Enter: {
88+
e.stopPropagation();
89+
const input = e.target as HTMLInputElement;
90+
const val = input.value;
91+
const isInvalid = val !== undefined && !dateIsValid(val);
92+
93+
if (isInvalid) {
94+
alert(`Sorry, IDK what to do with a ${picker} date of '${val}'
95+
Make sure it's in '${MONTH_DAY_YEAR}' and try again`);
96+
return;
97+
}
98+
99+
const date = getDateFromInput(val);
100+
101+
if (picker === "start") {
102+
onSelectStartDate(date);
103+
}
104+
105+
if (picker === "end") {
106+
onSelectEndDate(date);
107+
}
108+
109+
break;
110+
}
111+
case Key.Escape: {
112+
if (isStartDatePickerOpen) {
113+
e.stopPropagation();
114+
closeStartDatePicker();
115+
}
116+
if (isEndDatePickerOpen) {
117+
e.stopPropagation();
118+
closeEndDatePicker();
119+
}
120+
break;
121+
}
122+
case Key.Tab: {
123+
if (isStartDatePickerOpen) {
124+
setIsStartDatePickerOpen(false);
125+
}
126+
if (isEndDatePickerOpen) {
127+
setIsEndDatePickerOpen(false);
128+
}
129+
break;
130+
}
131+
default: {
132+
return;
133+
}
134+
}
135+
};
136+
const onSelectStartDate = (start: Date) => {
137+
setSelectedStartDate(start);
138+
setIsStartDatePickerOpen(false);
139+
adjustComplimentDateIfNeeded("start", start);
140+
};
141+
142+
const onSelectEndDate = (end: Date) => {
143+
setSelectedEndDate(end);
144+
setIsEndDatePickerOpen(false);
145+
adjustComplimentDateIfNeeded("end", end);
146+
};
147+
148+
return (
149+
<>
150+
<StyledDateFlex alignItems={AlignItems.CENTER}>
151+
<div onMouseUp={stopPropagation} onMouseDown={stopPropagation}>
152+
<DatePicker
153+
bgColor={darken(bgColor, 15)}
154+
calendarClassName="startDatePicker"
155+
inputColor={inputColor}
156+
isOpen={isStartDatePickerOpen}
157+
onCalendarClose={closeStartDatePicker}
158+
onCalendarOpen={() => {
159+
setIsStartDatePickerOpen(true);
160+
}}
161+
onChange={() => null}
162+
onInputClick={() => {
163+
isEndDatePickerOpen && setIsEndDatePickerOpen(false);
164+
setIsStartDatePickerOpen(true);
165+
}}
166+
onKeyDown={(e) => onPickerKeyDown("start", e)}
167+
onSelect={onSelectStartDate}
168+
selected={selectedStartDate}
169+
title="Pick Start Date"
170+
view="grid"
171+
/>
172+
</div>
173+
</StyledDateFlex>
174+
175+
<StyledDateFlex alignItems={AlignItems.CENTER}>
176+
<div onMouseUp={stopPropagation} onMouseDown={stopPropagation}>
177+
<DatePicker
178+
bgColor={darken(bgColor, 15)}
179+
calendarClassName="endDatePicker"
180+
inputColor={inputColor}
181+
isOpen={isEndDatePickerOpen}
182+
onCalendarClose={closeEndDatePicker}
183+
onCalendarOpen={() => setIsEndDatePickerOpen(true)}
184+
onChange={() => null}
185+
onInputClick={() => {
186+
isStartDatePickerOpen && setIsStartDatePickerOpen(false);
187+
setIsEndDatePickerOpen(true);
188+
}}
189+
onKeyDown={(e) => onPickerKeyDown("end", e)}
190+
onSelect={onSelectEndDate}
191+
selected={selectedEndDate}
192+
title="Pick End Date"
193+
view="grid"
194+
/>
195+
</div>
196+
</StyledDateFlex>
197+
</>
198+
);
199+
};

0 commit comments

Comments
 (0)