@@ -11,6 +11,7 @@ interface CalendarViewProps {
1111 currentDate : Date
1212 setCurrentDate : ( date : Date ) => void
1313 holidays : Holiday [ ]
14+ today : Date // Server-determined "today" to avoid hydration mismatch
1415}
1516
1617interface Holiday {
@@ -24,18 +25,25 @@ interface Holiday {
2425 leaveType : 'Full Day' | 'Morning' | 'Afternoon'
2526}
2627
27- export function CalendarView ( { currentDate, setCurrentDate, holidays } : CalendarViewProps ) {
28+ export function CalendarView ( { currentDate, setCurrentDate, holidays, today } : CalendarViewProps ) {
2829 const [ selectedDay , setSelectedDay ] = useState < Date | null > ( null )
2930
31+ // Helper to compare dates by their UTC year/month/day values
32+ const isSameUtcDay = ( a : Date , b : Date ) =>
33+ a . getUTCFullYear ( ) === b . getUTCFullYear ( ) &&
34+ a . getUTCMonth ( ) === b . getUTCMonth ( ) &&
35+ a . getUTCDate ( ) === b . getUTCDate ( )
36+
3037 const firstDayOfMonth =
31- ( new Date ( currentDate . getFullYear ( ) , currentDate . getMonth ( ) , 1 ) . getDay ( ) + 6 ) % 7
38+ ( new Date ( Date . UTC ( currentDate . getUTCFullYear ( ) , currentDate . getUTCMonth ( ) , 1 ) ) . getUTCDay ( ) + 6 ) % 7
3239
3340 const days = Array . from ( { length : 42 } , ( _ , i ) => {
3441 const day = new Date (
35- currentDate . getFullYear ( ) ,
36- currentDate . getMonth ( ) ,
37- i - firstDayOfMonth + 1 ,
38- currentDate . getHours ( ) ,
42+ Date . UTC (
43+ currentDate . getUTCFullYear ( ) ,
44+ currentDate . getUTCMonth ( ) ,
45+ i - firstDayOfMonth + 1 ,
46+ ) ,
3947 )
4048 const filteredHolidays = holidays . filter (
4149 ( h ) =>
@@ -44,28 +52,32 @@ export function CalendarView({ currentDate, setCurrentDate, holidays }: Calendar
4452 )
4553 return {
4654 date : day ,
47- isCurrentMonth : day . getMonth ( ) === currentDate . getMonth ( ) ,
48- isToday : day . toDateString ( ) === new Date ( ) . toDateString ( ) ,
55+ isCurrentMonth : day . getUTCMonth ( ) === currentDate . getUTCMonth ( ) ,
56+ isToday : isSameUtcDay ( day , today ) ,
4957 holidays : filteredHolidays ,
5058 }
5159 } )
5260
5361 const prevMonth = ( ) => {
54- setCurrentDate ( new Date ( currentDate . getFullYear ( ) , currentDate . getMonth ( ) - 1 , 1 ) )
62+ setCurrentDate ( new Date ( Date . UTC ( currentDate . getUTCFullYear ( ) , currentDate . getUTCMonth ( ) - 1 , 1 ) ) )
5563 }
5664 const nextMonth = ( ) => {
57- setCurrentDate ( new Date ( currentDate . getFullYear ( ) , currentDate . getMonth ( ) + 1 , 1 ) )
65+ setCurrentDate ( new Date ( Date . UTC ( currentDate . getUTCFullYear ( ) , currentDate . getUTCMonth ( ) + 1 , 1 ) ) )
5866 }
5967 const setToday = ( ) => {
60- setCurrentDate ( new Date ( ) )
68+ setCurrentDate ( TimeUtil . toUtcMidnight ( new Date ( ) ) )
6169 }
6270
71+ // Format month/year using UTC values to avoid hydration mismatch
72+ const months = [ 'January' , 'February' , 'March' , 'April' , 'May' , 'June' , 'July' , 'August' , 'September' , 'October' , 'November' , 'December' ]
73+ const monthYearDisplay = `${ months [ currentDate . getUTCMonth ( ) ] } ${ currentDate . getUTCFullYear ( ) } `
74+
6375 return (
6476 < div className = "lg:flex lg:h-full lg:flex-col" >
6577 < header className = "flex items-center justify-between border-b border-gray-200 px-6 py-4 lg:flex-none" >
6678 < h1 className = "text-base font-semibold text-foreground" >
6779 < time dateTime = { currentDate . toISOString ( ) } >
68- { currentDate . toLocaleString ( 'default' , { month : 'long' , year : 'numeric' } ) }
80+ { monthYearDisplay }
6981 </ time >
7082 </ h1 >
7183 < div className = "flex items-center" >
@@ -139,7 +151,7 @@ export function CalendarView({ currentDate, setCurrentDate, holidays }: Calendar
139151 day . isToday && 'bg-indigo-600 font-semibold text-white' ,
140152 ) }
141153 >
142- { day . date . getDate ( ) }
154+ { day . date . getUTCDate ( ) }
143155 </ time >
144156 { day . holidays . length > 0 && (
145157 < ol className = "mt-2 space-y-1 overflow-visible" >
@@ -189,7 +201,7 @@ export function CalendarView({ currentDate, setCurrentDate, holidays }: Calendar
189201 'flex h-6 w-6 items-center justify-center rounded-full bg-gray-900' ,
190202 ) }
191203 >
192- { day . date . getDate ( ) }
204+ { day . date . getUTCDate ( ) }
193205 </ time >
194206 < span className = "sr-only" > { day . holidays . length } holidays</ span >
195207 { day . holidays . length > 0 && (
0 commit comments