Skip to content

Commit 0d78a2c

Browse files
committed
Missing save the date time in returned value.
1 parent bf063fe commit 0d78a2c

File tree

8 files changed

+174
-14
lines changed

8 files changed

+174
-14
lines changed

pages/index.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,19 @@ export default function Playground() {
1111
endDate: null
1212
});
1313
const [primaryColor, setPrimaryColor] = useState("blue");
14-
const [useRange, setUseRange] = useState(true);
15-
const [showFooter, setShowFooter] = useState(false);
14+
const [useRange, setUseRange] = useState(false);
15+
const [showFooter, setShowFooter] = useState(true);
1616
const [showShortcuts, setShowShortcuts] = useState(false);
17-
const [asSingle, setAsSingle] = useState(false);
17+
const [asTimePicker, setAsTimePicker] = useState(true);
18+
const [asSingle, setAsSingle] = useState(true);
1819
const [placeholder, setPlaceholder] = useState("");
1920
const [separator, setSeparator] = useState("~");
2021
const [i18n, setI18n] = useState("en");
2122
const [disabled, setDisabled] = useState(false);
2223
const [inputClassName, setInputClassName] = useState("");
2324
const [containerClassName, setContainerClassName] = useState("");
2425
const [toggleClassName, setToggleClassName] = useState("");
25-
const [displayFormat, setDisplayFormat] = useState("YYYY-MM-DD");
26+
const [displayFormat, setDisplayFormat] = useState("DD/MM/YYYY hh:mm A");
2627
const [readOnly, setReadOnly] = useState(false);
2728
const [minDate, setMinDate] = useState("");
2829
const [maxDate, setMaxDate] = useState("");
@@ -92,6 +93,7 @@ export default function Playground() {
9293
}
9394
}}
9495
asSingle={asSingle}
96+
asTimePicker={asTimePicker}
9597
placeholder={placeholder}
9698
separator={separator}
9799
startFrom={
@@ -187,6 +189,20 @@ export default function Playground() {
187189
</label>
188190
</div>
189191
</div>
192+
<div className="mb-2 w-1/2 sm:w-full">
193+
<div className="inline-flex items-center">
194+
<input
195+
type="checkbox"
196+
className="mr-2 rounded"
197+
id="asTimePicker"
198+
checked={asTimePicker}
199+
onChange={e => setAsTimePicker(e.target.checked)}
200+
/>
201+
<label className="block" htmlFor="showFooter">
202+
As Time Picker
203+
</label>
204+
</div>
205+
</div>
190206
<div className="mb-2 w-1/2 sm:w-full">
191207
<div className="inline-flex items-center">
192208
<input

src/components/Calendar/index.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ const Calendar: React.FC<Props> = ({
5757
changeDatepickerValue,
5858
hideDatepicker,
5959
asSingle,
60+
asTimePicker,
6061
i18n,
6162
startWeekOn,
6263
input
@@ -129,7 +130,7 @@ const Calendar: React.FC<Props> = ({
129130
},
130131
ipt
131132
);
132-
hideDatepicker();
133+
if (!asTimePicker) hideDatepicker();
133134
}
134135

135136
if (period.start && period.end) {
@@ -185,16 +186,17 @@ const Calendar: React.FC<Props> = ({
185186
}
186187
},
187188
[
188-
asSingle,
189-
changeDatepickerValue,
190-
changeDayHover,
191-
changePeriod,
192189
date,
193-
hideDatepicker,
194-
period.end,
195190
period.start,
191+
period.end,
196192
showFooter,
197-
input
193+
input,
194+
changeDatepickerValue,
195+
asTimePicker,
196+
hideDatepicker,
197+
changeDayHover,
198+
changePeriod,
199+
asSingle
198200
]
199201
);
200202

src/components/Datepicker.tsx

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Calendar from "../components/Calendar";
55
import Footer from "../components/Footer";
66
import Input from "../components/Input";
77
import Shortcuts from "../components/Shortcuts";
8+
import Time from "../components/Time";
89
import { COLORS, DATE_FORMAT, DEFAULT_COLOR, LANGUAGE } from "../constants";
910
import DatepickerContext from "../contexts/DatepickerContext";
1011
import { formatDate, nextMonth, previousMonth } from "../helpers";
@@ -22,6 +23,7 @@ const Datepicker: React.FC<DatepickerType> = ({
2223
showShortcuts = false,
2324
configs = undefined,
2425
asSingle = false,
26+
asTimePicker = false,
2527
placeholder = null,
2628
separator = "~",
2729
startFrom = null,
@@ -61,6 +63,10 @@ const Datepicker: React.FC<DatepickerType> = ({
6163
const [inputText, setInputText] = useState<string>("");
6264
const [inputRef, setInputRef] = useState(React.createRef<HTMLInputElement>());
6365

66+
const [hour, setHour] = useState<string>("1");
67+
const [minute, setMinute] = useState<string>("00");
68+
const [periodDay, setPeriodDay] = useState<"AM" | "PM">("PM");
69+
6470
// Custom Hooks use
6571
useOnClickOutside(containerRef, () => {
6672
const container = containerRef.current;
@@ -93,6 +99,21 @@ const Datepicker: React.FC<DatepickerType> = ({
9399
}
94100
}, []);
95101

102+
/* Start Time */
103+
const changeHour = useCallback((hour: string) => {
104+
setHour(hour);
105+
}, []);
106+
107+
const changeMinute = useCallback((minute: string) => {
108+
setMinute(minute);
109+
}, []);
110+
111+
const changePeriodDay = useCallback((periodDay: "AM" | "PM") => {
112+
setPeriodDay(periodDay);
113+
}, []);
114+
115+
/* End Time */
116+
96117
/* Start First */
97118
const firstGotoDate = useCallback(
98119
(date: dayjs.Dayjs) => {
@@ -247,6 +268,7 @@ const Datepicker: React.FC<DatepickerType> = ({
247268
const contextValues = useMemo(() => {
248269
return {
249270
asSingle,
271+
asTimePicker,
250272
primaryColor: safePrimaryColor,
251273
configs,
252274
calendarContainer: calendarContainerRef,
@@ -260,6 +282,9 @@ const Datepicker: React.FC<DatepickerType> = ({
260282
changeInputText: (newText: string) => setInputText(newText),
261283
updateFirstDate: (newDate: dayjs.Dayjs) => firstGotoDate(newDate),
262284
changeDatepickerValue: onChange,
285+
changeHour,
286+
changeMinute,
287+
changePeriodDay,
263288
showFooter,
264289
placeholder,
265290
separator,
@@ -286,13 +311,17 @@ const Datepicker: React.FC<DatepickerType> = ({
286311
};
287312
}, [
288313
asSingle,
314+
asTimePicker,
289315
safePrimaryColor,
290316
configs,
291317
hideDatepicker,
292318
period,
293319
dayHover,
294320
inputText,
295321
onChange,
322+
changeHour,
323+
changeMinute,
324+
changePeriodDay,
296325
showFooter,
297326
placeholder,
298327
separator,
@@ -376,7 +405,7 @@ const Datepicker: React.FC<DatepickerType> = ({
376405
)}
377406
</div>
378407
</div>
379-
408+
{asSingle && asTimePicker && <Time />}
380409
{showFooter && <Footer />}
381410
</div>
382411
</div>

src/components/Input.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const Input: React.FC<Props> = (e: Props) => {
2525
hideDatepicker,
2626
changeDatepickerValue,
2727
asSingle,
28+
asTimePicker,
2829
placeholder,
2930
separator,
3031
disabled,
@@ -70,7 +71,12 @@ const Input: React.FC<Props> = (e: Props) => {
7071

7172
const dates = [];
7273

73-
if (asSingle) {
74+
if (asSingle && asTimePicker) {
75+
const date = parseFormattedDate(inputValue, displayFormat);
76+
if (dateIsValid(date.toDate())) {
77+
dates.push(date.format(DATE_FORMAT));
78+
}
79+
} else if (asSingle) {
7480
const date = parseFormattedDate(inputValue, displayFormat);
7581
if (dateIsValid(date.toDate())) {
7682
dates.push(date.format(DATE_FORMAT));

src/components/Time.tsx

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import dayjs from "dayjs";
2+
import React, { ChangeEvent, useCallback, useContext } from "react";
3+
4+
import { BG_COLOR, BORDER_COLOR, DATE_FORMAT, RING_COLOR } from "../constants";
5+
import DatepickerContext from "../contexts/DatepickerContext";
6+
import { classNames as cn } from "../helpers";
7+
8+
const Time: React.FC = () => {
9+
// Contexts
10+
11+
const { primaryColor, changeHour, changeMinute, changePeriodDay } =
12+
useContext(DatepickerContext);
13+
const ringFocusColor = RING_COLOR.focus[primaryColor as keyof typeof RING_COLOR.focus];
14+
15+
const HOURS = Array.from({ length: 12 });
16+
const MINUTES = Array.from({ length: 12 });
17+
18+
const selectClassname = cn(
19+
"!bg-none !bg-transparent !text-sm !text-center !outline-none !focus:outline-none",
20+
"!px-2 !py-1 rounded-[8px] !w-fit",
21+
"!border border-gray-300 focus:border-none",
22+
`${ringFocusColor}`
23+
);
24+
25+
const handleChangeHour = (e: ChangeEvent<HTMLSelectElement>) => changeHour(e.target.value);
26+
27+
const handleChangeMinute = (e: ChangeEvent<HTMLSelectElement>) => changeMinute(e.target.value);
28+
29+
const handleChangePeriodDay = (e: ChangeEvent<HTMLSelectElement>) =>
30+
changePeriodDay(e.target.value as "AM" | "PM");
31+
32+
return (
33+
<div className="w-full md:w-auto flex items-center justify-center space-x-3">
34+
<div className="pb-6">
35+
<select name="hour" className={selectClassname} onChange={handleChangeHour}>
36+
{HOURS.map((_, index) => {
37+
const hour = index + 1;
38+
return (
39+
<option key={hour} value={hour + 1}>
40+
{hour}
41+
</option>
42+
);
43+
})}
44+
</select>
45+
<span className="text-xl mx-3">:</span>
46+
<select
47+
name="minute"
48+
className={cn(selectClassname, "mr-4")}
49+
onChange={handleChangeMinute}
50+
>
51+
{MINUTES.map((_, index) => {
52+
const minute = index * 5;
53+
return (
54+
<option key={minute} value={minute + 1}>
55+
{new Intl.NumberFormat("en-US", {
56+
minimumIntegerDigits: 2
57+
}).format(minute)}
58+
</option>
59+
);
60+
})}
61+
</select>
62+
<select name="ampm" className={selectClassname} onChange={handleChangePeriodDay}>
63+
<option value="AM">AM</option>
64+
<option value="PM">PM</option>
65+
</select>
66+
</div>
67+
</div>
68+
);
69+
};
70+
71+
export default Time;

src/contexts/DatepickerContext.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,16 @@ import {
1616
interface DatepickerStore {
1717
input?: React.RefObject<HTMLInputElement>;
1818
asSingle?: boolean;
19+
asTimePicker?: boolean;
1920
primaryColor: ColorKeys;
2021
configs?: Configs;
2122
calendarContainer: React.RefObject<HTMLDivElement> | null;
2223
arrowContainer: React.RefObject<HTMLDivElement> | null;
2324
hideDatepicker: () => void;
2425
period: Period;
26+
changeHour: (hour: string) => void;
27+
changeMinute: (minute: string) => void;
28+
changePeriodDay: (periodDay: "AM" | "PM") => void;
2529
changePeriod: (period: Period) => void;
2630
dayHover: string | null;
2731
changeDayHover: (day: string | null) => void;
@@ -70,6 +74,12 @@ const DatepickerContext = createContext<DatepickerStore>({
7074
// eslint-disable-next-line @typescript-eslint/no-empty-function,@typescript-eslint/no-unused-vars
7175
changeInputText: text => {},
7276
// eslint-disable-next-line @typescript-eslint/no-empty-function,@typescript-eslint/no-unused-vars
77+
changeHour: text => {},
78+
// eslint-disable-next-line @typescript-eslint/no-empty-function,@typescript-eslint/no-unused-vars
79+
changeMinute: text => {},
80+
// eslint-disable-next-line @typescript-eslint/no-empty-function,@typescript-eslint/no-unused-vars
81+
changePeriodDay: text => {},
82+
// eslint-disable-next-line @typescript-eslint/no-empty-function,@typescript-eslint/no-unused-vars
7383
updateFirstDate: date => {},
7484
// eslint-disable-next-line @typescript-eslint/no-empty-function,@typescript-eslint/no-unused-vars
7585
changeDatepickerValue: (value: DateValueType, e: HTMLInputElement | null | undefined) => {},

src/helpers/index.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,3 +626,28 @@ export function loadLanguageModule(language = LANGUAGE) {
626626
export function dateIsValid(date: Date | number) {
627627
return date instanceof Date && !isNaN(date.getTime());
628628
}
629+
630+
export function formatDateTimeToISO(
631+
dateIncoming: Date,
632+
hourIncoming: number,
633+
minute: number,
634+
period: string
635+
): string {
636+
// Adjust hour based on period (AM/PM)
637+
const hour = (() => {
638+
if (period === "PM" && hourIncoming !== 12) return hourIncoming + 12;
639+
640+
if (period === "AM" && hourIncoming === 12) return 0;
641+
642+
return hourIncoming;
643+
})();
644+
645+
// Create a new Date object and set the components
646+
const date = new Date(dateIncoming);
647+
date.setHours(hour);
648+
date.setMinutes(minute);
649+
650+
// Format date to ISO 8601
651+
const isoString = date.toISOString();
652+
return isoString;
653+
}

src/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export interface DatepickerType {
6262
showShortcuts?: boolean;
6363
configs?: Configs;
6464
asSingle?: boolean;
65+
asTimePicker?: boolean;
6566
placeholder?: string;
6667
separator?: string;
6768
startFrom?: Date | null;

0 commit comments

Comments
 (0)