This component completely reusable component you can just copy and past it will be work and look like below images.
Here we need two files one is jsx file and one is css file both of the file given below.
DateRangePicker.jsx
import React, { useState, useEffect, useRef } from "react";
import DatePicker from "react-datepicker";
import { addDays, subDays, format, subMonths, isAfter, isBefore } from "date-fns";
// Import Css
import "react-datepicker/dist/react-datepicker.css";
import "./daterange.css";
const DateRangePicker = ({ onChange }) => {
const [startDate, setStartDate] = useState(null);
const [endDate, setEndDate] = useState(null);
const [dateType, setDateType] = useState("today");
const [showDatePicker, setShowDatePicker] = useState(false);
const [selectedRange, setSelectedRange] = useState(format(new Date(), "yyy-MM-dd"));
const [activeRange, setActiveRange] = useState("Today");
const [manualDate, setManualDate] = useState([
"Today",
"Yesterday",
"Last 7 Days",
"Last Month",
"Last 3 Month",
"Last Year",
"LifeTime"
]);
// Temporary state for handling date selection before confirmation
const [tempStartDate, setTempStartDate] = useState(new Date());
const [tempEndDate, setTempEndDate] = useState(null);
// Ref to the date picker container for detecting outside clicks
const datePickerRef = useRef(null);
const handleDateChange = (dates) => {
const [start, end] = dates;
setStartDate(format(start, "yyy-MM-dd"));
setEndDate(format(end, "yyy-MM-dd"));
setTempStartDate(start);
setTempEndDate(end);
setDateType("custom");
};
const handleConfirm = () => {
if (tempStartDate.getTime() === tempEndDate?.getTime()) {
setSelectedRange(format(tempStartDate, "yyy-MM-dd"));
} else {
setSelectedRange(`${format(tempStartDate, "yyy-MM-dd")} - ${format(tempEndDate, "yyy-MM-dd")}`);
}
setShowDatePicker(false);
onChange({ dateType: dateType, startDate: dateType === "custom"?"":startDate?.toString(), endDate: dateType === "custom"?"": endDate?.toString() });
};
console.log(startDate, endDate, dateType, "date");
const setCustomRange = (range) => {
const today = new Date();
let start, end;
switch (range) {
case "Today":
start = today;
end = today;
setDateType("today");
break;
case "Yesterday":
start = subDays(today, 1);
end = today;
setDateType("yesterday");
break;
case "Last 7 Days":
start = subDays(today, 6);
end = today;
setDateType("lastWeek");
break;
case "Last Month":
start = subMonths(today, 1);
end = today;
setDateType("lastMonth");
break;
case "Last 3 Month":
start = subMonths(today, 3);
end = today;
setDateType("lastTriMonth");
break;
case "Last Year":
start = subDays(today, 365);
end = today;
setDateType("lastYear");
break;
case "LifeTime":
start = new Date(2015, 0, 1);
end = today;
setDateType("overview");
break;
default:
break;
}
// Update the active range
setActiveRange(range);
// Set the range in temporary state without confirming
setStartDate(format(start, "yyy-MM-dd"));
setEndDate(format(end, "yyy-MM-dd"));
setTempStartDate(start);
setTempEndDate(end);
};
useEffect(() => {
const handleClickOutside = (event) => {
if (datePickerRef.current && !datePickerRef.current.contains(event.target)) {
setShowDatePicker(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);
return (
<div className="relative daterange">
<div className="relative w-full max-w-xs">
<input
type="text"
value={selectedRange}
placeholder="Select a date range"
onFocus={() => setShowDatePicker(true)}
readOnly
className="w-full max-w-xs p-2 border bg-white border-gray-50 rounded shadow-sm text-gray-600 text-sm font-semibold placeholder-gray-400 focus:outline-none focus:ring-1 focus:ring-offset-slate-100 cursor-pointer"
/>
<span className="absolute inset-y-0 right-2 flex items-center pointer-events-none">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M19 3h-2V1h-2v2H9V1H7v2H5c-1.1 0-1.99.9-1.99 2L3 19c0 1.1.89 2 1.99 2H19c1.1 0 1.99-.9 1.99-2L21 5c0-1.1-.89-2-1.99-2zM5 5h14v14H5V5z" />
</svg>
</span>
</div>
{showDatePicker && (
<div ref={datePickerRef} className="absolute right-0 flex bg-white rounded-lg shadow-md">
<div className="py-6 px-4 flex flex-col text-nowrap items-start gap-y-2 text-lg font-normal text-gray-800 shadow-md">
{manualDate.map((range) => (
<button key={range} className="flex items-center gap-x-1" onClick={() => setCustomRange(range)}>
<span className="relative inline-block w-5 h-5 rounded-full border border-gray-300 bg-white">
<span
className={`absolute inset-1 rounded-full ${activeRange === range ? "bg-[#F7E5BE]" : ""}`}
></span>
</span>
{range}
</button>
))}
</div>
<div className="pt-6 px-4">
<DatePicker
selected={tempStartDate}
onChange={handleDateChange}
startDate={tempStartDate}
endDate={tempEndDate}
selectsRange
inline
monthsShown={2}
maxDate={new Date()}
/>
<div className="flex justify-end items-center py-4">
{/* <div>
<h2 className="text-sm font-semibold text-gray-600">Selected Date: {selectedRange}</h2>
<p className="text-xs font-normal text-gray-400 capitalize">Dates are shown in Asia/Dhaka</p>
</div> */}
<button
onClick={handleConfirm}
class="px-3 py-1.5 bg-blue-500 rounded hover:bg-blue-600 text-xs font-semibold text-white uppercase"
>
Confirm
</button>
</div>
</div>
</div>
)}
</div>
);
};
export default DateRangePicker;
daterange.css
@import url("https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap");
.daterange .react-datepicker {
font-family: "Open Sans", serif;
display: flex;
border: none;
}
.daterange .react-datepicker__header {
background-color: transparent;
border: none;
}
.daterange .react-datepicker__navigation-icon:before {
color: rgb(31, 41, 55);
border-width: 2px 2px 0 0;
top: 12px;
}
.daterange .react-datepicker__current-month {
font-size: 16px;
line-height: 24px;
font-weight: 500;
color: #1f2937;
}
.daterange .react-datepicker__day-name {
font-size: 12px;
font-weight: 600;
color: rgb(156 163 175);
padding-bottom: 6px;
}
.daterange .react-datepicker__day {
font-size: 12px;
font-weight: 500;
color: #1f2937;
}
.daterange .react-datepicker__day--disabled {
color: rgb(156 163 175);
cursor: not-allowed;
}
.react-datepicker__day--in-range,
.react-datepicker__day--in-selecting-range:not(
.react-datepicker__day--in-range,
.react-datepicker__month-text--in-range,
.react-datepicker__quarter-text--in-range,
.react-datepicker__year-text--in-range
),
.react-datepicker__month-text--in-selecting-range:not(
.react-datepicker__day--in-range,
.react-datepicker__month-text--in-range,
.react-datepicker__quarter-text--in-range,
.react-datepicker__year-text--in-range
),
.react-datepicker__quarter-text--in-selecting-range:not(
.react-datepicker__day--in-range,
.react-datepicker__month-text--in-range,
.react-datepicker__quarter-text--in-range,
.react-datepicker__year-text--in-range
),
.react-datepicker__year-text--in-selecting-range:not(
.react-datepicker__day--in-range,
.react-datepicker__month-text--in-range,
.react-datepicker__quarter-text--in-range,
.react-datepicker__year-text--in-range
),
.react-datepicker__day-selected,
.react-datepicker__day--keyboard-selected,
.react-datepicker__day--keyboard-selected:not([aria-disabled="true"]):hover,
.react-datepicker__day--in-range:not([aria-disabled="true"]):hover,
.react-datepicker__day--selected:not([aria-disabled="true"]):hover,
.react-datepicker__day--in-selecting-range:not([aria-disabled="true"]):hover {
background-color: #f7e5be;
border-radius: 4px;
}
Top comments (0)