Merge branch 'etender' of https://git.zeptic.in/rohit/Procurelinc into dev
This commit is contained in:
Generated
-12692
File diff suppressed because it is too large
Load Diff
@@ -36,8 +36,6 @@
|
||||
"react-native-blob-util": "^0.24.6",
|
||||
"react-native-bouncy-checkbox": "^4.1.2",
|
||||
"react-native-date-picker": "^5.0.13",
|
||||
"react-native-element-dropdown": "^2.12.4",
|
||||
"react-native-file-viewer": "^2.1.5",
|
||||
"react-native-fs": "^2.20.0",
|
||||
"react-native-gesture-handler": "^2.30.0",
|
||||
"react-native-gifted-charts": "^1.4.70",
|
||||
|
||||
+1
-2
@@ -44,8 +44,7 @@ export const apiCall = async <R, D = {}>(
|
||||
'Content-Type': contentType || 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
console.log("Api response",response)
|
||||
|
||||
return response.data;
|
||||
} catch (error: any) {
|
||||
const errorMessage = error?.response?.data?.error;
|
||||
|
||||
@@ -1,27 +1,36 @@
|
||||
import { StyleSheet, Text, View, ScrollView, TouchableOpacity } from 'react-native';
|
||||
import React from 'react';
|
||||
import { InsideHeader } from '../../Component/Index';
|
||||
import colors from '../../Constant/Color';
|
||||
import { useNavigation, useRoute } from '@react-navigation/native';
|
||||
import { useProceedToBid } from '../../Services/BBPS/Hooks';
|
||||
import { format } from '../../Helper/DateFormat';
|
||||
import FontsFamily from '../../Constant/FontsFamily';
|
||||
import { StyleSheet, Text, View, ScrollView, StatusBar, TouchableOpacity, RefreshControl } from 'react-native'
|
||||
import React, { useEffect } from 'react'
|
||||
import { InsideHeader } from '../../Component/Index'
|
||||
import colors from '../../Constant/Color'
|
||||
import { useNavigation, useRoute } from '@react-navigation/native'
|
||||
import { useFetchTenderById, useProceedToBid } from '../../Services/BBPS/Hooks'
|
||||
import FontsFamily from '../../Constant/FontsFamily'
|
||||
|
||||
const ProceedToBidDetail = () => {
|
||||
const route: any = useRoute();
|
||||
const tenderData = route.params?.tender;
|
||||
const navigation = useNavigation<any>();
|
||||
const { data, refetch } = useProceedToBid(tenderData?.tenderId);
|
||||
// Sample data based on your JSON
|
||||
const route = useRoute<any>();
|
||||
const tenderDataId = route.params?.tender;
|
||||
const { data, refetch } = useProceedToBid(tenderDataId?.tenderId);
|
||||
const { data: tenderResponse , refetch:tenderRefetch}: any = useFetchTenderById(tenderDataId?.tenderId);
|
||||
const tenderData = tenderResponse?.data;
|
||||
const [refreshing, setRefreshing] = React.useState(false);
|
||||
|
||||
console.log("proceed to bid tender detail : ", tenderDataId)
|
||||
console.log("proceed to data detail : ", data)
|
||||
console.log("tender data for updated : ", tenderData)
|
||||
const navigation = useNavigation<any>()
|
||||
// Format date from array
|
||||
|
||||
const handleStartBidding = () => {
|
||||
refetch();
|
||||
if (data) {
|
||||
console.log(" ppp",tenderData ,"ll",data)
|
||||
navigation.navigate('TenderBidding', { tenderData: tenderData, bidData: data.data });
|
||||
}
|
||||
};
|
||||
|
||||
// Status indicator component
|
||||
const StatusIndicator = ({ status, label }: { status: any, label: string }) => (
|
||||
const StatusIndicator = ({ status, label }: { status: boolean; label: string }) => (
|
||||
<View style={styles.statusContainer}>
|
||||
<View style={[styles.statusDot, { backgroundColor: status ? colors.success : colors.error }]} />
|
||||
<Text style={[styles.statusText, { color: status ? colors.success : colors.error, fontFamily: FontsFamily.poppinsSemiBold }]}>
|
||||
@@ -31,16 +40,14 @@ const ProceedToBidDetail = () => {
|
||||
);
|
||||
|
||||
// Envelope log card component
|
||||
const EnvelopeLogCard = ({ log, title }: { log: any, title: string }) => {
|
||||
|
||||
return (
|
||||
<View style={styles.envelopeCard}>
|
||||
<View style={styles.cardHeader}>
|
||||
<Text style={[styles.cardTitle, { fontFamily: FontsFamily.poppinsSemiBold }]}>{title}</Text>
|
||||
<View style={[styles.envelopeBadge, { backgroundColor: colors.primary }]}>
|
||||
<Text style={[styles.envelopeBadgeText, { fontFamily: FontsFamily.poppinsSemiBold }]}>{log?.envelope}</Text>
|
||||
</View>
|
||||
const EnvelopeLogCard = ({ log, title }: { log: any; title: string }) => (
|
||||
<View style={styles.envelopeCard}>
|
||||
<View style={styles.cardHeader}>
|
||||
<Text style={styles.cardTitle}>{title}</Text>
|
||||
<View style={[styles.envelopeBadge, { backgroundColor: colors.primary }]}>
|
||||
<Text style={styles.envelopeBadgeText}>{log?.envelope}</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.logDetailRow}>
|
||||
<Text style={[styles.label, { fontFamily: FontsFamily.poppinsMedium }]}>Activity:</Text>
|
||||
@@ -78,7 +85,7 @@ const ProceedToBidDetail = () => {
|
||||
}
|
||||
|
||||
// Information row component
|
||||
const InfoRow = ({ label, value, isHighlighted = false }: { label: string, value: string, isHighlighted?: boolean }) => (
|
||||
const InfoRow = ({ label, value, isHighlighted = false }: { label: string; value: string; isHighlighted?: boolean }) => (
|
||||
<View style={styles.infoRow}>
|
||||
<Text style={[styles.infoLabel, { fontFamily: FontsFamily.poppinsMedium }]}>{label}:</Text>
|
||||
<Text style={[styles.infoValue, isHighlighted && styles.highlightedValue, { fontFamily: FontsFamily.poppinsSemiBold }]}>{value}</Text>
|
||||
@@ -86,7 +93,7 @@ const ProceedToBidDetail = () => {
|
||||
);
|
||||
|
||||
// Feature chip component
|
||||
const FeatureChip = ({ label, enabled }: { label: string, enabled: boolean }) => (
|
||||
const FeatureChip = ({ label, enabled }: { label: string; enabled: boolean }) => (
|
||||
<View style={[styles.chip, { backgroundColor: enabled ? colors.successLight : colors.lightGray }]}>
|
||||
<Text style={[styles.chipText, { color: enabled ? colors.success : colors.darkGray, fontFamily: FontsFamily.poppinsSemiBold }]}>
|
||||
{label} {enabled ? '✓' : '✗'}
|
||||
@@ -94,12 +101,33 @@ const ProceedToBidDetail = () => {
|
||||
</View>
|
||||
);
|
||||
|
||||
const onRefresh = async () => {
|
||||
try {
|
||||
setRefreshing(true);
|
||||
await refetch();
|
||||
} finally {
|
||||
setRefreshing(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(()=>{
|
||||
tenderRefetch()
|
||||
},[tenderDataId?.tenderId])
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, backgroundColor: colors.white }}>
|
||||
<InsideHeader title="Tender Detail" showArrow />
|
||||
|
||||
<ScrollView style={styles.container} showsVerticalScrollIndicator={false} contentContainerStyle={{ paddingBottom: 100 }}>
|
||||
{/* Tender Header */}
|
||||
<ScrollView style={styles.container} showsVerticalScrollIndicator={false}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={onRefresh}
|
||||
colors={[colors.primary]} // Android
|
||||
tintColor={colors.primary} // iOS
|
||||
/>
|
||||
}>
|
||||
{/* Tender Header Section */}
|
||||
<View style={styles.headerCard}>
|
||||
<View style={styles.tenderHeader}>
|
||||
<View>
|
||||
|
||||
@@ -21,6 +21,8 @@ const PurchaseTenderTile = ({ item, onPressDetails }: any) => {
|
||||
const { data: tenderResponse, }: any = useFetchTenderById(item?.tenderId);
|
||||
const tender = tenderResponse?.data;
|
||||
|
||||
|
||||
console.log("tender for bid : ", tender)
|
||||
const handlePressIn = () => {
|
||||
scale.value = withTiming(0.97, { duration: 120 });
|
||||
elevation.value = withTiming(3, { duration: 120 });
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { View, Text, TextInput, ScrollView, TouchableOpacity, StyleSheet, ActivityIndicator, Alert, } from 'react-native';
|
||||
import RNFS from 'react-native-fs';
|
||||
import * as XLSX from 'xlsx';
|
||||
import axios from 'axios';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { InsideHeader } from '../../../Component/Index';
|
||||
import colors from '../../../Constant/Color';
|
||||
import { GET_ENVELOPE_C, SUBMIT_ENVELOPE_C_UPLOAD } from '../../../Services/BBPS/ApiUrls';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
|
||||
|
||||
// Excel column keys
|
||||
const QTY_KEY = '__EMPTY_1';
|
||||
const RATE_KEY = '__EMPTY_2';
|
||||
const VALUE_KEY = '__EMPTY_3';
|
||||
const TOTAL_LABEL = 'TOTAL';
|
||||
|
||||
const EnvelopeCExcelPreview = (tenderData: any) => {
|
||||
const token = useSelector((state: any) => state.token.token);
|
||||
const navigation = useNavigation() as any;
|
||||
const [data, setData] = useState<any[]>([]);
|
||||
const [columns, setColumns] = useState<string[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
loadExcelFromApi();
|
||||
}, []);
|
||||
|
||||
// ArrayBuffer → Base64
|
||||
const arrayBufferToBase64 = (buffer: ArrayBuffer) => {
|
||||
let binary = '';
|
||||
const bytes = new Uint8Array(buffer);
|
||||
for (let i = 0; i < bytes.length; i++) {
|
||||
binary += String.fromCharCode(bytes[i]);
|
||||
}
|
||||
return global.btoa(binary);
|
||||
};
|
||||
|
||||
// Calculate TOTAL VALUE
|
||||
const calculateTotal = (rows: any[]) =>
|
||||
rows.reduce((sum, row) => {
|
||||
if (typeof row['DEMO DEPARTEMENT'] !== 'number') return sum;
|
||||
const val = Number(row[VALUE_KEY]);
|
||||
return sum + (isNaN(val) ? 0 : val);
|
||||
}, 0);
|
||||
|
||||
// LOAD EXCEL
|
||||
const loadExcelFromApi = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
|
||||
const response = await axios.get(`${GET_ENVELOPE_C}${tenderData?.tenderId?.tenderId}`, {
|
||||
responseType: 'arraybuffer',
|
||||
headers: {
|
||||
Authentication: `Bearer ${token.token}`,
|
||||
},
|
||||
});
|
||||
|
||||
const base64 = arrayBufferToBase64(response.data);
|
||||
const workbook = XLSX.read(base64, { type: 'base64' });
|
||||
const sheet = workbook.Sheets[workbook.SheetNames[0]];
|
||||
const rows: any[] = XLSX.utils.sheet_to_json(sheet, { defval: '' });
|
||||
|
||||
setColumns(Object.keys(rows[0] || {}));
|
||||
setData(rows);
|
||||
|
||||
await RNFS.writeFile(
|
||||
`${RNFS.DocumentDirectoryPath}/envelopeC.xlsx`,
|
||||
base64,
|
||||
'base64'
|
||||
);
|
||||
} catch (e) {
|
||||
Alert.alert('Error', 'Failed to load Excel');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// UPDATE CELL (QTY / RATE) + AUTO VALUE + AUTO TOTAL
|
||||
const updateCell = (rowIndex: number, key: string, value: string) => {
|
||||
const updated = [...data];
|
||||
const row = updated[rowIndex];
|
||||
|
||||
// TOTAL row locked
|
||||
if (row['DEMO DEPARTEMENT'] === TOTAL_LABEL) return;
|
||||
|
||||
// Allow only QTY & RATE edit
|
||||
if (key === QTY_KEY || key === RATE_KEY) {
|
||||
row[key] = value;
|
||||
|
||||
const qty = Number(row[QTY_KEY]);
|
||||
const rate = Number(row[RATE_KEY]);
|
||||
|
||||
// 🔥 Auto VALUE = QTY × RATE
|
||||
row[VALUE_KEY] =
|
||||
!isNaN(qty) && !isNaN(rate) ? qty * rate : 0;
|
||||
}
|
||||
|
||||
// 🔥 Update TOTAL
|
||||
const totalRowIndex = updated.findIndex(
|
||||
r => r['DEMO DEPARTEMENT'] === TOTAL_LABEL
|
||||
);
|
||||
|
||||
if (totalRowIndex !== -1) {
|
||||
updated[totalRowIndex][VALUE_KEY] = calculateTotal(updated);
|
||||
}
|
||||
|
||||
setData(updated);
|
||||
};
|
||||
|
||||
// SAVE UPDATED EXCEL
|
||||
const saveUpdatedExcel = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
|
||||
const worksheet = XLSX.utils.json_to_sheet(data);
|
||||
const workbook = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
|
||||
|
||||
// Generate binary string
|
||||
const binary = XLSX.write(workbook, {
|
||||
bookType: 'xlsx',
|
||||
type: 'binary',
|
||||
});
|
||||
|
||||
// Convert binary string to buffer
|
||||
const buffer = new Uint8Array(binary.length);
|
||||
for (let i = 0; i < binary.length; i++) {
|
||||
buffer[i] = binary.charCodeAt(i) & 0xff;
|
||||
}
|
||||
|
||||
|
||||
const filePath = `${RNFS.DocumentDirectoryPath}/envelopeC_updated.xlsx`;
|
||||
|
||||
// Write as binary
|
||||
await RNFS.writeFile(filePath, buffer.toString(), 'ascii');
|
||||
// const fileBinary = await RNFS.readFile(filePath, 'ascii');
|
||||
|
||||
// console.log('Excel binary content:', fileBinary);
|
||||
// Alert.alert('Success', 'Excel saved successfully');
|
||||
const formData = new FormData();
|
||||
|
||||
// requestDto payload
|
||||
formData.append(
|
||||
'requestDto',
|
||||
JSON.stringify({
|
||||
tenderId: tenderData?.tenderId?.tenderId,
|
||||
deptId: tenderData?.tenderId?.deptId,
|
||||
typesOfTender: tenderData?.tenderId?.typesOfTender,
|
||||
fieldValue: '',
|
||||
fieldValueInWord: 'zero',
|
||||
})
|
||||
);
|
||||
|
||||
// binary file
|
||||
formData.append('file', {
|
||||
uri: `file://${filePath}`,
|
||||
name: 'envelopeC_updated.xlsx',
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
});
|
||||
|
||||
const res = await axios.post(SUBMIT_ENVELOPE_C_UPLOAD, formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
Authentication: `Bearer ${token.token}`,
|
||||
},
|
||||
});
|
||||
navigation.goBack();
|
||||
console.log("res of updated excel file : ", res)
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
Alert.alert('Error', 'Save failed');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<View style={styles.loader}>
|
||||
<ActivityIndicator size="large" />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
|
||||
<ScrollView horizontal contentContainerStyle={{ paddingHorizontal: 10, paddingTop: 20, backgroundColor: colors.white }}>
|
||||
<View>
|
||||
{/* HEADER */}
|
||||
<View style={styles.row}>
|
||||
{columns.map(col => (
|
||||
<Text key={col} style={styles.headerCell}>
|
||||
{col}
|
||||
</Text>
|
||||
))}
|
||||
</View>
|
||||
|
||||
{/* DATA */}
|
||||
<ScrollView style={{ maxHeight: 420 }}>
|
||||
{data.map((row, rowIndex) => (
|
||||
<View key={rowIndex} style={styles.row}>
|
||||
{columns.map(key => {
|
||||
const isTotal = row['DEMO DEPARTEMENT'] === TOTAL_LABEL;
|
||||
const isEditable =
|
||||
!isTotal && (key === QTY_KEY || key === RATE_KEY);
|
||||
|
||||
return (
|
||||
<TextInput
|
||||
key={key}
|
||||
value={String(row[key])}
|
||||
editable={isEditable}
|
||||
keyboardType={
|
||||
key === QTY_KEY || key === RATE_KEY
|
||||
? 'numeric'
|
||||
: 'default'
|
||||
}
|
||||
style={[
|
||||
styles.cell,
|
||||
isTotal && styles.totalCell,
|
||||
key === VALUE_KEY && styles.valueCell,
|
||||
]}
|
||||
onChangeText={text =>
|
||||
updateCell(rowIndex, key, text)
|
||||
}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
))}
|
||||
</ScrollView>
|
||||
</View>
|
||||
</ScrollView>
|
||||
|
||||
<TouchableOpacity style={styles.button} onPress={saveUpdatedExcel}>
|
||||
<Text style={styles.buttonText}>Save Updated Excel</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default EnvelopeCExcelPreview;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: { flex: 1, backgroundColor: '#fff' },
|
||||
loader: { flex: 1, justifyContent: 'center', alignItems: 'center' },
|
||||
title: { fontSize: 18, fontWeight: '700', marginBottom: 10 },
|
||||
row: { flexDirection: 'row' },
|
||||
headerCell: {
|
||||
minWidth: 140,
|
||||
padding: 10,
|
||||
backgroundColor: '#f1f5f9',
|
||||
borderWidth: 1,
|
||||
fontWeight: '700',
|
||||
},
|
||||
cell: {
|
||||
minWidth: 140,
|
||||
padding: 10,
|
||||
borderWidth: 1,
|
||||
borderColor: '#cbd5e1',
|
||||
},
|
||||
valueCell: {
|
||||
backgroundColor: '#f8fafc',
|
||||
},
|
||||
totalCell: {
|
||||
backgroundColor: '#e5e7eb',
|
||||
fontWeight: '700',
|
||||
},
|
||||
button: {
|
||||
marginTop: 15,
|
||||
backgroundColor: colors.primary,
|
||||
padding: 14,
|
||||
borderRadius: 8,
|
||||
},
|
||||
buttonText: {
|
||||
color: '#fff',
|
||||
textAlign: 'center',
|
||||
fontWeight: '600',
|
||||
},
|
||||
});
|
||||
@@ -18,6 +18,9 @@ import colors from '../../../Constant/Color';
|
||||
import { SUBMIT_ENVELOPE_A, SUBMIT_ENVELOPE_B, SUBMIT_ENVELOPE_FILE_A, SUBMIT_ENVELOPE_FILE_B } from '../../../Services/BBPS/ApiUrls';
|
||||
import { CheckSquare, Square } from 'lucide-react-native';
|
||||
import { apiCall } from '../../../Axios/Axios';
|
||||
import EditableExcel from '../component/EditableExcel';
|
||||
import axios from 'axios';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
type EnvelopeType = 'A' | 'B' | 'C';
|
||||
type EnvelopeFormState = {
|
||||
@@ -39,6 +42,7 @@ interface InfoRowProps {
|
||||
const TenderBidding = () => {
|
||||
const route = useRoute<any>();
|
||||
const navigation = useNavigation();
|
||||
const token = useSelector((state: any) => state.token.token);
|
||||
|
||||
const [bidData] = useState<any>(route.params?.tenderData || null);
|
||||
const tenderData: any = route.params?.bidData || null;
|
||||
@@ -130,7 +134,7 @@ const TenderBidding = () => {
|
||||
const labelType = item?.[`labelType${envelopeType}`] || '';
|
||||
|
||||
const showInput =
|
||||
activeEnvelope === envelopeType !== 'C' &&
|
||||
activeEnvelope === envelopeType &&
|
||||
!bidData?.[`envelope${envelopeType}SubmittStatus`];
|
||||
|
||||
// console.log("tender ana : ", tenderData)
|
||||
@@ -214,11 +218,12 @@ const TenderBidding = () => {
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const hasC = activeEnvelope === 'C' && !tenderData?.envelopeCSubmittStatus;
|
||||
;
|
||||
const hasEnvelopes = () => {
|
||||
const hasA = tenderData?.tenderEnvelopeAList?.length > 0;
|
||||
const hasB = tenderData?.tenderEnvelopeBList?.length > 0;
|
||||
// const hasC = tenderData?.tenderEnvelopeCList?.length > 0;
|
||||
|
||||
return hasA || hasB;
|
||||
};
|
||||
|
||||
@@ -352,12 +357,12 @@ const TenderBidding = () => {
|
||||
console.log('Envelope A Payload:', payload);
|
||||
setLoading(true)
|
||||
if (envelopForm?.[activeEnvelope]?.[3]) {
|
||||
handleSubmitEnvelopeFile()
|
||||
handleSubmitEnvelopeFile(SUBMIT_ENVELOPE_FILE_A)
|
||||
return
|
||||
}
|
||||
try {
|
||||
|
||||
const res = await apiCall('post',SUBMIT_ENVELOPE_A, payload)
|
||||
const res = await apiCall('post', SUBMIT_ENVELOPE_A, payload) as any
|
||||
console.log("res A envelop : ", res)
|
||||
ToastAndroid.show(res?.message, ToastAndroid.SHORT)
|
||||
|
||||
@@ -382,11 +387,11 @@ const TenderBidding = () => {
|
||||
|
||||
|
||||
if (envelopForm?.[activeEnvelope]?.[3]) {
|
||||
handleSubmitEnvelopeFile()
|
||||
handleSubmitEnvelopeFile(SUBMIT_ENVELOPE_FILE_B)
|
||||
return
|
||||
}
|
||||
try {
|
||||
const res = await apiCall('post', SUBMIT_ENVELOPE_B, payload)
|
||||
const res = await apiCall('post', SUBMIT_ENVELOPE_B, payload) as any
|
||||
console.log("res B envelop : ", res)
|
||||
|
||||
ToastAndroid.show(res.message, ToastAndroid.SHORT)
|
||||
@@ -398,11 +403,10 @@ const TenderBidding = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleSubmitEnvelopeFile = async () => {
|
||||
|
||||
const handleSubmitEnvelopeFile = async (url: string) => {
|
||||
console.log("url :: ", url)
|
||||
setLoadingUpload(true)
|
||||
const payload = buildEnvelopePayload();
|
||||
console.log(`Envelope file ${activeEnvelope} Payload:`, payload);
|
||||
try {
|
||||
const formData = new FormData();
|
||||
|
||||
@@ -411,23 +415,27 @@ const TenderBidding = () => {
|
||||
name: envelopForm?.[activeEnvelope]?.[3].name,
|
||||
type: envelopForm?.[activeEnvelope]?.[3].type,
|
||||
});
|
||||
formData.append('requestDto', payload)
|
||||
|
||||
|
||||
console.log("reuestDto for fil doc : ", formData)
|
||||
const res = await apiCall('post', activeEnvelope === 'B' ? SUBMIT_ENVELOPE_FILE_B : SUBMIT_ENVELOPE_FILE_A, payload)
|
||||
console.log(`res file ${activeEnvelope} Payload:`, res)
|
||||
// formData.append('requestDto', payload)
|
||||
console.log("first token : ", token?.token)
|
||||
formData.append('requestDto', JSON.stringify(payload))
|
||||
console.log("payload for fil doc : ", formData)
|
||||
const res = await axios.post(url, formData, {
|
||||
headers: {
|
||||
Authentication: `Bearer ${token?.token}`,
|
||||
'Content-Type': 'multipart/form-data'
|
||||
},
|
||||
}) as any;
|
||||
console.log(`res file ${activeEnvelope} api response:`, res)
|
||||
ToastAndroid.show(res.message, ToastAndroid.SHORT)
|
||||
// navigation.goBack()
|
||||
} catch (error) {
|
||||
console.log(`Envelope file ${activeEnvelope} error:`, error)
|
||||
navigation.goBack()
|
||||
} catch (error: any) {
|
||||
console.log(`Envelope file ${activeEnvelope} error:`, error?.response || error.message || error);
|
||||
ToastAndroid.show('Upload failed', ToastAndroid.SHORT);
|
||||
} finally {
|
||||
setLoadingUpload(false)
|
||||
setLoadingUpload(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<InsideHeader title="Tender Bidding Start" showArrow />
|
||||
@@ -467,7 +475,7 @@ const TenderBidding = () => {
|
||||
if (tenderData?.envelopeASubmittStatus) {
|
||||
setActiveEnvelope('B')
|
||||
} else {
|
||||
Alert.alert('Info', 'First Fill Envelop A First')
|
||||
Alert.alert('Info', 'Submit Envelop A First')
|
||||
}
|
||||
}}
|
||||
/>
|
||||
@@ -476,13 +484,19 @@ const TenderBidding = () => {
|
||||
<EnvelopeButton
|
||||
title="Envelope C"
|
||||
envelopeType="C"
|
||||
onPress={() => setActiveEnvelope('C')}
|
||||
onPress={() => {
|
||||
if (tenderData?.envelopeBSubmittStatus) {
|
||||
setActiveEnvelope('C')
|
||||
} else {
|
||||
Alert.alert('Info', 'Submit Envelop B First')
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
{/* Envelope A List */}
|
||||
{tenderData?.[`tenderEnvelope${activeEnvelope}List`]?.length > 0 && activeEnvelope !== 'C' && (
|
||||
{tenderData?.[`tenderEnvelope${activeEnvelope}List`]?.length > 0 && (
|
||||
<View style={styles.card}>
|
||||
<Text style={styles.sectionTitle}>Envelope {activeEnvelope} Details</Text>
|
||||
<FlatList
|
||||
@@ -491,6 +505,7 @@ const TenderBidding = () => {
|
||||
renderItem={({ item }) => renderEnvelopeItem({ item, envelopeType: activeEnvelope })}
|
||||
scrollEnabled={false}
|
||||
/>
|
||||
|
||||
<View style={[styles.infoRow, { flexDirection: 'row', gap: 10 }]}>
|
||||
<TouchableOpacity onPress={() => setCheck(!check)}>
|
||||
{check ? (
|
||||
@@ -503,33 +518,62 @@ const TenderBidding = () => {
|
||||
</View>
|
||||
)}
|
||||
|
||||
{activeEnvelope === 'C' && (
|
||||
<View style={styles.card}>
|
||||
<Text style={styles.sectionTitle}>Envelope C Status</Text>
|
||||
|
||||
{tenderData?.envelopeCSubmittStatus ? (
|
||||
<>
|
||||
<Text style={{ color: 'green', marginBottom: 8 }}>
|
||||
Envelope C has been submitted successfully.
|
||||
</Text>
|
||||
|
||||
{tenderData?.envelopeC_Logs && (
|
||||
<>
|
||||
<Text>Date: {tenderData.envelopeC_Logs.dateTime}</Text>
|
||||
<Text>Message: {tenderData.envelopeC_Logs.logMessage}</Text>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<EditableExcel tenderId={tenderData} />
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
|
||||
<View style={styles.footer}>
|
||||
{hasEnvelopes() ? (
|
||||
{hasEnvelopes() && activeEnvelope !== 'C' ? (
|
||||
<TouchableOpacity
|
||||
style={styles.primaryButton}
|
||||
onPress={() => {
|
||||
if (!check) {
|
||||
Alert.alert('Info', 'check first terms & condition')
|
||||
Alert.alert('Info', 'check first terms & condition');
|
||||
return;
|
||||
}
|
||||
|
||||
if (activeEnvelope === 'A') {
|
||||
handleSubmitEnvelopeA()
|
||||
} else {
|
||||
handleSubmitEnvelopeB()
|
||||
handleSubmitEnvelopeA();
|
||||
} else if (activeEnvelope === 'B') {
|
||||
handleSubmitEnvelopeB();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Text style={styles.primaryButtonText}>{loading ? 'Submitting...' : `Submit Bid (${activeEnvelope})`}</Text>
|
||||
<Text style={styles.primaryButtonText}>
|
||||
{loading ? 'Submitting...' : `Submit Bid (${activeEnvelope})`}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
) : (
|
||||
<TouchableOpacity
|
||||
style={styles.secondaryButton}
|
||||
onPress={() => navigation.goBack()}
|
||||
|
||||
>
|
||||
<Text style={styles.secondaryButtonText}>Go Back</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
|
||||
</ScrollView>
|
||||
</View>
|
||||
|
||||
|
||||
@@ -78,8 +78,10 @@ const TENDER_LOGIN = `${BASE_URL}eproc/loginWithoutDecryption`
|
||||
const PROCEED_TO_BID = `${BASE_URL}tenderBidding/proceedToBid?tenderId=`
|
||||
const SUBMIT_ENVELOPE_A = `${BASE_URL}tenderBidding/getSaveEnvelopeAData`
|
||||
const SUBMIT_ENVELOPE_B = `${BASE_URL}tenderBidding/getSaveEnvelopeBData`
|
||||
const SUBMIT_ENVELOPE_FILE_A = `${BASE_URL}tenderBidding/addDocumentsEnvelopeA?requestDto=`
|
||||
const SUBMIT_ENVELOPE_FILE_B = `${BASE_URL}tenderBidding/addDocumentsEnvelopeB?requestDto=`
|
||||
const SUBMIT_ENVELOPE_FILE_A = `${BASE_URL}tenderBidding/addDocumentsEnvelopeA`
|
||||
const SUBMIT_ENVELOPE_FILE_B = `https://procurelinc.in/EProcurementSB/tenderBidding/addDocumentsEnvelopeB`
|
||||
const GET_ENVELOPE_C = `${BASE_URL}eTendering/getEnvelopeCTemplate/tenderId?tenderId=`
|
||||
const SUBMIT_ENVELOPE_C_UPLOAD = `${BASE_URL}tenderBidding/getSaveEnvelopeCData`
|
||||
|
||||
|
||||
|
||||
@@ -154,6 +156,8 @@ export {
|
||||
SUBMIT_ENVELOPE_A,
|
||||
SUBMIT_ENVELOPE_B,
|
||||
SUBMIT_ENVELOPE_FILE_A,
|
||||
SUBMIT_ENVELOPE_FILE_B
|
||||
SUBMIT_ENVELOPE_FILE_B,
|
||||
GET_ENVELOPE_C,
|
||||
SUBMIT_ENVELOPE_C_UPLOAD,
|
||||
};
|
||||
|
||||
|
||||
+15
-17
@@ -25,17 +25,16 @@ export const useDashboard = () => {
|
||||
// Auction & Tender
|
||||
|
||||
export const useFetchPurchaseTender = () => {
|
||||
return useInfiniteQuery({
|
||||
queryKey: ['fetchPurchaseTender'],
|
||||
initialPageParam: 1,
|
||||
queryFn: ({ pageParam }) =>
|
||||
fetchPurchaseTender({
|
||||
page: pageParam,
|
||||
size: 10,
|
||||
}),
|
||||
|
||||
getNextPageParam: (lastPage) => {
|
||||
const { page, size, totalCount } = lastPage;
|
||||
return useInfiniteQuery({
|
||||
queryKey: ['fetchPurchaseTender'],
|
||||
queryFn: ({ pageParam = 0 }) =>
|
||||
fetchPurchaseTender({
|
||||
page: pageParam,
|
||||
size: 10,
|
||||
}),
|
||||
initialPageParam: 0,
|
||||
getNextPageParam: (lastPage, allPages) => {
|
||||
const { totalCount } = lastPage;
|
||||
|
||||
const totalPages = Math.ceil(totalCount / size);
|
||||
|
||||
@@ -142,13 +141,12 @@ export const useOfflineTenderPurchase = () => {
|
||||
};
|
||||
|
||||
export const useFetchTenderById = (tenderId: string) => {
|
||||
return useQuery({
|
||||
queryKey: ['fetchTenderById', tenderId],
|
||||
queryFn: () => fetchTenderById(tenderId)
|
||||
|
||||
});
|
||||
return useQuery({
|
||||
queryKey: ['fetchTenderById', tenderId],
|
||||
queryFn: () => fetchTenderById(tenderId),
|
||||
enabled: !!tenderId, // prevents running with undefined id
|
||||
});
|
||||
}
|
||||
|
||||
export const useProceedToBid = (tenderId?: string) => {
|
||||
return useQuery({
|
||||
queryKey: ['proceedToBid', tenderId],
|
||||
|
||||
Reference in New Issue
Block a user