Merge branch 'dev' of https://git.zeptic.in/rohit/Procurelinc into dev
This commit is contained in:
@@ -1,11 +1,9 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
|
||||
export interface TenderItem {
|
||||
TenderNumber: string;
|
||||
[key: string]: any;
|
||||
tenderId: number;
|
||||
}
|
||||
|
||||
// ✅ DEFAULT = EMPTY ARRAY
|
||||
const initialState: TenderItem[] = [];
|
||||
|
||||
export const selectPurchaseTenderSlice = createSlice({
|
||||
@@ -27,7 +25,7 @@ export const selectPurchaseTenderSlice = createSlice({
|
||||
}
|
||||
},
|
||||
|
||||
clearPurchaseTender: () => [],
|
||||
clearPurchaseTender: () => initialState,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ const LiveTender = () => {
|
||||
return <Skelton />;
|
||||
}
|
||||
|
||||
console.log("data live : ", data )
|
||||
return (
|
||||
<View style={{ flex: 1 }}>
|
||||
<SearchInput onChange={() => { }} placeholder="Search...." />
|
||||
@@ -114,7 +115,7 @@ const LiveTender = () => {
|
||||
)}
|
||||
|
||||
<FlatList
|
||||
data={data?.data ?? []}
|
||||
data={data?.result ?? []}
|
||||
keyExtractor={(item) => String(item.auctionId)}
|
||||
renderItem={renderItem}
|
||||
showsVerticalScrollIndicator={false}
|
||||
@@ -135,6 +136,8 @@ const LiveTender = () => {
|
||||
windowSize={7}
|
||||
removeClippedSubviews
|
||||
updateCellsBatchingPeriod={50}
|
||||
onRefresh={refetch}
|
||||
refreshing={isRefetching}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -19,18 +19,18 @@ const LiveTenderTile: React.FC<LiveTenderTileProps> = ({
|
||||
purchaseEnd,
|
||||
tenderFees,
|
||||
tenderNumber,
|
||||
onDetailsPress
|
||||
}) => {
|
||||
const navigation: any = useNavigation();
|
||||
const purchaseEnded = !moment().isAfter(moment(purchaseEnd, 'DD-MM-YYYY HH:mm:ss'));
|
||||
|
||||
const contractorIds = typeof data?.contractorId === 'string'
|
||||
? data.contractorId.split(',').map((id:any) => id.trim())
|
||||
: Array.isArray(data?.contractorId)
|
||||
? data.contractorId
|
||||
: [];
|
||||
const contractorIds = typeof data?.contractorId === 'string'
|
||||
? data.contractorId.split(',').map((id: any) => id.trim())
|
||||
: Array.isArray(data?.contractorId)
|
||||
? data.contractorId
|
||||
: [];
|
||||
|
||||
const purchased = contractorIds.includes(String(contractorId));
|
||||
|
||||
const purchased = contractorIds.includes(String(contractorId));
|
||||
|
||||
return (
|
||||
<View style={styles.cardWrapper}>
|
||||
@@ -38,7 +38,7 @@ const purchased = contractorIds.includes(String(contractorId));
|
||||
<View
|
||||
style={[
|
||||
styles.statusTag,
|
||||
{ backgroundColor: isPurchased ? colors.error : purchaseEnded ? '#94a3b8' : (purchased?'#94a3b8':'#4ade80') },
|
||||
{ backgroundColor: isPurchased ? colors.error : purchaseEnded ? '#94a3b8' : (purchased ? '#94a3b8' : '#4ade80') },
|
||||
]}
|
||||
/>
|
||||
|
||||
@@ -67,7 +67,6 @@ const purchased = contractorIds.includes(String(contractorId));
|
||||
<Calendar size={16} color="#64748b" />
|
||||
<View style={styles.infoTextGroup}>
|
||||
<Text style={styles.infoLabel}>Start</Text>
|
||||
{/* <Text style={styles.infoValue}>{tenderDispatchDate ?? '-'}</Text> */}
|
||||
<Text style={styles.infoValue}>{format.date6(`${tenderDispatchDate}`)}</Text>
|
||||
|
||||
</View>
|
||||
@@ -86,7 +85,7 @@ const purchased = contractorIds.includes(String(contractorId));
|
||||
|
||||
{/* Action Bar */}
|
||||
<View style={styles.actionBar}>
|
||||
<TouchableOpacity style={styles.iconBtn} onPress={()=>navigation.navigate('LiveTenderDetail', data)}>
|
||||
<TouchableOpacity style={styles.iconBtn} onPress={() => navigation.navigate('LiveTenderDetail', data)}>
|
||||
<Info size={18} color={colors.primary} />
|
||||
<Text style={styles.iconBtnText}>Details</Text>
|
||||
</TouchableOpacity>
|
||||
@@ -96,7 +95,7 @@ const purchased = contractorIds.includes(String(contractorId));
|
||||
styles.mainButton,
|
||||
purchaseEnded
|
||||
? styles.btnDisabled
|
||||
:(purchased? styles.btnDisabled: isPurchased
|
||||
: (purchased ? styles.btnDisabled : isPurchased
|
||||
? styles.btnPurchased
|
||||
: styles.btnActive),
|
||||
]}
|
||||
@@ -109,7 +108,7 @@ const purchased = contractorIds.includes(String(contractorId));
|
||||
isPurchased && !purchaseEnded ? { color: colors.white } : { color: '#fff' },
|
||||
]}
|
||||
>
|
||||
{purchaseEnded ? 'Expired' : (purchased?'Purchased':isPurchased ? 'Remove' : 'Add to Cart')}
|
||||
{purchaseEnded ? 'Expired' : (purchased ? 'Purchased' : isPurchased ? 'Remove' : 'Add to Cart')}
|
||||
</Text>
|
||||
{(!purchaseEnded && !purchased) && (
|
||||
<ArrowRight size={16} color={isPurchased ? colors.white : '#fff'} />
|
||||
@@ -117,8 +116,6 @@ const purchased = contractorIds.includes(String(contractorId));
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* Tender Detail Modal */}
|
||||
{/* <TenderFullDetail visible={showDetail} data={data} onClose={() => setShowDetail(false)} /> */}
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -15,9 +15,9 @@ const ProceedToBidDetail = () => {
|
||||
const [refreshing, setRefreshing] = React.useState(false);
|
||||
const [loading, setLoading] = 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)
|
||||
// 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
|
||||
|
||||
@@ -125,7 +125,7 @@ const ProceedToBidDetail = () => {
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
tenderRefetch();
|
||||
}, [tenderData.tenderId])
|
||||
}, [tenderData?.tenderId])
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -23,8 +23,6 @@ const PurchaseTenderAllList = () => {
|
||||
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, isRefetching, refetch }: any = useFetchPurchaseTender();
|
||||
const [showRefreshBanner, setShowRefreshBanner] = useState(false);
|
||||
|
||||
|
||||
console.log("data for tender : ", data)
|
||||
useEffect(() => {
|
||||
if (isRefetching) {
|
||||
setShowRefreshBanner(true);
|
||||
@@ -36,6 +34,7 @@ const PurchaseTenderAllList = () => {
|
||||
return () => clearTimeout(timer);
|
||||
}
|
||||
}, [isRefetching]);
|
||||
|
||||
const format = 'DD-MM-YYYY HH:mm:ss';
|
||||
|
||||
function isTenderActive(item: any): boolean {
|
||||
|
||||
@@ -7,7 +7,7 @@ import colors from '../../Constant/Color';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import NavigationString from '../../Constant/NavigationString';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { togglePurchaseAuction } from '../../Redux/Slices/selectPurchaseAuction';
|
||||
import { togglePurchaseTender } from '../../Redux/Slices/SelectedPurchaseTender';
|
||||
|
||||
const PurchaseTenderList = () => {
|
||||
const Navigation: any = useNavigation()
|
||||
@@ -18,7 +18,6 @@ const PurchaseTenderList = () => {
|
||||
setExpandedIndex(prev => (prev === index ? null : index));
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<View style={styles.screen}>
|
||||
<InsideHeader title="Purchase" showArrow />
|
||||
@@ -27,12 +26,13 @@ const PurchaseTenderList = () => {
|
||||
{/* Header */}
|
||||
<View style={styles.header}>
|
||||
<Text style={styles.heading}>Tender Purchase List</Text>
|
||||
<Info size={20} color="#0F172A" />
|
||||
{/* <Info size={20} color="#0F172A" /> */}
|
||||
</View>
|
||||
|
||||
{/* Cards */}
|
||||
{SelectedPurchaseList.map((item: any, index: any) => {
|
||||
const expanded = expandedIndex === index;
|
||||
console.log("item gvsdvgfsv h ca : ", item)
|
||||
return (
|
||||
<Animated.View
|
||||
key={item.auctionId}
|
||||
@@ -79,7 +79,7 @@ const PurchaseTenderList = () => {
|
||||
{renderRow('Department', item.departmentName)}
|
||||
{renderRow('Purchase End', item.purchaseEnd)}
|
||||
|
||||
<TouchableOpacity style={styles.removeButton} onPress={() => { Dispatch(togglePurchaseAuction(item)) }}>
|
||||
<TouchableOpacity style={styles.removeButton} onPress={() => { Dispatch(togglePurchaseTender(item)) }}>
|
||||
<Trash2 size={18} color="#fff" />
|
||||
<Text style={styles.removeText}>Remove</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
@@ -104,7 +104,7 @@ const PurchaseTenderTile = ({ item, onPressDetails }: any) => {
|
||||
</View>
|
||||
|
||||
<TouchableOpacity
|
||||
// disabled={!isLive}
|
||||
disabled={!isLive}
|
||||
onPress={() => {
|
||||
if (isLive) {
|
||||
navigation.navigate('ProceedToBidDetail', { tender });
|
||||
|
||||
@@ -34,7 +34,7 @@ const Tender = () => {
|
||||
(state: any) => state?.selectPurchaseTender,
|
||||
);
|
||||
|
||||
const liveCount = liveTenderData?.totalCount || 0;
|
||||
const liveCount = liveTenderData?.pages?.[0]?.totalCount || 0;
|
||||
const purchaseCount = purchaseTenderData?.pages?.[0]?.totalCount || 0;
|
||||
|
||||
const [selectedTab, setSelectedTab] = useState<'live' | 'purchase'>('live');
|
||||
|
||||
@@ -18,9 +18,6 @@ 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 axios from 'axios';
|
||||
import { useSelector } from 'react-redux';
|
||||
import EnvelopeCExcelPreview from '../Component/EnvelopeCExcelPreview';
|
||||
|
||||
type EnvelopeType = 'A' | 'B' | 'C';
|
||||
@@ -43,8 +40,6 @@ 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;
|
||||
const [activeEnvelope, setActiveEnvelope] = useState<EnvelopeType>('A');
|
||||
@@ -54,18 +49,13 @@ const TenderBidding = () => {
|
||||
C: {},
|
||||
});
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [loadingUpload, setLoadingUpload] = useState(false)
|
||||
const [check, setCheck] = useState(false)
|
||||
const [uploadFileResponse, setUploadFileResponse] = useState<any>(null);
|
||||
|
||||
|
||||
const InfoRow = ({ title, value }: InfoRowProps) => (
|
||||
<View style={styles.infoRow}>
|
||||
<Text style={styles.label}>{title}</Text>
|
||||
<Text style={styles.value}>{value || '-'}</Text>
|
||||
</View>
|
||||
);
|
||||
|
||||
const EnvelopeButton = ({ title, envelopeType, onPress }: EnvelopeButtonProps & { envelopeType: EnvelopeType }) => (
|
||||
<TouchableOpacity
|
||||
onPress={onPress}
|
||||
@@ -80,8 +70,6 @@ const TenderBidding = () => {
|
||||
<Text style={styles.envelopeButtonText}>{title}</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
||||
|
||||
const handleEnvelopeChange = (
|
||||
envelopeType: EnvelopeType,
|
||||
sequenceId: number,
|
||||
@@ -95,7 +83,6 @@ const TenderBidding = () => {
|
||||
},
|
||||
}));
|
||||
};
|
||||
|
||||
const pickPdf = async (
|
||||
envelopeType: EnvelopeType,
|
||||
sequenceId: number
|
||||
@@ -116,8 +103,6 @@ const TenderBidding = () => {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const renderEnvelopeItem = ({
|
||||
item,
|
||||
envelopeType,
|
||||
@@ -137,22 +122,13 @@ const TenderBidding = () => {
|
||||
const showInput =
|
||||
activeEnvelope === envelopeType &&
|
||||
!bidData?.[`envelope${envelopeType}SubmittStatus`];
|
||||
|
||||
// console.log("tender ana : ", tenderData)
|
||||
return (
|
||||
<View key={sequenceId}>
|
||||
<View style={styles.envelopeItem}>
|
||||
<View style={{ flexDirection: 'row', gap: 20 }}>
|
||||
{/* <Text style={styles.label}>Label Name</Text> */}
|
||||
<Text style={styles.value}>{labelName || '-'}</Text>
|
||||
{item?.[`labelMandatory${activeEnvelope}`] && <Text style={{ color: validateEnvelope() ? 'gray' : 'red', }}>*</Text>}
|
||||
|
||||
</View>
|
||||
|
||||
{/* <View>
|
||||
<Text style={styles.label}>Label Type</Text>
|
||||
<Text style={styles.value}>{labelType || '-'}</Text>
|
||||
</View> */}
|
||||
</View>
|
||||
|
||||
{showInput ? (
|
||||
@@ -227,7 +203,6 @@ const TenderBidding = () => {
|
||||
|
||||
return hasA || hasB;
|
||||
};
|
||||
|
||||
const digitToWordMap: Record<string, string> = {
|
||||
'0': 'Zero',
|
||||
'1': 'One',
|
||||
@@ -240,14 +215,12 @@ const TenderBidding = () => {
|
||||
'8': 'Eight',
|
||||
'9': 'Nine',
|
||||
};
|
||||
|
||||
const convertDigitsToWords = (value: string): string => {
|
||||
return value
|
||||
.split('')
|
||||
.map(digit => digitToWordMap[digit] || '')
|
||||
.join(' ') || value;
|
||||
};
|
||||
|
||||
const buildEnvelopePayload = () => {
|
||||
|
||||
const list =
|
||||
@@ -319,7 +292,6 @@ const TenderBidding = () => {
|
||||
? fileData
|
||||
: saveData,
|
||||
};
|
||||
// console.log("payload : ", payload)
|
||||
return payload;
|
||||
|
||||
};
|
||||
@@ -334,13 +306,9 @@ const TenderBidding = () => {
|
||||
const value = formValues?.[seqId];
|
||||
|
||||
if (!isMandatory) return false;
|
||||
|
||||
// File upload
|
||||
if (item[`labelType${activeEnvelope}`] === '3') {
|
||||
return !value;
|
||||
}
|
||||
|
||||
// Text / numeric
|
||||
return !value || value.toString().trim() === '';
|
||||
});
|
||||
|
||||
@@ -353,30 +321,29 @@ const TenderBidding = () => {
|
||||
Alert.alert('Validation Error', 'Please fill all mandatory fields');
|
||||
return;
|
||||
}
|
||||
|
||||
const payload = buildEnvelopePayload();
|
||||
console.log('Envelope A Payload:', payload);
|
||||
setLoading(true)
|
||||
if (envelopForm?.[activeEnvelope]?.[3]) {
|
||||
handleSubmitEnvelopeFile(SUBMIT_ENVELOPE_FILE_A)
|
||||
return
|
||||
}
|
||||
try {
|
||||
const result = await handleSubmitEnvelopeFile(SUBMIT_ENVELOPE_FILE_A)
|
||||
|
||||
const res = await apiCall('post', SUBMIT_ENVELOPE_A, payload) as any
|
||||
console.log("res A envelop : ", res)
|
||||
ToastAndroid.show(res?.message, ToastAndroid.SHORT)
|
||||
if (result && result?.statusCode === 200) {
|
||||
try {
|
||||
const res = await apiCall('post', SUBMIT_ENVELOPE_A, payload) as any
|
||||
|
||||
|
||||
navigation.goBack()
|
||||
} catch (error) {
|
||||
console.log("error A envelop submit : ", error)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
if (res?.statusCode === 200) {
|
||||
navigation.goBack()
|
||||
ToastAndroid.show(res.message, ToastAndroid.SHORT)
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("error A envelop submit : ", error)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
} else {
|
||||
setLoading(false)
|
||||
Alert.alert('Error', 'File upload failed. Please try again.')
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const handleSubmitEnvelopeB = async () => {
|
||||
if (!validateEnvelope()) {
|
||||
Alert.alert('Validation Error', 'Please fill all mandatory fields');
|
||||
@@ -405,25 +372,16 @@ const TenderBidding = () => {
|
||||
Alert.alert('Error', 'File upload failed. Please try again.')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
const handleSubmitEnvelopeFile = async (url: string) => {
|
||||
console.log("url :: ", url)
|
||||
|
||||
const payload = buildEnvelopePayload();
|
||||
|
||||
const formData = new FormData();
|
||||
console.log("envelop form : ", envelopForm)
|
||||
|
||||
const fileDetail: any = envelopForm?.[activeEnvelope]?.[3]
|
||||
formData.append('files', {
|
||||
uri: envelopForm?.[activeEnvelope]?.[3].uri,
|
||||
name: envelopForm?.[activeEnvelope]?.[3].name,
|
||||
type: envelopForm?.[activeEnvelope]?.[3].type,
|
||||
uri: fileDetail.uri,
|
||||
name: fileDetail.name,
|
||||
type: fileDetail.type,
|
||||
});
|
||||
// formData.append('requestDto', payload)
|
||||
formData.append('requestDto', JSON.stringify(payload))
|
||||
console.log("formdata : ", formData)
|
||||
|
||||
@@ -557,9 +515,10 @@ const TenderBidding = () => {
|
||||
handleSubmitEnvelopeB();
|
||||
}
|
||||
}}
|
||||
// disabled={loading}
|
||||
>
|
||||
<Text style={styles.primaryButtonText}>
|
||||
{loading ? 'Submitting...' : `Submit Bid (${activeEnvelope})`}
|
||||
{loading ? <ActivityIndicator size={'small'} color={'#fff'} /> : `Submit Bid (${activeEnvelope})`}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
) : (
|
||||
|
||||
+30
-10
@@ -53,10 +53,30 @@ export const useFetchPurchaseTender = () => {
|
||||
|
||||
|
||||
export const useFetchLiveTender = () => {
|
||||
return useQuery({
|
||||
queryKey: ['fetchLiveTender',],
|
||||
queryFn: () => fetchLiveTender()
|
||||
});
|
||||
|
||||
return useInfiniteQuery({
|
||||
queryKey: ['fetchLiveTender'],
|
||||
queryFn: ({ pageParam = 0 }) => fetchLiveTender({
|
||||
page: pageParam,
|
||||
size: 10
|
||||
}),
|
||||
initialPageParam: 0,
|
||||
getNextPageParam: (lastPage, allPages) => {
|
||||
const { totalCount } = lastPage;
|
||||
console.log("last page : ", lastPage)
|
||||
console.log("all pages : ", allPages)
|
||||
const totalPages = Math.ceil(totalCount / 10);
|
||||
const nextPage = allPages.length;
|
||||
return nextPage < totalPages ? nextPage : undefined;
|
||||
},
|
||||
|
||||
select: (data) => ({
|
||||
...data,
|
||||
result: data.pages.flatMap(
|
||||
(page: any) => page?.data ?? []
|
||||
),
|
||||
}),
|
||||
})
|
||||
};
|
||||
export const useContractorProfile = () => {
|
||||
return useQuery({
|
||||
@@ -149,11 +169,11 @@ export const useOfflineTenderPurchase = () => {
|
||||
};
|
||||
|
||||
export const useFetchTenderById = (tenderId: string) => {
|
||||
return useQuery({
|
||||
queryKey: ['fetchTenderById', tenderId],
|
||||
queryFn: () => fetchTenderById(tenderId),
|
||||
enabled: !!tenderId, // prevents running with undefined id
|
||||
});
|
||||
return useQuery({
|
||||
queryKey: ['fetchTenderById', tenderId],
|
||||
queryFn: () => fetchTenderById(tenderId),
|
||||
enabled: !!tenderId, // prevents running with undefined id
|
||||
});
|
||||
}
|
||||
export const useProceedToBid = (tenderId?: string) => {
|
||||
return useQuery({
|
||||
@@ -319,7 +339,7 @@ export const useTenderDetails = () => {
|
||||
});
|
||||
};
|
||||
|
||||
export const useFetchLiveTenderById = (tenderId:number) => {
|
||||
export const useFetchLiveTenderById = (tenderId: number) => {
|
||||
return useQuery({
|
||||
queryKey: ['fetchLiveTenderById', tenderId],
|
||||
queryFn: () => fetchLiveTenderById(tenderId)
|
||||
|
||||
@@ -125,8 +125,11 @@ export const fetchPurchaseTender = async ({
|
||||
|
||||
|
||||
|
||||
export const fetchLiveTender = async (): Promise<any> => {
|
||||
const data = await apiCall<any>('get', `${LIVE_TENDER}`);
|
||||
export const fetchLiveTender = async ({page, size}:{page:number, size:number}): Promise<any> => {
|
||||
console.log("page : ", page)
|
||||
console.log("size : ", size)
|
||||
const data = await apiCall<any>('get', `${LIVE_TENDER}?page=${page}&size=${size}`);
|
||||
console.log("data : ", data)
|
||||
return data
|
||||
}
|
||||
export const fetchContractorProfile = async (): Promise<any> => {
|
||||
|
||||
Reference in New Issue
Block a user