import React, {FC, useEffect} from "react"; import DatePicker, {CalendarContainerProps} from "react-datepicker"; import classNames from "classnames"; import dayjs from "dayjs"; import customParseFormat from "dayjs/plugin/customParseFormat"; dayjs.extend(customParseFormat); export type CalendarProps = { source: string, onChange: (date: string) => void, size?: 'normal' | 'small' } /** * Works with dates in the format: Y-m-d H:i:s */ export const Calendar: FC = ({source, onChange, size = 'normal'}) => { const parseYmdHisDate = (dateString: string): { date: Date, isValid: boolean } => { if (!dateString) return {date: dayjs().startOf('day').toDate(), isValid: false}; const parsed = dayjs(dateString, ['YYYY-MM-DD HH:mm:ss', 'YYYY-MM-DD HH:mm', 'YYYY-MM-DD'], true); if (parsed.isValid()) { return {date: parsed.toDate(), isValid: true}; } return {date: dayjs().startOf('day').toDate(), isValid: false}; }; const formatToYmdHis = (date: Date): string => { return dayjs(date).format('YYYY-MM-DD HH:mm:ss'); }; const {date: selectedDate, isValid: isValidSourceDate} = parseYmdHisDate(source); useEffect(() => { if (!isValidSourceDate) { onChange(formatToYmdHis(selectedDate)); } }, [isValidSourceDate, source]); // Calculate min/max dates dynamically based on the source date const getDateRange = () => { const sourceDate = dayjs(selectedDate); const currentDate = dayjs(); // Use the earlier date between source and current as the base const baseDate = sourceDate.isBefore(currentDate) ? sourceDate : currentDate; return { minDate: baseDate.subtract(12, 'month').toDate(), maxDate: currentDate.add(12, 'month').toDate() }; }; const { minDate, maxDate } = getDateRange(); const handleDateChange = (date: Date | null) => { if (date) { const formattedDate = formatToYmdHis(date); onChange(formattedDate); } }; return (
classNames("hover:bg-gray-150 !box-content hover:text-gray-600 rounded-1 text-gray-500", { '!bg-blue-normal !text-blue-20': (() => { // noinspection UnnecessaryLocalVariableJS const isSameDay = date.getDate() === selectedDate.getDate() && date.getMonth() === selectedDate.getMonth() && date.getFullYear() === selectedDate.getFullYear(); return isSameDay; })(), 'p-[4px]': size === 'normal', '!m-0 p-px text-smaller-1': size === 'small', })} weekDayClassName={() => "!text-gray-300 !font-regular !text-smaller-1 !uppercase"} monthClassName={() => "bg-white font-medium"} />
) }