lightswind
Version:
A modern frontend library with pre-built Tailwind CSS components for building responsive and interactive user interfaces.
161 lines (144 loc) • 7.61 kB
JSX
import React, { useState, useEffect } from "react";
const DatePicker = () => {
const [currentDate, setCurrentDate] = useState(new Date());
const [selectedDate, setSelectedDate] = useState("");
const [isDatePickerOpen, setIsDatePickerOpen] = useState(false);
const [darkMode, setDarkMode] = useState(false); // Toggle between dark and light themes
const daysInMonth = (month, year) => new Date(year, month + 1, 0).getDate();
const firstDayOfMonth = (month, year) => new Date(year, month, 1).getDay();
const renderCalendar = () => {
const month = currentDate.getMonth();
const year = currentDate.getFullYear();
const firstDay = firstDayOfMonth(month, year);
const totalDays = daysInMonth(month, year);
const calendarCells = [];
for (let i = 0; i < firstDay; i++) {
calendarCells.push(<div key={"empty-" + i} />);
}
for (let day = 1; day <= totalDays; day++) {
calendarCells.push(
<div
key={day}
className={
"cursor-pointer flex items-center justify-center w-10 h-10 rounded-full transition-all " +
(darkMode
? "hover:bg-gray-700 text-gray-300 hover:text-gray-100"
: "hover:bg-blue-500 text-gray-700 hover:text-white")
}
onClick={() => handleDateSelect(day, month, year)}
>
{day}
</div>
);
}
return calendarCells;
};
const handleDateSelect = (day, month, year) => {
const date = new Date(year, month, day).toLocaleDateString();
setSelectedDate(date);
setIsDatePickerOpen(false);
};
const handlePrevMonth = () => {
setCurrentDate((prev) => new Date(prev.getFullYear(), prev.getMonth() - 1, 1));
};
const handleNextMonth = () => {
setCurrentDate((prev) => new Date(prev.getFullYear(), prev.getMonth() + 1, 1));
};
useEffect(() => {
const closeDatePicker = (e) => {
if (!e.target.closest(".datepicker-wrapper")) {
setIsDatePickerOpen(false);
}
};
window.addEventListener("click", closeDatePicker);
return () => {
window.removeEventListener("click", closeDatePicker);
};
}, []);
return (
<div
className=" min-h-screen flex justify-center items-center font-primarylw">
<div className="absolute top-4 right-4">
</div>
<div className="relative datepicker-wrapper w-full max-w-sm">
<input
type="text"
value={selectedDate}
onClick={() => setIsDatePickerOpen((prev) => !prev)}
readOnly
placeholder="Select Date"
className={
"w-full px-4 py-3 pl-10 pr-12 border rounded-lg shadow-sm focus:outline-none focus:ring-2 " +
(darkMode
? "bg-gray-800 border-gray-600 text-gray-300 focus:ring-gray-500"
: "bg-white border-gray-300 text-gray-900 focus:ring-blue-500")
}
/>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
className={
"absolute right-3 top-1/2 transform -translate-y-1/2 w-6 h-6 " +
(darkMode ? "text-gray-400" : "text-gray-500")
}
>
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 2.994v2.25m10.5-2.25v2.25m-14.252 13.5V7.491a2.25 2.25 0 0 1 2.25-2.25h13.5a2.25 2.25 0 0 1 2.25 2.25v11.251m-18 0a2.25 2.25 0 0 0 2.25 2.25h13.5a2.25 2.25 0 0 0 2.25-2.25m-18 0v-7.5a2.25 2.25 0 0 1 2.25-2.25h13.5a2.25 2.25 0 0 1 2.25 2.25v7.5m-6.75-6h2.25m-9 2.25h4.5m.002-2.25h.005v.006H12v-.006Zm-.001 4.5h.006v.006h-.006v-.005Zm-2.25.001h.005v.006H9.75v-.006Zm-2.25 0h.005v.005h-.006v-.005Zm6.75-2.247h.005v.005h-.005v-.005Zm0 2.247h.006v.006h-.006v-.006Zm2.25-2.248h.006V15H16.5v-.005Z" />
</svg>
{isDatePickerOpen && (
<div
className={
"absolute datepicker p-4 mt-2 rounded-lg shadow-lg border " +
(darkMode
? "bg-gray-800 border-gray-600 text-gray-300"
: "bg-white border-gray-300 text-gray-900")
}
>
<div className="flex justify-between items-center mb-3">
<button
className={
"text-sm transition " +
(darkMode
? "text-gray-400 hover:text-gray-200"
: "text-gray-600 hover:text-gray-800")
}
onClick={handlePrevMonth}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
<path stroke-linecap="round" stroke-linejoin="round" d="m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5" />
</svg>
</button>
<div className="font-semibold text-lg">
{currentDate.toLocaleString("default", { month: "long" })} {currentDate.getFullYear()}
</div>
<button
className={
"text-sm transition " +
(darkMode ? "text-gray-400 hover:text-gray-200" : "text-gray-600 hover:text-gray-800")
}
onClick={handleNextMonth}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
<path stroke-linecap="round" stroke-linejoin="round" d="m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5" />
</svg>
</button>
</div>
<div className="grid grid-cols-7 gap-2 text-center text-sm font-medium">
<div>Sun</div>
<div>Mon</div>
<div>Tue</div>
<div>Wed</div>
<div>Thu</div>
<div>Fri</div>
<div>Sat</div>
</div>
<div className="grid grid-cols-7 gap-2 mt-2">{renderCalendar()}</div>
</div>
)}
</div>
</div >
);
};
export default DatePicker;