import { Box, Button, Divider, Typography } from "@mui/material"; import { DateCalendar, PickersDay, PickersDayProps } from "@mui/x-date-pickers"; import { useContext, useEffect, useState } from "react"; import EthiopianDateCalendar from "./EthiopianDateCalendar"; import { EtDatePickerContext } from "../EtDatePickerContext"; import React from "react"; import { styled } from "@mui/material/styles"; import { EthiopianDate } from "../util/EthiopianDateUtils"; interface CustomPickerDayProps extends PickersDayProps { isRangeStart?: boolean; isRangeEnd?: boolean; inRange?: boolean; } // Styled component for the date range const StyledDay = styled(PickersDay as React.ComponentType>)(({ theme, isRangeStart, isRangeEnd, inRange }) => ({ ...(inRange && { backgroundColor: theme.palette.action.selected, // A light background for dates within the range borderRadius: 0, // Make it a rectangle for continuous range }), ...(isRangeStart && { backgroundColor: theme.palette.primary.main, color: theme.palette.primary.contrastText, borderTopLeftRadius: '50%', // Round corners for start of range borderBottomLeftRadius: '50%', }), ...(isRangeEnd && { backgroundColor: theme.palette.primary.main, color: theme.palette.primary.contrastText, borderTopRightRadius: '50%', // Round corners for end of range borderBottomRightRadius: '50%', }), // Override default PickersDay styles if needed '&:hover': { backgroundColor: isRangeStart || isRangeEnd ? theme.palette.primary.dark : inRange ? theme.palette.action.hover : undefined, }, })); const EtGrDateCalendar = () => { const etDatePickerContext = useContext(EtDatePickerContext); const { onDateChange, disableFuture, disablePast, minDate, maxDate, onMonthChange, gregDate, setGregDate, dateType, isRange, startDate, endDate, } = etDatePickerContext; const [gregDatePicker, setGregDatePicker] = useState(gregDate || null); const [hoveredDate, setHoveredDate] = useState(null); const [startMonth, setStartMonth] = useState(startDate || gregDate || new Date()); const [endMonth, setEndMonth] = useState(startDate ? new Date(startDate.getFullYear(), startDate.getMonth() + 1, 1) : gregDate ? new Date(gregDate.getFullYear(), gregDate.getMonth() + 1, 1) : new Date(new Date().getFullYear(), new Date().getMonth() + 1, 1)); useEffect(() => { if (isRange && startDate) { setStartMonth(startDate); setEndMonth(new Date(startDate.getFullYear(), startDate.getMonth() + 1, 1)); } else if (!isRange) { setGregDatePicker(gregDate || null); } }, [isRange, startDate, gregDate]); const handleTodayButtonClick = () => { if (isRange) { onDateChange([new Date(), null]); } else { onDateChange(new Date()); } }; const showEthiopianCalendar = dateType !== "GC"; const showGregorianCalendar = dateType === "GC"; return ( {isRange ? ( // Range mode: Display two calendars (dateType === "EC" || dateType === "AO" || dateType === "CUSTOM") ? ( // Ethiopian/Afan Oromo range pickers <> Start Date End Date ) : ( // Gregorian range pickers (dateType === "GC") <> Start Date monthsPerRow={3} value={startDate} onChange={(date) => { if (date) { if (!startDate || (startDate && endDate)) { etDatePickerContext.onDateChange([date, null]); } else if (date.getTime() < startDate.getTime()) { etDatePickerContext.onDateChange([date, startDate]); } else { etDatePickerContext.onDateChange([startDate, date]); } setHoveredDate(null); // Clear hovered date on selection } }} disableFuture={disableFuture} onMonthChange={(date) => { setStartMonth(date); setHoveredDate(null); // Clear hovered date on month change }} disablePast={disablePast} minDate={minDate} maxDate={maxDate} slots={{ day: StyledDay as React.ComponentType> }} slotProps={{ day: (ownerState: any) => { const isRangeStart = startDate && ownerState.day.getTime() === startDate.getTime(); const isRangeEnd = endDate && ownerState.day.getTime() === endDate.getTime(); const isInRange = ( startDate && ( (endDate && ownerState.day.getTime() > Math.min(startDate.getTime(), endDate.getTime()) && ownerState.day.getTime() < Math.max(startDate.getTime(), endDate.getTime())) || (!endDate && hoveredDate && ownerState.day.getTime() > Math.min(startDate.getTime(), hoveredDate.getTime()) && ownerState.day.getTime() < Math.max(startDate.getTime(), hoveredDate.getTime())) ) ); return { ...ownerState, isRangeStart: isRangeStart, isRangeEnd: isRangeEnd, inRange: isInRange, onMouseEnter: () => { if (isRange && startDate && !endDate) { setHoveredDate(ownerState.day); } }, onMouseLeave: () => { if (isRange && startDate && !endDate) { setHoveredDate(null); } }, }; }, }} openTo="day" views={['month', 'year', 'day']} /> End Date monthsPerRow={3} value={endDate || endMonth} onChange={(date) => { if (date) { if (!startDate || (startDate && endDate)) { etDatePickerContext.onDateChange([date, null]); } else if (date.getTime() < startDate.getTime()) { etDatePickerContext.onDateChange([date, startDate]); } else { etDatePickerContext.onDateChange([startDate, date]); } setHoveredDate(null); // Clear hovered date on selection } }} disableFuture={disableFuture} onMonthChange={(date) => { setEndMonth(date); setHoveredDate(null); // Clear hovered date on month change }} disablePast={disablePast} minDate={minDate} maxDate={maxDate} slots={{ day: StyledDay as React.ComponentType> }} slotProps={{ day: (ownerState: any) => { const isRangeStart = startDate && ownerState.day.getTime() === startDate.getTime(); const isRangeEnd = endDate && ownerState.day.getTime() === endDate.getTime(); const isInRange = ( startDate && ( (endDate && ownerState.day.getTime() > Math.min(startDate.getTime(), endDate.getTime()) && ownerState.day.getTime() < Math.max(startDate.getTime(), endDate.getTime())) || (!endDate && hoveredDate && ownerState.day.getTime() > Math.min(startDate.getTime(), hoveredDate.getTime()) && ownerState.day.getTime() < Math.max(startDate.getTime(), hoveredDate.getTime())) ) ); return { ...ownerState, isRangeStart: isRangeStart, isRangeEnd: isRangeEnd, inRange: isInRange, onMouseEnter: () => { if (isRange && startDate && !endDate) { setHoveredDate(ownerState.day); } }, onMouseLeave: () => { if (isRange && startDate && !endDate) { setHoveredDate(null); } }, }; }, }} openTo="day" views={['month', 'year', 'day']} /> ) ) : ( // Single date mode <> {showEthiopianCalendar && ( )} {showEthiopianCalendar && showGregorianCalendar && ( )} {showGregorianCalendar && ( monthsPerRow={3} value={gregDatePicker} onChange={(date) => { if (date) { onDateChange(date); } }} disableFuture={disableFuture} onMonthChange={(date) => { const newDate = new Date(date); newDate.setDate(gregDate?.getDate() ?? 15); onMonthChange(newDate); setGregDate(newDate); }} disablePast={disablePast} minDate={minDate} maxDate={maxDate} slots={{ day: StyledDay as React.ComponentType> }} slotProps={{ day: (ownerState: any) => ({ ...ownerState, isRangeStart: isRange && startDate && ownerState.day.getTime() === startDate.getTime(), isRangeEnd: isRange && endDate && ownerState.day.getTime() === endDate.getTime(), inRange: isRange && startDate && endDate && ownerState.day.getTime() > startDate.getTime() && ownerState.day.getTime() < endDate.getTime(), }), }} openTo="day" views={['month', 'year', 'day']} /> )} )} {/* Hide Today button if it is a range selection */} {!isRange && ( )} ); }; export default EtGrDateCalendar;