import React, { useState, useMemo, useCallback } from 'react'; import { StyleSheet, FlatList, TouchableOpacity, RefreshControl, TextInput } from 'react-native'; import { View, Text, useTheme } from '@bettoredge/styles'; import { Ionicons } from '@expo/vector-icons'; import type { CalcuttaAuctionItemProps, CalcuttaBidProps } from '@bettoredge/types'; import type { ItemImageMap } from '../../hooks/useCalcuttaItemImages'; import type { CalcuttaLifecycleState } from '../../helpers/lifecycleState'; import { SealedBidItemCard } from './SealedBidItemCard'; type ActiveFilter = 'all' | 'not_bid' | 'my_bids'; type BrowseFilter = 'all'; interface SealedBidItemsTabProps { items: CalcuttaAuctionItemProps[]; my_bids: CalcuttaBidProps[]; min_bid: number; bid_increment: number; escrow_balance: number; market_type: string; player_id?: string; lifecycleState: CalcuttaLifecycleState; itemImages?: ItemImageMap; onPlaceBid: (calcutta_auction_item_id: string, amount: number) => void; bidLoading: boolean; onRefresh: () => void; refreshing: boolean; disabled?: boolean; listHeader?: React.ReactNode; } const ACTIVE_FILTERS: { key: ActiveFilter; label: string }[] = [ { key: 'all', label: 'All' }, { key: 'not_bid', label: 'Not Bid' }, { key: 'my_bids', label: 'My Bids' }, ]; const BROWSE_FILTERS: { key: BrowseFilter; label: string }[] = [ { key: 'all', label: 'All' }, ]; export const SealedBidItemsTab: React.FC = ({ items, my_bids, min_bid, bid_increment, escrow_balance, market_type, player_id, lifecycleState, itemImages, onPlaceBid, bidLoading, onRefresh, refreshing, disabled, listHeader, }) => { const { theme } = useTheme(); const [activeFilter, setActiveFilter] = useState('all'); const [searchQuery, setSearchQuery] = useState(''); const isBrowseMode = lifecycleState === 'pending' || lifecycleState === 'scheduled'; const myBidItemIds = useMemo( () => new Set(my_bids.filter(b => b.bid_status === 'active' || b.bid_status === 'won').map(b => b.calcutta_auction_item_id)), [my_bids], ); const filteredItems = useMemo(() => { let result = items; if (!isBrowseMode) { switch (activeFilter) { case 'not_bid': result = result.filter(i => !myBidItemIds.has(i.calcutta_auction_item_id)); break; case 'my_bids': result = result.filter(i => myBidItemIds.has(i.calcutta_auction_item_id)); break; } } if (searchQuery.trim()) { const q = searchQuery.trim().toLowerCase(); result = result.filter(i => i.item_name.toLowerCase().includes(q)); } return result; }, [items, activeFilter, isBrowseMode, myBidItemIds, searchQuery]); const renderItem = useCallback(({ item }: { item: CalcuttaAuctionItemProps }) => { const myBid = my_bids.find( b => b.calcutta_auction_item_id === item.calcutta_auction_item_id && (b.bid_status === 'active' || b.bid_status === 'won') ); return ( onPlaceBid(item.calcutta_auction_item_id, amount)} bidLoading={bidLoading} disabled={disabled} /> ); }, [my_bids, min_bid, bid_increment, escrow_balance, market_type, player_id, lifecycleState, itemImages, onPlaceBid, bidLoading, disabled]); const filters = isBrowseMode ? BROWSE_FILTERS : ACTIVE_FILTERS; const currentFilter = isBrowseMode ? 'all' : activeFilter; const setFilter = (f: string) => setActiveFilter(f as ActiveFilter); const headerComponent = ( <>{listHeader} {/* Search */} {searchQuery.length > 0 && ( setSearchQuery('')} hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}> )} {/* Filter chips — hide single-filter row in browse mode */} {!isBrowseMode && ( {filters.map(f => { const active = currentFilter === f.key; return ( setFilter(f.key)} activeOpacity={0.7} > {f.label} ); })} )} ); return ( item.calcutta_auction_item_id} renderItem={renderItem} ListHeaderComponent={headerComponent} contentContainerStyle={styles.list} stickyHeaderIndices={[]} refreshControl={ } ListEmptyComponent={ {isBrowseMode ? 'No items available' : activeFilter === 'my_bids' ? 'No bids placed yet' : 'No items available'} } /> ); }; const styles = StyleSheet.create({ container: { flex: 1, }, searchRow: { flexDirection: 'row', alignItems: 'center', marginHorizontal: 12, marginTop: 10, paddingHorizontal: 12, height: 44, borderRadius: 10, borderWidth: 1, }, searchInput: { flex: 1, marginLeft: 8, fontSize: 15, lineHeight: 20, height: 44, padding: 0, }, filterRow: { flexDirection: 'row', paddingHorizontal: 12, paddingVertical: 10, gap: 8, }, chip: { paddingHorizontal: 12, paddingVertical: 6, borderRadius: 14, borderWidth: 1, }, list: { paddingBottom: 40, paddingTop: 8, }, empty: { textAlign: 'center', padding: 40, }, });