import React, { useState, useRef, useEffect } from 'react'; import { View, Dimensions, Image, ScrollView, NativeSyntheticEvent, NativeScrollEvent } from 'react-native'; import { MyTouchableOpacity, MyText, tw } from 'common-ui'; import { useRouter } from 'expo-router'; import { trpc } from '@/src/trpc-client'; import MaterialIcons from '@expo/vector-icons/MaterialIcons'; const { width: screenWidth } = Dimensions.get('window'); interface Banner { id: number; name: string; imageUrl: string; description?: string | null; productIds?: number[] | null; redirectUrl?: string | null; serialNum?: number | null; isActive: boolean; } export default function BannerCarousel() { const router = useRouter(); const scrollViewRef = useRef(null); const [currentIndex, setCurrentIndex] = useState(0); const [isAutoPlaying, setIsAutoPlaying] = useState(true); // Fetch banners data const { data: bannersData, isLoading, error } = trpc.user.banner.getBanners.useQuery(); const banners = bannersData?.banners || []; // Auto-play functionality useEffect(() => { if (banners.length <= 1 || !isAutoPlaying) return; // Don't auto-play if conditions not met const interval = setInterval(() => { setCurrentIndex((prevIndex) => { const nextIndex = (prevIndex + 1) % banners.length; // Auto-scroll to next slide if (scrollViewRef.current) { scrollViewRef.current.scrollTo({ x: nextIndex * (screenWidth - 32), animated: true, }); } return nextIndex; }); }, 6000); // 6 seconds return () => clearInterval(interval); // Cleanup on unmount }, [banners.length, isAutoPlaying]); if (isLoading) { return ( Loading banners... ); } if (error || !banners || banners.length === 0) return null; const handleBannerPress = (banner: Banner) => { if (banner.productIds && banner.productIds.length > 0) { // Navigate to the first product's detail page router.push(`/(drawer)/(tabs)/home/product-detail/${banner.productIds[0]}`); } else if (banner.redirectUrl) { // Handle external URL - could open in browser or handle deep links console.log('Banner redirect URL:', banner.redirectUrl); } // If no productIds or redirectUrl, banner is just for display }; const handleScroll = (event: NativeSyntheticEvent) => { const slideSize = screenWidth - 32; // width minus horizontal padding const index = Math.round(event.nativeEvent.contentOffset.x / slideSize); setCurrentIndex(index); }; const goToSlide = (index: number) => { setIsAutoPlaying(false); // Pause auto-play when user manually navigates if (scrollViewRef.current) { scrollViewRef.current.scrollTo({ x: index * (screenWidth - 32), animated: true, }); } setCurrentIndex(index); // Resume auto-play after a short delay setTimeout(() => setIsAutoPlaying(true), 1000); }; return ( setIsAutoPlaying(false)} onTouchEnd={() => setIsAutoPlaying(true)} onMomentumScrollEnd={() => setIsAutoPlaying(true)} > {banners.map((banner: Banner) => ( handleBannerPress(banner)} style={tw`mr-4 rounded-2xl overflow-hidden`} activeOpacity={0.9} > ))} {/* Pagination Dots */} {banners.length > 1 && ( {banners.map((_, index: number) => ( goToSlide(index)} style={tw`mx-1`} > ))} )} ); }