File "MyProfileBanner.tsx"
Full Path: /home/trinadezambia/public_html/student_panel/src/components/ui/pages/dashboard/MyProfileBanner.tsx
File size: 3.92 KB
MIME-type: text/html
Charset: utf-8
'use client';
import { useState, useEffect } from 'react';
import Image from 'next/image';
import Autoplay from 'embla-carousel-autoplay';
import {
Carousel,
CarouselContent,
CarouselItem,
type CarouselApi,
} from '@/components/ui/carousel';
import { type Slider } from '@/lib/api/student/functions';
import { useGetSliders } from '@/lib/api/student/queryHooks';
import { useTranslate } from '@/components/hooks/useTranslate';
export default function MyProfileBanner() {
const translate = useTranslate();
const [api, setApi] = useState<CarouselApi>();
const [current, setCurrent] = useState(0);
const { data: response, isLoading: loading } = useGetSliders();
const sliders: Slider[] = response?.data || [];
// Update current slide when carousel changes
useEffect(() => {
if (!api) return;
setCurrent(api.selectedScrollSnap());
api.on('select', () => {
setCurrent(api.selectedScrollSnap());
});
}, [api]);
// Handle pagination dot click
const scrollTo = (index: number) => {
if (api) {
api.scrollTo(index);
}
};
// Show loading state
if (loading) {
return (
<div className="rounded-[4px] mb-6 relative overflow-hidden">
<div className="w-full aspect-[2/1] md:aspect-[3/1] lg:aspect-auto lg:h-[400px] bg-gray-200 animate-pulse rounded-lg flex items-center justify-center">
<div className="text-gray-500">{translate('loadingBanner')}</div>
</div>
</div>
);
}
// Show message when no sliders are available
if (!loading && sliders.length === 0) {
return null;
}
return (
<div className="rounded-[4px] mb-6 relative overflow-hidden">
<Carousel
setApi={setApi}
opts={{
align: 'start',
loop: true,
}}
plugins={[
Autoplay({
delay: 4000, // Auto-slide every 4 seconds
stopOnInteraction: false, // Continue autoplay after user interaction
stopOnMouseEnter: true, // Pause autoplay when hovering over carousel
stopOnFocusIn: true, // Pause autoplay when focusing on carousel
}),
]}
className="w-full"
>
<CarouselContent>
{sliders.map((slider) => (
<CarouselItem key={slider.id}>
<div className="relative w-full aspect-[2/1] md:aspect-[3/1] lg:aspect-auto lg:h-[400px]">
{slider.link ? (
<a
href={slider.link}
target="_blank"
rel="noopener noreferrer"
className="block w-full h-full"
>
<Image
src={slider.image}
alt={`Banner Image ${slider.id}`}
fill
className="object-cover rounded-lg hover:opacity-90 transition-opacity"
priority={slider.id === sliders[0]?.id}
/>
</a>
) : (
<Image
src={slider.image}
alt={`Banner Image ${slider.id}`}
fill
className="object-cover rounded-lg"
priority={slider.id === sliders[0]?.id}
/>
)}
</div>
</CarouselItem>
))}
</CarouselContent>
</Carousel>
{/* Interactive Pagination Dots */}
<div className="flex justify-center space-x-2 my-8">
{sliders.map((_, index) => (
<button
key={index}
onClick={() => scrollTo(index)}
className={`w-3 h-3 rounded-full transition-all duration-300 ${current === index
? 'bg-[var(--secondary-color)] scale-110 w-[40px]'
: 'bg-gray-200 hover:bg-[var(--secondary-color)]'
}`}
aria-label={`${translate('goToSlide')} ${index + 1}`}
/>
))}
</div>
</div>
);
}