From cb009c77a4fbd124ef005c08d6e749ef3d32c157 Mon Sep 17 00:00:00 2001 From: pramod mahajan Date: Tue, 5 Aug 2025 23:54:22 +0530 Subject: [PATCH] customize date picker, flexible can set max and min date and also handle react-hook-form --- src/components/common/DatePicker.jsx | 92 +++++++++---- src/components/common/DateRangePicker.jsx | 158 +++++++++++++++++++--- 2 files changed, 200 insertions(+), 50 deletions(-) diff --git a/src/components/common/DatePicker.jsx b/src/components/common/DatePicker.jsx index 728b14fb..9645fddb 100644 --- a/src/components/common/DatePicker.jsx +++ b/src/components/common/DatePicker.jsx @@ -1,39 +1,71 @@ -import React, { useEffect, useRef } from "react"; +import { useEffect, useRef } from "react"; +import { useController } from "react-hook-form"; -const DatePicker = ({ onDateChange }) => { + +const DatePicker = ({ + name, + control, + placeholder = "DD-MM-YYYY", + className = "", + allowText = false, + maxDate=new Date(), + minDate, + ...rest +}) => { const inputRef = useRef(null); - useEffect(() => { - const fp = flatpickr(inputRef.current, { - dateFormat: "Y-m-d", - defaultDate: new Date(), - onChange: (selectedDates, dateStr) => { - if (onDateChange) { - onDateChange(dateStr); // Pass selected date to parent - } - } - }); + const { + field: { onChange, value, ref } + } = useController({ + name, + control + }); - return () => { - // Cleanup flatpickr instance - fp.destroy(); - }; - }, [onDateChange]); + useEffect(() => { + if (inputRef.current) { + flatpickr(inputRef.current, { + dateFormat: "d-m-Y", + allowInput: allowText, + defaultDate: value + ? flatpickr.parseDate(value, "Y-m-d") + : null, + maxDate:maxDate, + minDate:new Date(minDate?.split("T")[0]) ?? undefined, + onChange: function (selectedDates, dateStr) { + onChange(dateStr); + }, + ...rest + }); + } + }, [inputRef]); return ( -
-
- {/* */} - -
+
+ { + inputRef.current = el; + ref(el); + }} + readOnly={!allowText} + autoComplete="off" + /> + + { + if (inputRef.current && inputRef.current._flatpickr) { + inputRef.current._flatpickr.open(); + } + }} + > + +
); }; diff --git a/src/components/common/DateRangePicker.jsx b/src/components/common/DateRangePicker.jsx index e7239c53..1e95ef09 100644 --- a/src/components/common/DateRangePicker.jsx +++ b/src/components/common/DateRangePicker.jsx @@ -1,8 +1,10 @@ import React, { useEffect, useRef } from "react"; - +import { useController, useFormContext, useWatch } from "react-hook-form"; const DateRangePicker = ({ + md, + sm, onRangeChange, - DateDifference = 7, + DateDifference = 7, endDateMode = "yesterday", }) => { const inputRef = useRef(null); @@ -10,33 +12,34 @@ const DateRangePicker = ({ useEffect(() => { const endDate = new Date(); if (endDateMode === "yesterday") { - endDate.setDate(endDate.getDate() - 1); + endDate.setDate(endDate.getDate() - 1); } endDate.setHours(0, 0, 0, 0); - const startDate = new Date(endDate); + const startDate = new Date(endDate); startDate.setDate(endDate.getDate() - (DateDifference - 1)); startDate.setHours(0, 0, 0, 0); const fp = flatpickr(inputRef.current, { mode: "range", - dateFormat: "Y-m-d", - altInput: true, - altFormat: "d-m-Y", - defaultDate: [startDate, endDate], - static: true, + dateFormat: "Y-m-d", + altInput: true, + altFormat: "d-m-Y", + defaultDate: [startDate, endDate], + static: false, + // appendTo: document.body, clickOpens: true, - maxDate: endDate, // ✅ Disable future dates + maxDate: endDate, onChange: (selectedDates, dateStr) => { - const [startDateString, endDateString] = dateStr.split(" to "); + const [startDateString, endDateString] = dateStr.split(" To "); onRangeChange?.({ startDate: startDateString, endDate: endDateString }); }, }); onRangeChange?.({ - startDate: startDate.toLocaleDateString("en-CA"), - endDate: endDate.toLocaleDateString("en-CA"), + startDate: startDate.toLocaleDateString("en-CA"), + endDate: endDate.toLocaleDateString("en-CA"), }); return () => { @@ -45,14 +48,129 @@ const DateRangePicker = ({ }, [onRangeChange, DateDifference, endDateMode]); return ( - +
+ + + +
); }; export default DateRangePicker; + + + + + +export const DateRangePicker1 = ({ + startField = "startDate", + endField = "endDate", + placeholder = "Select date range", + className = "", + allowText = false, + resetSignal, // <- NEW prop + ...rest +}) => { + const inputRef = useRef(null); + const { control, setValue, getValues } = useFormContext(); + + const { + field: { ref }, + } = useController({ name: startField, control }); + + const applyDefaultDates = () => { + const today = new Date(); + const past = new Date(); + past.setDate(today.getDate() - 6); + + const format = (d) => flatpickr.formatDate(d, "d-m-Y"); + const formattedStart = format(past); + const formattedEnd = format(today); + + setValue(startField, formattedStart, { shouldValidate: true }); + setValue(endField, formattedEnd, { shouldValidate: true }); + + if (inputRef.current?._flatpickr) { + inputRef.current._flatpickr.setDate([past, today]); + } + }; + + useEffect(() => { + if (!inputRef.current || inputRef.current._flatpickr) return; + + const instance = flatpickr(inputRef.current, { + mode: "range", + dateFormat: "d-m-Y", + allowInput: allowText, + onChange: (selectedDates) => { + if (selectedDates.length === 2) { + const [start, end] = selectedDates; + const format = (d) => flatpickr.formatDate(d, "d-m-Y"); + setValue(startField, format(start), { shouldValidate: true }); + setValue(endField, format(end), { shouldValidate: true }); + } else { + setValue(startField, "", { shouldValidate: true }); + setValue(endField, "", { shouldValidate: true }); + } + }, + ...rest, + }); + + // Apply default if empty + const currentStart = getValues(startField); + const currentEnd = getValues(endField); + if (!currentStart && !currentEnd) { + applyDefaultDates(); + } else if (currentStart && currentEnd) { + instance.setDate([ + flatpickr.parseDate(currentStart, "d-m-Y"), + flatpickr.parseDate(currentEnd, "d-m-Y"), + ]); + } + + return () => instance.destroy(); + }, []); + + // Reapply default range on resetSignal change + useEffect(() => { + if (resetSignal !== undefined) { + applyDefaultDates(); + } + }, [resetSignal]); + + const start = getValues(startField); + const end = getValues(endField); + const formattedValue = start && end ? `${start} To ${end}` : ""; + + return ( +
+ { + inputRef.current = el; + ref(el); + }} + readOnly={!allowText} + autoComplete="off" + /> + inputRef.current?._flatpickr?.open()} + > + + +
+ ); +};