Skip to content

Commit

Permalink
Merge pull request #266 from julioflima/hotfix/init-time
Browse files Browse the repository at this point in the history
Feature Time Picker
  • Loading branch information
onesine authored Aug 13, 2024
2 parents 9065b07 + ae553e3 commit 0761692
Show file tree
Hide file tree
Showing 16 changed files with 346 additions and 63 deletions.
24 changes: 20 additions & 4 deletions pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,19 @@ export default function Playground() {
endDate: null
});
const [primaryColor, setPrimaryColor] = useState("blue");
const [useRange, setUseRange] = useState(true);
const [showFooter, setShowFooter] = useState(false);
const [useRange, setUseRange] = useState(false);
const [showFooter, setShowFooter] = useState(true);
const [showShortcuts, setShowShortcuts] = useState(false);
const [asSingle, setAsSingle] = useState(false);
const [asTimePicker, setAsTimePicker] = useState(true);
const [asSingle, setAsSingle] = useState(true);
const [placeholder, setPlaceholder] = useState("");
const [separator, setSeparator] = useState("~");
const [i18n, setI18n] = useState("en");
const [disabled, setDisabled] = useState(false);
const [inputClassName, setInputClassName] = useState("");
const [containerClassName, setContainerClassName] = useState("");
const [toggleClassName, setToggleClassName] = useState("");
const [displayFormat, setDisplayFormat] = useState("YYYY-MM-DD");
const [displayFormat, setDisplayFormat] = useState("DD/MM/YYYY hh:mm A");
const [readOnly, setReadOnly] = useState(false);
const [minDate, setMinDate] = useState("");
const [maxDate, setMaxDate] = useState("");
Expand Down Expand Up @@ -93,6 +94,7 @@ export default function Playground() {
}
}}
asSingle={asSingle}
asTimePicker={asTimePicker}
placeholder={placeholder}
separator={separator}
startFrom={
Expand Down Expand Up @@ -189,6 +191,20 @@ export default function Playground() {
</label>
</div>
</div>
<div className="mb-2 w-1/2 sm:w-full">
<div className="inline-flex items-center">
<input
type="checkbox"
className="mr-2 rounded"
id="asTimePicker"
checked={asTimePicker}
onChange={e => setAsTimePicker(e.target.checked)}
/>
<label className="block" htmlFor="showFooter">
As Time Picker
</label>
</div>
</div>
<div className="mb-2 w-1/2 sm:w-full">
<div className="inline-flex items-center">
<input
Expand Down
4 changes: 2 additions & 2 deletions src/components/Calendar/Days.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React, { useCallback, useContext } from "react";

import { BG_COLOR, TEXT_COLOR } from "../../constants";
import DatepickerContext from "../../contexts/DatepickerContext";
import { formatDate, nextMonth, previousMonth, classNames as cn } from "../../helpers";
import { classNames as cn, formatDate, nextMonth, previousMonth } from "../../helpers";
import { Period } from "../../types";

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

return (
<div className="grid grid-cols-7 gap-y-0.5 my-1">
<div className="my-1 grid grid-cols-7 gap-y-0.5">
{calendarData.days.previous.map((item, index) => (
<button
type="button"
Expand Down
2 changes: 1 addition & 1 deletion src/components/Calendar/Months.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const Months: React.FC<Props> = ({ currentMonth, clickMonth }) => {
const { i18n } = useContext(DatepickerContext);
loadLanguageModule(i18n);
return (
<div className="w-full grid grid-cols-2 gap-2 mt-2">
<div className="mt-2 grid w-full grid-cols-2 gap-2">
{MONTHS.map(item => (
<RoundedButton
key={item}
Expand Down
6 changes: 3 additions & 3 deletions src/components/Calendar/Week.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ const Week: React.FC = () => {
}, [startWeekOn]);

return (
<div className="grid grid-cols-7 border-b border-gray-300 dark:border-gray-700 py-2">
<div className="grid grid-cols-7 border-b border-gray-300 py-2 dark:border-gray-700">
{DAYS.map(item => (
<div key={item} className="tracking-wide text-gray-500 text-center">
<div key={item} className="text-center tracking-wide text-gray-500">
{ucFirst(
shortString(
dayjs(`2022-11-${6 + (item + startDateModifier)}`)
dayjs(`2022-11-${6 + (item + startDateModifier)}` as any)
.locale(i18n)
.format("ddd")
)
Expand Down
5 changes: 2 additions & 3 deletions src/components/Calendar/Years.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import React, { useContext } from "react";

import DatepickerContext from "../../contexts/DatepickerContext";
import { generateArrayNumber } from "../../helpers";
import { RoundedButton } from "../utils";

import DatepickerContext from "contexts/DatepickerContext";

interface Props {
year: number;
currentYear: number;
Expand Down Expand Up @@ -36,7 +35,7 @@ const Years: React.FC<Props> = ({ year, currentYear, minYear, maxYear, clickYear
}

return (
<div className="w-full grid grid-cols-2 gap-2 mt-2">
<div className="mt-2 grid w-full grid-cols-2 gap-2">
{generateArrayNumber(startDate, endDate).map((item, index) => (
<RoundedButton
key={index}
Expand Down
40 changes: 26 additions & 14 deletions src/components/Calendar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { CALENDAR_SIZE, DATE_FORMAT } from "../../constants";
import DatepickerContext from "../../contexts/DatepickerContext";
import {
formatDate,
formatDateTimeToISO,
getDaysInMonth,
getFirstDayInMonth,
getFirstDaysInMonth,
Expand All @@ -14,6 +15,7 @@ import {
nextMonth,
previousMonth
} from "../../helpers";
import { DateType } from "../../types";
import {
ChevronLeftIcon,
ChevronRightIcon,
Expand All @@ -27,8 +29,6 @@ import Months from "./Months";
import Week from "./Week";
import Years from "./Years";

import { DateType } from "types";

interface Props {
date: dayjs.Dayjs;
minDate?: DateType | null;
Expand All @@ -45,13 +45,17 @@ const Calendar: React.FC<Props> = props => {

// Contexts
const {
hour,
minute,
periodDay,
period,
changePeriod,
changeDayHover,
showFooter,
changeDatepickerValue,
hideDatepicker,
asSingle,
asTimePicker,
i18n,
startWeekOn,
input
Expand Down Expand Up @@ -120,12 +124,16 @@ const Calendar: React.FC<Props> = props => {
const ipt = input?.current;
changeDatepickerValue(
{
startDate: dayjs(start).format(DATE_FORMAT),
endDate: dayjs(end).format(DATE_FORMAT)
startDate: asTimePicker
? formatDateTimeToISO(start, hour, minute, periodDay)
: dayjs(start).format(DATE_FORMAT),
endDate: asTimePicker
? formatDateTimeToISO(end, hour, minute, periodDay)
: dayjs(end).format(DATE_FORMAT)
},
ipt
);
hideDatepicker();
if (!asTimePicker) hideDatepicker();
}

if (period.start && period.end) {
Expand Down Expand Up @@ -183,16 +191,20 @@ const Calendar: React.FC<Props> = props => {
}
},
[
asSingle,
changeDatepickerValue,
changeDayHover,
changePeriod,
date,
hideDatepicker,
period.end,
period.start,
period.end,
showFooter,
input
input,
changeDatepickerValue,
asTimePicker,
hour,
minute,
periodDay,
hideDatepicker,
changeDayHover,
changePeriod,
asSingle
]
);

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

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

<div className="px-0.5 sm:px-2 mt-0.5 min-h-[285px]">
<div className="mt-0.5 min-h-[285px] px-0.5 sm:px-2">
{showMonths && (
<Months currentMonth={calendarData.date.month() + 1} clickMonth={clickMonth} />
)}
Expand Down
59 changes: 44 additions & 15 deletions src/components/Datepicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import { COLORS, DATE_FORMAT, DEFAULT_COLOR, LANGUAGE } from "../constants";
import DatepickerContext from "../contexts/DatepickerContext";
import { formatDate, nextMonth, previousMonth } from "../helpers";
import useOnClickOutside from "../hooks";
import { Period, DatepickerType, ColorKeys } from "../types";
import { ColorKeys, DatepickerType, Period, PeriodDay } from "../types";

import Time from "./Time";
import { Arrow, VerticalDash } from "./utils";

const Datepicker = (props: DatepickerType) => {
Expand All @@ -27,6 +28,7 @@ const Datepicker = (props: DatepickerType) => {
placeholder = null,
separator = "~",
startFrom = null,
asTimePicker = false,
i18n = LANGUAGE,
disabled = false,
inputClassName = null,
Expand Down Expand Up @@ -66,6 +68,10 @@ const Datepicker = (props: DatepickerType) => {
const [inputText, setInputText] = useState<string>("");
const [inputRef, setInputRef] = useState(React.createRef<HTMLInputElement>());

const [hour, setHour] = useState<string>("8");
const [minute, setMinute] = useState<string>("00");
const [periodDay, setPeriodDay] = useState<PeriodDay>("AM");

// Custom Hooks use
useOnClickOutside(containerRef, () => {
const container = containerRef.current;
Expand Down Expand Up @@ -98,6 +104,14 @@ const Datepicker = (props: DatepickerType) => {
}
}, []);

/* Start Time */
const changeHour = useCallback((hour: string) => setHour(hour), []);

const changeMinute = useCallback((minute: string) => setMinute(minute), []);

const changePeriodDay = useCallback((periodDay: PeriodDay) => setPeriodDay(periodDay), []);
/* End Time */

/* Start First */
const firstGotoDate = useCallback(
(date: dayjs.Dayjs) => {
Expand Down Expand Up @@ -253,6 +267,7 @@ const Datepicker = (props: DatepickerType) => {
const contextValues = useMemo(() => {
return {
asSingle,
asTimePicker,
primaryColor: safePrimaryColor,
configs,
calendarContainer: calendarContainerRef,
Expand All @@ -266,6 +281,12 @@ const Datepicker = (props: DatepickerType) => {
changeInputText: (newText: string) => setInputText(newText),
updateFirstDate: (newDate: dayjs.Dayjs) => firstGotoDate(newDate),
changeDatepickerValue: onChange,
hour,
minute,
periodDay,
changeHour,
changeMinute,
changePeriodDay,
showFooter,
placeholder,
separator,
Expand Down Expand Up @@ -293,13 +314,20 @@ const Datepicker = (props: DatepickerType) => {
};
}, [
asSingle,
asTimePicker,
safePrimaryColor,
configs,
hideDatepicker,
period,
dayHover,
inputText,
onChange,
hour,
minute,
periodDay,
changeHour,
changeMinute,
changePeriodDay,
showFooter,
placeholder,
separator,
Expand Down Expand Up @@ -353,31 +381,33 @@ const Datepicker = (props: DatepickerType) => {
<div className={popupClassNameOverload} ref={calendarContainerRef}>
<Arrow ref={arrowRef} />

<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">
<div className="flex flex-col lg:flex-row py-2">
<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">
<div className="flex flex-col py-2 lg:flex-row">
{showShortcuts && <Shortcuts />}

<div
className={`flex items-stretch flex-col md:flex-row space-y-4 md:space-y-0 md:space-x-1.5 ${
className={`flex flex-col items-stretch space-y-4 md:flex-row md:space-x-1.5 md:space-y-0 ${
showShortcuts ? "md:pl-2" : "md:pl-1"
} pr-2 lg:pr-1`}
>
<Calendar
date={firstDate}
onClickPrevious={previousMonthFirst}
onClickNext={nextMonthFirst}
changeMonth={changeFirstMonth}
changeYear={changeFirstYear}
minDate={minDate}
maxDate={maxDate}
/>
<div>
<Calendar
date={firstDate}
onClickPrevious={previousMonthFirst}
onClickNext={nextMonthFirst}
changeMonth={changeFirstMonth}
changeYear={changeFirstYear}
minDate={minDate}
maxDate={maxDate}
/>
{asSingle && asTimePicker && <Time />}
</div>

{useRange && (
<>
<div className="flex items-center">
<VerticalDash />
</div>

<Calendar
date={secondDate}
onClickPrevious={previousMonthSecond}
Expand All @@ -391,7 +421,6 @@ const Datepicker = (props: DatepickerType) => {
)}
</div>
</div>

{showFooter && <Footer />}
</div>
</div>
Expand Down
Loading

0 comments on commit 0761692

Please sign in to comment.