Skip to content

Commit 99cbd09

Browse files
DateTimePicker input formatting, and rendering predefined list
1 parent 5f32ac9 commit 99cbd09

File tree

4 files changed

+767
-6
lines changed

4 files changed

+767
-6
lines changed

src/components/DatePicker/Common.tsx

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,21 @@ import { Container } from "../Container/Container";
66
import { useCalendar, UseCalendarOptions } from "@h6s/calendar";
77
import { IconButton } from "../IconButton/IconButton";
88
import { Text } from "../Typography/Text/Text";
9-
import { headerDateFormatter, selectedDateFormatter, weekdayFormatter } from "./utils";
9+
import { headerDateFormatter, selectedDateFormatter, selectedDateTimeFormatter, weekdayFormatter } from "./utils";
1010

1111
const explicitWidth = "250px";
1212

13-
const HighlightedInputWrapper = styled(InputWrapper)<{ $isActive: boolean }>`
14-
${({ $isActive, theme }) => {
13+
const HighlightedInputWrapper = styled(InputWrapper)<{ $isActive: boolean, $width?: string }>`
14+
${({ $isActive, $width, theme }) => {
1515
return `border: ${theme.click.datePicker.dateOption.stroke} solid ${
1616
$isActive
1717
? theme.click.datePicker.dateOption.color.stroke.active
1818
: theme.click.field.color.stroke.default
19-
};`;
19+
};
20+
width: ${$width ? $width : explicitWidth};
21+
${$width && `min-width: ${explicitWidth};`}
22+
`;
2023
}}
21-
22-
width: ${explicitWidth};
2324
}`;
2425

2526
interface DatePickerInputProps {
@@ -131,6 +132,77 @@ export const DateRangePickerInput = ({
131132
);
132133
};
133134

135+
interface DateTimePickerInputProps {
136+
isActive: boolean;
137+
disabled: boolean;
138+
id?: string;
139+
placeholder?: string;
140+
selectedEndDate?: Date;
141+
selectedStartDate?: Date;
142+
}
143+
144+
export const DateTimePickerInput = ({
145+
isActive,
146+
disabled,
147+
id,
148+
placeholder,
149+
selectedEndDate,
150+
selectedStartDate,
151+
}: DateTimePickerInputProps) => {
152+
const defaultId = useId();
153+
154+
let formattedValue = (
155+
<Text
156+
color="muted"
157+
component="span"
158+
>
159+
{placeholder ?? ""}
160+
</Text>
161+
);
162+
if (selectedStartDate) {
163+
if (selectedEndDate) {
164+
formattedValue = (
165+
<span>
166+
{selectedDateTimeFormatter.format(selectedStartDate).replace("AM", "am").replace("PM", 'pm')}{" "}
167+
{selectedDateTimeFormatter.format(selectedEndDate).replace("AM", "am").replace("PM", 'pm')}
168+
</span>
169+
);
170+
} else {
171+
formattedValue = (
172+
<span>
173+
{selectedDateTimeFormatter.format(selectedStartDate).replace("AM", "am").replace("PM", 'pm')}{" "}
174+
<Text
175+
color="muted"
176+
component="span"
177+
>
178+
– end date
179+
</Text>
180+
</span>
181+
);
182+
}
183+
}
184+
185+
return (
186+
<HighlightedInputWrapper
187+
$isActive={isActive}
188+
disabled={disabled}
189+
id={id ?? defaultId}
190+
$width="max-content"
191+
>
192+
<InputStartContent>
193+
<Icon name="calendar" />
194+
</InputStartContent>
195+
<InputElement
196+
$hasStartContent
197+
as="div"
198+
data-testid="daterangepicker-input"
199+
>
200+
{formattedValue}
201+
</InputElement>
202+
</HighlightedInputWrapper>
203+
);
204+
};
205+
134206
const DatePickerContainer = styled(Container)`
135207
background: ${({ theme }) =>
136208
theme.click.datePicker.dateOption.color.background.default};
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
import { Args, Meta, StoryObj } from "@storybook/react-vite";
2+
import { DateTimePicker } from "./DateTimePicker";
3+
import { getPredefinedTimePeriodsForDateTimePicker } from "./utils";
4+
5+
const meta: Meta<typeof DateTimePicker> = {
6+
component: DateTimePicker,
7+
args: {
8+
maxRangeLength: undefined,
9+
onSelectDateRange: (startDate: Date, endDate: Date) => {
10+
console.log("Date range selected: ", startDate, endDate);
11+
},
12+
},
13+
tags: ["autodocs"],
14+
title: "Display/DateTimePicker",
15+
};
16+
17+
export default meta;
18+
19+
type Story = StoryObj<typeof meta>;
20+
21+
export const Default: Story = {
22+
args: {
23+
predefinedDatesList: [],
24+
},
25+
render: (args: Args) => {
26+
const endDate = args.endDate ? new Date(args.endDate) : undefined;
27+
const startDate = args.startDate ? new Date(args.startDate) : undefined;
28+
29+
return (
30+
<DateTimePicker
31+
key="default"
32+
endDate={endDate}
33+
disabled={args.disabled}
34+
futureDatesDisabled={args.futureDatesDisabled}
35+
futureStartDatesDisabled={args.futureStartDatesDisabled}
36+
maxRangeLength={args.maxRangeLength}
37+
onSelectDateRange={args.onSelectDateRange}
38+
placeholder={args.placeholder}
39+
startDate={startDate}
40+
/>
41+
);
42+
},
43+
};
44+
45+
export const DateRangeWithMaxRange: Story = {
46+
args: {
47+
maxRangeLength: 15,
48+
predefinedDatesList: [],
49+
},
50+
render: (args: Args) => {
51+
const endDate = args.endDate ? new Date(args.endDate) : undefined;
52+
const startDate = args.startDate ? new Date(args.startDate) : undefined;
53+
54+
return (
55+
<DateTimePicker
56+
key="default"
57+
endDate={endDate}
58+
disabled={args.disabled}
59+
futureDatesDisabled={args.futureDatesDisabled}
60+
futureStartDatesDisabled={args.futureStartDatesDisabled}
61+
maxRangeLength={args.maxRangeLength}
62+
onSelectDateRange={args.onSelectDateRange}
63+
placeholder={args.placeholder}
64+
startDate={startDate}
65+
/>
66+
);
67+
},
68+
};
69+
70+
export const DateRangeFutureStartDatesDisabled: Story = {
71+
args: {
72+
futureStartDatesDisabled: true,
73+
predefinedDatesList: [],
74+
},
75+
};
76+
77+
export const PredefinedDatesLastSixMonths: Story = {
78+
render: (args: Args) => {
79+
const endDate = args.endDate ? new Date(args.endDate) : undefined;
80+
const startDate = args.startDate ? new Date(args.startDate) : undefined;
81+
const predefinedDatesList = getPredefinedTimePeriodsForDateTimePicker();
82+
83+
return (
84+
<DateTimePicker
85+
key="default"
86+
endDate={endDate}
87+
disabled={args.disabled}
88+
futureDatesDisabled={args.futureDatesDisabled}
89+
futureStartDatesDisabled={args.futureStartDatesDisabled}
90+
maxRangeLength={args.maxRangeLength}
91+
onSelectDateRange={args.onSelectDateRange}
92+
placeholder={args.placeholder}
93+
predefinedDatesList={predefinedDatesList}
94+
startDate={startDate}
95+
/>
96+
);
97+
},
98+
};
99+
100+
export const PredefinedDatesNextSixMonths: Story = {
101+
render: (args: Args) => {
102+
const endDate = args.endDate ? new Date(args.endDate) : undefined;
103+
const startDate = args.startDate ? new Date(args.startDate) : undefined;
104+
const predefinedDatesList = getPredefinedTimePeriodsForDateTimePicker();
105+
106+
return (
107+
<DateTimePicker
108+
key="default"
109+
endDate={endDate}
110+
disabled={args.disabled}
111+
futureDatesDisabled={args.futureDatesDisabled}
112+
futureStartDatesDisabled={args.futureStartDatesDisabled}
113+
maxRangeLength={args.maxRangeLength}
114+
onSelectDateRange={args.onSelectDateRange}
115+
placeholder={args.placeholder}
116+
predefinedDatesList={predefinedDatesList}
117+
startDate={startDate}
118+
/>
119+
);
120+
},
121+
};
122+
123+
export const PredefinedDatesArbitraryDates: Story = {
124+
render: (args: Args) => {
125+
const endDate = args.endDate ? new Date(args.endDate) : undefined;
126+
const startDate = args.startDate ? new Date(args.startDate) : undefined;
127+
const predefinedDatesList = [
128+
{ startDate: new Date("04/14/2025"), endDate: new Date("05/14/2025") },
129+
{ startDate: new Date("05/14/2025"), endDate: new Date("06/14/2025") },
130+
{ startDate: new Date("06/14/2025"), endDate: new Date("07/14/2025") },
131+
];
132+
133+
return (
134+
<DateTimePicker
135+
key="default"
136+
endDate={endDate}
137+
disabled={args.disabled}
138+
futureDatesDisabled={args.futureDatesDisabled}
139+
futureStartDatesDisabled={args.futureStartDatesDisabled}
140+
maxRangeLength={args.maxRangeLength}
141+
onSelectDateRange={args.onSelectDateRange}
142+
placeholder={args.placeholder}
143+
predefinedDatesList={predefinedDatesList}
144+
startDate={startDate}
145+
/>
146+
);
147+
},
148+
};
149+
150+
export const PredefinedDatesScrollable: Story = {
151+
render: (args: Args) => {
152+
const endDate = args.endDate ? new Date(args.endDate) : undefined;
153+
const startDate = args.startDate ? new Date(args.startDate) : undefined;
154+
const predefinedDatesList = [
155+
{ startDate: new Date("09/14/2024"), endDate: new Date("10/14/2024") },
156+
{ startDate: new Date("10/14/2024"), endDate: new Date("11/14/2024") },
157+
{ startDate: new Date("11/14/2024"), endDate: new Date("12/14/2024") },
158+
{ startDate: new Date("12/14/2024"), endDate: new Date("01/14/2025") },
159+
{ startDate: new Date("01/14/2025"), endDate: new Date("02/14/2025") },
160+
{ startDate: new Date("02/14/2025"), endDate: new Date("03/14/2025") },
161+
{ startDate: new Date("03/14/2025"), endDate: new Date("04/14/2025") },
162+
{ startDate: new Date("04/14/2025"), endDate: new Date("05/14/2025") },
163+
{ startDate: new Date("05/14/2025"), endDate: new Date("06/14/2025") },
164+
{ startDate: new Date("06/14/2025"), endDate: new Date("07/14/2025") },
165+
];
166+
167+
return (
168+
<DateTimePicker
169+
key="default"
170+
endDate={endDate}
171+
disabled={args.disabled}
172+
futureDatesDisabled={args.futureDatesDisabled}
173+
futureStartDatesDisabled={args.futureStartDatesDisabled}
174+
maxRangeLength={args.maxRangeLength}
175+
onSelectDateRange={args.onSelectDateRange}
176+
placeholder={args.placeholder}
177+
predefinedDatesList={predefinedDatesList}
178+
startDate={startDate}
179+
/>
180+
);
181+
},
182+
};

0 commit comments

Comments
 (0)