diff --git a/package-lock.json b/package-lock.json index 8292e86..91c64a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@react-native-community/blur": "^4.4.1", "@react-native-documents/picker": "^11.0.3", "@react-native-masked-view/masked-view": "^0.3.2", + "@react-native-vector-icons/fontisto": "^12.4.0", "@react-navigation/bottom-tabs": "^7.9.0", "@react-navigation/native": "^7.1.26", "@react-navigation/stack": "^7.6.13", @@ -3034,6 +3035,132 @@ "react-native": ">=0.57" } }, + "node_modules/@react-native-vector-icons/common": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/@react-native-vector-icons/common/-/common-12.4.0.tgz", + "integrity": "sha512-t9W0q+AW7WH1Oj5aEg7wGNXDLZJb5sIVkAWo5qtad3PcbBADqoCdikRK/ToLK+xlB0TxjcuL0T74ogudMkYGeA==", + "license": "MIT", + "dependencies": { + "find-up": "^7.0.0", + "picocolors": "^1.1.1", + "plist": "^3.1.0" + }, + "bin": { + "rnvi-update-plist": "lib/commonjs/scripts/updatePlist.js" + }, + "engines": { + "node": ">=20.19.0 <21.0.0 || >=22.0.0" + }, + "peerDependencies": { + "@react-native-vector-icons/get-image": "^12.3.0", + "react": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "@react-native-vector-icons/get-image": { + "optional": true + } + } + }, + "node_modules/@react-native-vector-icons/common/node_modules/find-up": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz", + "integrity": "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==", + "license": "MIT", + "dependencies": { + "locate-path": "^7.2.0", + "path-exists": "^5.0.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-vector-icons/common/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "license": "MIT", + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-vector-icons/common/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-vector-icons/common/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "license": "MIT", + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-vector-icons/common/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/@react-native-vector-icons/common/node_modules/yocto-queue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-vector-icons/fontisto": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/@react-native-vector-icons/fontisto/-/fontisto-12.4.0.tgz", + "integrity": "sha512-0XFOXDTV03Lvz7d0LmzNtvt7BgAupmUcv4HzVdtSccQ9Ak4lmLeBnO6kbP1v4iqcrsATR1xPrhQxTWWIJ90oFQ==", + "license": "MIT", + "dependencies": { + "@react-native-vector-icons/common": "^12.4.0" + }, + "engines": { + "node": ">= 18.0.0" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/@react-native/assets-registry": { "version": "0.79.0", "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.79.0.tgz", @@ -4377,6 +4504,15 @@ "devOptional": true, "license": "MIT" }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", + "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -11176,6 +11312,20 @@ "node": ">=8" } }, + "node_modules/plist": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", + "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.8.8", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -13493,6 +13643,18 @@ "node": ">=4" } }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -13841,6 +14003,15 @@ "async-limiter": "~1.0.0" } }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index 0b27beb..3c534f4 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@react-native-community/blur": "^4.4.1", "@react-native-documents/picker": "^11.0.3", "@react-native-masked-view/masked-view": "^0.3.2", + "@react-native-vector-icons/fontisto": "^12.4.0", "@react-navigation/bottom-tabs": "^7.9.0", "@react-navigation/native": "^7.1.26", "@react-navigation/stack": "^7.6.13", diff --git a/src/Constant/Color.tsx b/src/Constant/Color.tsx index 7f2a093..a936d45 100644 --- a/src/Constant/Color.tsx +++ b/src/Constant/Color.tsx @@ -7,6 +7,7 @@ const colors = { // Secondary (Warm contrast) secondary: '#1B4B66', // Deep blue for balance secondaryLight: '#639599', // Muted blue + secondaryHighLight: '#e1eff2', // Very light blue (backgrounds) // Status colors success: '#22C55E', // Green diff --git a/src/Screens/Tender/tenderBidding/TenderBidding.tsx b/src/Screens/Tender/tenderBidding/TenderBidding.tsx index 53b7ec3..d0f86aa 100644 --- a/src/Screens/Tender/tenderBidding/TenderBidding.tsx +++ b/src/Screens/Tender/tenderBidding/TenderBidding.tsx @@ -15,6 +15,10 @@ import MyInput from '../../../../src/Component/MyInput'; import { pick, types } from '@react-native-documents/picker'; import { InsideHeader } from '../../../Component/Index'; import colors from '../../../Constant/Color'; +import { SUBMIT_ENVELOPE_A, SUBMIT_ENVELOPE_B } from '../../../Services/BBPS/ApiUrls'; +import axios from 'axios'; +import { Fontisto } from '@react-native-vector-icons/fontisto'; +import { useSubmitEnvelopeA, useSubmitEnvelopeB } from '../../../Services/BBPS/Hooks'; type EnvelopeType = 'A' | 'B' | 'C'; type EnvelopeFormState = { @@ -33,27 +37,18 @@ interface InfoRowProps { value: string; } -interface TenderBiddingData { - data?: { - tenderNumber?: string; - nitNo?: string; - emdInFig?: string; - tenderRebid?: boolean; - showEA?: boolean; - showEB?: boolean; - showEC?: boolean; - tenderEnvelopeAList?: any[]; - tenderEnvelopeBList?: any[]; - tenderEnvelopeCList?: any[]; - }; -} - const TenderBidding = () => { - const route = useRoute(); + const route = useRoute(); const navigation = useNavigation(); + const { mutate: submitEnvelopeA, isPending } = useSubmitEnvelopeA(() => { + navigation.goBack() + }) + const { mutate: submitEnvelopeB, isPending: isPendingB } = useSubmitEnvelopeB(() => { + navigation.goBack() + }) const [bidData] = useState(route.params?.tenderData || null); - const tenderData = route.params?.bidData || null; + const tenderData: any= route.params?.bidData || null; const [activeEnvelope, setActiveEnvelope] = useState('A'); const [isLoading, setIsLoading] = useState(false); const [envelopForm, setEnvelopForm] = useState({ @@ -64,7 +59,7 @@ const TenderBidding = () => { const [loading, setLoading] = useState(false) const [loadingUpload, setLoadingUpload] = useState(false) const [check, setCheck] = useState(false) - + const InfoRow = ({ title, value }: InfoRowProps) => ( @@ -145,7 +140,7 @@ const TenderBidding = () => { activeEnvelope === envelopeType !== 'C' && !bidData?.[`envelope${envelopeType}SubmittStatus`]; - + // console.log("tender ana : ", tenderData) return ( @@ -255,8 +250,9 @@ const TenderBidding = () => { }; const buildEnvelopePayload = () => { + const list = - bidData?.[`tenderEnvelope${activeEnvelope}List`] || []; + tenderData?.[`tenderEnvelope${activeEnvelope}List`] || []; const formValues = envelopForm?.[activeEnvelope] || {}; // 🔹 NON-FILE FIELDS (labelType !== '3') @@ -306,17 +302,17 @@ const TenderBidding = () => { }; }); - return payload = { - deptId: bidData?.deptId, - tenderId: bidData?.tenderId, + const payload: any = { + deptId: tenderData?.deptId, + tenderId: tenderData?.tenderId, [`tenderEnvelope${activeEnvelope}NameId`]: - bidData?.[`tenderEnvelope${activeEnvelope}List`]?.[0]?.[ + tenderData?.[`tenderEnvelope${activeEnvelope}List`]?.[0]?.[ `tenderEnvelope${activeEnvelope}NameId` ], [`envelope${activeEnvelope}TemplateName`]: - bidData?.[`tenderEnvelope${activeEnvelope}List`]?.[0]?.[ + tenderData?.[`tenderEnvelope${activeEnvelope}List`]?.[0]?.[ `envelope${activeEnvelope}TemplateName` ], @@ -324,10 +320,11 @@ const TenderBidding = () => { ? fileData : saveData, }; + // console.log("payload : ", payload) + return payload; }; - const validateEnvelope = () => { const list = bidData?.[`tenderEnvelope${activeEnvelope}List`] || []; const formValues = envelopForm[activeEnvelope]; @@ -351,57 +348,35 @@ const TenderBidding = () => { return !missing; }; - - const handleSubmitEnvelopeA = async () => { + const handleSubmitEnvelopeA = () => { if (!validateEnvelope()) { - Alert.alert('Validation Error', 'Please fill all mandatory fields'); - return; + Alert.alert('Validation Error', 'Please fill all mandatory fields') + return } - const payload = buildEnvelopePayload(); - console.log('Envelope A Payload:', payload); - setLoading(true) + const payload = buildEnvelopePayload() + console.log('Envelope A Payload:', payload) + if (envelopForm?.[activeEnvelope]?.[3]) { handleSubmitEnvelopeFile() } - try { - const res = await apiCallForPostWithToken(SUBMIT_ENVELOPE_A, payload) - console.log("res A envelop : ", res) - ToastAndroid.show(res.message, ToastAndroid.SHORT) - - - navigation.goBack() - } catch (error) { - console.log("error A envelop submit : ", error) - } finally { - setLoading(false) - } - }; - - - const handleSubmitEnvelopeB = async () => { + submitEnvelopeA(payload) + } + const handleSubmitEnvelopeB = () => { if (!validateEnvelope()) { - Alert.alert('Validation Error', 'Please fill all mandatory fields'); - return; + Alert.alert('Validation Error', 'Please fill all mandatory fields') + return } - setLoading(true) - const payload = buildEnvelopePayload(); - console.log('Envelope B Payload:', payload); + + const payload = buildEnvelopePayload() + console.log('Envelope A Payload:', payload) + if (envelopForm?.[activeEnvelope]?.[3]) { handleSubmitEnvelopeFile() } - try { - const res = await apiCallForPostWithToken(SUBMIT_ENVELOPE_B, payload) - console.log("res B envelop : ", res) - ToastAndroid.show(res.message, ToastAndroid.SHORT) - navigation.goBack() - } catch (error) { - console.log("error B envelop submit : ", error) - } finally { - setLoading(false) - } + submitEnvelopeB(payload) } const handleSubmitEnvelopeFile = async () => { @@ -422,7 +397,7 @@ const TenderBidding = () => { console.log("reuestDto for fil doc : ", formData) // return - const res = await apiCallForPostWithToken(activeEnvelope === 'B' ? SUBMIT_ENVELOPE_B : SUBMIT_ENVELOPE_A, payload) + const res = await axios.post(activeEnvelope === 'B' ? SUBMIT_ENVELOPE_B : SUBMIT_ENVELOPE_A, payload) console.log(`res file ${activeEnvelope} Payload:`, res) ToastAndroid.show(res.message, ToastAndroid.SHORT) // navigation.goBack() @@ -508,13 +483,13 @@ const TenderBidding = () => { renderItem={({ item }) => renderEnvelopeItem({ item, envelopeType: activeEnvelope })} scrollEnabled={false} /> - {/* + setCheck(!check)}> {check ? : } Check First Terms&Condition - */} + )} @@ -566,7 +541,7 @@ const styles = StyleSheet.create({ alignItems: 'center', }, card: { - backgroundColor: '#fff', + backgroundColor: colors.primaryHighlight, borderRadius: 12, padding: 16, marginBottom: 16, @@ -607,7 +582,7 @@ const styles = StyleSheet.create({ flexWrap: 'wrap', }, envelopeButton: { - backgroundColor: '#EEF2FF', + backgroundColor: colors.secondaryHighLight, paddingVertical: 10, paddingHorizontal: 14, borderRadius: 8, @@ -615,7 +590,7 @@ const styles = StyleSheet.create({ alignItems: 'center', }, envelopeButtonText: { - color: '#3F51B5', + color: colors.primary, fontWeight: '600', fontSize: 14, }, @@ -625,7 +600,7 @@ const styles = StyleSheet.create({ borderRadius: 10, padding: 12, marginBottom: 12, - backgroundColor: '#f9f9f9', + backgroundColor: colors.primaryHighlight, flexDirection: 'row', justifyContent: 'space-between' }, @@ -635,7 +610,7 @@ const styles = StyleSheet.create({ marginVertical: 20, }, primaryButton: { - backgroundColor: '#3F51B5', + backgroundColor: colors.primary, paddingVertical: 14, paddingHorizontal: 28, borderRadius: 10, @@ -657,7 +632,7 @@ const styles = StyleSheet.create({ alignItems: 'center', }, secondaryButtonText: { - color: '#3F51B5', + color: colors.primary, fontWeight: '600', fontSize: 15, }, diff --git a/src/Services/BBPS/Hooks.ts b/src/Services/BBPS/Hooks.ts index 2d3c1c9..21f1e6e 100644 --- a/src/Services/BBPS/Hooks.ts +++ b/src/Services/BBPS/Hooks.ts @@ -1,5 +1,6 @@ import { useInfiniteQuery, useMutation, useQuery } from '@tanstack/react-query'; -import { fetchDashboard, fetchLiveAuction, fetchLiveTender, fetchPurchaseAuction, fetchPurchaseTender, offlineAuctionPurchase, userLogin, offlineTenderPurchase, fetchTenderById, proceedToBid } from './apis'; +import { fetchDashboard, fetchLiveAuction, fetchLiveTender, fetchPurchaseAuction, fetchPurchaseTender, offlineAuctionPurchase, userLogin, offlineTenderPurchase, fetchTenderById, proceedToBid, submitEnvelopeA, submitEnvelopeB } from './apis'; +import { ToastAndroid } from 'react-native'; // User @@ -121,3 +122,29 @@ export const useProceedToBid = (tenderId?: string) => { }; +export const useSubmitEnvelopeA = (onSuccessCallback?: () => void) => { + return useMutation({ + mutationFn: submitEnvelopeA, + onSuccess: (data) => { + ToastAndroid.show(data?.message || 'Submitted successfully', ToastAndroid.SHORT) + onSuccessCallback?.() + }, + onError: (error: any) => { + console.log('Envelope A submit error:', error) + ToastAndroid.show('Something went wrong', ToastAndroid.SHORT) + }, + }) +} +export const useSubmitEnvelopeB = (onSuccessCallback?: () => void) => { + return useMutation({ + mutationFn: submitEnvelopeB, + onSuccess: (data) => { + ToastAndroid.show(data?.message || 'Submitted successfully', ToastAndroid.SHORT) + onSuccessCallback?.() + }, + onError: (error: any) => { + console.log('Envelope A submit error:', error) + ToastAndroid.show('Something went wrong', ToastAndroid.SHORT) + }, + }) +} \ No newline at end of file diff --git a/src/Services/BBPS/apis.ts b/src/Services/BBPS/apis.ts index d952b04..cf22cde 100644 --- a/src/Services/BBPS/apis.ts +++ b/src/Services/BBPS/apis.ts @@ -1,5 +1,5 @@ import axios from "axios"; -import { DASHBOARD_COUNT, GET_MY_AUCTION, GET_MY_TENDER, GET_TENDER_DETAILS, LIVE_AUCTION, LIVE_TENDER, LOG_IN_URL, PROCEED_PURCHASE_AUCTION, PROCEED_TO_BID, PURCHASE_TENDER_OFFLINE, TENDER_LOGIN } from "./ApiUrls"; +import { DASHBOARD_COUNT, GET_MY_AUCTION, GET_MY_TENDER, GET_TENDER_DETAILS, LIVE_AUCTION, LIVE_TENDER, LOG_IN_URL, PROCEED_PURCHASE_AUCTION, PROCEED_TO_BID, PURCHASE_TENDER_OFFLINE, SUBMIT_ENVELOPE_A, SUBMIT_ENVELOPE_B, SUBMIT_ENVELOPE_FILE_A, SUBMIT_ENVELOPE_FILE_B, TENDER_LOGIN } from "./ApiUrls"; import { apiCall } from "../../Axios/Axios"; // User @@ -83,3 +83,16 @@ export const proceedToBid = async (tenderId: string): Promise => { ); return data; } + +export const submitEnvelopeA = async (payload: any) => { + const { data } = await apiCall('post', SUBMIT_ENVELOPE_A, payload) + return data +} +export const submitEnvelopeB = async (payload: any) => { + const { data } = await apiCall('post', SUBMIT_ENVELOPE_B, payload) + return data +} +export const submitEnvelopeFileB = async (payload: any) => { + const { data } = await apiCall('post', SUBMIT_ENVELOPE_FILE_B, payload) + return data +} \ No newline at end of file