"use client"; import { useState, useMemo } from 'react'; interface RecordDatePickerProps { value: string | null; dailyCounts: Record; onChange: (date: string) => void; } export default function RecordDatePicker({ value, dailyCounts, onChange }: RecordDatePickerProps) { const today = new Date(); const initialDate = value ? new Date(value) : today; const [currentYear, setCurrentYear] = useState(initialDate.getFullYear()); const [currentMonth, setCurrentMonth] = useState(initialDate.getMonth()); const weekDays = ['日', '一', '二', '三', '四', '五', '六']; const calendarDays = useMemo(() => { const year = currentYear; const month = currentMonth; const firstDayOfMonth = new Date(year, month, 1); const lastDayOfMonth = new Date(year, month + 1, 0); const daysInMonth = lastDayOfMonth.getDate(); const startDayIndex = firstDayOfMonth.getDay(); const totalCells = Math.ceil((startDayIndex + daysInMonth) / 7) * 7; const days = []; const startDate = new Date(year, month, 1 - startDayIndex); for (let i = 0; i < totalCells; i++) { const date = new Date(startDate); date.setDate(startDate.getDate() + i); const dateString = `${date.getFullYear()}-${(date.getMonth() + 1) .toString() .padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`; days.push({ date, day: date.getDate(), isCurrentMonth: date.getMonth() === month, dateString, count: dailyCounts[dateString] || 0 }); } return days; }, [currentYear, currentMonth, dailyCounts]); const maxCount = useMemo(() => { let max = 0; calendarDays.forEach((day) => { if (day.count > max) { max = day.count; } }); return max; }, [calendarDays]); const selectDay = (day: { date: Date; dateString: string; isCurrentMonth: boolean }) => { if (!day.isCurrentMonth) { setCurrentYear(day.date.getFullYear()); setCurrentMonth(day.date.getMonth()); } onChange(day.dateString); }; const getDayStyle = (day: { dateString: string; count: number }) => { const styles: React.CSSProperties = {}; if (value === day.dateString) { styles.outline = '2px solid #2563EB'; } if (day.count > 0) { const ratio = maxCount > 0 ? day.count / maxCount : 0; const opacity = 0.3 + ratio * 0.7; styles.backgroundColor = `rgba(16, 185, 129, ${opacity})`; styles.color = opacity > 0.6 ? 'white' : 'black'; } else { styles.backgroundColor = 'transparent'; styles.color = 'inherit'; } return styles; }; const prevMonth = () => { if (currentMonth === 0) { setCurrentYear(currentYear - 1); setCurrentMonth(11); } else { setCurrentMonth(currentMonth - 1); } }; const nextMonth = () => { if (currentMonth === 11) { setCurrentYear(currentYear + 1); setCurrentMonth(0); } else { setCurrentMonth(currentMonth + 1); } }; return (
{/* 月份切换头部 */}
{currentYear} - {(currentMonth + 1).toString().padStart(2, '0')}
{/* 星期标题 */}
{weekDays.map((day) => (
{day}
))}
{/* 日历网格 */}
{calendarDays.map((day, index) => (
selectDay(day)} >
{day.day}
))}
); }