import React, { useCallback, useEffect, useState } from 'react'; import { View, FlatList, StyleSheet, Platform, Alert, BackHandler, Text, ToastAndroid } from 'react-native'; import LottieView from 'lottie-react-native'; import { InsideHeader } from '../../Component/Index'; import colors from '../../Constant/Color'; import { useWebSocketService } from '../../socket/Socket'; import Variables from '../../Constant/Variable'; import { useSelector } from 'react-redux'; import { apiCall } from '../../Axios/Axios'; import { AUCTION_ONE_TIME_BID, GET_AUCTION_DETAILS, REVERSE_AUCTION_ITEM, SELECTED_AUCTION_ITEM } from '../../Services/ApiCall/ApiUrls'; import { CommonActions, useFocusEffect, useNavigation } from '@react-navigation/native'; import NavigationString from '../../Constant/NavigationString'; import CountdownTimer from '../../Component/Counter/CountdownTimer'; import { useTheme } from '../../Hooks/useTheme'; import AppText from '../../components/AppText'; import ReverseBiddingCard from './Component/ReverseBiddingCard'; import ConfirmBidModal from './Component/ConfirmBidModal'; import GoBackModal from './Component/GoBackModal'; const StartReverseBidding = () => { const { colors } = useTheme(); const styles = React.useMemo(() => makeStyles(colors), [colors]); const SelectedAuction = useSelector((state: any) => state.auction.auction); const loginUser = useSelector((state: any) => state.token.token) const Navigation: any = useNavigation() const [items, setItems] = useState([]); const [bidValues, setBidValues] = useState>({}); const [allBoolean, setAllBoolean] = useState({ showSuccess: false, showDialog: false, showBackDialog: false, bidPayload: {} as any, oneTimeBid: false, rebid: false, reload: false }) const { subscribe, createRoom, placeBid } = useWebSocketService( Variables.webSocketUrl, () => console.log('Connected!'), (error) => console.log('WebSocket Error:', error), loginUser.token, ); const getAuction = async () => { const selectedRes = await apiCall('get', GET_AUCTION_DETAILS, {}, { id: SelectedAuction.auctionId }); if (selectedRes.statusCode == 200 && selectedRes.data.contractorId.length) { setAllBoolean((prev: any) => ({ ...prev, oneTimeBid: true })) } } const getOneTimeBidValue = async () => { try { const selectedRes = await apiCall('get', AUCTION_ONE_TIME_BID, {}, { auctionId: SelectedAuction.auctionId }); if (selectedRes.statusCode == 200) { return selectedRes.data } else { return [] } } catch (error) { } } const getAllAcutionItems = async () => { try { const payload = { auctionNumber: SelectedAuction.auctionNumber }; let auctionItem: any[] = []; if (SelectedAuction.auctionPattern === 'Reverse') { const res = await apiCall('get', REVERSE_AUCTION_ITEM, {}, payload); if (res?.statusCode === 200) auctionItem = res.data || []; } const selectedRes = await apiCall('get', SELECTED_AUCTION_ITEM, {}, payload); const uniqueArray: number[] = Array.from( new Set(selectedRes?.data || []) ); const filteredItems = auctionItem.filter(item => uniqueArray.includes(item.id) ); if (SelectedAuction.auctionCategories == 'Live') { const result = await createRoom(SelectedAuction.auctionNumber); subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, data => { console.log('🔥 BID UPDATE:', data); }); const bidAmountMap2 = new Map(); (result || []).forEach((r: any) => { bidAmountMap2.set(r.auctionItemId, { bidAmount: r.bidAmount, contractorId: r.contractorId, }); }); // Check One Time bid enable butoon if (SelectedAuction.auctionCategories != 'Live') { const myBid = result.find( (bid: any) => bid.contractorId === loginUser.contractorId ); if (myBid) { setAllBoolean((prev: any) => ({ ...prev, oneTimeBid: true })) } } const bidAmountMap = new Map(); (result || []).forEach((r: any) => { bidAmountMap.set(r.auctionItemId, r.bidAmount); }); const updatedFilteredItems = filteredItems.map(item => { const bidData = bidAmountMap2.get(item.id); return { ...item, bidAmount: bidData?.bidAmount ?? item.auctionStartValue, bidAvilable: bidData?.bidAmount ?? 0, me: bidData?.contractorId == loginUser.contractorId ? true : false }; }); const initialBids: Record = {}; updatedFilteredItems.forEach(item => { initialBids[item.id] = item.bidAmount; }); setBidValues(initialBids); setItems(updatedFilteredItems); } else { let result = [] if (SelectedAuction.rebidAllowed) { setAllBoolean((prev: any) => ({ ...prev, rebid: true })) } if (SelectedAuction.auctionCategories != 'Live') { result = await getOneTimeBidValue() } const bidMap = new Map(); result.forEach((bid: any) => { bidMap.set(bid.auctionItemId, bid); }); const mergedData = auctionItem.map((item: any) => { const bid = bidMap.get(item.id); if (!bid) { return { ...item, bidAmount: item.auctionStartValue, contractorId: item.contractorId, }; } return { ...item, bidAmount: bid.bidAmount, bidId: bid.bidId, contractorId: bid.contractorId, contractorName: bid.contractorName, me: bid.contractorId === loginUser.contractorId, bidTime: bid.bidTime, }; }); const initialBids: Record = {}; mergedData.forEach(item => { initialBids[item.id] = item.bidAmount; }); setBidValues(initialBids); setItems(mergedData) setBidValues(initialBids); } } catch (error) { console.error('Error fetching auction items:', error); } }; subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, async (message) => { const result = message[message.length - 1] const updatedBidItem = (prev: any[]) => prev.map(item => item.id === result.auctionItemId ? { ...item, bidAmount: result.bidAmount, me: result.contractorId == loginUser.contractorId ? true : false } : item ); setItems(updatedBidItem); setBidValues(prev => ({ ...prev, [result.auctionItemId]: result.bidAmount, })); try { } catch (err) { console.log('JSON parse error:', err); } }); useEffect(() => { if (SelectedAuction.auctionCategories == 'One-time') { getAuction() } getAllAcutionItems(); subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, (data) => { }); }, [allBoolean.reload]); useEffect(() => { const initial: Record = {}; items.forEach((item: any) => { initial[item.id] = item.bidAmount + item.bidVariationValue; }); setBidValues(initial); }, []); const handleUpdate = (id: number, val: number) => { setBidValues(prev => ({ ...prev, [id]: prev[id] + val })); }; const submitBid = async (item: any) => { const payload = { itemId: item.id, bidAmount: bidValues[item.id], auctionId: SelectedAuction.auctionId, contractorId: loginUser.contractorId, fullName: loginUser.fullName, roomId: SelectedAuction.auctionNumber, }; setAllBoolean((prev: any) => ({ ...prev, bidPayload: payload, showDialog: true })); }; const placeBidSubmit = async (data: any) => { setAllBoolean((prev: any) => ({ ...prev, showDialog: false })); try { const result: any = await placeBid(data); if (result?.status && result.data) { const updatedBidItem = (prev: any[]) => prev.map(item => item.id === result.data.auctionItemId ? { ...item, bidAmount: result.data.bidAmount, me: result.data?.contractorId == loginUser.contractorId ? true : false } : item ); getAllAcutionItems() } } catch (error) { console.error('Error placing bid:', error); } }; useFocusEffect( useCallback(() => { const onBackPress = () => { setAllBoolean((prev: any) => ({ ...prev, showBackDialog: true })); return true; // block default back action }; const subscription = BackHandler.addEventListener( 'hardwareBackPress', onBackPress ); return () => subscription.remove(); }, [Navigation]) ); return ( {SelectedAuction.deptName} item.id.toString()} renderItem={({ item, index }) => ( handleUpdate(item.id, item.emdAmount)} onDecrease={() => handleUpdate(item.id, -item.emdAmount)} onPlaceBid={() => { submitBid(item) }} SelectedAuction={SelectedAuction} allBoolean={allBoolean} setAllBoolean={setAllBoolean} /> )} contentContainerStyle={{ padding: 16 }} /> {allBoolean.showSuccess && ( )} setAllBoolean(prev => ({ ...prev, showDialog: false }))} onConfirm={() => placeBidSubmit(allBoolean.bidPayload)} bidAmount={allBoolean.bidPayload?.bidAmount} /> setAllBoolean(prev => ({ ...prev, showBackDialog: false }))} onConfirm={() => { setAllBoolean(prev => ({ ...prev, showBackDialog: false })); Navigation.dispatch( CommonActions.reset({ index: 0, routes: [{ name: NavigationString.Home }], }) ); }} /> ); }; export default StartReverseBidding; const makeStyles = (colors: any) => StyleSheet.create({ container: { flex: 1, backgroundColor: colors.background }, container2: { paddingHorizontal: 16, paddingTop: 12, paddingBottom: 8, }, title: { marginBottom: 6, } as any, timerWrapper: { alignItems: 'center', }, overlay: { ...StyleSheet.absoluteFillObject, backgroundColor: colors.overlay, justifyContent: 'center', alignItems: 'center', zIndex: 99 }, });