Auciton process complete
This commit is contained in:
@@ -1,6 +1,14 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<!-- Android 12 and below -->
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="28" />
|
||||
|
||||
<!-- Android 13+ -->
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
||||
|
||||
<application
|
||||
android:name=".MainApplication"
|
||||
|
||||
Generated
+137
@@ -30,8 +30,10 @@
|
||||
"react-native": "0.79.0",
|
||||
"react-native-alert-notification": "^0.4.2",
|
||||
"react-native-app-intro-slider": "^4.0.4",
|
||||
"react-native-blob-util": "^0.24.6",
|
||||
"react-native-bouncy-checkbox": "^4.1.2",
|
||||
"react-native-date-picker": "^5.0.13",
|
||||
"react-native-fs": "^2.20.0",
|
||||
"react-native-gesture-handler": "^2.30.0",
|
||||
"react-native-gifted-charts": "^1.4.70",
|
||||
"react-native-haptic-feedback": "^2.3.3",
|
||||
@@ -2210,6 +2212,27 @@
|
||||
"deprecated": "Use @eslint/object-schema instead",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@isaacs/balanced-match": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
|
||||
"integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/brace-expansion": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz",
|
||||
"integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@isaacs/balanced-match": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/ttlcache": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz",
|
||||
@@ -4968,6 +4991,11 @@
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/base-64": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz",
|
||||
"integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA=="
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
@@ -10589,6 +10617,15 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/minipass": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
@@ -11084,6 +11121,31 @@
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/path-scurry": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz",
|
||||
"integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"lru-cache": "^11.0.0",
|
||||
"minipass": "^7.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/path-scurry/node_modules/lru-cache": {
|
||||
"version": "11.2.4",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz",
|
||||
"integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/path-type": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
|
||||
@@ -11597,6 +11659,56 @@
|
||||
"integrity": "sha512-Zkjaol6X3BbZkHUpVDj2LjdidpS6rCgKi0fx80xgGKa0pHxBRd4swWTv2bHnnvu5k1/HXwYk0mY2TbK+2jHl5w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/react-native-blob-util": {
|
||||
"version": "0.24.6",
|
||||
"resolved": "https://registry.npmjs.org/react-native-blob-util/-/react-native-blob-util-0.24.6.tgz",
|
||||
"integrity": "sha512-e4231VTT0bO1Yh9KGtY6jXq7pkLXgDTz+ziClEEbiGwWBuG92Z+wFRLptlzdVbibW8XtrO1XrdtiE8AOlplEXQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base-64": "0.1.0",
|
||||
"glob": "13.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ronradtke"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-blob-util/node_modules/glob": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz",
|
||||
"integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"minimatch": "^10.1.1",
|
||||
"minipass": "^7.1.2",
|
||||
"path-scurry": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-blob-util/node_modules/minimatch": {
|
||||
"version": "10.1.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz",
|
||||
"integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"@isaacs/brace-expansion": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-bouncy-checkbox": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/react-native-bouncy-checkbox/-/react-native-bouncy-checkbox-4.1.2.tgz",
|
||||
@@ -11616,6 +11728,25 @@
|
||||
"react-native": ">= 0.64.3"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-fs": {
|
||||
"version": "2.20.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-fs/-/react-native-fs-2.20.0.tgz",
|
||||
"integrity": "sha512-VkTBzs7fIDUiy/XajOSNk0XazFE9l+QlMAce7lGuebZcag5CnjszB+u4BdqzwaQOdcYb5wsJIsqq4kxInIRpJQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base-64": "^0.1.0",
|
||||
"utf8": "^3.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react-native": "*",
|
||||
"react-native-windows": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react-native-windows": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-gesture-handler": {
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.30.0.tgz",
|
||||
@@ -13602,6 +13733,12 @@
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/utf8": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz",
|
||||
"integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
|
||||
@@ -32,8 +32,10 @@
|
||||
"react-native": "0.79.0",
|
||||
"react-native-alert-notification": "^0.4.2",
|
||||
"react-native-app-intro-slider": "^4.0.4",
|
||||
"react-native-blob-util": "^0.24.6",
|
||||
"react-native-bouncy-checkbox": "^4.1.2",
|
||||
"react-native-date-picker": "^5.0.13",
|
||||
"react-native-fs": "^2.20.0",
|
||||
"react-native-gesture-handler": "^2.30.0",
|
||||
"react-native-gifted-charts": "^1.4.70",
|
||||
"react-native-haptic-feedback": "^2.3.3",
|
||||
|
||||
@@ -5,7 +5,6 @@ export interface AuctionItem {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
// ✅ DEFAULT = EMPTY ARRAY
|
||||
const initialState: AuctionItem[] = [];
|
||||
|
||||
export const selectPurchaseAuctionSlice = createSlice({
|
||||
|
||||
@@ -1,52 +1,40 @@
|
||||
import React, { useCallback, useState, useEffect } from 'react';
|
||||
import React, { useCallback, useState, useEffect, useRef } from 'react';
|
||||
import { View, FlatList, ActivityIndicator, RefreshControl, Text } from 'react-native';
|
||||
import Animated, { FadeInDown, FadeOutUp } from 'react-native-reanimated';
|
||||
import LiveAuctionTile from './LiveAuctionTile';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { useFetchLiveAuction } from '../../Services/BBPS/Hooks';
|
||||
import { SearchInput } from '../../Component/Serach/SeacrhInput';
|
||||
import { Skelton } from '../../Component/Index';
|
||||
import colors from '../../Constant/Color';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { selectPurchaseAuctionSlice, togglePurchaseAuction } from '../../Redux/Slices/selectPurchaseAuction';
|
||||
import { togglePurchaseAuction } from '../../Redux/Slices/selectPurchaseAuction';
|
||||
import { apiCall } from '../../Axios/Axios';
|
||||
import { GET_MY_AUCTION, LIVE_AUCTION } from '../../Services/BBPS/ApiUrls';
|
||||
import moment from 'moment';
|
||||
import { GET_MY_AUCTION } from '../../Services/BBPS/ApiUrls';
|
||||
|
||||
const LiveAuction = () => {
|
||||
const navigation: any = useNavigation();
|
||||
const Dispatch = useDispatch()
|
||||
const onEndReachedCalledDuringMomentum = useRef(true);
|
||||
const SelectedPurchaseList = useSelector((state: any) => state.selectPurchaseAuction);
|
||||
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, isRefetching, refetch }: any = useFetchLiveAuction();
|
||||
const [showRefreshBanner, setShowRefreshBanner] = useState(false);
|
||||
const [allBoolean, setAllBoolean] = useState({ liveAuctionData: [] })
|
||||
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, isRefetching, refetch, isPending }: any = useFetchLiveAuction();
|
||||
|
||||
useEffect(() => {
|
||||
if (isRefetching) {
|
||||
setShowRefreshBanner(true);
|
||||
} else {
|
||||
const timer = setTimeout(() => {
|
||||
setShowRefreshBanner(false);
|
||||
}, 1000);
|
||||
// My Methods
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
const getMyAuction = async () => {
|
||||
try {
|
||||
const res = await apiCall<any>('get', `${GET_MY_AUCTION}`,);
|
||||
if (res?.statusCode === 200) {
|
||||
const purchasedIds = new Set(res.data.map((item: any) => item.auctionId));
|
||||
const filteredLive = data?.result.map((item: any) => ({ ...item, active: !purchasedIds.has(item.auctionId) }));
|
||||
setAllBoolean(prev => ({ ...prev, liveAuctionData: filteredLive }));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('getMyAuction error', error);
|
||||
} finally {
|
||||
setAllBoolean(prev => ({ ...prev, isLoading: false }));
|
||||
}
|
||||
}, [isRefetching]);
|
||||
|
||||
const loadMore = useCallback(() => {
|
||||
if (hasNextPage && !isFetchingNextPage) {
|
||||
fetchNextPage();
|
||||
}
|
||||
}, [hasNextPage, isFetchingNextPage]);
|
||||
|
||||
const renderFooter = useCallback(() => {
|
||||
if (!isFetchingNextPage) return null;
|
||||
return (
|
||||
<View style={{ paddingVertical: 12 }}>
|
||||
<ActivityIndicator size="small" color={colors.primary} />
|
||||
</View>
|
||||
);
|
||||
}, [isFetchingNextPage]);
|
||||
};
|
||||
|
||||
const renderItem = useCallback(
|
||||
({ item, index }: any) => {
|
||||
@@ -68,32 +56,35 @@ const LiveAuction = () => {
|
||||
[SelectedPurchaseList]
|
||||
);
|
||||
|
||||
const getMyAuction = async () => {
|
||||
try {
|
||||
const loadMore = useCallback(() => {
|
||||
if (onEndReachedCalledDuringMomentum.current) return;
|
||||
|
||||
const res = await apiCall<any>('get', `${GET_MY_AUCTION}`,);
|
||||
if (!hasNextPage || isFetchingNextPage) return;
|
||||
|
||||
if (res?.statusCode === 200) {
|
||||
const purchasedIds = new Set(
|
||||
res.data.map((item: any) => item.auctionId),
|
||||
);
|
||||
fetchNextPage();
|
||||
onEndReachedCalledDuringMomentum.current = true;
|
||||
}, [hasNextPage, isFetchingNextPage, fetchNextPage]);
|
||||
|
||||
const filteredLive = data?.result.map((item: any) => ({
|
||||
...item,
|
||||
active: !purchasedIds.has(item.auctionId), // false if match, true otherwise
|
||||
}));
|
||||
const renderFooter = useCallback(() => {
|
||||
if (!isFetchingNextPage) return null;
|
||||
return (
|
||||
<View style={{ paddingVertical: 12 }}>
|
||||
<ActivityIndicator size="small" color={colors.primary} />
|
||||
</View>
|
||||
);
|
||||
}, [isFetchingNextPage]);
|
||||
|
||||
setAllBoolean(prev => ({
|
||||
...prev,
|
||||
liveAuctionData: filteredLive
|
||||
}));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('getMyAuction error', error);
|
||||
} finally {
|
||||
setAllBoolean(prev => ({ ...prev, isLoading: false }));
|
||||
useEffect(() => {
|
||||
if (isRefetching) {
|
||||
setShowRefreshBanner(true);
|
||||
} else {
|
||||
const timer = setTimeout(() => {
|
||||
setShowRefreshBanner(false);
|
||||
}, 1000);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}
|
||||
};
|
||||
}, [isRefetching]);
|
||||
|
||||
useEffect(() => {
|
||||
if (data?.result?.length > 0) {
|
||||
@@ -148,27 +139,34 @@ const LiveAuction = () => {
|
||||
|
||||
<FlatList
|
||||
data={allBoolean.liveAuctionData ?? []}
|
||||
keyExtractor={(item: any) => String(item.auctionNumber)}
|
||||
renderItem={renderItem}
|
||||
showsVerticalScrollIndicator={false}
|
||||
contentContainerStyle={{ paddingBottom: 50, paddingTop: 10 }}
|
||||
|
||||
onEndReached={loadMore}
|
||||
onEndReachedThreshold={0.2}
|
||||
onEndReachedThreshold={0.1}
|
||||
|
||||
onMomentumScrollBegin={() => {
|
||||
onEndReachedCalledDuringMomentum.current = false;
|
||||
}}
|
||||
|
||||
ListFooterComponent={renderFooter}
|
||||
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={isRefetching}
|
||||
onRefresh={refetch}
|
||||
tintColor="transparent" // Set to transparent if you only want your custom banner to show
|
||||
tintColor="transparent"
|
||||
colors={[colors.primary]}
|
||||
/>
|
||||
}
|
||||
|
||||
initialNumToRender={6}
|
||||
maxToRenderPerBatch={6}
|
||||
windowSize={7}
|
||||
removeClippedSubviews
|
||||
updateCellsBatchingPeriod={50}
|
||||
/>
|
||||
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -21,8 +21,6 @@ const LiveAuctionTile: React.FC<LiveAuctionTileProps> = ({
|
||||
|
||||
return (
|
||||
<View style={styles.cardWrapper}>
|
||||
{/* Status Tag */}
|
||||
|
||||
{
|
||||
!showDetail ?
|
||||
<>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { memo, useState } from 'react';
|
||||
import React, { memo, useEffect, useState } from 'react';
|
||||
import { View, Text, StyleSheet, TouchableOpacity, ScrollView, SafeAreaView, Platform, StatusBar } from 'react-native';
|
||||
import Modal from 'react-native-modal';
|
||||
import moment from 'moment';
|
||||
@@ -6,26 +6,29 @@ import { Briefcase, Calendar, FileText, Download, Eye, Layers, ArrowLeft, Clock
|
||||
import colors from '../../../Constant/Color';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import AuctionItemDetail from './AuctionItemDetail';
|
||||
import { useAucitonDocDownload, useAuctionItem, useGetAuciton, useGetAucitonDocument } from '../../../Services/BBPS/Hooks';
|
||||
import ReactNativeBlobUtil from 'react-native-blob-util';
|
||||
import { AUCTION_DOCUMENT_DOWNLOAD, ITEM_DOCUMENT_DOWNLOAD } from '../../../Services/BBPS/ApiUrls';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Loader } from '../../../Component/Index';
|
||||
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
onClose: () => void;
|
||||
data?: any;
|
||||
}
|
||||
interface Props { visible: boolean; onClose: () => void; data?: any }
|
||||
|
||||
const AuctionFullDetail: React.FC<Props> = ({ visible, onClose, data }) => {
|
||||
const inset = useSafeAreaInsets()
|
||||
const [allBoolean, setAllBoolean] = useState({ showItemDetail: false })
|
||||
const { data: auctionData, isLoading } = useGetAuciton({ auctionId: data?.auctionId })
|
||||
const [aucitonDetail, setAuciotnDetail] = useState<any>(auctionData)
|
||||
const [allBoolean, setAllBoolean] = useState({ showItemDetail: false, selectedItem: {}, fileLoading: false });
|
||||
const { data: auctionDocuments } = useGetAucitonDocument({ auctionId: data?.auctionId })
|
||||
const { mutate: downloadDocument, isPending } = useAucitonDocDownload()
|
||||
const { mutate } = useAuctionItem()
|
||||
const formatDate = (date?: string) => {
|
||||
if (!date) return '-';
|
||||
return moment(date, 'DD-MM-YYYY HH:mm:ss').format('DD MMM YYYY, hh:mm A');
|
||||
};
|
||||
|
||||
const isLive = data?.purchaseEnd
|
||||
? moment().isBefore(moment(data.purchaseEnd, 'DD-MM-YYYY HH:mm:ss'))
|
||||
: false;
|
||||
const isLive = data?.purchaseEnd ? moment().isBefore(moment(data.purchaseEnd, 'DD-MM-YYYY HH:mm:ss')) : false;
|
||||
|
||||
// Internal Components
|
||||
const Section = ({ title, icon: Icon, children }: any) => (
|
||||
<View style={styles.sectionContainer}>
|
||||
<View style={styles.sectionHeader}>
|
||||
@@ -43,6 +46,64 @@ const AuctionFullDetail: React.FC<Props> = ({ visible, onClose, data }) => {
|
||||
</View>
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
const handleDownload = async (id: number, fileName: string) => {
|
||||
try {
|
||||
setAllBoolean((prev: any) => ({ ...prev, fileLoading: true }));
|
||||
const { dirs } = ReactNativeBlobUtil.fs;
|
||||
|
||||
// ✅ PUBLIC DOWNLOADS DIRECTORY
|
||||
const path = `${dirs.DownloadDir}/${fileName}.pdf`;
|
||||
|
||||
console.log('📂 Saving to:', path);
|
||||
|
||||
const downloadUrl = `${AUCTION_DOCUMENT_DOWNLOAD}?documentId=${id}&isAmendment=false`;
|
||||
console.log('🌐 Download URL:', downloadUrl);
|
||||
|
||||
const response = await ReactNativeBlobUtil.config({
|
||||
fileCache: false, // important for public folder
|
||||
addAndroidDownloads: {
|
||||
useDownloadManager: true,
|
||||
notification: true,
|
||||
path,
|
||||
mime: 'application/pdf',
|
||||
title: `${fileName}.pdf`,
|
||||
description: 'Downloading document',
|
||||
mediaScannable: true, // 👈 makes it visible instantly
|
||||
},
|
||||
}).fetch('GET', downloadUrl, {
|
||||
Accept: 'application/pdf',
|
||||
});
|
||||
|
||||
console.log('✅ Download completed');
|
||||
console.log('📦 Status:', response.info().status);
|
||||
console.log('📦 Headers:', response.info().headers);
|
||||
console.log('📍 Saved at:', path);
|
||||
|
||||
const stat = await ReactNativeBlobUtil.fs.stat(path);
|
||||
console.log('📦 File size:', stat.size);
|
||||
|
||||
} catch (error: any) {
|
||||
console.log('❌ Download failed');
|
||||
console.log('❌ Error:', error?.message || error);
|
||||
} finally {
|
||||
setAllBoolean((prev: any) => ({ ...prev, fileLoading: false }));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
mutate({ auctionNumber: data?.auctionNumber, status: data?.auctionPattern }, {
|
||||
onSuccess: (res) => {
|
||||
setAuciotnDetail((prev: any) => ({ ...prev, auctionItems: res.data, auctionDocuments }))
|
||||
}, onError: (err) => {
|
||||
console.log(err, '-----auction item error');
|
||||
}
|
||||
});
|
||||
}, [data.auctionNumber, auctionDocuments]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isVisible={visible}
|
||||
@@ -94,12 +155,11 @@ const AuctionFullDetail: React.FC<Props> = ({ visible, onClose, data }) => {
|
||||
{/* 2. Work Description */}
|
||||
<Section title="Auction Details" icon={Briefcase}>
|
||||
<View style={styles.grid}>
|
||||
<InfoBox label="Auction Name" value={'Auction of cars'} />
|
||||
<InfoBox label="Category Of Auction " value={'Live'} />
|
||||
<InfoBox label="Auto Time Increment " value={'yes'} />
|
||||
<InfoBox label="Auction Fees (In Figure) " value={'500'} />
|
||||
<InfoBox label="Auction Fees (In Words)" value={'Five Hundred'} />
|
||||
<InfoBox label="Auction Keyword" value={'Dev Furniture, Furnture'} />
|
||||
<InfoBox label="Auction Name" value={auctionData?.auctionOfWork} />
|
||||
<InfoBox label="Category Of Auction " value={auctionData?.auctionCategories} />
|
||||
<InfoBox label="Auction Fees (In Figure) " value={auctionData?.auctionFees} />
|
||||
<InfoBox label="Auction Fees (In Words)" value={auctionData?.auctionFeesInWord} />
|
||||
<InfoBox label="Auction Keyword" value={auctionData?.auctionKeywordName} />
|
||||
</View>
|
||||
</Section>
|
||||
|
||||
@@ -129,68 +189,55 @@ const AuctionFullDetail: React.FC<Props> = ({ visible, onClose, data }) => {
|
||||
<View style={styles.tableWrapper}>
|
||||
<View style={styles.tableHead}>
|
||||
<Text style={[styles.tableLabel, { flex: 2 }]}>Item</Text>
|
||||
<Text style={styles.tableLabel}>Qty</Text>
|
||||
<Text style={styles.tableLabel}>Time</Text>
|
||||
<Text style={[styles.tableLabel, { textAlign: 'right' }]}>View</Text>
|
||||
</View>
|
||||
{/* Dummy Item Row */}
|
||||
<View style={styles.tableRow}>
|
||||
<View style={{ flex: 2 }}>
|
||||
<Text style={styles.itemMain}>Sick Sari / Laundry</Text>
|
||||
<Text style={styles.itemSub}>Category: Sari</Text>
|
||||
{aucitonDetail?.auctionItems?.map((item: any, index: number) => (
|
||||
<View style={styles.tableRow}>
|
||||
<View style={{ flex: 2 }}>
|
||||
<Text style={styles.itemMain}>{item.productName}</Text>
|
||||
<Text style={styles.itemSub}>Category: {item?.categoryName}</Text>
|
||||
</View>
|
||||
<Text style={styles.itemQty}>{item.timeDurationType}</Text>
|
||||
<TouchableOpacity style={styles.actionIcon} onPress={() => { setAllBoolean((prev: any) => ({ ...prev, showItemDetail: true, selectedItem: item })) }}>
|
||||
<Eye size={18} color={colors.primary} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Text style={styles.itemQty}>120,000</Text>
|
||||
<TouchableOpacity style={styles.actionIcon} onPress={() => { setAllBoolean((prev: any) => ({ ...prev, showItemDetail: true })) }}>
|
||||
<Eye size={18} color={colors.primary} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</Section>
|
||||
|
||||
{/* 5. Downloads */}
|
||||
<Section title="Downloads" icon={Download}>
|
||||
<TouchableOpacity style={styles.fileCard}>
|
||||
<View style={styles.fileIcon}><FileText size={20} color="#ef4444" /></View>
|
||||
<View style={{ flex: 1 }}>
|
||||
<Text style={styles.fileName}>Auction_Notice_Main.pdf</Text>
|
||||
<Text style={styles.fileSize}>1.2 MB • PDF</Text>
|
||||
</View>
|
||||
<Download size={20} color="#94a3b8" />
|
||||
</TouchableOpacity>
|
||||
{aucitonDetail?.auctionDocuments?.map((doc: any, index: number) => (
|
||||
<TouchableOpacity style={styles.fileCard} onPress={() => {
|
||||
handleDownload(
|
||||
doc.auctionDocumentId,
|
||||
doc.fileName.replace('.pdf', '')
|
||||
)
|
||||
}}>
|
||||
<View style={styles.fileIcon}><FileText size={20} color="#ef4444" /></View>
|
||||
<View style={{ flex: 1 }}>
|
||||
<Text style={styles.fileName}>{doc.fileName}</Text>
|
||||
</View>
|
||||
{allBoolean.fileLoading ? (
|
||||
<View >
|
||||
<Loader size='small' color='#94a3b8' />
|
||||
</View>
|
||||
) : (
|
||||
<Download size={20} color="#94a3b8" />
|
||||
)}
|
||||
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</Section>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
{/* Sticky Footer */}
|
||||
<View style={styles.footer}>
|
||||
<TouchableOpacity
|
||||
style={[styles.mainBtn, !isLive && styles.btnDisabled]}
|
||||
disabled={!isLive}
|
||||
>
|
||||
<Text style={styles.mainBtnText}>
|
||||
{isLive ? 'Add to Cart / Purchase' : 'Auction Closed'}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<AuctionItemDetail
|
||||
data={{
|
||||
productName: "sick sari",
|
||||
timeDuration: "112 YEAR",
|
||||
category: "laundry",
|
||||
subCategory: "sari",
|
||||
reservePriceFig: "120000",
|
||||
reservePriceWords: "One Lakh Twenty Thousand",
|
||||
auctionStartFig: "120000",
|
||||
auctionStartWords: "One Lakh Twenty Thousand",
|
||||
bidVariationFig: "200",
|
||||
bidVariationWords: "Two Hundred",
|
||||
emdFig: "2000",
|
||||
emdWords: "Two Thousand",
|
||||
description: "Auction of cars",
|
||||
documentName: "BBPS screens.pdf"
|
||||
}} onClose={() => { setAllBoolean((prev: any) => ({ ...prev, showItemDetail: false })) }} visible={allBoolean.showItemDetail} />
|
||||
{allBoolean.showItemDetail && <AuctionItemDetail data={allBoolean.selectedItem} onClose={() => { setAllBoolean((prev: any) => ({ ...prev, showItemDetail: false })) }} visible={allBoolean.showItemDetail} />}
|
||||
</View>
|
||||
</Modal>
|
||||
</Modal >
|
||||
);
|
||||
};
|
||||
|
||||
@@ -242,7 +289,7 @@ const styles = StyleSheet.create({
|
||||
liveText: { fontSize: 11, fontWeight: '800', color: '#475569' },
|
||||
|
||||
scrollView: { flex: 1, backgroundColor: '#f8fafc' },
|
||||
scrollContent: { padding: 16, paddingBottom: 100 },
|
||||
scrollContent: { padding: 16, paddingBottom: 30 },
|
||||
|
||||
sectionContainer: {
|
||||
backgroundColor: '#fff',
|
||||
|
||||
@@ -1,60 +1,21 @@
|
||||
import React, { memo } from 'react';
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
StyleSheet,
|
||||
TouchableOpacity,
|
||||
ScrollView,
|
||||
SafeAreaView,
|
||||
Platform,
|
||||
StatusBar,
|
||||
Dimensions
|
||||
} from 'react-native';
|
||||
import React, { memo, useState } from 'react';
|
||||
import { View, Text, StyleSheet, TouchableOpacity, ScrollView, Platform, Dimensions } from 'react-native';
|
||||
import Modal from 'react-native-modal';
|
||||
import {
|
||||
X,
|
||||
Package,
|
||||
Clock,
|
||||
Tag,
|
||||
IndianRupee,
|
||||
FileText,
|
||||
Download,
|
||||
ArrowLeft,
|
||||
Info,
|
||||
Layers,
|
||||
ChevronRight
|
||||
} from 'lucide-react-native';
|
||||
import { Package, IndianRupee, FileText, Download, ArrowLeft, Info, } from 'lucide-react-native';
|
||||
import colors from '../../../Constant/Color';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { useAucitonItemDetail } from '../../../Services/BBPS/Hooks';
|
||||
import ReactNativeBlobUtil from 'react-native-blob-util';
|
||||
import { AUCTION_ITEM_DOCUMENT_DOWNLOAD } from '../../../Services/BBPS/ApiUrls';
|
||||
import { Loader } from '../../../Component/Index';
|
||||
|
||||
const { width } = Dimensions.get('window');
|
||||
interface Props { visible: boolean; onClose: () => void; data?: any; }
|
||||
|
||||
// --- Exact Dummy Data Mapping ---
|
||||
const ITEM_DUMMY_DATA = {
|
||||
productName: "sick sari",
|
||||
timeDuration: "112 YEAR",
|
||||
category: "laundry",
|
||||
subCategory: "sari",
|
||||
reservePriceFig: "120000",
|
||||
reservePriceWords: "One Lakh Twenty Thousand",
|
||||
auctionStartFig: "120000",
|
||||
auctionStartWords: "One Lakh Twenty Thousand",
|
||||
bidVariationFig: "200",
|
||||
bidVariationWords: "Two Hundred",
|
||||
emdFig: "2000",
|
||||
emdWords: "Two Thousand",
|
||||
description: "Auction of cars",
|
||||
documentName: "BBPS screens.pdf"
|
||||
};
|
||||
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
onClose: () => void;
|
||||
data?: typeof ITEM_DUMMY_DATA;
|
||||
}
|
||||
|
||||
const AuctionItemDetail: React.FC<Props> = ({ visible, onClose, data = ITEM_DUMMY_DATA }) => {
|
||||
const AuctionItemDetail: React.FC<Props> = ({ visible, onClose, data }) => {
|
||||
const inset = useSafeAreaInsets()
|
||||
const [allBoolean, setAllBoolean] = useState({ fileLoading: false });
|
||||
const { data: itemData } = useAucitonItemDetail({ auctionItemId: data.id });
|
||||
|
||||
const Section = ({ title, icon: Icon, children }: any) => (
|
||||
<View style={styles.sectionCard}>
|
||||
<View style={styles.sectionHeader}>
|
||||
@@ -75,6 +36,50 @@ const AuctionItemDetail: React.FC<Props> = ({ visible, onClose, data = ITEM_DUMM
|
||||
</View>
|
||||
);
|
||||
|
||||
const handleDownload = async (id: number, fileName: string) => {
|
||||
try {
|
||||
setAllBoolean((prev: any) => ({ ...prev, fileLoading: true }));
|
||||
const { dirs } = ReactNativeBlobUtil.fs;
|
||||
|
||||
// ✅ PUBLIC DOWNLOADS DIRECTORY
|
||||
const path = `${dirs.DownloadDir}/${fileName}.pdf`;
|
||||
|
||||
console.log('📂 Saving to:', path);
|
||||
|
||||
const downloadUrl = `${AUCTION_ITEM_DOCUMENT_DOWNLOAD}?auctionItemId=${id}`;
|
||||
console.log('🌐 Download URL:', downloadUrl);
|
||||
|
||||
const response = await ReactNativeBlobUtil.config({
|
||||
fileCache: false, // important for public folder
|
||||
addAndroidDownloads: {
|
||||
useDownloadManager: true,
|
||||
notification: true,
|
||||
path,
|
||||
mime: 'application/pdf',
|
||||
title: `${fileName}.pdf`,
|
||||
description: 'Downloading document',
|
||||
mediaScannable: true, // 👈 makes it visible instantly
|
||||
},
|
||||
}).fetch('GET', downloadUrl, {
|
||||
Accept: 'application/pdf',
|
||||
});
|
||||
|
||||
console.log('✅ Download completed');
|
||||
console.log('📦 Status:', response.info().status);
|
||||
console.log('📦 Headers:', response.info().headers);
|
||||
console.log('📍 Saved at:', path);
|
||||
|
||||
const stat = await ReactNativeBlobUtil.fs.stat(path);
|
||||
console.log('📦 File size:', stat.size);
|
||||
|
||||
} catch (error: any) {
|
||||
console.log('❌ Download failed');
|
||||
console.log('❌ Error:', error?.message || error);
|
||||
} finally {
|
||||
setAllBoolean((prev: any) => ({ ...prev, fileLoading: false }));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isVisible={visible}
|
||||
@@ -106,72 +111,76 @@ const AuctionItemDetail: React.FC<Props> = ({ visible, onClose, data = ITEM_DUMM
|
||||
contentContainerStyle={styles.scrollContent}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
{/* Product Identity Card */}
|
||||
<Section title="Product Specification" icon={Package}>
|
||||
<View style={styles.identityHeader}>
|
||||
<Text style={styles.productNameText}>{data.productName.toUpperCase()}</Text>
|
||||
<View style={styles.categoryBadge}>
|
||||
<Text style={styles.categoryText}>{data.category}</Text>
|
||||
<Text style={styles.categoryText}>{data.categoryName}</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.specGrid}>
|
||||
<View style={styles.specItem}>
|
||||
<Text style={styles.label}>Sub Category</Text>
|
||||
<Text style={styles.specValue}>{data.subCategory}</Text>
|
||||
<Text style={styles.specValue}>{data.subCategoryName}</Text>
|
||||
</View>
|
||||
<View style={styles.specItem}>
|
||||
<Text style={styles.label}>Duration</Text>
|
||||
<Text style={styles.specValue}>{data.timeDuration}</Text>
|
||||
<Text style={styles.specValue}>{data.timeDurationType}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</Section>
|
||||
|
||||
{/* Pricing & Financials */}
|
||||
<Section title="Reserve & Bid Values" icon={IndianRupee}>
|
||||
<PriceTile
|
||||
label="Reserve Price"
|
||||
fig={data.reservePriceFig}
|
||||
words={data.reservePriceWords}
|
||||
fig={data.reservePrice}
|
||||
words={data.reservePriceInWords}
|
||||
full
|
||||
/>
|
||||
<View style={styles.hDivider} />
|
||||
<PriceTile
|
||||
label="Auction Start Value"
|
||||
fig={data.auctionStartFig}
|
||||
words={data.auctionStartWords}
|
||||
fig={data.reservePrice}
|
||||
words={data.reservePriceInWords}
|
||||
full
|
||||
/>
|
||||
<View style={styles.hDivider} />
|
||||
<View style={styles.row}>
|
||||
{/* <View style={styles.row}>
|
||||
<PriceTile label="Bid Variation" fig={data.bidVariationFig} words={data.bidVariationWords} />
|
||||
<PriceTile label="EMD Amount" fig={data.emdFig} words={data.emdWords} />
|
||||
</View>
|
||||
<PriceTile label="Auction Start Value" fig={data.auctionStartValue} words={data.auctionStartValueInWords
|
||||
} />
|
||||
</View> */}
|
||||
</Section>
|
||||
|
||||
{/* Description Card */}
|
||||
<Section title="Brief Description" icon={Info}>
|
||||
<Text style={styles.descContent}>{data.description}</Text>
|
||||
<Text style={styles.descContent}>{data.briefDescription}</Text>
|
||||
</Section>
|
||||
|
||||
{/* Documents Card */}
|
||||
<Section title="View Documents" icon={FileText}>
|
||||
{itemData?.length && <Section title="View Documents" icon={FileText}>
|
||||
<View style={styles.docTableHead}>
|
||||
<Text style={styles.tableLabel}>Sr No.</Text>
|
||||
<Text style={[styles.tableLabel, { flex: 2 }]}>Document Name</Text>
|
||||
<Text style={styles.tableLabel}>Action</Text>
|
||||
</View>
|
||||
|
||||
<TouchableOpacity style={styles.docRow} activeOpacity={0.7}>
|
||||
<Text style={styles.docIndex}>1</Text>
|
||||
<View style={{ flex: 2 }}>
|
||||
<Text style={styles.docTitle} numberOfLines={1}>{data.documentName}</Text>
|
||||
</View>
|
||||
<View style={styles.downloadIconBox}>
|
||||
<Download size={18} color={colors.primary} />
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</Section>
|
||||
{itemData?.map((doc: any, index: any) => (
|
||||
<TouchableOpacity style={styles.docRow} activeOpacity={0.7} onPress={() => { handleDownload(doc.assetId, doc.fileName) }} key={index}>
|
||||
<Text style={styles.docIndex}>{index + 1}</Text>
|
||||
<View style={{ flex: 2 }}>
|
||||
<Text style={styles.docTitle} numberOfLines={1}>{doc.fileName}</Text>
|
||||
</View>
|
||||
<View style={styles.downloadIconBox}>
|
||||
{allBoolean.fileLoading ? (
|
||||
<View >
|
||||
<Loader size='small' color='#94a3b8' />
|
||||
</View>
|
||||
) : (
|
||||
<Download size={20} color={colors.primary} />
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>))}
|
||||
</Section>}
|
||||
|
||||
</ScrollView>
|
||||
</View>
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { View, Text, FlatList, StyleSheet, TouchableOpacity, Alert } from 'react-native';
|
||||
import { InsideHeader, Loader } from '../../Component/Index';
|
||||
import colors from '../../Constant/Color';
|
||||
import { CreditCard, Calendar, User, DollarSign, ArrowRight } from 'lucide-react-native';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useOfflineAuctionPurchase } from '../../Services/BBPS/Hooks';
|
||||
import { useOfflineAuctionPurchase, usePurchaseAuctionList } from '../../Services/BBPS/Hooks';
|
||||
import { showSuccessAlert } from '../../Constant/ShowDailog';
|
||||
import { clearPurchaseAuction } from '../../Redux/Slices/selectPurchaseAuction';
|
||||
import { CommonActions, useNavigation } from '@react-navigation/native';
|
||||
import { CommonActions, useFocusEffect, useNavigation } from '@react-navigation/native';
|
||||
import NavigationString from '../../Constant/NavigationString';
|
||||
import Skeleton from '../../Component/Skelton/Skelton';
|
||||
|
||||
const dummyAuctionList = [
|
||||
{
|
||||
@@ -23,39 +24,18 @@ const dummyAuctionList = [
|
||||
portalCharge: 100,
|
||||
payableAmount: 3050,
|
||||
},
|
||||
{
|
||||
auctionId: 2,
|
||||
auctionNumber: 'AUC-2025-002',
|
||||
auctionPattern: 'Two Stage',
|
||||
auctionDispatchDate: '28 Feb 2025',
|
||||
auctionDispatcherNumber: 'DISP-002',
|
||||
auctionFees: 1800,
|
||||
gst: 18,
|
||||
gstAmount: 324,
|
||||
portalCharge: 80,
|
||||
payableAmount: 2204,
|
||||
},
|
||||
{
|
||||
auctionId: 3,
|
||||
auctionNumber: 'AUC-2025-003',
|
||||
auctionPattern: 'Single Stage',
|
||||
auctionDispatchDate: '01 Mar 2025',
|
||||
auctionDispatcherNumber: 'DISP-003',
|
||||
auctionFees: 3200,
|
||||
gst: 18,
|
||||
gstAmount: 576,
|
||||
portalCharge: 120,
|
||||
payableAmount: 3896,
|
||||
},
|
||||
];
|
||||
|
||||
const PurchaseAuctionList = () => {
|
||||
const Navigation = useNavigation()
|
||||
const Dispatch = useDispatch()
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [list, setList] = useState(dummyAuctionList);
|
||||
const [list, setList] = useState([]);
|
||||
const SelectedPurchaseList = useSelector((state: any) => state.selectPurchaseAuction);
|
||||
const LoginUser = useSelector((state: any) => state.token.token);
|
||||
const { mutate, isPending } = useOfflineAuctionPurchase()
|
||||
const { mutate: purchaseListMutation, isPending: purchaseListPending } = usePurchaseAuctionList();
|
||||
|
||||
const calculateTotalAmount = (item: any) => {
|
||||
const gstAmount =
|
||||
(Number(item.auctionFees) + Number(item.portalCharge)) *
|
||||
@@ -68,7 +48,7 @@ const PurchaseAuctionList = () => {
|
||||
|
||||
const handleOfflinePurchase = async () => {
|
||||
const body = {
|
||||
auctionDetails: SelectedPurchaseList.map((b: any) => ({
|
||||
auctionDetails: list.map((b: any) => ({
|
||||
auctionDispatchDate: b?.auctionDispatchDate,
|
||||
auctionDispatcherNumber: b?.auctionDispatcherNumber,
|
||||
auctionFees: b?.auctionFees,
|
||||
@@ -155,16 +135,37 @@ const PurchaseAuctionList = () => {
|
||||
</View>
|
||||
);
|
||||
|
||||
const getPurchaseList = () => {
|
||||
const auctionNumbers: string[] = SelectedPurchaseList.map(
|
||||
(item: { auctionNumber: string }) => item.auctionNumber
|
||||
);
|
||||
purchaseListMutation({ auctionNumbers, contractorId: LoginUser.contractorId }, {
|
||||
onSuccess: (res) => {
|
||||
if (res.statusCode == 200) {
|
||||
setList(res.data)
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
console.log(error, "=================purchase list error");
|
||||
}
|
||||
})
|
||||
}
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
getPurchaseList()
|
||||
}, [SelectedPurchaseList])
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, backgroundColor: colors.white }}>
|
||||
<InsideHeader title="Purchase List" showArrow />
|
||||
<View style={styles.screen}>
|
||||
<FlatList
|
||||
data={SelectedPurchaseList}
|
||||
{purchaseListPending ? <Skeleton /> : <FlatList
|
||||
data={list}
|
||||
renderItem={renderItem}
|
||||
keyExtractor={(item) => item.auctionId.toString()}
|
||||
contentContainerStyle={styles.container}
|
||||
/>
|
||||
/>}
|
||||
</View>
|
||||
|
||||
<View style={styles.bottomButtonContainer}>
|
||||
|
||||
@@ -31,7 +31,6 @@ const PurchaseAuctionTile = ({ item, onPressDetails, onStartBidding, buttonEnabl
|
||||
const statusColor = isAuctionEnd ? '#EF4444' : buttonEnable ? colors.primary : '#94A3B8';
|
||||
|
||||
const lightStatusBg = isAuctionEnd ? '#FEF2F2' : buttonEnable ? '#EFF6FF' : '#F8FAFC';
|
||||
console.log(item?.keyDates?.auctionBidding?.endDateTime, 'kk');
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1 }}>
|
||||
|
||||
@@ -26,7 +26,7 @@ const PurchaseList = () => {
|
||||
{/* Header */}
|
||||
<View style={styles.header}>
|
||||
<Text style={styles.heading}>Purchase List</Text>
|
||||
<Info size={20} color="#0F172A" />
|
||||
{/* <Info size={20} color="#0F172A" /> */}
|
||||
</View>
|
||||
|
||||
{/* Cards */}
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
import React, { memo, useCallback, useRef } from 'react';
|
||||
import { View, Text, TouchableOpacity, StyleSheet, Platform } from 'react-native';
|
||||
import React, { memo, useCallback, useRef, useState } from 'react';
|
||||
import { View, Text, TouchableOpacity, StyleSheet, Platform, TextInput, Alert } from 'react-native';
|
||||
import Animated, { FadeInUp, Layout, interpolate, useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated';
|
||||
import colors from '../../../Constant/Color';
|
||||
import AuctionItemDetail from '../../Auction/Modal/AuctionItemDetail';
|
||||
import MainStyle from '../../../Styles/MainStyle';
|
||||
import { Loader } from '../../../Component/Index';
|
||||
import { useSelector } from 'react-redux';
|
||||
import axios from 'axios';
|
||||
import Variables from '../../../Constant/Variable';
|
||||
import { showErrorAlert, showSuccessAlert } from '../../../Constant/ShowDailog';
|
||||
|
||||
const BiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid, SelectedAuction }: any) => {
|
||||
const [showDetail, setShowDetail] = React.useState(false);
|
||||
const BiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid, SelectedAuction, allBoolean, setAllBoolean }: any) => {
|
||||
const Token = useSelector((state: any) => state.token.token)
|
||||
const [showDetail, setShowDetail] = useState(false);
|
||||
const [value, setValue] = useState(`${item.bidAmount}`);
|
||||
const [allState, setAllState] = useState({ isLoading: false })
|
||||
const isMin = bidValue <= item.bidAmount;
|
||||
|
||||
// 🔒 Persist expand state safely
|
||||
@@ -26,6 +34,11 @@ const BiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid, Selec
|
||||
opacity: interpolate(animation.value, [0, 0.5, 1], [0, 0, 1]),
|
||||
marginTop: interpolate(animation.value, [0, 1], [0, 15]),
|
||||
}));
|
||||
const bodyStyle2 = useAnimatedStyle(() => ({
|
||||
height: interpolate(animation.value, [0, 1], [0, 100]),
|
||||
opacity: interpolate(animation.value, [0, 0.5, 1], [0, 0, 1]),
|
||||
marginTop: interpolate(animation.value, [0, 1], [0, 15]),
|
||||
}));
|
||||
|
||||
const arrowStyle = useAnimatedStyle(() => ({
|
||||
transform: [
|
||||
@@ -34,6 +47,53 @@ const BiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid, Selec
|
||||
},
|
||||
],
|
||||
}));
|
||||
const MAX_VALUE = Number(item.bidAmount);
|
||||
|
||||
const handleChange = (text: string) => {
|
||||
let cleaned = text.replace(/[^0-9.]/g, '');
|
||||
if ((cleaned.match(/\./g) || []).length > 1) return;
|
||||
setValue(cleaned);
|
||||
};
|
||||
|
||||
|
||||
const oneTimePlaceBid = async () => {
|
||||
try {
|
||||
if (Number(value) < MAX_VALUE) {
|
||||
showErrorAlert("Enter the greather vlaue to current bid value")
|
||||
return false
|
||||
}
|
||||
setAllState((prev: any) => ({ ...prev, isLoading: true }))
|
||||
const payload = {
|
||||
itemId: item.id,
|
||||
bidAmount: Number(value),
|
||||
auctionId: SelectedAuction.auctionId,
|
||||
contractorId: Token.contractorId,
|
||||
fullName: Token.fullName,
|
||||
};
|
||||
|
||||
|
||||
const res = await axios.post(
|
||||
`${Variables.socketUrl}bidding/placeBidForAuction`,
|
||||
[payload],
|
||||
{ headers: { Authentication: `Bearer ${Token.token}` } }
|
||||
);
|
||||
|
||||
if (res.data.statusCode === 200) {
|
||||
showSuccessAlert(res.data.message);
|
||||
}
|
||||
setAllBoolean((prev: any) => ({ ...prev, reload: !prev.reload }))
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
showErrorAlert(error.response?.data.message)
|
||||
} else {
|
||||
console.log('UNKNOWN ERROR:', error);
|
||||
}
|
||||
|
||||
} finally {
|
||||
setAllState((prev: any) => ({ ...prev, isLoading: false }))
|
||||
}
|
||||
}
|
||||
// console.log(item, 'jkjjj');
|
||||
|
||||
return (
|
||||
<View>
|
||||
@@ -80,7 +140,7 @@ const BiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid, Selec
|
||||
<View style={styles.priceRow}>
|
||||
<View>
|
||||
<Text style={styles.label}>Current Bid</Text>
|
||||
<Text style={styles.mainPrice}>₹{item?.bidAmount}</Text>
|
||||
<Text style={styles.mainPrice}>₹{item?.bidAmount || item.auctionStartValueFigure}</Text>
|
||||
</View>
|
||||
|
||||
<View style={{ alignItems: 'flex-end' }}>
|
||||
@@ -92,12 +152,12 @@ const BiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid, Selec
|
||||
</View>
|
||||
|
||||
{/* COLLAPSIBLE BODY */}
|
||||
<Animated.View style={[styles.collapsibleContainer, bodyStyle]}>
|
||||
<Animated.View style={[styles.collapsibleContainer, (!allBoolean.rebid && item.contractorId == undefined) ? bodyStyle : bodyStyle2]}>
|
||||
<View style={styles.divider} />
|
||||
|
||||
<Text style={styles.bidLabel}>Set Your Bid</Text>
|
||||
|
||||
<View style={styles.stepperContainer}>
|
||||
{!allBoolean.oneTimeBid && <View style={styles.stepperContainer}>
|
||||
<TouchableOpacity
|
||||
onPress={onDecrease}
|
||||
disabled={isMin}
|
||||
@@ -114,16 +174,30 @@ const BiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid, Selec
|
||||
<TouchableOpacity onPress={onIncrease} style={styles.stepBtn}>
|
||||
<Text style={styles.stepText}>+</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>}
|
||||
{
|
||||
(allBoolean.oneTimeBid || allBoolean.rebid) && <View style={styles.inputBox2}>
|
||||
<Text style={styles.currency2}>₹</Text>
|
||||
|
||||
<TouchableOpacity
|
||||
style={styles.submitBtn}
|
||||
onPress={onPlaceBid}
|
||||
// activeOpacity={0.85}
|
||||
<TextInput
|
||||
value={value}
|
||||
onChangeText={handleChange}
|
||||
keyboardType="decimal-pad"
|
||||
placeholder="0.00"
|
||||
style={styles.input}
|
||||
placeholderTextColor="#94A3B8"
|
||||
/>
|
||||
</View>
|
||||
}
|
||||
|
||||
{(!allBoolean.rebid && item.contractorId == undefined) ? <TouchableOpacity
|
||||
style={[styles.submitBtn]}
|
||||
onPress={(allBoolean.oneTimeBid || allBoolean.rebid) ? oneTimePlaceBid : onPlaceBid}
|
||||
>
|
||||
<Text style={styles.submitBtnText}>Confirm Bid</Text>
|
||||
</TouchableOpacity>
|
||||
{
|
||||
allState.isLoading ? <Loader size='small' color={colors.white} /> : <Text style={styles.submitBtnText}>Confirm Bid</Text>
|
||||
}
|
||||
</TouchableOpacity> : null}
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
:
|
||||
@@ -135,7 +209,31 @@ const BiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid, Selec
|
||||
};
|
||||
|
||||
export default memo(BiddingCard);
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
inputBox2: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#F1F5F9',
|
||||
borderRadius: 12,
|
||||
height: 45,
|
||||
paddingHorizontal: 12,
|
||||
width: '100%',
|
||||
marginBottom: 20
|
||||
},
|
||||
currency2: {
|
||||
fontSize: 16,
|
||||
fontWeight: 'bold',
|
||||
color: '#64748B',
|
||||
marginRight: 4,
|
||||
},
|
||||
input: {
|
||||
flex: 1,
|
||||
fontSize: 18,
|
||||
fontWeight: '700',
|
||||
color: '#0F172A',
|
||||
width: '100%'
|
||||
},
|
||||
card: {
|
||||
backgroundColor: '#FFF',
|
||||
borderRadius: 24,
|
||||
|
||||
+155
-9
@@ -11,9 +11,12 @@ import { useNavigation } from '@react-navigation/native';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useAuctionItem, useEmdCheck } from '../../Services/BBPS/Hooks';
|
||||
import { apiCall } from '../../Axios/Axios';
|
||||
import { AUCTION_ITEM_SUBMIT, CHECK_TECHNICAL_DOCUMENTAION, GET_TECHNICAL_DOCUMENTAION } from '../../Services/BBPS/ApiUrls';
|
||||
import { AUCITON_SINGLE_EMD, AUCTION_ITEM_SUBMIT, CHECK_TECHNICAL_DOCUMENTAION, GET_AUCTION_DETAILS, GET_TECHNICAL_DOCUMENTAION } from '../../Services/BBPS/ApiUrls';
|
||||
import TemplateFormModal from './Component/TemplateFormModal';
|
||||
import { SelectedItem } from './Type/BidType';
|
||||
import FontsFamily from '../../Constant/FontsFamily';
|
||||
import { all } from 'axios';
|
||||
import { showSuccessAlert } from '../../Constant/ShowDailog';
|
||||
|
||||
|
||||
const Emd = () => {
|
||||
@@ -21,7 +24,7 @@ const Emd = () => {
|
||||
const SelectedAuction = useSelector((state: any) => state.auction.auction)
|
||||
const [selectedItems, setSelectedItems] = useState<SelectedItem[]>([]);
|
||||
const [acceptedPolicy, setAcceptedPolicy] = useState(false);
|
||||
const [allBoolean, setAllBoolean] = useState({ isSubmitEmdLoading: false, isEmdComplete: false, auctionItems: [], technicalDocumentStatus: false, selectTemplate: {}, technicalDocModalVisible: false })
|
||||
const [allBoolean, setAllBoolean]: any = useState({ isSubmitEmdLoading: false, isEmdComplete: false, auctionItems: [], technicalDocumentStatus: false, selectTemplate: {}, technicalDocModalVisible: false, emdType: false, fileName: '', file: {} })
|
||||
const { mutate } = useEmdCheck()
|
||||
const { mutate: AuctionItemMutate, isPending } = useAuctionItem()
|
||||
|
||||
@@ -62,8 +65,15 @@ const Emd = () => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
const pickFileSingle = async () => {
|
||||
try {
|
||||
const res = await pick({ type: ['application/pdf'] });
|
||||
const file = res[0];
|
||||
setAllBoolean((prev: any) => ({ ...prev, file: { name: file.name ?? 'document.pdf', uri: file.uri, type: 'application/pdf' } }))
|
||||
} catch {
|
||||
console.log('Pick cancelled');
|
||||
}
|
||||
};
|
||||
/* ---------------- Render Item ---------------- */
|
||||
const renderItem = ({ item }: any) => {
|
||||
const selected = isSelected(item.id);
|
||||
@@ -201,15 +211,33 @@ const Emd = () => {
|
||||
setAllBoolean((prev: any) => ({ ...prev, isLoading: false }))
|
||||
}
|
||||
}
|
||||
const getAuction = async () => {
|
||||
const selectedRes = await apiCall<any>('get', GET_AUCTION_DETAILS, {}, { id: SelectedAuction.auctionId });
|
||||
const emdType = String(selectedRes.data.emd)
|
||||
.trim()
|
||||
.replace(/\s+/g, ' ')
|
||||
.toLowerCase();
|
||||
|
||||
|
||||
if (selectedRes.statusCode == 200 && emdType === 'auction wise') {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const AlreadyEmdCheck = async () => {
|
||||
try {
|
||||
mutate({ auctionNumber: SelectedAuction.auctionNumber }, {
|
||||
onSuccess: (res => {
|
||||
console.log(SelectedAuction.auctionNumber, res , SelectedAuction,'iiiiiiiiiiiiiiiiiiiiiiiii');
|
||||
|
||||
onSuccess: (async (res) => {
|
||||
if (res.statusCode == 200) {
|
||||
|
||||
if (res.message == 'No EMD Documents') {
|
||||
const result = await getAuction()
|
||||
if (result) {
|
||||
setAllBoolean((prev: any) => ({ ...prev, emdType: true }))
|
||||
return
|
||||
}
|
||||
setAllBoolean((prev: any) => ({ ...prev, isEmdComplete: false }))
|
||||
getAuctionItem()
|
||||
} else {
|
||||
@@ -307,7 +335,53 @@ const Emd = () => {
|
||||
getTemplateDocumentation()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const singleEmdSubmit = async () => {
|
||||
try {
|
||||
setAllBoolean((prev: any) => ({ ...prev, isSubmitEmdLoading: true }))
|
||||
|
||||
if (!acceptedPolicy) {
|
||||
Alert.alert('Policy Required', 'Please accept terms');
|
||||
return;
|
||||
}
|
||||
const formData = new FormData();
|
||||
|
||||
formData.append('auctionId', SelectedAuction.auctionId);
|
||||
formData.append('productImageName', allBoolean.fileName);
|
||||
formData.append('files', allBoolean.file);
|
||||
|
||||
const response = await apiCall<any>(
|
||||
'post',
|
||||
AUCITON_SINGLE_EMD,
|
||||
formData,
|
||||
{},
|
||||
'multipart/form-data'
|
||||
);
|
||||
|
||||
if (response?.statusCode === 200) {
|
||||
showSuccessAlert(response.message || 'EMD submitted successfully');
|
||||
if (SelectedAuction.auctionPattern === 'Forward') {
|
||||
Navigation.navigate(NavigationString.StartBidding)
|
||||
} else {
|
||||
Navigation.navigate(NavigationString.StartReverseBidding)
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
if (error?.response) {
|
||||
console.log('Server error:', error.response.data);
|
||||
} else if (error?.request) {
|
||||
console.log('Network error:', error.request);
|
||||
} else {
|
||||
console.log('Error message:', error.message);
|
||||
}
|
||||
} finally {
|
||||
setAllBoolean((prev: any) => ({ ...prev, isSubmitEmdLoading: false }))
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// getAuction()
|
||||
AlreadyEmdCheck()
|
||||
}, [])
|
||||
|
||||
@@ -323,7 +397,49 @@ const Emd = () => {
|
||||
<Skelton />
|
||||
) : allBoolean.isEmdComplete ? (
|
||||
<EmdComplete onNext={EmdContinueHandle} />
|
||||
) : <>
|
||||
) : allBoolean.emdType ? <View style={{ flex: 1 }}>
|
||||
<View style={styles.container2}>
|
||||
<Text style={{ color: colors.black, fontSize: 17, fontFamily: FontsFamily.poppinsSemiBold }}>Document Name</Text>
|
||||
<TextInput
|
||||
style={styles.input2}
|
||||
placeholder="Enter document name...."
|
||||
value={allBoolean.fileName}
|
||||
editable={true}
|
||||
placeholderTextColor={colors.grayText}
|
||||
onChangeText={(text) => { setAllBoolean((prev: any) => ({ ...prev, fileName: text })) }}
|
||||
/>
|
||||
|
||||
<TouchableOpacity style={styles.button} onPress={() => { pickFileSingle() }}>
|
||||
<Text style={styles.buttonText}>{allBoolean?.file?.name ? allBoolean?.file?.name : 'Choose File'}</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={styles.bottom}>
|
||||
<BouncyCheckbox
|
||||
size={18}
|
||||
fillColor={colors.primary}
|
||||
iconStyle={{ borderRadius: 5, borderWidth: 1.5, borderColor: colors.primary }}
|
||||
innerIconStyle={{ borderRadius: 5 }}
|
||||
isChecked={acceptedPolicy}
|
||||
onPress={() => setAcceptedPolicy(p => !p)}
|
||||
text="I agree to Terms & Privacy Policy"
|
||||
textStyle={styles.policyText}
|
||||
/>
|
||||
|
||||
<TouchableOpacity
|
||||
style={[
|
||||
styles.submitBtn,
|
||||
!acceptedPolicy && styles.disabled,
|
||||
]}
|
||||
onPress={singleEmdSubmit}
|
||||
disabled={!acceptedPolicy}
|
||||
>
|
||||
{
|
||||
allBoolean.isSubmitEmdLoading ? <Loader size='small' color={colors.white} /> : <Text style={styles.submitText}>Submit EMD</Text>
|
||||
}
|
||||
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View> : <>
|
||||
<FlatList
|
||||
data={allBoolean.auctionItems}
|
||||
keyExtractor={(item: any) => item.auctionId}
|
||||
@@ -369,9 +485,29 @@ export default Emd;
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
paddingHorizontal: 10
|
||||
// paddingHorizontal: 10,
|
||||
backgroundColor: colors.white
|
||||
},
|
||||
container2: {
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 10,
|
||||
backgroundColor: colors.white,
|
||||
elevation: 2,
|
||||
borderRadius: 10,
|
||||
marginTop: 20,
|
||||
marginHorizontal: 10
|
||||
|
||||
},
|
||||
button: {
|
||||
backgroundColor: colors.primary,
|
||||
padding: 12,
|
||||
borderRadius: 6,
|
||||
alignItems: 'center',
|
||||
},
|
||||
buttonText: {
|
||||
color: '#fff',
|
||||
fontWeight: '600',
|
||||
},
|
||||
card: {
|
||||
backgroundColor: '#FFFFFF',
|
||||
marginHorizontal: 5,
|
||||
@@ -433,6 +569,16 @@ const styles = StyleSheet.create({
|
||||
fontSize: 14,
|
||||
color: colors.black
|
||||
},
|
||||
input2: {
|
||||
borderWidth: 1,
|
||||
borderColor: '#CBD5E1',
|
||||
borderRadius: 14,
|
||||
padding: 12,
|
||||
backgroundColor: '#FFFFFF',
|
||||
fontSize: 14,
|
||||
color: colors.black,
|
||||
marginBottom: 20
|
||||
},
|
||||
|
||||
uploadBtn: {
|
||||
marginTop: 12,
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useWebSocketService } from '../../socket/Socket';
|
||||
import Variables from '../../Constant/Variable';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { apiCall } from '../../Axios/Axios';
|
||||
import { FORWARD_AUCTION_ITEM, REVERSE_AUCTION_ITEM, SELECTED_AUCTION_ITEM } from '../../Services/BBPS/ApiUrls';
|
||||
import { AUCTION_ONE_TIME_BID, FORWARD_AUCTION_ITEM, GET_AUCTION_DETAILS, REVERSE_AUCTION_ITEM, SELECTED_AUCTION_ITEM } from '../../Services/BBPS/ApiUrls';
|
||||
import BiddingCard from './Component/BiddingCard';
|
||||
import { CommonActions, useFocusEffect, useNavigation } from '@react-navigation/native';
|
||||
import NavigationString from '../../Constant/NavigationString';
|
||||
@@ -20,7 +20,7 @@ const StartBidding = () => {
|
||||
const Navigation: any = useNavigation()
|
||||
const [items, setItems] = useState<any>([]);
|
||||
const [bidValues, setBidValues] = useState<Record<number, number>>({});
|
||||
const [allBoolean, setAllBoolean] = useState({ showSuccess: false, showDialog: false, bidPayload: {} })
|
||||
const [allBoolean, setAllBoolean] = useState({ showSuccess: false, showDialog: false, bidPayload: {}, oneTimeBid: false, rebid: false, reload: false })
|
||||
const { subscribe, createRoom, placeBid } = useWebSocketService(
|
||||
Variables.webSocketUrl,
|
||||
() => console.log('Connected!'),
|
||||
@@ -28,6 +28,25 @@ const StartBidding = () => {
|
||||
loginUser.token,
|
||||
);
|
||||
|
||||
const getAuction = async () => {
|
||||
const selectedRes = await apiCall<any>('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<any>('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 };
|
||||
@@ -36,13 +55,9 @@ const StartBidding = () => {
|
||||
if (SelectedAuction.auctionPattern === 'Forward') {
|
||||
const res = await apiCall<any>('get', FORWARD_AUCTION_ITEM, {}, payload);
|
||||
if (res?.statusCode === 200) auctionItem = res.data || [];
|
||||
} else {
|
||||
const res = await apiCall<any>('get', REVERSE_AUCTION_ITEM, {}, payload);
|
||||
if (res?.statusCode === 200) auctionItem = res.data || [];
|
||||
}
|
||||
|
||||
const selectedRes = await apiCall<any>('get', SELECTED_AUCTION_ITEM, {}, payload);
|
||||
console.log(selectedRes,'jhhhhhhhhhh');
|
||||
|
||||
const uniqueArray: number[] = Array.from(
|
||||
new Set(selectedRes?.data || [])
|
||||
@@ -52,47 +67,96 @@ console.log(selectedRes,'jhhhhhhhhhh');
|
||||
uniqueArray.includes(item.id)
|
||||
);
|
||||
|
||||
if (SelectedAuction.auctionCategories == 'Live') {
|
||||
const result = await createRoom(SelectedAuction.auctionNumber);
|
||||
|
||||
const result = await createRoom(SelectedAuction.auctionNumber);
|
||||
|
||||
subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, data => {
|
||||
console.log('🔥 BID UPDATE:', data);
|
||||
});
|
||||
|
||||
const bidAmountMap2 = new Map<number, { bidAmount: number; contractorId: number }>();
|
||||
|
||||
(result || []).forEach((r: any) => {
|
||||
bidAmountMap2.set(r.auctionItemId, {
|
||||
bidAmount: r.bidAmount,
|
||||
contractorId: r.contractorId,
|
||||
subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, data => {
|
||||
console.log('🔥 BID UPDATE:', data);
|
||||
});
|
||||
});
|
||||
const bidAmountMap2 = new Map<number, { bidAmount: number; contractorId: number }>();
|
||||
|
||||
(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<number, number>();
|
||||
const bidAmountMap = new Map<number, number>();
|
||||
|
||||
(result || []).forEach((r: any) => {
|
||||
bidAmountMap.set(r.auctionItemId, r.bidAmount);
|
||||
});
|
||||
(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.auctionStartValueFigure,
|
||||
bidAvilable: bidData?.bidAmount ?? 0,
|
||||
me: bidData?.contractorId == loginUser.contractorId ? true : false
|
||||
};
|
||||
});
|
||||
const updatedFilteredItems = filteredItems.map(item => {
|
||||
const bidData = bidAmountMap2.get(item.id);
|
||||
return {
|
||||
...item,
|
||||
bidAmount: bidData?.bidAmount ?? item.auctionStartValueFigure,
|
||||
bidAvilable: bidData?.bidAmount ?? 0,
|
||||
me: bidData?.contractorId == loginUser.contractorId ? true : false
|
||||
};
|
||||
});
|
||||
|
||||
const initialBids: Record<number, number> = {};
|
||||
updatedFilteredItems.forEach(item => {
|
||||
initialBids[item.id] = item.bidAmount;
|
||||
});
|
||||
setBidValues(initialBids);
|
||||
setItems(updatedFilteredItems);
|
||||
const initialBids: Record<number, number> = {};
|
||||
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<number, any>();
|
||||
|
||||
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.auctionStartValueFigure,
|
||||
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<number, number> = {};
|
||||
mergedData.forEach(item => {
|
||||
initialBids[item.id] = item.bidAmount;
|
||||
});
|
||||
setBidValues(initialBids);
|
||||
setItems(mergedData)
|
||||
setBidValues(initialBids);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching auction items:', error);
|
||||
}
|
||||
@@ -122,11 +186,14 @@ console.log(selectedRes,'jhhhhhhhhhh');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (SelectedAuction.auctionCategories == 'One-time') {
|
||||
getAuction()
|
||||
}
|
||||
getAllAcutionItems();
|
||||
subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, (data) => { });
|
||||
}, []);
|
||||
|
||||
}, [allBoolean.reload]);
|
||||
|
||||
useEffect(() => {
|
||||
const initial: Record<number, number> = {};
|
||||
@@ -233,6 +300,8 @@ console.log(selectedRes,'jhhhhhhhhhh');
|
||||
return () => subscription.remove();
|
||||
}, [Navigation])
|
||||
);
|
||||
// console.log(bidValues, 'jjfdlsjfldsjfl');
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<InsideHeader title="Bidding Panel" showArrow />
|
||||
@@ -261,9 +330,11 @@ console.log(selectedRes,'jhhhhhhhhhh');
|
||||
onDecrease={() => handleUpdate(item.id, -item.bidVariationValue)}
|
||||
onPlaceBid={() => { submitBid(item) }}
|
||||
SelectedAuction={SelectedAuction}
|
||||
allBoolean={allBoolean}
|
||||
setAllBoolean={setAllBoolean}
|
||||
/>
|
||||
)}
|
||||
contentContainerStyle={{ padding: 16 }}
|
||||
contentContainerStyle={{ padding: 16, paddingBottom: 300 }}
|
||||
/>
|
||||
|
||||
{allBoolean.showSuccess && (
|
||||
|
||||
@@ -142,17 +142,6 @@ const Home = () => {
|
||||
},
|
||||
];
|
||||
|
||||
/* ---------------- WebSocket ---------------- */
|
||||
const { connect } = useWebSocketService(
|
||||
Variables.webSocketUrl,
|
||||
() => console.log('WebSocket Connected'),
|
||||
error => console.log('WebSocket Error:', error),
|
||||
);
|
||||
|
||||
useFocusEffect(() => {
|
||||
connect();
|
||||
});
|
||||
|
||||
return (
|
||||
<View style={styles.screen}>
|
||||
<Header title="Dashboard" />
|
||||
|
||||
@@ -61,13 +61,25 @@ const ITEM_DOCUMENT_DOWNLOAD = `${BASE_URL_Auction}api/auction/home/downloadDocu
|
||||
|
||||
// Rohit
|
||||
const DASHBOARD_COUNT = `${BASE_URL_Auction}api/auction/home/dashboard/counts`
|
||||
const AUCTION_ONE_TIME_BID =`${BASE_URL_Auction}api/bidding/getBidForAuction`
|
||||
const AUCTION_ONE_TIME_BID = `${BASE_URL_Auction}api/bidding/getBidForAuction`
|
||||
const AUCITON_SINGLE_EMD = `${BASE_URL_Auction}api/auction/addEMDDocumentsAuctionWise`
|
||||
const PURCHASE_AUCTION_LIST = `${BASE_URL_Auction}api/auction/proceedToPurchase`
|
||||
const VIEW_AUCTION_ITEM_DETAIL = `${BASE_URL_Auction}api/auction/home/viewDocumentsForAuctionItemDetails`
|
||||
const VIEW_AUCTION_DOCUMENTS = `${BASE_URL_Auction}api/auction/viewDocumentsForAuction`
|
||||
const AUCTION_DOCUMENT_DOWNLOAD = `${BASE_URL_Auction}api/auction/home/downloadDocumentForAuction`
|
||||
const AUCTION_ITEM_DOCUMENT_DOWNLOAD = `${BASE_URL_Auction}api/auction/home/downloadDocument/auctionItemId`
|
||||
|
||||
export {
|
||||
// Rohit
|
||||
VIEW_AUCTION_ITEM_DETAIL,
|
||||
AUCTION_ITEM_DOCUMENT_DOWNLOAD,
|
||||
AUCTION_DOCUMENT_DOWNLOAD,
|
||||
VIEW_AUCTION_DOCUMENTS,
|
||||
AUCITON_SINGLE_EMD,
|
||||
DASHBOARD_COUNT,
|
||||
AUCTION_ONE_TIME_BID,
|
||||
ITEM_DOCUMENT_DOWNLOAD,
|
||||
PURCHASE_AUCTION_LIST,
|
||||
ITEM_DETAIL,
|
||||
TECHNICAL_DOCUMENT_SUBMIT,
|
||||
TECHNICAL_VALUE_SUBMIT,
|
||||
|
||||
+51
-13
@@ -1,5 +1,5 @@
|
||||
import { useInfiniteQuery, useMutation, useQuery } from '@tanstack/react-query';
|
||||
import { fetchAuctionItem, fetchDashboard, fetchEmdCheck, fetchLiveAuction, fetchLiveTender, fetchPurchaseAuction, fetchPurchaseTender, offlineAuctionPurchase, userLogin } from './apis';
|
||||
import { fetchAuctionItem, fetchDashboard, fetchEmdCheck, fetchLiveAuction, fetchLiveTender, fetchPurchaseAuction, fetchPurchaseAuctionList, fetchPurchaseTender, getAuction, offlineAuctionPurchase, userLogin, viewAuctionDocumentDownload, viewAuctionDocuments, viewAuctionItemDocuments } from './apis';
|
||||
|
||||
// User
|
||||
|
||||
@@ -32,6 +32,7 @@ export const useFetchLiveTender = () => {
|
||||
queryFn: () => fetchLiveTender()
|
||||
});
|
||||
};
|
||||
|
||||
export const useFetchPurchaseAuction = () => {
|
||||
return useQuery({
|
||||
queryKey: ['fetchPurchaseAuction',],
|
||||
@@ -39,25 +40,28 @@ export const useFetchPurchaseAuction = () => {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
export const useFetchLiveAuction = () => {
|
||||
return useInfiniteQuery<any>({
|
||||
queryKey: ['fetchLiveAuction',],
|
||||
queryFn: ({ pageParam = 1 }) =>
|
||||
queryKey: ['fetchLiveAuction'],
|
||||
queryFn: ({ pageParam = 0 }) =>
|
||||
fetchLiveAuction({
|
||||
page: pageParam,
|
||||
size: 10,
|
||||
}),
|
||||
initialPageParam: 1,
|
||||
getNextPageParam: (lastPage) => {
|
||||
const { page, size, totalCount } = lastPage;
|
||||
initialPageParam: 0,
|
||||
|
||||
getNextPageParam: (lastPage, allPages) => {
|
||||
const { size, totalCount } = lastPage;
|
||||
const totalPages = Math.ceil(totalCount / size);
|
||||
const nextPage = page + 1;
|
||||
const nextPage = allPages.length;
|
||||
return nextPage < totalPages ? nextPage : undefined;
|
||||
},
|
||||
select: (data) => {
|
||||
|
||||
const mergedResults = data.pages.flatMap((page: any) => page.data ?? []);
|
||||
select: (data) => {
|
||||
const mergedResults = data.pages.flatMap(
|
||||
(page: any) => page?.data ?? []
|
||||
);
|
||||
|
||||
return {
|
||||
...data,
|
||||
result: mergedResults,
|
||||
@@ -67,7 +71,6 @@ export const useFetchLiveAuction = () => {
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Auction Purchase offline
|
||||
|
||||
export const useOfflineAuctionPurchase = () => {
|
||||
@@ -85,6 +88,41 @@ export const useEmdCheck = () => {
|
||||
|
||||
export const useAuctionItem = () => {
|
||||
return useMutation({
|
||||
mutationFn: (payload: any) => fetchAuctionItem(payload),
|
||||
mutationFn: (payload: { auctionNumber: string, status: string }) => fetchAuctionItem(payload),
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// Purchase Auction List
|
||||
export const usePurchaseAuctionList = () => {
|
||||
return useMutation({
|
||||
mutationFn: (payload: any) => fetchPurchaseAuctionList(payload),
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetAuciton = (payload: { auctionId: string }) => {
|
||||
return useQuery({
|
||||
queryKey: ['getAuction'],
|
||||
queryFn: () => getAuction(payload)
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetAucitonDocument = (payload: { auctionId: number }) => {
|
||||
return useQuery({
|
||||
queryKey: ['viewAuctionDocuments'],
|
||||
queryFn: () => viewAuctionDocuments(payload)
|
||||
});
|
||||
};
|
||||
|
||||
export const useAucitonItemDetail = (payload: { auctionItemId: number }) => {
|
||||
return useQuery({
|
||||
queryKey: ['viewAuctionItemDocuments'],
|
||||
queryFn: () => viewAuctionItemDocuments(payload)
|
||||
});
|
||||
};
|
||||
|
||||
export const useAucitonDocDownload = () => {
|
||||
return useMutation({
|
||||
mutationFn: (payload: { documentId: number, isAmendment: boolean }) => viewAuctionDocumentDownload(payload),
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import axios from "axios";
|
||||
import { DASHBOARD_COUNT, EMD_CHECK, FORARD_AUCTION_ITEM, GET_MY_AUCTION, GET_MY_TENDER, LIVE_AUCTION, LIVE_TENDER, LOG_IN_URL, PROCEED_PURCHASE_AUCTION, PURCHASE_OFFLINE_AUCTION, REVERSE_AUCTION_ITEM } from "./ApiUrls";
|
||||
import { AUCTION_DOCUMENT_DOWNLOAD, DASHBOARD_COUNT, EMD_CHECK, FORARD_AUCTION_ITEM, GET_AUCTION_DETAILS, GET_MY_AUCTION, GET_MY_TENDER, LIVE_AUCTION, LIVE_TENDER, LOG_IN_URL, PROCEED_PURCHASE_AUCTION, PURCHASE_AUCTION_LIST, PURCHASE_OFFLINE_AUCTION, REVERSE_AUCTION_ITEM, VIEW_AUCTION_DOCUMENTS, VIEW_AUCTION_ITEM_DETAIL } from "./ApiUrls";
|
||||
import { apiCall } from "../../Axios/Axios";
|
||||
|
||||
// User
|
||||
@@ -32,7 +32,7 @@ export const fetchPurchaseAuction = async (): Promise<any> => {
|
||||
return data
|
||||
}
|
||||
export const fetchLiveAuction = async (payload: any): Promise<any> => {
|
||||
const data = await apiCall<any>('get', `${LIVE_AUCTION}`, {}, { payload });
|
||||
const data = await apiCall<any>('get', `${LIVE_AUCTION}`, {}, payload);
|
||||
return data
|
||||
}
|
||||
|
||||
@@ -71,4 +71,27 @@ export const fetchAuctionItem = async (payload: any): Promise<any> => {
|
||||
} catch (error: any) {
|
||||
throw error.response?.data || error.message;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
export const fetchPurchaseAuctionList = async (payload: any): Promise<any> => {
|
||||
const data = await apiCall<any>('post', `${PURCHASE_AUCTION_LIST}`, payload);
|
||||
return data
|
||||
}
|
||||
|
||||
export const getAuction = async (payload: any) => {
|
||||
const selectedRes = await apiCall<any>('get', GET_AUCTION_DETAILS, {}, { id: payload.auctionId });
|
||||
return selectedRes.data;
|
||||
}
|
||||
export const viewAuctionItemDocuments = async (payload: { auctionItemId: number }) => {
|
||||
const selectedRes = await apiCall<any>('get', VIEW_AUCTION_ITEM_DETAIL, {}, payload);
|
||||
return selectedRes.data;
|
||||
}
|
||||
export const viewAuctionDocuments = async (payload: { auctionId: number }) => {
|
||||
const selectedRes = await apiCall<any>('get', VIEW_AUCTION_DOCUMENTS, {}, payload);
|
||||
return selectedRes.data;
|
||||
}
|
||||
export const viewAuctionDocumentDownload = async (payload: { documentId: number, isAmendment: boolean }) => {
|
||||
const selectedRes = await apiCall<any>('get', AUCTION_DOCUMENT_DOWNLOAD, {}, payload);
|
||||
return selectedRes.data;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// import React, { useCallback, useEffect, useState } from 'react';
|
||||
// import { View, FlatList, StyleSheet, Platform, Alert, BackHandler, Text, ToastAndroid } from 'react-native';
|
||||
// import { View, FlatList, StyleSheet, Platform, Alert, BackHandler, Text } from 'react-native';
|
||||
// import LottieView from 'lottie-react-native';
|
||||
// import { InsideHeader } from '../../Component/Index';
|
||||
// import colors from '../../Constant/Color';
|
||||
@@ -36,12 +36,13 @@
|
||||
// if (SelectedAuction.auctionPattern === 'Forward') {
|
||||
// const res = await apiCall<any>('get', FORWARD_AUCTION_ITEM, {}, payload);
|
||||
// if (res?.statusCode === 200) auctionItem = res.data || [];
|
||||
// } else if(SelectedAuction.auctionPattern === 'Reverse') {
|
||||
// } else {
|
||||
// const res = await apiCall<any>('get', REVERSE_AUCTION_ITEM, {}, payload);
|
||||
// if (res?.statusCode === 200) auctionItem = res.data || [];
|
||||
// }
|
||||
|
||||
// const selectedRes = await apiCall<any>('get', SELECTED_AUCTION_ITEM, {}, payload);
|
||||
// console.log(selectedRes, 'jhhhhhhhhhh');
|
||||
|
||||
// const uniqueArray: number[] = Array.from(
|
||||
// new Set(selectedRes?.data || [])
|
||||
@@ -98,7 +99,7 @@
|
||||
// };
|
||||
|
||||
// subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, async (message) => {
|
||||
|
||||
// // console.log('RAW MESSAGE:', message[message.length - 1]);
|
||||
// const result = message[message.length - 1]
|
||||
|
||||
// const updatedBidItem = (prev: any[]) =>
|
||||
@@ -160,6 +161,7 @@
|
||||
// {
|
||||
// text: 'Submit',
|
||||
// onPress: () => {
|
||||
|
||||
// placeBidSubmit(payload);
|
||||
// },
|
||||
// },
|
||||
@@ -180,7 +182,6 @@
|
||||
// : item
|
||||
// );
|
||||
|
||||
// // ToastAndroid.show(result.message, ToastAndroid.SHORT)
|
||||
// // setItems(updatedBidItem);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user