import React, { useState, useEffect, useCallback, useRef } from 'react'; import { View, Text, ScrollView, TouchableOpacity, FlatList, Image, NativeSyntheticEvent, NativeScrollEvent, Dimensions, } from 'react-native'; import { useNavigation, CompositeNavigationProp, useFocusEffect, } from '@react-navigation/native'; import { BottomTabNavigationProp } from '@react-navigation/bottom-tabs'; import { StackNavigationProp } from '@react-navigation/stack'; import { getStyles } from './homeScreen.styles'; import { ProductCard, SearchBar } from '@components'; import { useAppTheme } from '@theme'; import { Product } from '../../../interfaces'; import { AppStackParamList } from '../../../navigation/appStack'; import { MainTabParamList } from '../../../navigation/mainTabNavigator'; import { fetchCustomerDetails, getAllOffersThunk, useAppDispatch, useAppSelector, } from '@store'; import { getAllCategoriesThunk, getAllProductsThunk } from './thunk'; type NavProp = CompositeNavigationProp< BottomTabNavigationProp, StackNavigationProp >; const { width } = Dimensions.get('window'); const BANNER_STEP = width - 32 + 12; // card width + margin const ALL_CATEGORY = { id: 'all', name: 'All', slug: 'all', imageUrl: null, isActive: true, parentId: null }; const getCategoryEmoji = (name: string): string => { const n = name.toLowerCase(); if (n.includes('food')) return '๐Ÿ”'; if (n.includes('grocer')) return '๐Ÿ›’'; if (n.includes('pharma') || n.includes('medic')) return '๐Ÿ’Š'; if (n.includes('meat')) return '๐Ÿฅฉ'; if (n.includes('flower')) return '๐Ÿ’'; if (n.includes('electronic')) return '๐Ÿ“ฑ'; if (n.includes('cloth') || n.includes('fashion')) return '๐Ÿ‘—'; if (n.includes('bakery') || n.includes('cake')) return '๐ŸŽ‚'; return '๐Ÿ“ฆ'; }; const PROMOS = [ { key: 'promo1', colors: ['#05824C', '#0AA25E'], eyebrow: 'Limited time', title: '50% OFF', subtitle: 'On your first order, up to โ‚น150', cta: 'Order now', }, { key: 'promo2', colors: ['#7B3FF2', '#9B6BF5'], eyebrow: 'Free delivery', title: 'โ‚น0 Delivery', subtitle: 'On orders above โ‚น299 today', cta: 'Explore', }, { key: 'promo3', colors: ['#E85D3D', '#F0805F'], eyebrow: 'Pharmacy', title: 'Meds in 20 min', subtitle: 'Genuine medicines, fast delivery', cta: 'Shop now', }, ]; export const HomeScreen: React.FC = () => { const { colors } = useAppTheme(); const styles = getStyles(colors); const navigation = useNavigation(); const dispatch = useAppDispatch(); const { products, isLoading, categories } = useAppSelector( state => state.home, ); const [selectedCategory, setSelectedCategory] = useState('all'); const [activeBanner, setActiveBanner] = useState(0); useEffect(() => { dispatch(getAllProductsThunk()); dispatch(fetchCustomerDetails()); dispatch(getAllCategoriesThunk()); }, [dispatch]); useFocusEffect( useCallback(() => { dispatch(getAllOffersThunk()); }, [dispatch]), ); // Build category list: prepend synthetic 'All', then append API categories const dynamicCategories = [ALL_CATEGORY, ...categories]; const filteredProducts = selectedCategory === 'all' ? products : products.filter(p => p.category?.name === selectedCategory); const handleSearchFocus = useCallback(() => { navigation.navigate('SearchScreen'); }, [navigation]); const handleBannerScroll = useCallback( (e: NativeSyntheticEvent) => { const index = Math.round(e.nativeEvent.contentOffset.x / BANNER_STEP); setActiveBanner(index); }, [], ); return ( {/* Top bar */} ๐Ÿ“ Deliver to Koramangala 4th Block โ–ผ navigation.navigate('CartScreen')} > ๐Ÿงบ {/* Search */} {}} placeholder="Search providers or items..." onFocus={handleSearchFocus} /> {/* Promo carousel */} item.key} showsHorizontalScrollIndicator={false} contentContainerStyle={styles.bannerListContent} snapToInterval={BANNER_STEP} decelerationRate="fast" onScroll={handleBannerScroll} scrollEventThrottle={16} renderItem={({ item }) => ( {item.eyebrow} {item.title} {item.subtitle} {item.cta} )} /> {PROMOS.map((_, i) => ( ))} {/* Categories */} item.id} showsHorizontalScrollIndicator={false} contentContainerStyle={styles.chipRow} renderItem={({ item }) => { const isSelected = selectedCategory === item.id; const emoji = item.id === 'all' ? '๐Ÿ ' : getCategoryEmoji(item.name); return ( { if (item.id === 'all') { setSelectedCategory('all'); } else { navigation.navigate('SearchScreen', { categoryId: item.id, categoryName: item.name, }); } }} > {emoji} {item.name} ); }} /> {/* Section header */} {selectedCategory === 'all' ? 'Popular near you' : selectedCategory} {filteredProducts.length} product {filteredProducts.length === 1 ? '' : 's'} available See all {/* Product list */} {filteredProducts.length === 0 && ( ๐Ÿ›๏ธ No products found )} {filteredProducts.map(product => ( { navigation.navigate('ProviderDetailsScreen', { providerId: product.id, providerName: product.name, }); }} /> ))} ); };