import React, { useEffect, useState } from 'react'; import { View, Text, FlatList, TouchableOpacity, StyleSheet, TextInput, Alert, ActivityIndicator, } from 'react-native'; import { pick } from '@react-native-documents/picker'; import Animated, { FadeInDown, FadeOutUp, Layout } from 'react-native-reanimated'; import BouncyCheckbox from 'react-native-bouncy-checkbox'; import { InsideHeader, Skelton } from '../../Component/Index'; import EmdComplete from './Component/EmdComplete'; import NavigationString from '../../Constant/NavigationString'; import { useNavigation } from '@react-navigation/native'; import { useSelector } from 'react-redux'; import { useAuctionItem, useEmdCheck } from '../../Services/ApiCall/Hooks'; import { apiCall } from '../../Axios/Axios'; import { AUCITON_SINGLE_EMD, AUCTION_ITEM_SUBMIT, CHECK_TECHNICAL_DOCUMENTAION, GET_AUCTION_DETAILS, GET_TECHNICAL_DOCUMENTAION, } from '../../Services/ApiCall/ApiUrls'; import TemplateFormModal from './Component/TemplateFormModal'; import { SelectedItem } from './Type/BidType'; import { showSuccessAlert } from '../../Constant/ShowDailog'; import { useTheme } from '../../Hooks/useTheme'; import AppText from '../../components/AppText'; import { FileText, Upload, CheckCircle2, ShieldCheck, Paperclip, ChevronRight, PackageCheck, BadgeIndianRupee, } from 'lucide-react-native'; const Emd = () => { const Navigation: any = useNavigation(); const { colors, spacing, shadows, typography } = useTheme(); const SelectedAuction = useSelector((state: any) => state.auction.auction); const [selectedItems, setSelectedItems] = useState([]); const [acceptedPolicy, setAcceptedPolicy] = useState(false); const [isInitialLoading, setIsInitialLoading] = useState(true); const [allBoolean, setAllBoolean]: any = useState({ isSubmitEmdLoading: false, isEmdComplete: false, auctionItems: [], technicalDocumentStatus: false, selectTemplate: {}, technicalDocModalVisible: false, emdType: false, fileName: '', file: {}, }); const { mutate } = useEmdCheck(); const { mutate: AuctionItemMutate, isPending } = useAuctionItem(); const isSelected = (id: number) => selectedItems.some(i => i.auctionItemId === id); const toggleSelect = (item: any, checked: boolean) => { if (!checked) { setSelectedItems(prev => prev.filter(i => i.auctionItemId !== item.id)); } else { setSelectedItems(prev => [ ...prev, { auctionItemId: item.id, productImageName: '', file: null }, ]); } }; const updateSelectedItem = (id: number, data: Partial) => { setSelectedItems(prev => prev.map(i => (i.auctionItemId === id ? { ...i, ...data } : i)), ); }; const pickFile = async (id: number) => { try { const res = await pick({ type: ['application/pdf'] }); const file = res[0]; updateSelectedItem(id, { file: { name: file.name ?? 'document.pdf', uri: file.uri, type: 'application/pdf' }, }); } catch { console.log('Pick cancelled'); } }; const pickFileSingle = async () => { try { const res = await pick({ type: ['application/pdf'] }); const file = res[0]; setAllBoolean((prev: any) => ({ ...prev, file: { name: file.name ?? 'document.pdf', uri: file.uri, type: 'application/pdf' }, })); } catch { console.log('Pick cancelled'); } }; /* ── Render Item ── */ const renderItem = ({ item }: any) => { console.log(item, "item"); const selected = isSelected(item.id); const selectedData = selectedItems.find(i => i.auctionItemId === item.id); return ( {/* Card Header */} {item.productName} {/* */} EMD ₹ {item.emdAmount} toggleSelect(item, checked)} /> {/* Existing doc */} Existing:{' '} {item.itemDocumentName ?? 'Not Uploaded'} {/* Expanded Form */} {selected && ( updateSelectedItem(item.id, { productImageName: text })} style={[styles.textInput, { borderColor: colors.border, backgroundColor: colors.background, color: colors.text }]} placeholderTextColor={colors.textSecondary} /> pickFile(item.id)} activeOpacity={0.85} > {selectedData?.file ? 'Change PDF' : 'Upload PDF'} {selectedData?.file && ( {selectedData.file.name} )} )} ); }; /* ── API calls (unchanged logic) ── */ const getAuctionItem = async () => { try { const payload = { auctionNumber: SelectedAuction.auctionNumber, status: SelectedAuction.auctionPattern }; AuctionItemMutate(payload, { onSuccess: res => { if (res.statusCode === 200) { setAllBoolean((prev: any) => ({ ...prev, auctionItems: Array.isArray(res?.data) ? res.data : [res.data] })); } }, onError: () => { }, }); } catch (error) { console.log('Auction fetch error', error); } }; const getTemplateDocumentation = async () => { try { if (SelectedAuction.technicalDocReq) { const res = await apiCall('get', CHECK_TECHNICAL_DOCUMENTAION, {}, { auctionId: SelectedAuction.auctionId }); if (res.data) { setAllBoolean((prev: any) => ({ ...prev, technicalDocumentStatus: true })); } else { const res2 = await apiCall('get', GET_TECHNICAL_DOCUMENTAION); const auctionIdToFind = String(SelectedAuction.auctionId); const matchedObject = res2.data.find((item: any) => item.auctionIds?.split(',')?.map((id: any) => id.trim())?.includes(auctionIdToFind), ); setAllBoolean((prev: any) => ({ ...prev, selectTemplate: matchedObject, technicalDocModalVisible: true })); } } } catch (error) { console.log('Auction fetch error', error); } }; const getAuction = async () => { const selectedRes = await apiCall('get', GET_AUCTION_DETAILS, {}, { id: SelectedAuction.auctionId }); const emdType = String(selectedRes.data.emd).trim().replace(/\s+/g, ' ').toLowerCase(); return selectedRes.statusCode === 200 && emdType === 'auction wise'; }; const AlreadyEmdCheck = async () => { try { setIsInitialLoading(true); mutate( { auctionNumber: SelectedAuction.auctionNumber }, { onSuccess: async res => { try { if (res.statusCode === 200) { if (res.message === 'No EMD Documents') { const result = await getAuction(); if (result) { setAllBoolean((prev: any) => ({ ...prev, emdType: true })); return; } setAllBoolean((prev: any) => ({ ...prev, isEmdComplete: false })); getAuctionItem(); } else { if (!SelectedAuction.technicalDocReq) { setAllBoolean((prev: any) => ({ ...prev, isEmdComplete: true, technicalDocumentStatus: true })); } else { setAllBoolean((prev: any) => ({ ...prev, isEmdComplete: true })); getTemplateDocumentation(); } } } } finally { setIsInitialLoading(false); } }, onError: () => { setIsInitialLoading(false); }, }, ); } catch (error) { console.log('EMD Check Error:', error); setIsInitialLoading(false); } }; const handleSubmit = async () => { setAllBoolean((prev: any) => ({ ...prev, isSubmitEmdLoading: true })); if (!acceptedPolicy) { Alert.alert('Policy Required', 'Please accept terms'); return; } if (selectedItems.length === 0) { Alert.alert('Select Item', 'Please select at least one item'); return; } for (const item of selectedItems) { if (!item.productImageName || !item.file) { Alert.alert('Incomplete', 'Upload documents for all selected items'); return; } } try { const formData = new FormData(); formData.append('auctionId', String(SelectedAuction.auctionId)); selectedItems.forEach((item: any) => { formData.append('auctionItemId', String(item.auctionItemId)); formData.append('productImageName', item.productImageName); formData.append('files', { uri: item.file.uri, name: item.file.name, type: item.file.type || 'application/pdf' } as any); }); const res = await apiCall('post', AUCTION_ITEM_SUBMIT, formData, {}, 'multipart/form-data'); if (res.statusCode === 200) { if (SelectedAuction.technicalDocReq) { getTemplateDocumentation(); } else { Navigation.navigate(SelectedAuction.auctionPattern === 'Forward' ? NavigationString.StartBidding : NavigationString.StartReverseBidding); } } } catch (error) { Alert.alert('Error', 'Failed to submit EMD'); } finally { setAllBoolean((prev: any) => ({ ...prev, isSubmitEmdLoading: false })); } }; const EmdContinueHandle = async () => { if (allBoolean.technicalDocumentStatus) { Navigation.navigate(SelectedAuction.auctionPattern === 'Forward' ? NavigationString.StartBidding : NavigationString.StartReverseBidding); } else { getTemplateDocumentation(); } }; const singleEmdSubmit = async () => { try { setAllBoolean((prev: any) => ({ ...prev, isSubmitEmdLoading: true })); if (!acceptedPolicy) { Alert.alert('Policy Required', 'Please accept terms'); return; } const formData = new FormData(); formData.append('auctionId', SelectedAuction.auctionId); formData.append('productImageName', allBoolean.fileName); formData.append('files', allBoolean.file); const response = await apiCall('post', AUCITON_SINGLE_EMD, formData, {}, 'multipart/form-data'); if (response?.statusCode === 200) { showSuccessAlert(response.message || 'EMD submitted successfully'); Navigation.navigate(SelectedAuction.auctionPattern === 'Forward' ? NavigationString.StartBidding : NavigationString.StartReverseBidding); } } catch (error: any) { console.log('Error:', error?.message || error); } finally { setAllBoolean((prev: any) => ({ ...prev, isSubmitEmdLoading: false })); } }; useEffect(() => { AlreadyEmdCheck(); }, []); const styles = makeStyles(colors, spacing, shadows, typography); /* ── Policy + Submit footer ── */ const BottomBar = ({ onSubmit }: { onSubmit: () => void }) => ( setAcceptedPolicy(p => !p)} /> I agree to{' '} Terms & Privacy Policy {allBoolean.isSubmitEmdLoading ? ( ) : ( <> Submit EMD )} ); return ( {SelectedAuction.technicalDocReq && allBoolean.technicalDocModalVisible && ( )} {(isPending || isInitialLoading) ? ( ) : allBoolean.isEmdComplete ? ( ) : allBoolean.emdType ? ( /* ── Single EMD (auction-wise) ── */ {/* Icon banner */} Auction-wise EMD Upload a single document for this auction {/* Document name */} DOCUMENT NAME setAllBoolean((prev: any) => ({ ...prev, fileName: text }))} /> {/* File picker */} {allBoolean?.file?.name ? 'Change PDF' : 'Choose PDF'} {allBoolean?.file?.name ? ( {allBoolean.file.name} ) : null} ) : ( /* ── Item-wise EMD ── */ String(item.id)} renderItem={renderItem} contentContainerStyle={styles.listContent} showsVerticalScrollIndicator={false} /> )} ); }; export default Emd; /* ─── Styles factory ─── */ const makeStyles = (colors: any, spacing: any, shadows: any, typography?: any) => StyleSheet.create({ root: { flex: 1, backgroundColor: colors.background, }, listContent: { padding: spacing.m, paddingBottom: 160, }, /* ── Item card ── */ card: { borderRadius: 18, marginBottom: spacing.m, padding: spacing.m, borderWidth: 1, borderColor: colors.border, ...shadows.light, }, cardHeader: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', gap: spacing.s, }, cardLeft: { flexDirection: 'row', alignItems: 'center', flex: 1, gap: spacing.s, }, itemIconBox: { width: 40, height: 40, borderRadius: 12, alignItems: 'center', justifyContent: 'center', }, itemTitle: { fontFamily: typography?.fonts?.bold, marginBottom: 3, } as any, emdRow: { flexDirection: 'row', alignItems: 'center', gap: 3, }, emdAmount: { fontFamily: typography?.fonts?.bold, } as any, existingDocRow: { flexDirection: 'row', alignItems: 'center', gap: 5, marginTop: spacing.s, paddingHorizontal: spacing.s + 2, paddingVertical: 6, borderRadius: 8, }, expandedForm: { marginTop: spacing.s, }, separator: { height: StyleSheet.hairlineWidth, marginBottom: spacing.m, }, textInput: { borderWidth: 1.2, borderRadius: 14, padding: 12, fontSize: 14, marginBottom: spacing.s, }, uploadBtn: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 7, paddingVertical: 13, borderRadius: 14, }, uploadText: { fontFamily: typography?.fonts?.bold, } as any, fileNameRow: { flexDirection: 'row', alignItems: 'center', gap: 6, marginTop: spacing.s, paddingHorizontal: spacing.s + 4, paddingVertical: 8, borderRadius: 10, }, /* ── Single EMD card ── */ singleEmdCard: { margin: spacing.m, backgroundColor: colors.surface, borderRadius: 20, padding: spacing.m, ...shadows.light, }, singleEmdBanner: { flexDirection: 'row', alignItems: 'center', gap: spacing.m, borderRadius: 14, padding: spacing.m, marginBottom: spacing.m, }, fieldLabel: { fontFamily: typography?.fonts?.bold, letterSpacing: 1, marginBottom: spacing.xs + 2, } as any, /* ── Bottom bar ── */ bottomBar: { height: 160, padding: spacing.m, paddingBottom: spacing.m + 60, backgroundColor: colors.surface, borderTopWidth: StyleSheet.hairlineWidth, borderTopColor: colors.border, ...shadows.large, }, policyRow: { flexDirection: 'row', alignItems: 'center', gap: spacing.s, marginBottom: spacing.m, }, policyText: { flex: 1, lineHeight: 20, fontSize: 13, fontWeight: '500', color: colors.text, } as any, submitBtn: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 8, paddingVertical: 15, borderRadius: 16, }, disabledBtn: { opacity: 0.6, }, submitText: { fontSize: 14, fontWeight: '800', color: '#fff', letterSpacing: 0.5, textTransform: 'uppercase', } as any, });