This commit is contained in:
Abin Toppo
2026-01-14 15:13:51 +05:30
16 changed files with 186 additions and 141 deletions
+4 -7
View File
@@ -1,14 +1,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<!-- Android 12 and below -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
<!-- Android 13+ -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<application
android:name=".MainApplication"
+12 -11
View File
@@ -11,8 +11,7 @@ export const apiCall = async <R, D = {}>(
): Promise<R> => {
try {
const token: any = store.getState().token.token;
console.log("abin-------",url)
const response = await axios({
method,
url,
@@ -23,25 +22,27 @@ export const apiCall = async <R, D = {}>(
'Content-Type': contentType || 'application/json',
},
});
console.log("abin-------",response)
return response.data;
} catch (error: any) {
const errorMessage = error?.response?.data?.error;
console.log(errorMessage, '---------------------------api error message');
// console.log(error?.response?.data.error, '---------------------------api error message');
if (error?.response?.status === 401) {
if (error?.response?.statusCode === 401) {
store.dispatch(setToken({}));
return {
success: false,
message: 'JWT Error - Token expired or malformed',
} as R;
}
const data = {
data: {
success: false,
message: error?.response?.data?.message || 'No Response From Server',
}
return {
success: false,
message: error?.response?.data?.message || 'No Response From Server',
} as R;
}
return data as any
}
};
+41 -10
View File
@@ -1,7 +1,12 @@
import { Filter, Search } from "lucide-react-native";
import React from "react";
import React, { useEffect, useRef, useState } from "react";
import { View, Text, TextInput, StyleSheet, TouchableOpacity, Platform } from "react-native";
import Animated, { useAnimatedStyle, useSharedValue, withTiming, interpolateColor } from "react-native-reanimated";
import Animated, {
useAnimatedStyle,
useSharedValue,
withTiming,
interpolateColor,
} from "react-native-reanimated";
import colors from "../../Constant/Color";
export interface SearchType {
@@ -10,12 +15,22 @@ export interface SearchType {
label?: string;
filter?: boolean;
filterPress?: () => void;
debounceDelay?: number; // 👈 optional
}
const AnimatedView = Animated.createAnimatedComponent(View);
export const SearchInput: React.FC<SearchType> = ({ placeholder, onChange, label, filter = true, filterPress }) => {
export const SearchInput: React.FC<SearchType> = ({
placeholder,
onChange,
label,
filter = true,
filterPress,
debounceDelay = 500, // 👈 default debounce
}) => {
const isFocused = useSharedValue(0);
const [text, setText] = useState('');
const debounceRef = useRef<NodeJS.Timeout | null>(null);
const inputContainerStyle = useAnimatedStyle(() => {
const borderColor = interpolateColor(
@@ -25,13 +40,30 @@ export const SearchInput: React.FC<SearchType> = ({ placeholder, onChange, label
);
return {
borderColor: borderColor,
borderColor,
borderWidth: withTiming(isFocused.value ? 1.5 : 1),
transform: [{ scale: withTiming(isFocused.value ? 1.01 : 1) }],
shadowOpacity: withTiming(isFocused.value ? 0.1 : 0),
};
});
// 🔥 Debounce logic
useEffect(() => {
if (debounceRef.current) {
clearTimeout(debounceRef.current);
}
debounceRef.current = setTimeout(() => {
onChange(text.trim());
}, debounceDelay);
return () => {
if (debounceRef.current) {
clearTimeout(debounceRef.current);
}
};
}, [text]);
return (
<View style={styles.container}>
{label && <Text style={styles.label}>{label}</Text>}
@@ -40,13 +72,14 @@ export const SearchInput: React.FC<SearchType> = ({ placeholder, onChange, label
<AnimatedView style={[styles.inputWrapper, inputContainerStyle]}>
<Search
size={18}
color={isFocused.value ? colors.grayText : colors.grayText}
color={colors.grayText}
style={styles.searchIcon}
/>
<TextInput
style={styles.input}
placeholder={placeholder}
onChangeText={onChange}
value={text}
onChangeText={setText} // 👈 update local state only
placeholderTextColor={colors.grayText}
onFocus={() => (isFocused.value = withTiming(1))}
onBlur={() => (isFocused.value = withTiming(0))}
@@ -94,11 +127,9 @@ const styles = StyleSheet.create({
borderRadius: 12,
paddingHorizontal: 12,
borderWidth: 1,
// Shadow for iOS
shadowColor: "#000",
shadowOffset: { width: 0, height: 2 },
shadowRadius: 4,
// Elevation for Android
elevation: 2,
},
searchIcon: {
@@ -125,5 +156,5 @@ const styles = StyleSheet.create({
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 2,
}
});
},
});
-2
View File
@@ -1,12 +1,10 @@
import moment from 'moment';
export const format = {
// Internal helper to safely parse any input
parse: (date: string | Date) => {
if (!date) return null;
let d = date;
if (typeof date === 'string') {
// Replace IST or other known timezone abbreviations with UTC offset
d = date.replace('IST', '+0530');
}
return moment(d);
+4 -3
View File
@@ -18,13 +18,14 @@ const LiveAuction = () => {
const onEndReachedCalledDuringMomentum = useRef(true);
const SelectedPurchaseList = useSelector((state: any) => state.selectPurchaseAuction);
const [showRefreshBanner, setShowRefreshBanner] = useState(false);
const [allBoolean, setAllBoolean] = useState({ liveAuctionData: [] })
const [allBoolean, setAllBoolean] = useState({ liveAuctionData: [], isLoading: false })
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, isRefetching, refetch, isPending }: any = useFetchLiveAuction();
// My Methods
const getMyAuction = async () => {
try {
setAllBoolean(prev => ({ ...prev, isLoading: true }))
const res = await apiCall<any>('get', `${GET_MY_AUCTION}`,);
if (res?.statusCode === 200) {
const purchasedIds = new Set(res.data.map((item: any) => item.auctionId));
@@ -100,7 +101,7 @@ const LiveAuction = () => {
return (
<View style={{ flex: 1 }}>
<SearchInput onChange={() => { }} placeholder="Search...." />
<SearchInput onChange={() => { }} placeholder="Search...." filter={false} />
{showRefreshBanner && (
<Animated.View
@@ -139,7 +140,7 @@ const LiveAuction = () => {
</Animated.View>
)}
{
isPending ? <Skeleton /> :
isPending || allBoolean.isLoading ? <Skeleton /> :
<FlatList
data={allBoolean.liveAuctionData ?? []}
renderItem={renderItem}
@@ -72,7 +72,6 @@ const AuctionItemDetail: React.FC<Props> = ({ visible, onClose, data }) => {
};
return (
<Modal
visible={visible}
transparent={false}
+36 -39
View File
@@ -1,30 +1,14 @@
import React, { useState } from 'react';
import {
Modal,
View,
Text,
StyleSheet,
TouchableOpacity,
Pressable,
} from 'react-native';
import { Modal, View, Text, StyleSheet, TouchableOpacity, Pressable } from 'react-native';
import DatePicker from 'react-native-date-picker';
import moment from 'moment';
import colors from '../../../Constant/Color';
import FontsFamily from '../../../Constant/FontsFamily';
import { AuctionStatus, Props } from '../types/types';
type AuctionStatus = 'RUNNING' | 'ENDED' | 'NOT_STARTED' | null;
interface Props {
visible: boolean;
onClose: () => void;
onApply: (filters: {
fromDate: Date | null;
toDate: Date | null;
status: AuctionStatus;
}) => void;
}
const FilterModal: React.FC<Props> = ({ visible, onClose, onApply }) => {
const FilterModal: React.FC<Props> = ({ visible, onClose, setFilter, filter }) => {
const [fromDate, setFromDate] = useState<Date | null>(null);
const [toDate, setToDate] = useState<Date | null>(null);
const [status, setStatus] = useState<AuctionStatus>(null);
@@ -38,16 +22,26 @@ const FilterModal: React.FC<Props> = ({ visible, onClose, onApply }) => {
};
const handleConfirm = (date: Date) => {
if (pickerType === 'FROM') {
setFromDate(date);
console.log('FROM date set');
} else {
setToDate(date);
console.log('TO date set');
}
setOpenPicker(false);
};
const handleApply = () => {
onApply({ fromDate, toDate, status });
const payload = {
fromDate: fromDate ? fromDate.toISOString() : null,
toDate: toDate ? toDate.toISOString() : null,
status,
};
setFilter({ ...payload, auctionNumber: filter.auctionNumber || '' });
onClose();
};
@@ -67,7 +61,7 @@ const FilterModal: React.FC<Props> = ({ visible, onClose, onApply }) => {
<View style={styles.container}>
<Text style={styles.title}>Filter Auctions</Text>
{/* ===== DATE RANGE ===== */}
{/* DATE RANGE */}
<Text style={styles.sectionTitle}>Date Range</Text>
<View style={styles.dateRow}>
@@ -96,7 +90,7 @@ const FilterModal: React.FC<Props> = ({ visible, onClose, onApply }) => {
</TouchableOpacity>
</View>
{/* ===== STATUS ===== */}
{/* STATUS */}
<Text style={styles.sectionTitle}>Auction Status</Text>
<View style={styles.statusRow}>
@@ -109,7 +103,9 @@ const FilterModal: React.FC<Props> = ({ visible, onClose, onApply }) => {
return (
<TouchableOpacity
key={item.value}
onPress={() => setStatus(item.value as AuctionStatus)}
onPress={() =>
setStatus(item.value as AuctionStatus)
}
style={[
styles.statusPill,
active && styles.statusActive,
@@ -128,20 +124,25 @@ const FilterModal: React.FC<Props> = ({ visible, onClose, onApply }) => {
})}
</View>
{/* ===== FOOTER ===== */}
{/* FOOTER */}
<View style={styles.footer}>
{/* <TouchableOpacity style={styles.cancelBtn} onPress={onClose}>
<Text style={styles.cancelText}>Cancel</Text>
</TouchableOpacity> */}
<TouchableOpacity style={styles.applyBtn} onPress={handleApply}>
<TouchableOpacity
style={[styles.applyBtn]}
onPress={() => { setFilter({}), onClose() }}
>
<Text style={styles.applyText}>Clear</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.applyBtn}
onPress={handleApply}
>
<Text style={styles.applyText}>Apply</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
{/* ===== DATE PICKER ===== */}
{/* DATE PICKER */}
<DatePicker
modal
open={openPicker}
@@ -160,7 +161,6 @@ const FilterModal: React.FC<Props> = ({ visible, onClose, onApply }) => {
export default FilterModal;
const styles = StyleSheet.create({
overlay: {
flex: 1,
@@ -229,31 +229,28 @@ const styles = StyleSheet.create({
statusText: {
fontSize: 13,
color: '#334155',
fontFamily:FontsFamily.poppinsSemiBold
fontFamily: FontsFamily.poppinsSemiBold,
},
statusActiveText: {
color: '#fff',
},
footer: {
marginTop: 24,
flexDirection: 'row',
justifyContent: 'space-between',
marginTop: 24,
alignItems: 'center'
},
cancelBtn: {
padding: 12,
},
applyBtn: {
backgroundColor: colors.primary,
paddingHorizontal: 20,
paddingVertical: 12,
borderRadius: 12,
width: '100%'
width: '49%',
},
applyText: {
color: '#fff',
fontSize: 16,
textAlign: 'center',
fontFamily: FontsFamily.poppinsSemiBold
fontFamily: FontsFamily.poppinsSemiBold,
},
});
+6 -4
View File
@@ -19,7 +19,8 @@ const PurchaseAuction = () => {
const navigation = useNavigation() as any;
const Dispatch = useDispatch()
const onEndReachedCalledDuringMomentum = useRef(true);
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, isRefetching, refetch, isPending }: any = useFetchLiveAuctionPage();
const [filter, setFilter] = useState({})
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, isRefetching, refetch, isPending }: any = useFetchLiveAuctionPage(filter);
const [allBoolean, setAllBoolean] = useState<allBooleanProps>({ isShowFilter: false })
const format = 'DD-MM-YYYY HH:mm:ss';
@@ -60,9 +61,10 @@ const PurchaseAuction = () => {
);
}, [isFetchingNextPage]);
return (
<View style={{ flex: 1 }}>
<SearchInput onChange={() => { }} placeholder='Search....' filterPress={() => { setAllBoolean((prev: any) => ({ ...prev, isShowFilter: !prev.isShowFilter })) }} />
<SearchInput onChange={(val) => { setFilter(prev => ({ ...prev, auctionNumber: val })) }} placeholder='Search....' filterPress={() => { setAllBoolean((prev: any) => ({ ...prev, isShowFilter: !prev.isShowFilter })) }} />
{isPending ? <Skelton />
:
<FlatList
@@ -108,8 +110,8 @@ const PurchaseAuction = () => {
/>
}
{allBoolean.isShowFilter && <View style={{ flex: 1 }}>
<FilterModal visible={allBoolean.isShowFilter} onClose={() => { setAllBoolean((prev: any) => ({ ...prev, isShowFilter: false })) }} onApply={() => { }} />
</View>}
<FilterModal visible={allBoolean.isShowFilter} onClose={() => { setAllBoolean((prev: any) => ({ ...prev, isShowFilter: false })) }} setFilter={setFilter} filter={filter} />
</View>}.
</View>
);
+19
View File
@@ -15,4 +15,23 @@ export interface LiveAuctionTileProps {
export interface allBooleanProps {
showDetail?: boolean
isShowFilter?: boolean
filterValue?: {
fromDate?: any,
toDate?: any,
status?: any
}
}
export type AuctionStatus = 'RUNNING' | 'ENDED' | 'NOT_STARTED' | null;
export interface Props {
visible: boolean;
onClose: () => void;
setFilter: (data: {
fromDate?: string | null;
toDate?: string | null;
status?: AuctionStatus;
auctionNumber?: any
}) => void;
filter: any
}
@@ -18,7 +18,7 @@ const TemplateFormModal: React.FC<Props> = ({ visible, template, setAllBoolean }
const SelectedAuction = useSelector((state: any) => state.auction.auction)
const Navigation: any = useNavigation()
const [loading, setLoading] = useState(false)
const initialValues = template.labels.reduce((acc: any, label: any) => {
const initialValues = template?.labels?.reduce((acc: any, label: any) => {
acc[label.labelName] = ''
return acc
}, {})
@@ -150,7 +150,7 @@ const TemplateFormModal: React.FC<Props> = ({ visible, template, setAllBoolean }
([labelName, labelValue]: any) => {
if (typeof labelValue === 'object' && labelValue?.uri) {
hasFile = true
fileFormData.append(labelName, {
fileFormData.append('files', {
uri: labelValue.uri,
name: labelValue.name,
type: labelValue.type,
@@ -166,14 +166,13 @@ const TemplateFormModal: React.FC<Props> = ({ visible, template, setAllBoolean }
const rs1: any = await apiCall('post', TECHNICAL_VALUE_SUBMIT, jsonBody)
if (hasFile) {
fileFormData.append(
'auctiontId',
String(SelectedAuction.auctionId)
'auctionTemplateValueIds',
String(rs1?.data[0]?.valueId)
)
fileFormData.append(
'technicalDocumentTemplateId',
'templateNameId',
String(payload.templateNameId)
)
@@ -184,7 +183,7 @@ const TemplateFormModal: React.FC<Props> = ({ visible, template, setAllBoolean }
{},
'multipart/form-data'
)
console.log(res2, '-------------res2');
if (rs1.statusCode == 200 && res2.statusCode == 200) {
Navigation.navigate(NavigationString.StartBidding)
setAllBoolean((prev: any) => ({ ...prev, technicalDocModalVisible: false }))
@@ -397,7 +396,7 @@ const styles = StyleSheet.create({
submitRow: {
marginTop: 20,
alignItems: 'flex-end',
height:50
height: 50
},
submitBtn: {
backgroundColor: colors.primary,
-3
View File
@@ -15,7 +15,6 @@ import { AUCITON_SINGLE_EMD, AUCTION_ITEM_SUBMIT, CHECK_TECHNICAL_DOCUMENTAION,
import TemplateFormModal from './Component/TemplateFormModal';
import { SelectedItem } from './Type/BidType';
import FontsFamily from '../../Constant/FontsFamily';
import { all } from 'axios';
import { showSuccessAlert } from '../../Constant/ShowDailog';
@@ -231,7 +230,6 @@ const Emd = () => {
mutate({ auctionNumber: SelectedAuction.auctionNumber }, {
onSuccess: (async (res) => {
if (res.statusCode == 200) {
if (res.message == 'No EMD Documents') {
const result = await getAuction()
if (result) {
@@ -381,7 +379,6 @@ const Emd = () => {
};
useEffect(() => {
// getAuction()
AlreadyEmdCheck()
}, [])
+1
View File
@@ -5,6 +5,7 @@ import { Layers, Clock, ShoppingCart, X, FileText } from 'lucide-react-native';
import { Header } from '../../Component/Index';
import colors from '../../Constant/Color';
import { useDashboard } from '../../Services/BBPS/Hooks';
import { log } from 'console';
const { width } = Dimensions.get('window');
const CARD_WIDTH = (width - 48) / 2;
+1 -1
View File
@@ -66,7 +66,7 @@ const DASHBOARD_COUNT = `${BASE_URL_Auction}api/auction/home/dashboard/counts`
const AUCTION_ONE_TIME_BID = `${BASE_URL_Auction}api/bidding/getBidForAuction`
const AUCITON_SINGLE_EMD = `${BASE_URL_Auction}api/auction/addEMDDocumentsAuctionWise`
const PURCHASE_AUCTION_LIST = `${BASE_URL_Auction}api/auction/proceedToPurchase`
const VIEW_AUCTION_ITEM_DETAIL = `${BASE_URL_Auction}api/auction/home/viewDocumentsForAuctionItemDetails`
const VIEW_AUCTION_ITEM_DETAIL = `${BASE_URL_Auction}api/auction/viewDocumentsForAuctionItemDetails`
const VIEW_AUCTION_DOCUMENTS = `${BASE_URL_Auction}api/auction/viewDocumentsForAuction`
const AUCTION_DOCUMENT_DOWNLOAD = `${BASE_URL_Auction}api/auction/home/downloadDocumentForAuction`
const AUCTION_ITEM_DOCUMENT_DOWNLOAD = `${BASE_URL_Auction}api/auction/home/downloadDocument/auctionItemId`
+53 -52
View File
@@ -66,13 +66,14 @@ export const useFetchPurchaseAuction = () => {
});
};
export const useFetchLiveAuctionPage = () => {
export const useFetchLiveAuctionPage = (payload: any) => {
return useInfiniteQuery<any>({
queryKey: ['fetchPurchaseAuctionPage'],
queryKey: ['fetchPurchaseAuctionPage', payload],
queryFn: ({ pageParam = 0 }) =>
fetchPurchaseAuctionPage({
page: pageParam,
size: 10,
...payload
}),
initialPageParam: 0,
@@ -148,11 +149,11 @@ return useQuery({
});
}
export const useProceedToBid = (tenderId?: string) => {
return useQuery({
queryKey: ['proceedToBid', tenderId],
queryFn: () => proceedToBid(tenderId as string),
enabled: false, // 👈 manual trigger
});
return useQuery({
queryKey: ['proceedToBid', tenderId],
queryFn: () => proceedToBid(tenderId as string),
enabled: false, // 👈 manual trigger
});
};
export const useAuctionItem = () => {
@@ -169,11 +170,11 @@ export const useEmdCheck = () => {
});
};
export const useGetDesignation = () => {
export const useGetDesignation = () => {
return useQuery({
queryKey: ['Designation'],
queryFn: () => getDesignation()
});
}
@@ -190,75 +191,75 @@ export const useRagistrationState = () => {
};
export const usefetchMasterData = () => {
export const usefetchMasterData = () => {
return useQuery({
queryKey: ['MasterData'],
queryFn: () => fetchMasterData()
});
}
export const useCityDropdown = () => {
export const useCityDropdown = () => {
return useMutation({
mutationFn: (stateId: number) => fetchCityDropdown(stateId),
});
};
export const useVerifyPan = () =>
useMutation({
mutationFn: verifyPanHandler,
});
useMutation({
mutationFn: verifyPanHandler,
});
export const useSendAadhaarOtp = () =>
useMutation({
mutationFn: sendAadhaarOtp,
});
export const useSendAadhaarOtp = () =>
useMutation({
mutationFn: sendAadhaarOtp,
});
export const useVerifyAadhaarOtp = () =>
useMutation({
mutationFn: verifyAadhaarOtp,
});
export const useVerifyAadhaarOtp = () =>
useMutation({
mutationFn: verifyAadhaarOtp,
});
export const useVerifyGstNumber = () =>
useMutation({
mutationFn: verifyGstNumber,
});
export const useVerifyGstNumber = () =>
useMutation({
mutationFn: verifyGstNumber,
});
export const useContractorStageTwoSubmit = () =>
useMutation({
mutationFn: contractorStageTwoSubmit,
});
export const useContractorStageThreeSubmit = () =>
useMutation({
mutationFn: contractorStageThreeSubmit,
});
export const usePartnerShipSubmit = () =>
useMutation({
mutationFn: partnerShipSubmit,
});
export const useContractorStageTwoSubmit = () =>
useMutation({
mutationFn: contractorStageTwoSubmit,
});
export const useContractorStageThreeSubmit = () =>
useMutation({
mutationFn: contractorStageThreeSubmit,
});
export const usePartnerShipSubmit = () =>
useMutation({
mutationFn: partnerShipSubmit,
});
export const useSubmitEnvelopeA = () =>
useMutation({
mutationFn: submitEnvelopeA,
})
useMutation({
mutationFn: submitEnvelopeA,
})
export const useSubmitEnvelopeB = () =>
useMutation({
mutationFn: submitEnvelopeB,
})
useMutation({
mutationFn: submitEnvelopeB,
})
export const useUploadEnvelopeFile = () =>
useMutation({
mutationFn: uploadEnvelopeFile,
})
useMutation({
mutationFn: uploadEnvelopeFile,
})
@@ -285,7 +286,7 @@ export const useGetAucitonDocument = (payload: { auctionId: number }) => {
export const useAucitonItemDetail = (payload: { auctionItemId: number }) => {
return useQuery({
queryKey: ['viewAuctionItemDocuments'],
queryKey: [],
queryFn: () => viewAuctionItemDocuments(payload)
});
};
+2
View File
@@ -51,6 +51,8 @@ export const fetchPurchaseAuction = async (): Promise<any> => {
return data
}
export const fetchPurchaseAuctionPage = async (payload: any): Promise<any> => {
console.log(payload,'[[[[[[[[[[[[[[[[[[[[[[[[');
const data = await apiCall<any>('get', `${PURCHASE_AUCTION_PAGE}`, {}, payload);
return data
}
View File