app crash from fill b upload

This commit is contained in:
Jaanu423
2026-01-13 16:03:47 +05:30
parent 39924066bc
commit e5f13c81f4
7 changed files with 152 additions and 81 deletions
+1
View File
@@ -24,6 +24,7 @@ export const apiCall = async <R, D = {}>(
'Content-Type': contentType || 'application/json', 'Content-Type': contentType || 'application/json',
}, },
}); });
return response.data; return response.data;
} catch (error: any) { } catch (error: any) {
const errorMessage = error?.response?.data?.error; const errorMessage = error?.response?.data?.error;
+40 -14
View File
@@ -1,24 +1,30 @@
import { StyleSheet, Text, View, ScrollView, StatusBar, TouchableOpacity } from 'react-native' import { StyleSheet, Text, View, ScrollView, StatusBar, TouchableOpacity, RefreshControl } from 'react-native'
import React from 'react' import React, { useEffect } from 'react'
import { InsideHeader } from '../../Component/Index' import { InsideHeader } from '../../Component/Index'
import colors from '../../Constant/Color' import colors from '../../Constant/Color'
import { useNavigation, useRoute } from '@react-navigation/native' import { useNavigation, useRoute } from '@react-navigation/native'
import { useProceedToBid } from '../../Services/BBPS/Hooks' import { useFetchTenderById, useProceedToBid } from '../../Services/BBPS/Hooks'
const ProceedToBidDetail = () => { const ProceedToBidDetail = () => {
// Sample data based on your JSON // Sample data based on your JSON
const route = useRoute() const route = useRoute<any>();
const tenderData = route.params?.tender; const tenderDataId = route.params?.tender;
const {data, refetch} = useProceedToBid(tenderData?.tenderId); 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 : ", tenderData) 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>() const navigation = useNavigation<any>()
// Format date from array // Format date from array
const handleStartBidding = () => { const handleStartBidding = () => {
refetch(); refetch();
if (data) { if (data) {
navigation.navigate('TenderBidding', { tenderData: tenderData , bidData: data.data }); console.log(" ppp",tenderData ,"ll",data)
navigation.navigate('TenderBidding', { tenderData: tenderData, bidData: data.data });
} }
} }
const formatDate = (dateArray: any[]) => { const formatDate = (dateArray: any[]) => {
@@ -28,7 +34,7 @@ const ProceedToBidDetail = () => {
}; };
// Status indicator component // Status indicator component
const StatusIndicator = ({ status, label }) => ( const StatusIndicator = ({ status, label }: { status: boolean; label: string }) => (
<View style={styles.statusContainer}> <View style={styles.statusContainer}>
<View style={[styles.statusDot, { backgroundColor: status ? colors.success : colors.error }]} /> <View style={[styles.statusDot, { backgroundColor: status ? colors.success : colors.error }]} />
<Text style={[styles.statusText, { color: status ? colors.success : colors.error }]}> <Text style={[styles.statusText, { color: status ? colors.success : colors.error }]}>
@@ -38,7 +44,7 @@ const ProceedToBidDetail = () => {
); );
// Envelope log card component // Envelope log card component
const EnvelopeLogCard = ({ log, title }) => ( const EnvelopeLogCard = ({ log, title }: { log: any; title: string }) => (
<View style={styles.envelopeCard}> <View style={styles.envelopeCard}>
<View style={styles.cardHeader}> <View style={styles.cardHeader}>
<Text style={styles.cardTitle}>{title}</Text> <Text style={styles.cardTitle}>{title}</Text>
@@ -82,7 +88,7 @@ const ProceedToBidDetail = () => {
); );
// Information row component // Information row component
const InfoRow = ({ label, value, isHighlighted = false }) => ( const InfoRow = ({ label, value, isHighlighted = false }: { label: string; value: string; isHighlighted?: boolean }) => (
<View style={styles.infoRow}> <View style={styles.infoRow}>
<Text style={styles.infoLabel}>{label}:</Text> <Text style={styles.infoLabel}>{label}:</Text>
<Text style={[styles.infoValue, isHighlighted && styles.highlightedValue]}>{value}</Text> <Text style={[styles.infoValue, isHighlighted && styles.highlightedValue]}>{value}</Text>
@@ -90,7 +96,7 @@ const ProceedToBidDetail = () => {
); );
// Feature chip component // Feature chip component
const FeatureChip = ({ label, enabled }) => ( const FeatureChip = ({ label, enabled }: { label: string; enabled: boolean }) => (
<View style={[styles.chip, { backgroundColor: enabled ? colors.successLight : colors.lightGray }]}> <View style={[styles.chip, { backgroundColor: enabled ? colors.successLight : colors.lightGray }]}>
<Text style={[styles.chipText, { color: enabled ? colors.success : colors.darkGray }]}> <Text style={[styles.chipText, { color: enabled ? colors.success : colors.darkGray }]}>
{label} {enabled ? '✓' : '✗'} {label} {enabled ? '✓' : '✗'}
@@ -98,12 +104,32 @@ const ProceedToBidDetail = () => {
</View> </View>
); );
const onRefresh = async () => {
try {
setRefreshing(true);
await refetch();
} finally {
setRefreshing(false);
}
};
useEffect(()=>{
tenderRefetch()
},[tenderDataId?.tenderId])
return ( return (
<View style={{ flex: 1, backgroundColor: colors.white }}> <View style={{ flex: 1, backgroundColor: colors.white }}>
<StatusBar backgroundColor={colors.primary} barStyle="light-content" />
<InsideHeader title="Tender Detail" showArrow /> <InsideHeader title="Tender Detail" showArrow />
<ScrollView style={styles.container} showsVerticalScrollIndicator={false}> <ScrollView style={styles.container} showsVerticalScrollIndicator={false}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={onRefresh}
colors={[colors.primary]} // Android
tintColor={colors.primary} // iOS
/>
}>
{/* Tender Header Section */} {/* Tender Header Section */}
<View style={styles.headerCard}> <View style={styles.headerCard}>
<View style={styles.tenderHeader}> <View style={styles.tenderHeader}>
+1 -8
View File
@@ -36,15 +36,8 @@ const PurchaseTenderTile = ({
const { data: tenderResponse, }: any = useFetchTenderById(item?.tenderId); const { data: tenderResponse, }: any = useFetchTenderById(item?.tenderId);
const tender = tenderResponse?.data; const tender = tenderResponse?.data;
// console.log("item my : ", item)
{
if (item?.nitNumber == 'TN/111') {
console.log("tender item : ", item?.nitNumber)
}
}
console.log("tender for bid : ", tender)
const handlePressIn = () => { const handlePressIn = () => {
scale.value = withTiming(0.97, { duration: 120 }); scale.value = withTiming(0.97, { duration: 120 });
elevation.value = withTiming(3, { duration: 120 }); elevation.value = withTiming(3, { duration: 120 });
+54 -12
View File
@@ -6,7 +6,8 @@ import axios from 'axios';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { InsideHeader } from '../../../Component/Index'; import { InsideHeader } from '../../../Component/Index';
import colors from '../../../Constant/Color'; import colors from '../../../Constant/Color';
import { SUBMIT_ENVELOPE_C } from '../../../Services/BBPS/ApiUrls'; import { GET_ENVELOPE_C, SUBMIT_ENVELOPE_C_UPLOAD } from '../../../Services/BBPS/ApiUrls';
import { useNavigation } from '@react-navigation/native';
// Excel column keys // Excel column keys
@@ -15,13 +16,13 @@ const RATE_KEY = '__EMPTY_2';
const VALUE_KEY = '__EMPTY_3'; const VALUE_KEY = '__EMPTY_3';
const TOTAL_LABEL = 'TOTAL'; const TOTAL_LABEL = 'TOTAL';
const EnvelopeCExcelPreview = (tenderId:any) => { const EnvelopeCExcelPreview = (tenderData: any) => {
const token = useSelector((state: any) => state.token.token); const token = useSelector((state: any) => state.token.token);
const navigation = useNavigation() as any;
const [data, setData] = useState<any[]>([]); const [data, setData] = useState<any[]>([]);
const [columns, setColumns] = useState<string[]>([]); const [columns, setColumns] = useState<string[]>([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
console.log("tender id for excel : ", tenderId)
useEffect(() => { useEffect(() => {
loadExcelFromApi(); loadExcelFromApi();
}, []); }, []);
@@ -49,7 +50,7 @@ const EnvelopeCExcelPreview = (tenderId:any) => {
try { try {
setLoading(true); setLoading(true);
const response = await axios.get(`${SUBMIT_ENVELOPE_C}${tenderId?.tenderId}`, { const response = await axios.get(`${GET_ENVELOPE_C}${tenderData?.tenderId?.tenderId}`, {
responseType: 'arraybuffer', responseType: 'arraybuffer',
headers: { headers: {
Authentication: `Bearer ${token.token}`, Authentication: `Bearer ${token.token}`,
@@ -117,25 +118,66 @@ const EnvelopeCExcelPreview = (tenderId:any) => {
const workbook = XLSX.utils.book_new(); const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1'); XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
const base64 = XLSX.write(workbook, { // Generate binary string
const binary = XLSX.write(workbook, {
bookType: 'xlsx', bookType: 'xlsx',
type: 'base64', type: 'binary',
}); });
await RNFS.writeFile( // Convert binary string to buffer
`${RNFS.DocumentDirectoryPath}/envelopeC_updated.xlsx`, const buffer = new Uint8Array(binary.length);
base64, for (let i = 0; i < binary.length; i++) {
'base64' 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',
})
); );
Alert.alert('Success', 'Excel saved with auto-calculation'); // 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) { } catch (e) {
console.error(e);
Alert.alert('Error', 'Save failed'); Alert.alert('Error', 'Save failed');
} finally { } finally {
setLoading(false); setLoading(false);
} }
}; };
if (loading) { if (loading) {
return ( return (
<View style={styles.loader}> <View style={styles.loader}>
@@ -230,7 +272,7 @@ const styles = StyleSheet.create({
}, },
button: { button: {
marginTop: 15, marginTop: 15,
backgroundColor: '#2563eb', backgroundColor: colors.primary,
padding: 14, padding: 14,
borderRadius: 8, borderRadius: 8,
}, },
@@ -19,6 +19,8 @@ import { SUBMIT_ENVELOPE_A, SUBMIT_ENVELOPE_B, SUBMIT_ENVELOPE_FILE_A, SUBMIT_EN
import { Fontisto } from '@react-native-vector-icons/fontisto'; import { Fontisto } from '@react-native-vector-icons/fontisto';
import { apiCall } from '../../../Axios/Axios'; import { apiCall } from '../../../Axios/Axios';
import EditableExcel from '../component/EditableExcel'; import EditableExcel from '../component/EditableExcel';
import axios from 'axios';
import { useSelector } from 'react-redux';
type EnvelopeType = 'A' | 'B' | 'C'; type EnvelopeType = 'A' | 'B' | 'C';
type EnvelopeFormState = { type EnvelopeFormState = {
@@ -40,6 +42,7 @@ interface InfoRowProps {
const TenderBidding = () => { const TenderBidding = () => {
const route = useRoute<any>(); const route = useRoute<any>();
const navigation = useNavigation(); const navigation = useNavigation();
const token = useSelector((state: any) => state.token.token);
const [bidData] = useState<any>(route.params?.tenderData || null); const [bidData] = useState<any>(route.params?.tenderData || null);
const tenderData: any = route.params?.bidData || null; const tenderData: any = route.params?.bidData || null;
@@ -209,7 +212,6 @@ const TenderBidding = () => {
keyboardType="numeric" keyboardType="numeric"
/> />
)} )}
<Text>this is envelope {activeEnvelope}</Text>
</> </>
) : <Text>Envelop {activeEnvelope} unavailable</Text>} ) : <Text>Envelop {activeEnvelope} unavailable</Text>}
@@ -355,12 +357,12 @@ const TenderBidding = () => {
console.log('Envelope A Payload:', payload); console.log('Envelope A Payload:', payload);
setLoading(true) setLoading(true)
if (envelopForm?.[activeEnvelope]?.[3]) { if (envelopForm?.[activeEnvelope]?.[3]) {
handleSubmitEnvelopeFile() handleSubmitEnvelopeFile(SUBMIT_ENVELOPE_FILE_A)
return return
} }
try { 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) console.log("res A envelop : ", res)
ToastAndroid.show(res.message, ToastAndroid.SHORT) ToastAndroid.show(res.message, ToastAndroid.SHORT)
@@ -385,11 +387,11 @@ const TenderBidding = () => {
if (envelopForm?.[activeEnvelope]?.[3]) { if (envelopForm?.[activeEnvelope]?.[3]) {
handleSubmitEnvelopeFile() handleSubmitEnvelopeFile(SUBMIT_ENVELOPE_FILE_B)
return return
} }
try { 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) console.log("res B envelop : ", res)
ToastAndroid.show(res.message, ToastAndroid.SHORT) ToastAndroid.show(res.message, ToastAndroid.SHORT)
@@ -401,11 +403,10 @@ const TenderBidding = () => {
} }
} }
const handleSubmitEnvelopeFile = async () => { const handleSubmitEnvelopeFile = async (url: string) => {
console.log("url :: ", url)
setLoadingUpload(true) setLoadingUpload(true)
const payload = buildEnvelopePayload(); const payload = buildEnvelopePayload();
console.log(`Envelope file ${activeEnvelope} Payload:`, payload);
try { try {
const formData = new FormData(); const formData = new FormData();
@@ -414,26 +415,27 @@ const TenderBidding = () => {
name: envelopForm?.[activeEnvelope]?.[3].name, name: envelopForm?.[activeEnvelope]?.[3].name,
type: envelopForm?.[activeEnvelope]?.[3].type, type: envelopForm?.[activeEnvelope]?.[3].type,
}); });
formData.append('requestDto', payload) // formData.append('requestDto', payload)
console.log("first token : ", token?.token)
formData.append('requestDto', JSON.stringify(payload))
console.log("reuestDto for fil doc : ", formData) console.log("payload for fil doc : ", formData)
const res = await apiCall('post', activeEnvelope === 'B' ? SUBMIT_ENVELOPE_FILE_B : SUBMIT_ENVELOPE_FILE_A, payload) const res = await axios.post(url, formData, {
console.log(`res file ${activeEnvelope} Payload:`, res) 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) ToastAndroid.show(res.message, ToastAndroid.SHORT)
// navigation.goBack() navigation.goBack()
} catch (error) { } catch (error: any) {
console.log(`Envelope file ${activeEnvelope} error:`, error) console.log(`Envelope file ${activeEnvelope} error:`, error?.response || error.message || error);
ToastAndroid.show('Upload failed', ToastAndroid.SHORT);
} finally { } finally {
setLoadingUpload(false) setLoadingUpload(false);
} }
} }
const handleSubmitEnvelopeC = async () => {
Alert.alert('Info', 'Envelope C submission not implemented yet');
}
return ( return (
<View style={styles.container}> <View style={styles.container}>
<InsideHeader title="Tender Bidding Start" showArrow /> <InsideHeader title="Tender Bidding Start" showArrow />
@@ -473,7 +475,7 @@ const TenderBidding = () => {
if (tenderData?.envelopeASubmittStatus) { if (tenderData?.envelopeASubmittStatus) {
setActiveEnvelope('B') setActiveEnvelope('B')
} else { } else {
Alert.alert('Info', 'First Fill Envelop A First') Alert.alert('Info', 'Submit Envelop A First')
} }
}} }}
/> />
@@ -482,7 +484,13 @@ const TenderBidding = () => {
<EnvelopeButton <EnvelopeButton
title="Envelope C" title="Envelope C"
envelopeType="C" envelopeType="C"
onPress={() => setActiveEnvelope('C')} onPress={() => {
if (tenderData?.envelopeBSubmittStatus) {
setActiveEnvelope('C')
} else {
Alert.alert('Info', 'Submit Envelop B First')
}
}}
/> />
)} )}
</View> </View>
@@ -527,43 +535,43 @@ const TenderBidding = () => {
</> </>
) : ( ) : (
<> <>
<EditableExcel tenderId={tenderData?.tenderId} /> <EditableExcel tenderId={tenderData} />
</> </>
)} )}
</View> </View>
)} )}
<View style={styles.footer}> <View style={styles.footer}>
{hasEnvelopes() ? ( {hasEnvelopes() && activeEnvelope !== 'C' ? (
<TouchableOpacity <TouchableOpacity
style={styles.primaryButton} style={styles.primaryButton}
onPress={() => { onPress={() => {
if (!check) { if (!check) {
Alert.alert('Info', 'check first terms & condition') Alert.alert('Info', 'check first terms & condition');
return;
} }
if (activeEnvelope === 'A') { if (activeEnvelope === 'A') {
handleSubmitEnvelopeA() handleSubmitEnvelopeA();
} } else if (activeEnvelope === 'B') {
else if (activeEnvelope === 'B') { handleSubmitEnvelopeB();
handleSubmitEnvelopeB()
}
else {
handleSubmitEnvelopeC()
} }
}} }}
> >
<Text style={styles.primaryButtonText}>{loading ? 'Submitting...' : `Submit Bid (${activeEnvelope})`}</Text> <Text style={styles.primaryButtonText}>
{loading ? 'Submitting...' : `Submit Bid (${activeEnvelope})`}
</Text>
</TouchableOpacity> </TouchableOpacity>
) : ( ) : (
<TouchableOpacity <TouchableOpacity
style={styles.secondaryButton} style={styles.secondaryButton}
onPress={() => navigation.goBack()} onPress={() => navigation.goBack()}
> >
<Text style={styles.secondaryButtonText}>Go Back</Text> <Text style={styles.secondaryButtonText}>Go Back</Text>
</TouchableOpacity> </TouchableOpacity>
)} )}
</View> </View>
</ScrollView> </ScrollView>
</View> </View>
+6 -4
View File
@@ -69,9 +69,10 @@ const TENDER_LOGIN = `${BASE_URL}eproc/loginWithoutDecryption`
const PROCEED_TO_BID = `${BASE_URL}tenderBidding/proceedToBid?tenderId=` const PROCEED_TO_BID = `${BASE_URL}tenderBidding/proceedToBid?tenderId=`
const SUBMIT_ENVELOPE_A = `${BASE_URL}tenderBidding/getSaveEnvelopeAData` const SUBMIT_ENVELOPE_A = `${BASE_URL}tenderBidding/getSaveEnvelopeAData`
const SUBMIT_ENVELOPE_B = `${BASE_URL}tenderBidding/getSaveEnvelopeBData` const SUBMIT_ENVELOPE_B = `${BASE_URL}tenderBidding/getSaveEnvelopeBData`
const SUBMIT_ENVELOPE_FILE_A = `${BASE_URL}tenderBidding/addDocumentsEnvelopeA?requestDto=` const SUBMIT_ENVELOPE_FILE_A = `${BASE_URL}tenderBidding/addDocumentsEnvelopeA`
const SUBMIT_ENVELOPE_FILE_B = `${BASE_URL}tenderBidding/addDocumentsEnvelopeB?requestDto=` const SUBMIT_ENVELOPE_FILE_B = `https://procurelinc.in/EProcurementSB/tenderBidding/addDocumentsEnvelopeB`
const SUBMIT_ENVELOPE_C = `${BASE_URL}eTendering/getEnvelopeCTemplate/tenderId?tenderId=` const GET_ENVELOPE_C = `${BASE_URL}eTendering/getEnvelopeCTemplate/tenderId?tenderId=`
const SUBMIT_ENVELOPE_C_UPLOAD = `${BASE_URL}tenderBidding/getSaveEnvelopeCData`
@@ -139,6 +140,7 @@ export {
SUBMIT_ENVELOPE_B, SUBMIT_ENVELOPE_B,
SUBMIT_ENVELOPE_FILE_A, SUBMIT_ENVELOPE_FILE_A,
SUBMIT_ENVELOPE_FILE_B, SUBMIT_ENVELOPE_FILE_B,
SUBMIT_ENVELOPE_C GET_ENVELOPE_C,
SUBMIT_ENVELOPE_C_UPLOAD,
}; };
+5 -6
View File
@@ -104,13 +104,12 @@ export const useOfflineTenderPurchase = () => {
}; };
export const useFetchTenderById = (tenderId: string) => { export const useFetchTenderById = (tenderId: string) => {
return useQuery({ return useQuery({
queryKey: ['fetchTenderById', tenderId], queryKey: ['fetchTenderById', tenderId],
queryFn: () => fetchTenderById(tenderId) queryFn: () => fetchTenderById(tenderId),
enabled: !!tenderId, // prevents running with undefined id
}); });
} }
export const useProceedToBid = (tenderId?: string) => { export const useProceedToBid = (tenderId?: string) => {
return useQuery({ return useQuery({
queryKey: ['proceedToBid', tenderId], queryKey: ['proceedToBid', tenderId],