Skip to content

Commit 0761692

Browse files
authored
Merge pull request #266 from julioflima/hotfix/init-time
Feature Time Picker
2 parents 9065b07 + ae553e3 commit 0761692

File tree

16 files changed

+346
-63
lines changed

16 files changed

+346
-63
lines changed

pages/index.js

+20-4
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("");
@@ -93,6 +94,7 @@ export default function Playground() {
9394
}
9495
}}
9596
asSingle={asSingle}
97+
asTimePicker={asTimePicker}
9698
placeholder={placeholder}
9799
separator={separator}
98100
startFrom={
@@ -189,6 +191,20 @@ export default function Playground() {
189191
</label>
190192
</div>
191193
</div>
194+
<div className="mb-2 w-1/2 sm:w-full">
195+
<div className="inline-flex items-center">
196+
<input
197+
type="checkbox"
198+
className="mr-2 rounded"
199+
id="asTimePicker"
200+
checked={asTimePicker}
201+
onChange={e => setAsTimePicker(e.target.checked)}
202+
/>
203+
<label className="block" htmlFor="showFooter">
204+
As Time Picker
205+
</label>
206+
</div>
207+
</div>
192208
<div className="mb-2 w-1/2 sm:w-full">
193209
<div className="inline-flex items-center">
194210
<input

src/components/Calendar/Days.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import React, { useCallback, useContext } from "react";
44

55
import { BG_COLOR, TEXT_COLOR } from "../../constants";
66
import DatepickerContext from "../../contexts/DatepickerContext";
7-
import { formatDate, nextMonth, previousMonth, classNames as cn } from "../../helpers";
7+
import { classNames as cn, formatDate, nextMonth, previousMonth } from "../../helpers";
88
import { Period } from "../../types";
99

1010
dayjs.extend(isBetween);
@@ -342,7 +342,7 @@ const Days: React.FC<Props> = props => {
342342
);
343343

344344
return (
345-
<div className="grid grid-cols-7 gap-y-0.5 my-1">
345+
<div className="my-1 grid grid-cols-7 gap-y-0.5">
346346
{calendarData.days.previous.map((item, index) => (
347347
<button
348348
type="button"

src/components/Calendar/Months.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const Months: React.FC<Props> = ({ currentMonth, clickMonth }) => {
1515
const { i18n } = useContext(DatepickerContext);
1616
loadLanguageModule(i18n);
1717
return (
18-
<div className="w-full grid grid-cols-2 gap-2 mt-2">
18+
<div className="mt-2 grid w-full grid-cols-2 gap-2">
1919
{MONTHS.map(item => (
2020
<RoundedButton
2121
key={item}

src/components/Calendar/Week.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ const Week: React.FC = () => {
3333
}, [startWeekOn]);
3434

3535
return (
36-
<div className="grid grid-cols-7 border-b border-gray-300 dark:border-gray-700 py-2">
36+
<div className="grid grid-cols-7 border-b border-gray-300 py-2 dark:border-gray-700">
3737
{DAYS.map(item => (
38-
<div key={item} className="tracking-wide text-gray-500 text-center">
38+
<div key={item} className="text-center tracking-wide text-gray-500">
3939
{ucFirst(
4040
shortString(
41-
dayjs(`2022-11-${6 + (item + startDateModifier)}`)
41+
dayjs(`2022-11-${6 + (item + startDateModifier)}` as any)
4242
.locale(i18n)
4343
.format("ddd")
4444
)

src/components/Calendar/Years.tsx

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import React, { useContext } from "react";
22

3+
import DatepickerContext from "../../contexts/DatepickerContext";
34
import { generateArrayNumber } from "../../helpers";
45
import { RoundedButton } from "../utils";
56

6-
import DatepickerContext from "contexts/DatepickerContext";
7-
87
interface Props {
98
year: number;
109
currentYear: number;
@@ -36,7 +35,7 @@ const Years: React.FC<Props> = ({ year, currentYear, minYear, maxYear, clickYear
3635
}
3736

3837
return (
39-
<div className="w-full grid grid-cols-2 gap-2 mt-2">
38+
<div className="mt-2 grid w-full grid-cols-2 gap-2">
4039
{generateArrayNumber(startDate, endDate).map((item, index) => (
4140
<RoundedButton
4241
key={index}

src/components/Calendar/index.tsx

+26-14
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { CALENDAR_SIZE, DATE_FORMAT } from "../../constants";
55
import DatepickerContext from "../../contexts/DatepickerContext";
66
import {
77
formatDate,
8+
formatDateTimeToISO,
89
getDaysInMonth,
910
getFirstDayInMonth,
1011
getFirstDaysInMonth,
@@ -14,6 +15,7 @@ import {
1415
nextMonth,
1516
previousMonth
1617
} from "../../helpers";
18+
import { DateType } from "../../types";
1719
import {
1820
ChevronLeftIcon,
1921
ChevronRightIcon,
@@ -27,8 +29,6 @@ import Months from "./Months";
2729
import Week from "./Week";
2830
import Years from "./Years";
2931

30-
import { DateType } from "types";
31-
3232
interface Props {
3333
date: dayjs.Dayjs;
3434
minDate?: DateType | null;
@@ -45,13 +45,17 @@ const Calendar: React.FC<Props> = props => {
4545

4646
// Contexts
4747
const {
48+
hour,
49+
minute,
50+
periodDay,
4851
period,
4952
changePeriod,
5053
changeDayHover,
5154
showFooter,
5255
changeDatepickerValue,
5356
hideDatepicker,
5457
asSingle,
58+
asTimePicker,
5559
i18n,
5660
startWeekOn,
5761
input
@@ -120,12 +124,16 @@ const Calendar: React.FC<Props> = props => {
120124
const ipt = input?.current;
121125
changeDatepickerValue(
122126
{
123-
startDate: dayjs(start).format(DATE_FORMAT),
124-
endDate: dayjs(end).format(DATE_FORMAT)
127+
startDate: asTimePicker
128+
? formatDateTimeToISO(start, hour, minute, periodDay)
129+
: dayjs(start).format(DATE_FORMAT),
130+
endDate: asTimePicker
131+
? formatDateTimeToISO(end, hour, minute, periodDay)
132+
: dayjs(end).format(DATE_FORMAT)
125133
},
126134
ipt
127135
);
128-
hideDatepicker();
136+
if (!asTimePicker) hideDatepicker();
129137
}
130138

131139
if (period.start && period.end) {
@@ -183,16 +191,20 @@ const Calendar: React.FC<Props> = props => {
183191
}
184192
},
185193
[
186-
asSingle,
187-
changeDatepickerValue,
188-
changeDayHover,
189-
changePeriod,
190194
date,
191-
hideDatepicker,
192-
period.end,
193195
period.start,
196+
period.end,
194197
showFooter,
195-
input
198+
input,
199+
changeDatepickerValue,
200+
asTimePicker,
201+
hour,
202+
minute,
203+
periodDay,
204+
hideDatepicker,
205+
changeDayHover,
206+
changePeriod,
207+
asSingle
196208
]
197209
);
198210

@@ -241,7 +253,7 @@ const Calendar: React.FC<Props> = props => {
241253

242254
return (
243255
<div className="w-full md:w-[296px] md:min-w-[296px]">
244-
<div className="flex items-center space-x-1.5 border border-gray-300 dark:border-gray-700 rounded-md px-2 py-1.5">
256+
<div className="flex items-center space-x-1.5 rounded-md border border-gray-300 px-2 py-1.5 dark:border-gray-700">
245257
{!showMonths && !showYears && (
246258
<div className="flex-none">
247259
<RoundedButton roundedFull={true} onClick={onClickPrevious}>
@@ -309,7 +321,7 @@ const Calendar: React.FC<Props> = props => {
309321
)}
310322
</div>
311323

312-
<div className="px-0.5 sm:px-2 mt-0.5 min-h-[285px]">
324+
<div className="mt-0.5 min-h-[285px] px-0.5 sm:px-2">
313325
{showMonths && (
314326
<Months currentMonth={calendarData.date.month() + 1} clickMonth={clickMonth} />
315327
)}

src/components/Datepicker.tsx

+44-15
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ import { COLORS, DATE_FORMAT, DEFAULT_COLOR, LANGUAGE } from "../constants";
99
import DatepickerContext from "../contexts/DatepickerContext";
1010
import { formatDate, nextMonth, previousMonth } from "../helpers";
1111
import useOnClickOutside from "../hooks";
12-
import { Period, DatepickerType, ColorKeys } from "../types";
12+
import { ColorKeys, DatepickerType, Period, PeriodDay } from "../types";
1313

14+
import Time from "./Time";
1415
import { Arrow, VerticalDash } from "./utils";
1516

1617
const Datepicker = (props: DatepickerType) => {
@@ -27,6 +28,7 @@ const Datepicker = (props: DatepickerType) => {
2728
placeholder = null,
2829
separator = "~",
2930
startFrom = null,
31+
asTimePicker = false,
3032
i18n = LANGUAGE,
3133
disabled = false,
3234
inputClassName = null,
@@ -66,6 +68,10 @@ const Datepicker = (props: DatepickerType) => {
6668
const [inputText, setInputText] = useState<string>("");
6769
const [inputRef, setInputRef] = useState(React.createRef<HTMLInputElement>());
6870

71+
const [hour, setHour] = useState<string>("8");
72+
const [minute, setMinute] = useState<string>("00");
73+
const [periodDay, setPeriodDay] = useState<PeriodDay>("AM");
74+
6975
// Custom Hooks use
7076
useOnClickOutside(containerRef, () => {
7177
const container = containerRef.current;
@@ -98,6 +104,14 @@ const Datepicker = (props: DatepickerType) => {
98104
}
99105
}, []);
100106

107+
/* Start Time */
108+
const changeHour = useCallback((hour: string) => setHour(hour), []);
109+
110+
const changeMinute = useCallback((minute: string) => setMinute(minute), []);
111+
112+
const changePeriodDay = useCallback((periodDay: PeriodDay) => setPeriodDay(periodDay), []);
113+
/* End Time */
114+
101115
/* Start First */
102116
const firstGotoDate = useCallback(
103117
(date: dayjs.Dayjs) => {
@@ -253,6 +267,7 @@ const Datepicker = (props: DatepickerType) => {
253267
const contextValues = useMemo(() => {
254268
return {
255269
asSingle,
270+
asTimePicker,
256271
primaryColor: safePrimaryColor,
257272
configs,
258273
calendarContainer: calendarContainerRef,
@@ -266,6 +281,12 @@ const Datepicker = (props: DatepickerType) => {
266281
changeInputText: (newText: string) => setInputText(newText),
267282
updateFirstDate: (newDate: dayjs.Dayjs) => firstGotoDate(newDate),
268283
changeDatepickerValue: onChange,
284+
hour,
285+
minute,
286+
periodDay,
287+
changeHour,
288+
changeMinute,
289+
changePeriodDay,
269290
showFooter,
270291
placeholder,
271292
separator,
@@ -293,13 +314,20 @@ const Datepicker = (props: DatepickerType) => {
293314
};
294315
}, [
295316
asSingle,
317+
asTimePicker,
296318
safePrimaryColor,
297319
configs,
298320
hideDatepicker,
299321
period,
300322
dayHover,
301323
inputText,
302324
onChange,
325+
hour,
326+
minute,
327+
periodDay,
328+
changeHour,
329+
changeMinute,
330+
changePeriodDay,
303331
showFooter,
304332
placeholder,
305333
separator,
@@ -353,31 +381,33 @@ const Datepicker = (props: DatepickerType) => {
353381
<div className={popupClassNameOverload} ref={calendarContainerRef}>
354382
<Arrow ref={arrowRef} />
355383

356-
<div className="mt-2.5 shadow-sm border border-gray-300 px-1 py-0.5 bg-white dark:bg-slate-800 dark:text-white dark:border-slate-600 rounded-lg">
357-
<div className="flex flex-col lg:flex-row py-2">
384+
<div className="mt-2.5 rounded-lg border border-gray-300 bg-white px-1 py-0.5 shadow-sm dark:border-slate-600 dark:bg-slate-800 dark:text-white">
385+
<div className="flex flex-col py-2 lg:flex-row">
358386
{showShortcuts && <Shortcuts />}
359387

360388
<div
361-
className={`flex items-stretch flex-col md:flex-row space-y-4 md:space-y-0 md:space-x-1.5 ${
389+
className={`flex flex-col items-stretch space-y-4 md:flex-row md:space-x-1.5 md:space-y-0 ${
362390
showShortcuts ? "md:pl-2" : "md:pl-1"
363391
} pr-2 lg:pr-1`}
364392
>
365-
<Calendar
366-
date={firstDate}
367-
onClickPrevious={previousMonthFirst}
368-
onClickNext={nextMonthFirst}
369-
changeMonth={changeFirstMonth}
370-
changeYear={changeFirstYear}
371-
minDate={minDate}
372-
maxDate={maxDate}
373-
/>
393+
<div>
394+
<Calendar
395+
date={firstDate}
396+
onClickPrevious={previousMonthFirst}
397+
onClickNext={nextMonthFirst}
398+
changeMonth={changeFirstMonth}
399+
changeYear={changeFirstYear}
400+
minDate={minDate}
401+
maxDate={maxDate}
402+
/>
403+
{asSingle && asTimePicker && <Time />}
404+
</div>
374405

375406
{useRange && (
376407
<>
377408
<div className="flex items-center">
378409
<VerticalDash />
379410
</div>
380-
381411
<Calendar
382412
date={secondDate}
383413
onClickPrevious={previousMonthSecond}
@@ -391,7 +421,6 @@ const Datepicker = (props: DatepickerType) => {
391421
)}
392422
</div>
393423
</div>
394-
395424
{showFooter && <Footer />}
396425
</div>
397426
</div>

0 commit comments

Comments
 (0)