commit
This commit is contained in:
@@ -1,285 +1,285 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { View, Text, TextInput, ScrollView, TouchableOpacity, StyleSheet, ActivityIndicator, Alert, } from 'react-native';
|
||||
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';
|
||||
|
||||
/* -------------------- UTILS -------------------- */
|
||||
|
||||
// Excel column keys
|
||||
const QTY_KEY = '__EMPTY_1';
|
||||
const RATE_KEY = '__EMPTY_2';
|
||||
const VALUE_KEY = '__EMPTY_3';
|
||||
const TOTAL_LABEL = 'TOTAL';
|
||||
// Convert 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);
|
||||
};
|
||||
|
||||
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);
|
||||
console.log("kllkl",tenderData)
|
||||
useEffect(() => {
|
||||
loadExcelFromApi();
|
||||
}, []);
|
||||
// Find column dynamically by keywords
|
||||
const findColumnKey = (columns: string[], keywords: string[]) =>
|
||||
columns.find(col =>
|
||||
keywords.some(k => col.toLowerCase().includes(k.toLowerCase()))
|
||||
);
|
||||
|
||||
// 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]);
|
||||
// Detect TOTAL row (any column contains TOTAL)
|
||||
const isTotalRow = (row: any) =>
|
||||
Object.values(row).some(v => String(v).toUpperCase() === 'TOTAL');
|
||||
|
||||
/* -------------------- COMPONENT -------------------- */
|
||||
|
||||
const EnvelopeCExcelPreview = (props: any) => {
|
||||
const tenderData = props;
|
||||
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();
|
||||
}, []);
|
||||
|
||||
/* -------------------- 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}`,
|
||||
},
|
||||
}
|
||||
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);
|
||||
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: '' });
|
||||
|
||||
// LOAD EXCEL
|
||||
const loadExcelFromApi = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setColumns(Object.keys(rows[0] || {}));
|
||||
setData(rows);
|
||||
|
||||
const response = await axios.get(`${GET_ENVELOPE_C}${tenderData?.tenderId?.tenderId}`, {
|
||||
responseType: 'arraybuffer',
|
||||
headers: {
|
||||
Authentication: `Bearer ${token.token}`,
|
||||
},
|
||||
});
|
||||
console.log("excel response",response)
|
||||
} catch (e) {
|
||||
Alert.alert('Error', 'Failed to load Excel');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
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: '' });
|
||||
/* -------------------- UPDATE CELL -------------------- */
|
||||
|
||||
setColumns(Object.keys(rows[0] || {}));
|
||||
setData(rows);
|
||||
const updateCell = (rowIndex: number, key: string, value: string) => {
|
||||
const updated = [...data];
|
||||
const row = updated[rowIndex];
|
||||
|
||||
await RNFS.writeFile(
|
||||
`${RNFS.DocumentDirectoryPath}/envelopeC.xlsx`,
|
||||
base64,
|
||||
'base64'
|
||||
);
|
||||
} catch (e) {
|
||||
Alert.alert('Error', 'Failed to load Excel');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
if (isTotalRow(row)) return;
|
||||
|
||||
// UPDATE CELL (QTY / RATE) + AUTO VALUE + AUTO TOTAL
|
||||
const updateCell = (rowIndex: number, key: string, value: string) => {
|
||||
const updated = [...data];
|
||||
const row = updated[rowIndex];
|
||||
const qtyKey:any = findColumnKey(columns, ['qty', 'quantity']);
|
||||
const rateKey:any = findColumnKey(columns, ['rate', 'price']);
|
||||
const valueKey = findColumnKey(columns, ['value', 'amount', 'total']);
|
||||
|
||||
// TOTAL row locked
|
||||
if (row['DEMO DEPARTEMENT'] === TOTAL_LABEL) return;
|
||||
if (key === qtyKey || key === rateKey) {
|
||||
row[key] = value;
|
||||
|
||||
// Allow only QTY & RATE edit
|
||||
if (key === QTY_KEY || key === RATE_KEY) {
|
||||
row[key] = value;
|
||||
const qty = Number(row[qtyKey]);
|
||||
const rate = Number(row[rateKey]);
|
||||
|
||||
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>
|
||||
);
|
||||
if (valueKey) {
|
||||
row[valueKey] =
|
||||
!isNaN(qty) && !isNaN(rate) ? qty * rate : 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Recalculate TOTAL
|
||||
const totalRowIndex = updated.findIndex(isTotalRow);
|
||||
if (totalRowIndex !== -1 && valueKey) {
|
||||
updated[totalRowIndex][valueKey] = updated.reduce((sum, r) => {
|
||||
if (isTotalRow(r)) return sum;
|
||||
const val = Number(r[valueKey]);
|
||||
return sum + (isNaN(val) ? 0 : val);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
setData(updated);
|
||||
};
|
||||
|
||||
/* -------------------- SAVE & UPLOAD 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');
|
||||
|
||||
const binary = XLSX.write(workbook, {
|
||||
bookType: 'xlsx',
|
||||
type: 'binary',
|
||||
});
|
||||
|
||||
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`;
|
||||
await RNFS.writeFile(filePath, buffer.toString(), 'ascii');
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append(
|
||||
'requestDto',
|
||||
JSON.stringify({
|
||||
tenderId: tenderData?.tenderId?.tenderId,
|
||||
deptId: tenderData?.tenderId?.deptId,
|
||||
typesOfTender: tenderData?.tenderId?.typesOfTender,
|
||||
fieldValue: '',
|
||||
fieldValueInWord: 'zero',
|
||||
})
|
||||
);
|
||||
|
||||
formData.append('file', {
|
||||
uri: `file://${filePath}`,
|
||||
name: 'envelopeC_updated.xlsx',
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
});
|
||||
|
||||
await axios.post(SUBMIT_ENVELOPE_C_UPLOAD, formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
Authentication: `Bearer ${token.token}`,
|
||||
},
|
||||
});
|
||||
|
||||
navigation.goBack();
|
||||
} catch (e) {
|
||||
Alert.alert('Error', 'Save failed');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
/* -------------------- UI -------------------- */
|
||||
|
||||
if (loading) {
|
||||
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>
|
||||
|
||||
{tenderData?.buttonEnable && <TouchableOpacity style={styles.button} onPress={saveUpdatedExcel}>
|
||||
<Text style={styles.buttonText}>Save Updated Excel</Text>
|
||||
</TouchableOpacity>}
|
||||
</View>
|
||||
<View style={styles.loader}>
|
||||
<ActivityIndicator size="large" />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const qtyKey = findColumnKey(columns, ['qty', 'quantity']);
|
||||
const rateKey = findColumnKey(columns, ['rate', 'price']);
|
||||
const valueKey = findColumnKey(columns, ['value', 'amount', 'total']);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ScrollView horizontal contentContainerStyle={{ padding: 10 }}>
|
||||
<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 editable =
|
||||
!isTotalRow(row) && (key === qtyKey || key === rateKey);
|
||||
|
||||
return (
|
||||
<TextInput
|
||||
key={key}
|
||||
value={String(row[key])}
|
||||
editable={editable}
|
||||
keyboardType={editable ? 'numeric' : 'default'}
|
||||
style={[
|
||||
styles.cell,
|
||||
isTotalRow(row) && styles.totalCell,
|
||||
key === valueKey && styles.valueCell,
|
||||
]}
|
||||
onChangeText={text =>
|
||||
updateCell(rowIndex, key, text)
|
||||
}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
))}
|
||||
</ScrollView>
|
||||
</View>
|
||||
</ScrollView>
|
||||
|
||||
{tenderData?.buttonEnable && (
|
||||
<TouchableOpacity style={styles.button} onPress={saveUpdatedExcel}>
|
||||
<Text style={styles.buttonText}>Save Updated Excel</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default EnvelopeCExcelPreview;
|
||||
|
||||
/* -------------------- STYLES -------------------- */
|
||||
|
||||
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',
|
||||
},
|
||||
container: { flex: 1, backgroundColor: '#fff' },
|
||||
loader: { flex: 1, justifyContent: 'center', alignItems: 'center' },
|
||||
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: {
|
||||
margin: 15,
|
||||
backgroundColor: colors.primary,
|
||||
padding: 14,
|
||||
borderRadius: 8,
|
||||
},
|
||||
buttonText: {
|
||||
color: '#fff',
|
||||
textAlign: 'center',
|
||||
fontWeight: '600',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -17,7 +17,7 @@ const LiveTender = () => {
|
||||
console.log("userdata",user)
|
||||
const SelectedPurchaseList = useSelector((state: any) => state.selectPurchaseTender);
|
||||
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, isRefetching, refetch }: any = useFetchLiveTender();
|
||||
|
||||
console.log("to show ",data)
|
||||
const [showRefreshBanner, setShowRefreshBanner] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -49,6 +49,8 @@ const LiveTender = () => {
|
||||
|
||||
const renderItem = useCallback(
|
||||
({ item, index }: any) => {
|
||||
console.log("opopopopoopopopop",item.tenderNumber,item)
|
||||
if(item.tenderStatus==="Cancelled") return null;
|
||||
const isPurchase = SelectedPurchaseList.findIndex((prev: any) => prev.tenderId === item.tenderId)
|
||||
return <LiveTenderTile
|
||||
contractorId={user?.id}
|
||||
|
||||
@@ -52,6 +52,7 @@ const LiveTenderDetail = () => {
|
||||
const tender = route?.params;
|
||||
console.log("object---",tender)
|
||||
const { data } = useFetchLiveTenderById(tender?.tenderId);
|
||||
console.log("huh",data)
|
||||
const [downloadingId, setDownloadingId] = useState<string | number | null>(null);
|
||||
const insets = useSafeAreaInsets()
|
||||
if (!data?.data?.[0]) return null;
|
||||
@@ -198,38 +199,40 @@ const LiveTenderDetail = () => {
|
||||
<InfoRow
|
||||
label="Purchase Start"
|
||||
value={formatDateTime(
|
||||
tenderData?.keydates?.tenderPurchaseDate?.startDateTime,
|
||||
tender.tenderStatus === "Amended" ? tenderData?.tenderKeyDatesAmendment?.tenderPurchaseDate?.startDateTime : tenderData?.keydates?.tenderPurchaseDate?.startDateTime
|
||||
)}
|
||||
/>
|
||||
<InfoRow
|
||||
label="Purchase End"
|
||||
value={formatDateTime(
|
||||
tenderData?.keydates?.tenderPurchaseDate?.endDateTime,
|
||||
tender.tenderStatus === "Amended" ? tenderData?.tenderKeyDatesAmendment?.tenderPurchaseDate?.endDateTime : tenderData?.keydates?.tenderPurchaseDate?.endDateTime
|
||||
)}
|
||||
/>
|
||||
<InfoRow
|
||||
label="Bid Submission Start"
|
||||
value={formatDateTime(
|
||||
tenderData?.keydates?.bidSubmissionDate?.startDateTime,
|
||||
tender.tenderStatus === "Amended" ? tenderData?.tenderKeyDatesAmendment?.bidSubmissionDate?.startDateTime : tenderData?.keydates?.bidSubmissionDate?.startDateTime
|
||||
)}
|
||||
/>
|
||||
<InfoRow
|
||||
label="Bid Submission End"
|
||||
value={formatDateTime(
|
||||
tenderData?.keydates?.bidSubmissionDate?.endDateTime,
|
||||
tender.tenderStatus === "Amended" ? tenderData?.tenderKeyDatesAmendment?.bidSubmissionDate?.endDateTime : tenderData?.keydates?.bidSubmissionDate?.endDateTime,
|
||||
)}
|
||||
/>
|
||||
<InfoRow
|
||||
label="Opening Envelope A"
|
||||
value={formatDateTime(tenderData?.keydates?.openingEA)}
|
||||
value={formatDateTime(
|
||||
tender.tenderStatus === "Amended" ? tenderData?.tenderKeyDatesAmendment?.openingEA : tenderData?.keydates?.openingEA
|
||||
)}
|
||||
/>
|
||||
<InfoRow
|
||||
label="Opening Envelope B"
|
||||
value={formatDateTime(tenderData?.keydates?.openingEB)}
|
||||
value={formatDateTime(tender.tenderStatus === "Amended" ? tenderData?.tenderKeyDatesAmendment?.openingEB : tenderData?.keydates?.openingEB)}
|
||||
/>
|
||||
<InfoRow
|
||||
label="Opening Envelope C"
|
||||
value={formatDateTime(tenderData?.keydates?.openingEC)}
|
||||
value={formatDateTime(tender.tenderStatus === "Amended" ? tenderData?.tenderKeyDatesAmendment?.openingEC : tenderData?.keydates?.openingEC)}
|
||||
/>
|
||||
</View>
|
||||
</Section>
|
||||
|
||||
@@ -21,7 +21,7 @@ const LiveTenderTile: React.FC<LiveTenderTileProps> = ({
|
||||
tenderNumber,
|
||||
}) => {
|
||||
const navigation: any = useNavigation();
|
||||
const purchaseEnded = !moment().isAfter(moment(purchaseEnd, 'DD-MM-YYYY HH:mm:ss'));
|
||||
const purchaseEnded = moment().isAfter(moment(purchaseEnd, 'YYYY-MM-DD HH:mm:ss'));
|
||||
|
||||
const contractorIds = typeof data?.contractorId === 'string'
|
||||
? data.contractorId.split(',').map((id: any) => id.trim())
|
||||
@@ -30,7 +30,10 @@ const LiveTenderTile: React.FC<LiveTenderTileProps> = ({
|
||||
: [];
|
||||
|
||||
const purchased = contractorIds.includes(String(contractorId));
|
||||
|
||||
console.log("item is ",data)
|
||||
if(data.tenderStatus==="Amended"){
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.cardWrapper}>
|
||||
@@ -77,7 +80,7 @@ const LiveTenderTile: React.FC<LiveTenderTileProps> = ({
|
||||
<View style={styles.infoTextGroup}>
|
||||
<Text style={styles.infoLabel}>Deadline</Text>
|
||||
<Text style={[styles.infoValue, purchaseEnded && { color: '#ef4444' }]}>
|
||||
{moment(purchaseEnd, 'DD-MM-YYYY HH:mm:ss').format('DD MMM, YY')}
|
||||
{moment(purchaseEnd, 'YYYY-MM-DD HH:mm:ss').format('DD MMM, YY')}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
@@ -108,7 +111,7 @@ const LiveTenderTile: React.FC<LiveTenderTileProps> = ({
|
||||
isPurchased && !purchaseEnded ? { color: colors.white } : { color: '#fff' },
|
||||
]}
|
||||
>
|
||||
{purchaseEnded ? 'Expired' : (purchased ? 'Purchased' : isPurchased ? 'Remove' : 'Add to Cart')}
|
||||
{purchaseEnded ? (purchased ? 'Purchased' : 'Expired') : (purchased ? 'Purchased' : isPurchased ? 'Remove' : 'Add to Cart')}
|
||||
</Text>
|
||||
{(!purchaseEnded && !purchased) && (
|
||||
<ArrowRight size={16} color={isPurchased ? colors.white : '#fff'} />
|
||||
|
||||
Reference in New Issue
Block a user