CalendarPicker
CalendarPicker.tsx
import React, { useState } from 'react';
import styles from './CalendarPicker.module.css';
interface CalendarPickerProps {
selectedDate: Date;
onDateSelect: (date: Date) => void;
}
const CalendarPicker = ({ selectedDate, onDateSelect }: CalendarPickerProps) => {
const [currentMonth, setCurrentMonth] = useState<number>(selectedDate.getMonth());
const [currentYear, setCurrentYear] = useState<number>(selectedDate.getFullYear());
const handlePrevMonth = () => {
setCurrentMonth((prevMonth) => (prevMonth === 0 ? 11 : prevMonth - 1));
setCurrentYear((prevYear) => (currentMonth === 0 ? prevYear - 1 : prevYear));
};
const handleNextMonth = () => {
setCurrentMonth((prevMonth) => (prevMonth === 11 ? 0 : prevMonth + 1));
setCurrentYear((prevYear) => (currentMonth === 11 ? prevYear + 1 : prevYear));
};
const handleDateClick = (day: number) => {
const selectedDate = new Date(currentYear, currentMonth, day);
onDateSelect(selectedDate);
};
const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();
const firstDayOfMonth = new Date(currentYear, currentMonth, 1).getDay();
const daysBeforeFirst = Array.from({ length: firstDayOfMonth }, (_, i) => i);
const daysAfterLast = Array.from({ length: 6 - new Date(currentYear, currentMonth, daysInMonth).getDay() }, (_, i) => daysInMonth + i);
const days = [...daysBeforeFirst, ...Array.from({ length: daysInMonth }, (_, i) => i + 1), ...daysAfterLast];
return (
<div className={styles.calendarPicker}>
<div className={styles.header}>
<button className={styles.button} onClick={handlePrevMonth}>
<
</button>
<h2 className={styles.month}>{new Date(currentYear, currentMonth).toLocaleString('default', { month: 'long' })}</h2>
<button className={styles.button} onClick={handleNextMonth}>
>
</button>
</div>
<div className={styles.days}>
<div className={styles.day}>Sun</div>
<div className={styles.day}>Mon</div>
<div className={styles.day}>Tue</div>
<div className={styles.day}>Wed</div>
<div className={styles.day}>Thu</div>
<div className={styles.day}>Fri</div>
<div className={styles.day}>Sat</div>
</div>
<div className={styles.grid}>
{days.map((day) =>
day > daysBeforeFirst.length && day <= daysInMonth + daysBeforeFirst.length ? (
<div
key={day}
className={day === selectedDate.getDate() && currentMonth === selectedDate.getMonth() && currentYear === selectedDate.getFullYear() ? styles.activeDay : styles.day}
onClick={() => handleDateClick(day)}
>
{day - daysBeforeFirst.length}
</div>
) : (
<div key={day} className={styles.emptyDay} />
)
)}
</div>
</div>
);
};
export default CalendarPicker;
CalendarPicker.module.css
.calendarPicker {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-family: Arial, sans-serif;
padding: 16px;
}
.header {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 16px;
}
.month {
margin: 0 16px;
font-size: 24px;
}
.button {
border: none;
background: none;
font-size: 24px;
cursor: pointer;
transition: transform 0.2s;
outline: none;
padding: 0;
margin: 0;
}
.button:hover {
transform: scale(1.1);
}
.days {
display: flex;
justify-content: space-around;
margin-bottom: 16px;
}
.day {
font-size: 18px;
font-weight: bold;
text-align: center;
width: 24px;
height: 24px;
line-height: 24px;
border-radius: 50%;
cursor: pointer;
transition: background-color 0.2s;
}
.activeDay {
background-color: #0077cc;
color: #fff;
}
.day:hover {
background-color: #f2f2f2;
}
.emptyDay {
width: 24px;
height: 24px;
}