@@ -47,6 +47,8 @@ export default function EventCarousel({ items }: EventCarouselProps) {
4747 const [ visibleCount , setVisibleCount ] = useState ( 3 ) ;
4848 const [ itemWidth , setItemWidth ] = useState ( 0 ) ;
4949
50+ const isEmpty = items . length === 0 ;
51+
5052 const maxIndex = Math . max ( items . length - visibleCount , 0 ) ;
5153 const slideLeft = ( ) => {
5254 setCurrentIndex ( ( prev ) => Math . max ( prev - 1 , 0 ) ) ;
@@ -56,16 +58,21 @@ export default function EventCarousel({ items }: EventCarouselProps) {
5658 } ;
5759 const translateX = - ( currentIndex * ( itemWidth + GAP ) ) ;
5860
59- /* Observe item width */
61+ /* Observe item width – re-run when items change so we measure after first item mounts */
6062 useEffect ( ( ) => {
61- if ( ! firstItemRef . current ) return ;
62- const observer = new ResizeObserver ( ( ) => {
63- const width = firstItemRef . current ?. clientWidth ?? 0 ;
64- setItemWidth ( width ) ;
65- } ) ;
66- observer . observe ( firstItemRef . current ) ;
63+ const el = firstItemRef . current ;
64+ if ( ! el || items . length === 0 ) return ;
65+ const readWidth = ( ) => {
66+ requestAnimationFrame ( ( ) => {
67+ const w = firstItemRef . current ?. clientWidth ?? 0 ;
68+ setItemWidth ( w ) ;
69+ } ) ;
70+ } ;
71+ readWidth ( ) ;
72+ const observer = new ResizeObserver ( readWidth ) ;
73+ observer . observe ( el ) ;
6774 return ( ) => observer . disconnect ( ) ;
68- } , [ ] ) ;
75+ } , [ items . length ] ) ;
6976
7077 useEffect ( ( ) => {
7178 const updateVisibleCount = ( ) => {
@@ -87,28 +94,35 @@ export default function EventCarousel({ items }: EventCarouselProps) {
8794 < h2 className = "font-jersey10 text-4xl tracking-wide text-white" >
8895 Upcoming Events
8996 </ h2 >
90-
91- < div className = "ml-5 flex gap-3 text-lg text-white/60" >
92- < ChevronLeft
93- className = { `hover:text-white ${
94- currentIndex === 0 ? "opacity-40" : "cursor-pointer"
95- } `}
96- onClick = { slideLeft }
97- />
98- < ChevronRight
99- className = { `hover:text-white ${
100- currentIndex === maxIndex ? "opacity-40" : "cursor-pointer"
101- } `}
102- onClick = { slideRight }
103- />
104- </ div >
97+ { ! isEmpty && (
98+ < div className = "ml-5 flex gap-3 text-lg text-white/60" >
99+ < ChevronLeft
100+ className = { `hover:text-white ${
101+ currentIndex === 0 ? "opacity-40" : "cursor-pointer"
102+ } `}
103+ onClick = { slideLeft }
104+ />
105+ < ChevronRight
106+ className = { `hover:text-white ${
107+ currentIndex === maxIndex ? "opacity-40" : "cursor-pointer"
108+ } `}
109+ onClick = { slideRight }
110+ />
111+ </ div >
112+ ) }
105113 </ div >
106114
107- < Link href = "/events" className = "font-jersey10" >
108- < Button > See More { `>` } </ Button >
109- </ Link >
115+ { ! isEmpty && (
116+ < Link href = "/events" className = "font-jersey10" >
117+ < Button > See More { `>` } </ Button >
118+ </ Link >
119+ ) }
110120 </ div >
111121
122+ { isEmpty && (
123+ < p className = "mt-10 px-10 text-sm text-primary" > No events available.</ p >
124+ ) }
125+
112126 < div className = "mt-10 px-10" >
113127 < div ref = { viewportRef } className = "overflow-hidden" >
114128 < div
0 commit comments