import React, { useEffect, useState } from 'react'; import { View, StyleSheet, FlatList, RefreshControl, TextInput, Pressable, Text } from 'react-native'; import { CompositeNavigationProp } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { BottomTabNavigationProp } from '@react-navigation/bottom-tabs'; import Ionicons from '@react-native-vector-icons/ionicons'; import Animated, { FadeIn, FadeOut } from 'react-native-reanimated'; import { ScreenShell } from '../../../components'; import { useTheme } from '../../../theme'; import { TAB_BAR_HEIGHT } from '../../../utils/layoutConstants'; import { useAppDispatch, useAppSelector } from '../../../app/hooks'; import type { AgentTabParamList, AgentCustomersStackParamList } from '../navigation/agentNavigationTypes'; import { useGetAgentCustomersQuery } from '../services/agentApi'; import { agentActions } from '../store/agentSlice'; import { selectFilteredCustomers, selectCustomerFilter, selectCustomerSearch } from '../store/agentSelectors'; import { CUSTOMER_FILTERS } from '../constants/agentConstants'; import type { CustomerFilter } from '../types/agentTypes'; import { CustomerCard } from '../components/CustomerCard'; import { AgentSkeletonLoader } from '../components/AgentSkeletonLoader'; import { AgentEmptyState } from '../components/AgentEmptyState'; type NavigationProp = CompositeNavigationProp< NativeStackNavigationProp, BottomTabNavigationProp >; export default function CustomerListScreen({ navigation }: { navigation: NavigationProp }) { const theme = useTheme(); const dispatch = useAppDispatch(); const customers = useAppSelector(selectFilteredCustomers); const activeFilter = useAppSelector(selectCustomerFilter); const searchQuery = useAppSelector(selectCustomerSearch); const { data, isLoading, isFetching, refetch, error } = useGetAgentCustomersQuery(undefined, { refetchOnMountOrArgChange: true, }); const [refreshing, setRefreshing] = useState(false); useEffect(() => { if (data) { dispatch(agentActions.setCustomers(data)); } }, [data, dispatch]); const handleRefresh = async () => { setRefreshing(true); await refetch(); setRefreshing(false); }; const handleSearch = (text: string) => { dispatch(agentActions.setCustomerSearch(text)); }; const handleFilter = (filter: CustomerFilter) => { dispatch(agentActions.setCustomerFilter(filter)); }; return ( {/* Search Bar */} {searchQuery.length > 0 && ( handleSearch('')} style={styles.clearBtn}> )} {/* Filters */} item.id} contentContainerStyle={styles.filterList} renderItem={({ item }) => { const isActive = activeFilter === item.id; return ( handleFilter(item.id)} > {item.label} ); }} /> {/* List Area */} {isLoading && customers.length === 0 ? ( ) : error && customers.length === 0 ? ( ) : ( item.id} contentContainerStyle={styles.listContent} showsVerticalScrollIndicator={false} refreshControl={ } ListEmptyComponent={() => ( handleSearch('') : undefined} /> )} renderItem={({ item, index }) => ( navigation.navigate('CustomerDetail', { customerId: item.id })} /> )} /> )} {/* FAB to add new customer */} navigation.navigate('AddEditCustomer', {})} > ); } const styles = StyleSheet.create({ headerArea: { paddingHorizontal: 16, paddingTop: 16, paddingBottom: 8, zIndex: 10, }, searchBar: { flexDirection: 'row', alignItems: 'center', height: 48, borderRadius: 24, borderWidth: 1, paddingHorizontal: 16, marginBottom: 16, }, searchInput: { flex: 1, height: '100%', marginLeft: 8, fontSize: 15, }, clearBtn: { padding: 4, }, filterArea: { marginBottom: 8, }, filterList: { gap: 8, }, filterChip: { paddingHorizontal: 16, paddingVertical: 8, borderRadius: 16, borderWidth: 1, }, filterText: { fontSize: 13, fontWeight: '600', }, listArea: { flex: 1, }, listContent: { padding: 16, paddingBottom: TAB_BAR_HEIGHT + 16, }, fab: { position: 'absolute', right: 20, bottom: TAB_BAR_HEIGHT + 20, // above tab bar width: 56, height: 56, borderRadius: 28, alignItems: 'center', justifyContent: 'center', shadowColor: '#000', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.2, shadowRadius: 8, elevation: 5, }, });