@@ -200,12 +200,14 @@ interface EventsCalendarProps {
200200 onReloadEvents : ( ) => void
201201}
202202
203+ type ScheduleType = 'my' | 'team'
204+
203205const EventsCalendar : React . FC < EventsCalendarProps > = ( {
204206 newEvents,
205207 onReloadEvents,
206208} ) => {
207209 const isSmallScreen = useIsSmallScreen ( )
208- const [ scheduleType , setScheduleType ] = useState < 'my' | 'team' > ( 'my' )
210+ const [ scheduleType , setScheduleType ] = useState < ScheduleType > ( 'my' )
209211 const [ hideWeekends , setHideWeekends ] = useState ( false )
210212 const [ rawEvents , setRawEvents ] = useState < CheckInType [ ] > ( [ ] )
211213 const [ currentDate , setCurrentDate ] = useState ( new Date ( ) )
@@ -239,6 +241,8 @@ const EventsCalendar: React.FC<EventsCalendarProps> = ({
239241 useEffect ( ( ) => {
240242 const fetchEvents = async ( ) => {
241243 setLoading ( true )
244+ setError ( '' )
245+
242246 try {
243247 const data =
244248 scheduleType === 'my' && assigneeId
@@ -247,6 +251,7 @@ const EventsCalendar: React.FC<EventsCalendarProps> = ({
247251 setRawEvents ( data )
248252 } catch ( err ) {
249253 console . error ( 'Failed to fetch events:' , err )
254+ setError ( 'Error loading events' )
250255 } finally {
251256 setLoading ( false )
252257 }
@@ -258,7 +263,7 @@ const EventsCalendar: React.FC<EventsCalendarProps> = ({
258263
259264 setReloadEvents ( false )
260265 onReloadEvents ( )
261- } , [ scheduleType , assigneeId , reloadEvents , newEvents ] )
266+ } , [ scheduleType , assigneeId , reloadEvents , newEvents , onReloadEvents ] )
262267
263268 const events = useMemo ( ( ) => {
264269 if ( ! rawEvents ) return [ ]
@@ -278,10 +283,6 @@ const EventsCalendar: React.FC<EventsCalendarProps> = ({
278283 } ) )
279284 } , [ rawEvents ] )
280285
281- if ( loading ) return < div className = "p-4" > Loading calendar...</ div >
282- if ( error )
283- return < div className = "p-4 text-red-500" > Error loading events</ div >
284-
285286 const CustomToolbar = ( toolbar : any ) => {
286287 const goToBack = ( ) => {
287288 toolbar . onNavigate ( 'PREV' )
@@ -385,7 +386,11 @@ const EventsCalendar: React.FC<EventsCalendarProps> = ({
385386 { /* Toggle - row below title on screens smaller than lg, same width at all breakpoints */ }
386387 < div className = "relative inline-flex w-fit items-center justify-start self-start rounded-[20px] bg-zinc-200 p-1 lg:self-center" >
387388 < div
388- className = { `absolute transition-all duration-300 ease-in-out ${ scheduleType === 'my' ? 'left-1' : 'left-[calc(100%-50%-4px)]' } h-[calc(100%-8px)] w-[calc(50%-4px)] rounded-[16px] bg-black` }
389+ className = { `absolute inset-y-1 left-1 w-[calc(50%-4px)] rounded-[16px] bg-black transition-transform duration-300 ease-out ${
390+ scheduleType === 'team'
391+ ? 'translate-x-full'
392+ : 'translate-x-0'
393+ } `}
389394 />
390395 < button
391396 onClick = { ( ) => setScheduleType ( 'my' ) }
@@ -413,43 +418,68 @@ const EventsCalendar: React.FC<EventsCalendarProps> = ({
413418 </ div >
414419
415420 { /* Calendar */ }
416- < div className = "h-[calc(100vh-12rem)] min-h-[400px] overflow-hidden [&_.rbc-header]:border-b-0 [&_.rbc-header]:bg-gray-50 [&_.rbc-header]:py-3 [&_.rbc-header]:font-medium [&_.rbc-time-content]:border-t [&_.rbc-time-content]:border-gray-200 [&_.rbc-time-gutter_.rbc-timeslot-group]:border-r [&_.rbc-time-header]:border-gray-200 [&_.rbc-timeslot-group]:border-gray-200" >
417- < Calendar < any >
418- localizer = { localizer }
419- events = { events }
420- view = { hideWeekends ? Views . WORK_WEEK : Views . WEEK }
421- defaultView = { Views . WEEK }
422- views = { {
423- week : ( isSmallScreen ? ThreeDayView : true ) as any ,
424- work_week : ( isSmallScreen
425- ? ThreeDayWorkWeekView
426- : true ) as any ,
427- } }
428- date = { currentDate }
429- onNavigate = { ( date ) => setCurrentDate ( date ) }
430- startAccessor = "start"
431- endAccessor = "end"
432- style = { { height : '100%' } }
433- className = "[&_.rbc-event-label]:hidden [&_.rbc-timeslot-group]:!min-h-[100px]"
434- timeslots = { 1 }
435- step = { 60 }
436- defaultDate = { new Date ( ) }
437- scrollToTime = { scrollTime }
438- tooltipAccessor = "location"
439- onSelectEvent = { ( event ) => setSelectedEvent ( event ) }
440- components = { {
441- toolbar : CustomToolbar ,
442- event : CustomEvent ,
443- } }
444- eventPropGetter = { ( event ) => ( {
445- className : 'rounded-md border-none bg-background' ,
446- style : {
447- backgroundColor : event . assigneeId
448- ? getUserColor ( event . assigneeId )
449- : '#4EA0C9' ,
450- } ,
451- } ) }
452- />
421+ < div className = "relative h-[calc(100vh-12rem)] min-h-[400px] overflow-hidden [&_.rbc-header]:border-b-0 [&_.rbc-header]:bg-gray-50 [&_.rbc-header]:py-3 [&_.rbc-header]:font-medium [&_.rbc-time-content]:border-t [&_.rbc-time-content]:border-gray-200 [&_.rbc-time-gutter_.rbc-timeslot-group]:border-r [&_.rbc-time-header]:border-gray-200 [&_.rbc-timeslot-group]:border-gray-200" >
422+ { error ? (
423+ < div className = "flex h-full items-center justify-center rounded-xl border border-red-200 bg-red-50 px-4 text-red-600" >
424+ { error }
425+ </ div >
426+ ) : (
427+ < >
428+ < div
429+ className = { `h-full transition-opacity duration-200 ${
430+ loading ? 'pointer-events-none opacity-40' : ''
431+ } `}
432+ >
433+ < Calendar < any >
434+ localizer = { localizer }
435+ events = { events }
436+ view = { hideWeekends ? Views . WORK_WEEK : Views . WEEK }
437+ defaultView = { Views . WEEK }
438+ views = { {
439+ week : ( isSmallScreen
440+ ? ThreeDayView
441+ : true ) as any ,
442+ work_week : ( isSmallScreen
443+ ? ThreeDayWorkWeekView
444+ : true ) as any ,
445+ } }
446+ date = { currentDate }
447+ onNavigate = { ( date ) => setCurrentDate ( date ) }
448+ startAccessor = "start"
449+ endAccessor = "end"
450+ style = { { height : '100%' } }
451+ className = "[&_.rbc-event-label]:hidden [&_.rbc-timeslot-group]:!min-h-[100px]"
452+ timeslots = { 1 }
453+ step = { 60 }
454+ defaultDate = { new Date ( ) }
455+ scrollToTime = { scrollTime }
456+ tooltipAccessor = "location"
457+ onSelectEvent = { ( event ) => setSelectedEvent ( event ) }
458+ components = { {
459+ toolbar : CustomToolbar ,
460+ event : CustomEvent ,
461+ } }
462+ eventPropGetter = { ( event ) => ( {
463+ className : 'rounded-md border-none bg-background' ,
464+ style : {
465+ backgroundColor : event . assigneeId
466+ ? getUserColor ( event . assigneeId )
467+ : '#4EA0C9' ,
468+ } ,
469+ } ) }
470+ />
471+ </ div >
472+
473+ { loading && (
474+ < div className = "absolute inset-0 z-10 flex items-center justify-center bg-background/70 backdrop-blur-[1px]" >
475+ < div className = "flex items-center gap-3 rounded-full border border-border bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm" >
476+ < span className = "h-4 w-4 animate-spin rounded-full border-2 border-foreground/20 border-t-foreground" />
477+ Loading calendar...
478+ </ div >
479+ </ div >
480+ ) }
481+ </ >
482+ ) }
453483 </ div >
454484
455485 < EditScheduledCheckIn
0 commit comments