From 2f42c03d582e70b3c8bc31aebf250755cb5fb72d Mon Sep 17 00:00:00 2001 From: Abin Toppo Date: Thu, 15 Jan 2026 17:21:34 +0530 Subject: [PATCH] premerge --- src/Component/SideDrawer/SideDrawer.tsx | 31 +- src/Constant/NavigationString.tsx | 1 + src/Navigation/Bottom.tsx | 5 +- src/Screens/Profile/ProfileTab.tsx | 1062 +++++++++++++++++++++++ src/Screens/index.ts | 2 + src/Services/BBPS/ApiUrls.tsx | 5 +- src/Services/BBPS/Hooks.ts | 15 +- src/Services/BBPS/apis.ts | 23 +- 8 files changed, 1126 insertions(+), 18 deletions(-) create mode 100644 src/Screens/Profile/ProfileTab.tsx diff --git a/src/Component/SideDrawer/SideDrawer.tsx b/src/Component/SideDrawer/SideDrawer.tsx index 49e580c..b49bea9 100644 --- a/src/Component/SideDrawer/SideDrawer.tsx +++ b/src/Component/SideDrawer/SideDrawer.tsx @@ -4,9 +4,10 @@ import Modal from 'react-native-modal'; import Animated, { useSharedValue, useAnimatedStyle, withTiming, withDelay } from 'react-native-reanimated'; import { Home, Gavel, FileText, User, LogOut, ChevronRight } from 'lucide-react-native'; import { CommonActions, useNavigation } from '@react-navigation/native'; -import { useDispatch } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import { removeToken } from '../../Redux/Slices/Token'; import NavigationString from '../../Constant/NavigationString'; +import colors from '../../Constant/Color'; const { width, height } = Dimensions.get('window'); const DRAWER_WIDTH = width * 0.78; @@ -16,8 +17,9 @@ interface Props { visible: boolean; onClose: () => void; } const SideDrawer: React.FC = ({ visible, onClose }) => { const navigation: any = useNavigation(); const dispatch = useDispatch(); + const userData = useSelector((state: any) => state.token?.token); - const user = { name: 'Rohit Kumar', role: 'Procurement Manager', avatar: 'https://i.pravatar.cc/150?img=12', }; + const user = { name: userData?.fullName, role: userData?.role, }; const translateX = useSharedValue(-DRAWER_WIDTH); useEffect(() => { @@ -31,6 +33,11 @@ const SideDrawer: React.FC = ({ visible, onClose }) => { })); const menuItems = [ + { + label: 'Profile', + icon: User, + onPress: () => navigation.navigate(NavigationString.Profile), + }, { label: 'Home', icon: Home, @@ -45,12 +52,8 @@ const SideDrawer: React.FC = ({ visible, onClose }) => { label: 'Tenders', icon: FileText, onPress: () => navigation.navigate(NavigationString.Tender), - } - // { - // label: 'Profile', - // icon: User, - // onPress: () => { }, - // }, + }, + ]; return ( @@ -75,7 +78,9 @@ const SideDrawer: React.FC = ({ visible, onClose }) => { */} - + + + {user.name} {user.role} @@ -180,9 +185,11 @@ const styles = StyleSheet.create({ }, avatar: { - width: 72, - height: 72, - borderRadius: 36, + justifyContent:'center', + alignItems:'center', + backgroundColor:colors.primary, + padding:25, + borderRadius:60, marginBottom: 10, }, diff --git a/src/Constant/NavigationString.tsx b/src/Constant/NavigationString.tsx index 047e4f8..9bf09e7 100644 --- a/src/Constant/NavigationString.tsx +++ b/src/Constant/NavigationString.tsx @@ -20,5 +20,6 @@ const NavigationString = { Partnership:'Partnership', LiveTenderDetail:'LiveTenderDetail', AuctionDetail: 'AuctionDetail', + Profile:'Profile' } export default NavigationString \ No newline at end of file diff --git a/src/Navigation/Bottom.tsx b/src/Navigation/Bottom.tsx index 287c776..2fb1e70 100644 --- a/src/Navigation/Bottom.tsx +++ b/src/Navigation/Bottom.tsx @@ -25,7 +25,7 @@ const TabButton = ({ route, isFocused, onPress }: any) => { Home: { outline: "Home", filled: "Home" }, Auction: { outline: "Gavel", filled: "Gavel" }, Tender: { outline: "FileText", filled: "FileText" }, - EditableExcel: { outline: "FileText", filled: "FileText" }, + Profile: { outline: "User", filled: "User" }, }; const IconName = LucideIcons[isFocused ? icons[route.name].filled : icons[route.name].outline]; const scaleAnim = useRef(new Animated.Value(1)).current; @@ -148,7 +148,8 @@ export default function BottomTab() { - + {/* */} + diff --git a/src/Screens/Profile/ProfileTab.tsx b/src/Screens/Profile/ProfileTab.tsx new file mode 100644 index 0000000..3b316ca --- /dev/null +++ b/src/Screens/Profile/ProfileTab.tsx @@ -0,0 +1,1062 @@ +import React, { useEffect, useMemo, useState } from 'react'; +import { + View, + Text, + ScrollView, + StyleSheet, + TouchableOpacity, + RefreshControl, + ActivityIndicator, + Dimensions, + Platform, + ViewStyle, + TextStyle, + Modal, + TextInput, + KeyboardAvoidingView, + Alert, +} from 'react-native'; +import { LinearGradient } from 'react-native-linear-gradient'; +import { + AlertCircle, + UserCircle, + User, + Mail, + Phone, + Briefcase, + Building2, + Building, + Tag, + Network, + Globe, + Award, + MapPin, + Home, + Map, + Mailbox, + FileText, + CreditCard, + Type, + Calendar, + Receipt, + ClipboardCheck, + Star, + List, + Factory, + CheckCircle2, + CheckCircle, + CalendarClock, + ShieldCheck, + LucideIcon, + Edit, + X, + Save, +} from 'lucide-react-native'; + +import { useContractorProfile, useUpdateUserProfile } from '../../Services/BBPS/Hooks'; +import colors from '../../Constant/Color'; + +const { width } = Dimensions.get('window'); + +// Type Definitions +interface ContractorData { + contractorId: number; + firstName: string; + middleName: string; + lastName: string; + fullName: string; + emailId: string; + mobileNo: string; + company: string; + contractorType: string; + dialCode: string; + twoFactorAuthEnabled: boolean; + colorCodeHSL: string | null; + isActive: string; + isEnabled: boolean | null; + role: string; + contractorStatus: boolean; + designation: string | null; + contOtherId: number; + contCompanyType: string | null; + contOrganization: string; + agentAddress: string; + agentPincode: string; + agentCity: string; + agentState: string | null; + agentWebsite: string; + agentRegno: string; + orgPAN: string; + orgPANdob: string; + orgPANname: string; + gistnNo: string; + comAadharNo: string; + contractorClass: string; + socialCategory: string; + wizardStepStatus: string; + registrationStatus: string; + indianOrgName: string; + expiryDate: string; + msmeStatus: string; +} + +interface ProfileHeaderProps { + data: ContractorData; +} + +interface QuickStatsProps { + data: ContractorData; +} + +interface InfoSectionProps { + title: string; + IconComponent: LucideIcon; + children: React.ReactNode; + delay?: number; + onEdit?: () => void; + showEdit?: boolean; +} + +interface InfoRowProps { + label: string; + value: string | null | undefined; + IconComponent: LucideIcon; + valueColor?: string; +} + +interface StatItem { + Icon: LucideIcon; + label: string; + value: string; + color: string; +} + +interface UpdateProfilePayload { + firstName: string; + middleName: string; + lastName: string; + mobileNo: string; + emailId: string; + fullname: string; +} + +// Helper function to check if value is valid +const isValidValue = (value: any): boolean => { + if (value === null || value === undefined) return false; + if (typeof value === 'string') { + const trimmed = value.trim(); + return trimmed.length > 0 && trimmed.toLowerCase() !== 'n/a'; + } + return true; +}; + +// Main Component +const ProfileTab: React.FC = () => { + const { data, refetch, isLoading, error } = useContractorProfile(); + const [editModalVisible, setEditModalVisible] = useState(false); + + if (isLoading) { + return ( + + + Loading profile... + + ); + } + + if (error) { + return ( + + + {error} + + Retry + + + ); + } + + if (!data) return null; + + return ( + <> + + } + showsVerticalScrollIndicator={false} + removeClippedSubviews={true} + maxToRenderPerBatch={10} + updateCellsBatchingPeriod={50} + initialNumToRender={8} + windowSize={10} + > + {/* Header with Gradient */} + + + {/* Quick Stats */} + + + {/* Personal Information */} + setEditModalVisible(true)} + > + + + + + + + {/* Company Details */} + + + + + + + + + {/* Address Information */} + + + + + + + + {/* Tax & Legal */} + + + + + + + + + {/* Registration Status */} + + + + + + + + + + + {/* Edit Modal */} + setEditModalVisible(false)} + data={data} + onSuccess={refetch} + /> + + ); +}; + +// Edit Profile Modal Component +interface EditProfileModalProps { + visible: boolean; + onClose: () => void; + data: ContractorData; + onSuccess: () => void; +} + +const EditProfileModal: React.FC = ({ + visible, + onClose, + data, + onSuccess, +}) => { + const [formData, setFormData] = useState({ + firstName: data.firstName || '', + middleName: data.middleName || '', + lastName: data.lastName || '', + mobileNo: data.mobileNo || '', + emailId: data.emailId || '', + fullname: data.fullName || '', + }); + + const [errors, setErrors] = useState>({}); + + const updateProfileMutation = useUpdateUserProfile(); + + // Reset form when modal opens + useEffect(() => { + if (visible) { + setFormData({ + firstName: data.firstName || '', + middleName: data.middleName || '', + lastName: data.lastName || '', + mobileNo: data.mobileNo || '', + emailId: data.emailId || '', + fullname: data.fullName || '', + }); + setErrors({}); + } + }, [visible, data]); + + const validateForm = (): boolean => { + const newErrors: Partial = {}; + + if (!formData.firstName.trim()) { + newErrors.firstName = 'First name is required'; + } + + if (!formData.lastName.trim()) { + newErrors.lastName = 'Last name is required'; + } + + if (!formData.emailId.trim()) { + newErrors.emailId = 'Email is required'; + } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.emailId)) { + newErrors.emailId = 'Invalid email format'; + } + + if (!formData.mobileNo.trim()) { + newErrors.mobileNo = 'Mobile number is required'; + } else if (!/^\d{10}$/.test(formData.mobileNo.replace(/\s/g, ''))) { + newErrors.mobileNo = 'Invalid mobile number'; + } + + // Auto-generate fullname + const generatedFullName = `${formData.firstName} ${formData.middleName} ${formData.lastName}`.trim(); + setFormData(prev => ({ ...prev, fullname: generatedFullName })); + + setErrors(newErrors); + return Object.keys(newErrors).length === 0; + }; + + const handleSave = async () => { + if (!validateForm()) { + return; + } + + try { + await updateProfileMutation.mutateAsync(formData); + Alert.alert('Success', 'Profile updated successfully'); + onSuccess(); + onClose(); + } catch (error: any) { + Alert.alert('Error', error?.message || 'Failed to update profile'); + } + }; + + return ( + + + + {/* Header */} + + Edit Personal Information + + + + + + {/* Form */} + + {/* First Name */} + + First Name * + setFormData({ ...formData, firstName: text })} + placeholder="Enter first name" + placeholderTextColor={colors.grayText} + /> + {errors.firstName && ( + {errors.firstName} + )} + + + {/* Middle Name */} + + Middle Name + setFormData({ ...formData, middleName: text })} + placeholder="Enter middle name" + placeholderTextColor={colors.grayText} + /> + + + {/* Last Name */} + + Last Name * + setFormData({ ...formData, lastName: text })} + placeholder="Enter last name" + placeholderTextColor={colors.grayText} + /> + {errors.lastName && ( + {errors.lastName} + )} + + + {/* Email */} + + Email * + setFormData({ ...formData, emailId: text })} + placeholder="Enter email" + placeholderTextColor={colors.grayText} + keyboardType="email-address" + autoCapitalize="none" + /> + {errors.emailId && ( + {errors.emailId} + )} + + + {/* Mobile Number */} + + Mobile Number * + setFormData({ ...formData, mobileNo: text })} + placeholder="Enter mobile number" + placeholderTextColor={colors.grayText} + keyboardType="phone-pad" + maxLength={10} + /> + {errors.mobileNo && ( + {errors.mobileNo} + )} + + + + {/* Footer Buttons */} + + + Cancel + + + + {updateProfileMutation.isPending ? ( + + ) : ( + <> + + Save + + )} + + + + + + ); +}; + +// Profile Header Component - OPTIMIZED +const ProfileHeader: React.FC = React.memo(({ data }) => { + const getInitials = (name: string): string => { + if (!name || typeof name !== 'string' || name.trim().length === 0) { + const fallbackName = `${data.firstName || ''} ${data.lastName || ''}`.trim(); + if (fallbackName) { + return fallbackName + .split(' ') + .filter((n) => n.length > 0) + .map((n) => n[0]) + .join('') + .toUpperCase() + .substring(0, 2); + } + return 'NA'; + } + + return ( + name + .split(' ') + .filter((n) => n.length > 0) + .map((n) => n[0]) + .join('') + .toUpperCase() + .substring(0, 2) || 'NA' + ); + }; + + const getStatusColor = (): string => { + if (data.isActive === 'Active') return colors.success; + return colors.error; + }; + + return ( + + + + + {getInitials(data.fullName)} + + + + + + + + {data.fullName || + `${data.firstName} ${data.lastName}`.trim() || + 'Unknown User'} + + + + + {data.role} + + + + ); +}); + +ProfileHeader.displayName = 'ProfileHeader'; + +// Quick Stats Component - OPTIMIZED +const QuickStats: React.FC = React.memo(({ data }) => { + const stats: StatItem[] = useMemo( + () => [ + { + Icon: CheckCircle, + label: 'Status', + value: data.isActive, + color: colors.success, + }, + { + Icon: ShieldCheck, + label: '2FA', + value: data.twoFactorAuthEnabled ? 'Enabled' : 'Disabled', + color: data.twoFactorAuthEnabled ? colors.success : colors.grayText, + }, + { + Icon: FileText, + label: 'Registration', + value: data.registrationStatus, + color: colors.info, + }, + ], + [data.isActive, data.twoFactorAuthEnabled, data.registrationStatus] + ); + + return ( + + {stats.map((stat) => ( + + + + {stat.value} + + {stat.label} + + ))} + + ); +}); + +QuickStats.displayName = 'QuickStats'; + +// Info Section Component - OPTIMIZED +const InfoSection: React.FC = React.memo( + ({ title, IconComponent, children, onEdit, showEdit = false }) => { + return ( + + + + + + + {title} + + {showEdit && onEdit && ( + + + + )} + + {children} + + ); + } +); + +InfoSection.displayName = 'InfoSection'; + +// Info Row Component - OPTIMIZED +const InfoRow: React.FC = React.memo( + ({ label, value, IconComponent, valueColor }) => { + // Return null if value is not valid + if (!isValidValue(value)) { + return null; + } + + return ( + + + + + + + + {label} + + {value} + + + + + + ); + } +); + +InfoRow.displayName = 'InfoRow'; + +// Styles +interface Styles { + container: ViewStyle; + contentContainer: ViewStyle; + centerContainer: ViewStyle; + loadingText: TextStyle; + errorText: TextStyle; + retryButton: ViewStyle; + retryButtonText: TextStyle; + headerGradient: ViewStyle; + avatarContainer: ViewStyle; + avatar: ViewStyle; + avatarText: TextStyle; + statusBadge: ViewStyle; + statusDot: ViewStyle; + headerName: TextStyle; + roleBadge: ViewStyle; + roleText: TextStyle; + statsContainer: ViewStyle; + statCard: ViewStyle; + statValue: TextStyle; + statLabel: TextStyle; + section: ViewStyle; + sectionHeader: ViewStyle; + sectionHeaderLeft: ViewStyle; + sectionIconContainer: ViewStyle; + sectionTitle: TextStyle; + sectionContent: ViewStyle; + infoRow: ViewStyle; + infoRowTouchable: ViewStyle; + infoRowContent: ViewStyle; + infoIconContainer: ViewStyle; + infoTextContainer: ViewStyle; + infoLabel: TextStyle; + infoValue: TextStyle; + editButton: ViewStyle; + modalOverlay: ViewStyle; + modalContent: ViewStyle; + modalHeader: ViewStyle; + modalTitle: TextStyle; + closeButton: ViewStyle; + formContainer: ViewStyle; + inputGroup: ViewStyle; + inputLabel: TextStyle; + input: TextStyle; + inputError: TextStyle; + errorText: TextStyle; + modalFooter: ViewStyle; + button: ViewStyle; + cancelButton: ViewStyle; + saveButton: ViewStyle; + cancelButtonText: TextStyle; + saveButtonText: TextStyle; +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: colors.lightGray, + }, + contentContainer: { + paddingBottom: 20, + }, + centerContainer: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: colors.white, + padding: 20, + }, + loadingText: { + marginTop: 16, + fontSize: 16, + color: colors.grayText, + fontWeight: '500', + }, + errorText: { + marginTop: 16, + fontSize: 16, + color: colors.error, + textAlign: 'center', + fontWeight: '500', + }, + retryButton: { + marginTop: 20, + backgroundColor: colors.primary, + paddingHorizontal: 32, + paddingVertical: 12, + borderRadius: 12, + elevation: 2, + shadowColor: colors.shadow, + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.2, + shadowRadius: 4, + }, + retryButtonText: { + color: colors.white, + fontSize: 16, + fontWeight: '600', + }, + + // Header Styles + headerGradient: { + paddingTop: Platform.OS === 'ios' ? 60 : 40, + paddingBottom: 30, + alignItems: 'center', + borderBottomLeftRadius: 32, + borderBottomRightRadius: 32, + elevation: 8, + shadowColor: colors.shadow, + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.3, + shadowRadius: 8, + }, + avatarContainer: { + position: 'relative', + marginBottom: 16, + }, + avatar: { + width: 100, + height: 100, + borderRadius: 50, + backgroundColor: colors.white, + justifyContent: 'center', + alignItems: 'center', + borderWidth: 4, + borderColor: colors.white, + elevation: 4, + shadowColor: colors.shadow, + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.2, + shadowRadius: 4, + }, + avatarText: { + fontSize: 36, + fontWeight: '700', + color: colors.primary, + }, + statusBadge: { + position: 'absolute', + bottom: 4, + right: 4, + width: 24, + height: 24, + borderRadius: 12, + borderWidth: 3, + borderColor: colors.white, + justifyContent: 'center', + alignItems: 'center', + }, + statusDot: { + width: 10, + height: 10, + borderRadius: 5, + backgroundColor: colors.white, + }, + headerName: { + fontSize: 26, + fontWeight: '700', + color: colors.white, + marginBottom: 8, + textAlign: 'center', + paddingHorizontal: 20, + }, + roleBadge: { + flexDirection: 'row', + alignItems: 'center', + backgroundColor: 'rgba(255, 255, 255, 0.25)', + paddingHorizontal: 16, + paddingVertical: 6, + borderRadius: 20, + gap: 6, + }, + roleText: { + color: colors.white, + fontSize: 14, + fontWeight: '600', + }, + + // Stats Styles + statsContainer: { + flexDirection: 'row', + marginHorizontal: 16, + marginTop: -30, + gap: 12, + zIndex: 10, + }, + statCard: { + flex: 1, + backgroundColor: colors.white, + borderRadius: 16, + padding: 16, + alignItems: 'center', + elevation: 4, + shadowColor: colors.shadow, + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.15, + shadowRadius: 6, + }, + statValue: { + fontSize: 14, + fontWeight: '700', + color: colors.darkText, + marginTop: 8, + textAlign: 'center', + }, + statLabel: { + fontSize: 12, + color: colors.grayText, + marginTop: 4, + }, + + // Section Styles + section: { + marginHorizontal: 16, + marginTop: 24, + backgroundColor: colors.white, + borderRadius: 20, + padding: 20, + elevation: 2, + shadowColor: colors.shadow, + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.1, + shadowRadius: 4, + }, + sectionHeader: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + marginBottom: 16, + paddingBottom: 12, + borderBottomWidth: 1, + borderBottomColor: colors.border, + }, + sectionHeaderLeft: { + flexDirection: 'row', + alignItems: 'center', + flex: 1, + }, + sectionIconContainer: { + width: 40, + height: 40, + borderRadius: 12, + backgroundColor: colors.primaryHighlight, + justifyContent: 'center', + alignItems: 'center', + marginRight: 12, + }, + sectionTitle: { + fontSize: 18, + fontWeight: '700', + color: colors.darkText, + flex: 1, + }, + sectionContent: { + gap: 12, + }, + editButton: { + padding: 8, + borderRadius: 8, + backgroundColor: colors.primaryHighlight, + }, + + // Info Row Styles + infoRow: { + borderRadius: 12, + overflow: 'hidden', + }, + infoRowTouchable: { + padding: 14, + backgroundColor: colors.lightestGray, + borderRadius: 12, + }, + infoRowContent: { + flexDirection: 'row', + alignItems: 'flex-start', + }, + infoIconContainer: { + width: 32, + height: 32, + borderRadius: 8, + backgroundColor: colors.white, + justifyContent: 'center', + alignItems: 'center', + marginRight: 12, + marginTop: 2, + }, + infoTextContainer: { + flex: 1, + gap: 4, + }, + infoLabel: { + fontSize: 13, + color: colors.grayText, + fontWeight: '500', + lineHeight: 18, + }, + infoValue: { + fontSize: 15, + color: colors.darkText, + fontWeight: '600', + lineHeight: 21, + }, + + // Modal Styles + modalOverlay: { + flex: 1, + backgroundColor: 'rgba(0, 0, 0, 0.5)', + justifyContent: 'flex-end', + }, + modalContent: { + backgroundColor: colors.white, + borderTopLeftRadius: 24, + borderTopRightRadius: 24, + maxHeight: '90%', + paddingTop: 20, + }, + modalHeader: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + paddingHorizontal: 20, + paddingBottom: 16, + borderBottomWidth: 1, + borderBottomColor: colors.border, + }, + modalTitle: { + fontSize: 20, + fontWeight: '700', + color: colors.darkText, + }, + closeButton: { + padding: 4, + }, + formContainer: { + padding: 20, + maxHeight: 500, + }, + inputGroup: { + marginBottom: 20, + }, + inputLabel: { + fontSize: 14, + fontWeight: '600', + color: colors.darkText, + marginBottom: 8, + }, + input: { + borderWidth: 1, + borderColor: colors.border, + borderRadius: 12, + padding: 14, + fontSize: 15, + color: colors.darkText, + backgroundColor: colors.white, + }, + inputError: { + borderColor: colors.error, + }, + errorText: { + fontSize: 12, + color: colors.error, + marginTop: 4, + }, + modalFooter: { + flexDirection: 'row', + padding: 20, + gap: 12, + borderTopWidth: 1, + borderTopColor: colors.border, + }, + button: { + flex: 1, + paddingVertical: 14, + borderRadius: 12, + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'row', + gap: 8, + }, + cancelButton: { + backgroundColor: colors.lightestGray, + }, + saveButton: { + backgroundColor: colors.primary, + }, + cancelButtonText: { + fontSize: 16, + fontWeight: '600', + color: colors.darkText, + }, + saveButtonText: { + fontSize: 16, + fontWeight: '600', + color: colors.white, + }, +}); + +export default ProfileTab; diff --git a/src/Screens/index.ts b/src/Screens/index.ts index 1091eb6..4d1c0b0 100644 --- a/src/Screens/index.ts +++ b/src/Screens/index.ts @@ -7,6 +7,7 @@ import StartReverseBidding from "./Bidding/StartReverseBidding"; import Home from "./Home/Home"; import Login from "./Login/Login"; import Onboarding from "./Onboarding/Onboarding"; +import ProfileTab from "./Profile/ProfileTab"; import Partnership from "./Ragistration/PartnerShip"; import Registration from "./Ragistration/Ragistration"; import Signup from "./SignUp/SignUp"; @@ -39,6 +40,7 @@ const Screens = { Registration, Partnership, LiveTenderDetail, + ProfileTab } diff --git a/src/Services/BBPS/ApiUrls.tsx b/src/Services/BBPS/ApiUrls.tsx index 875754b..c95320f 100644 --- a/src/Services/BBPS/ApiUrls.tsx +++ b/src/Services/BBPS/ApiUrls.tsx @@ -82,6 +82,8 @@ const SUBMIT_ENVELOPE_FILE_A = `${BASE_URL}tenderBidding/addDocumentsEnvelopeA` const SUBMIT_ENVELOPE_FILE_B = `https://procurelinc.in/EProcurementSB/tenderBidding/addDocumentsEnvelopeB` const GET_ENVELOPE_C = `${BASE_URL}eTendering/getEnvelopeCTemplate/tenderId?tenderId=` const SUBMIT_ENVELOPE_C_UPLOAD = `${BASE_URL}tenderBidding/getSaveEnvelopeCData` +const GET_CONTRACTOR_PROFILE =`${BASE_URL}contractor/getcontractorfulldetails +` @@ -159,6 +161,7 @@ export { SUBMIT_ENVELOPE_FILE_B, GET_ENVELOPE_C, SUBMIT_ENVELOPE_C_UPLOAD, - GET_TENDER_BY_ID + GET_TENDER_BY_ID, + GET_CONTRACTOR_PROFILE }; diff --git a/src/Services/BBPS/Hooks.ts b/src/Services/BBPS/Hooks.ts index 22bc298..342ab65 100644 --- a/src/Services/BBPS/Hooks.ts +++ b/src/Services/BBPS/Hooks.ts @@ -1,5 +1,5 @@ import { useInfiniteQuery, useMutation, useQuery } from '@tanstack/react-query'; -import { contractorStageThreeSubmit, contractorStageTwoSubmit, fetchAuctionItem, fetchCityDropdown, fetchDashboard, fetchEmdCheck, fetchLiveAuction, fetchLiveTender, fetchMasterData, fetchPurchaseAuction, fetchPurchaseAuctionList, fetchPurchaseTender, fetchTenderById, getAuction, getDesignation, getRagistrationState, offlineAuctionPurchase, offlineTenderPurchase, partnerShipSubmit, proceedToBid, registerContractor, sendAadhaarOtp, submitEnvelopeA, submitEnvelopeB, uploadEnvelopeFile, userAuctionLogin, userLogin, verifyAadhaarOtp, verifyGstNumber, verifyPanHandler, viewAuctionDocumentDownload, viewAuctionDocuments, viewAuctionItemDocuments, fetchPurchaseAuctionPage, tenderDetails, fetchLiveTenderById } from './apis'; +import { contractorStageThreeSubmit, contractorStageTwoSubmit, fetchAuctionItem, fetchCityDropdown, fetchDashboard, fetchEmdCheck, fetchLiveAuction, fetchLiveTender, fetchMasterData, fetchPurchaseAuction, fetchPurchaseAuctionList, fetchPurchaseTender, fetchTenderById, getAuction, getDesignation, getRagistrationState, offlineAuctionPurchase, offlineTenderPurchase, partnerShipSubmit, proceedToBid, registerContractor, sendAadhaarOtp, submitEnvelopeA, submitEnvelopeB, uploadEnvelopeFile, userAuctionLogin, userLogin, verifyAadhaarOtp, verifyGstNumber, verifyPanHandler, viewAuctionDocumentDownload, viewAuctionDocuments, viewAuctionItemDocuments, fetchPurchaseAuctionPage, tenderDetails, fetchLiveTenderById, fetchContractorProfile, updateUserProfile } from './apis'; // User @@ -58,6 +58,13 @@ export const useFetchLiveTender = () => { queryFn: () => fetchLiveTender() }); }; +export const useContractorProfile = () => { + return useQuery({ + queryKey: ['Profile',], + queryFn: () => fetchContractorProfile() + }); +}; + export const useFetchPurchaseAuction = () => { return useQuery({ @@ -190,6 +197,12 @@ export const useRagistrationState = () => { }); }; +export const useUpdateUserProfile = () => { + return useMutation({ + mutationFn: (payload:any) => updateUserProfile(payload), + }); +}; + export const usefetchMasterData = () => { return useQuery({ diff --git a/src/Services/BBPS/apis.ts b/src/Services/BBPS/apis.ts index 6523944..fe862d8 100644 --- a/src/Services/BBPS/apis.ts +++ b/src/Services/BBPS/apis.ts @@ -1,5 +1,5 @@ import axios from "axios"; -import { AUCTION_DOCUMENT_DOWNLOAD, DASHBOARD_COUNT, EMD_CHECK, FORARD_AUCTION_ITEM, GET_AUCTION_DETAILS, GET_MY_AUCTION, GET_MY_TENDER, GET_TENDER_DETAILS, LIVE_AUCTION, LIVE_TENDER, LOG_IN_URL, PROCEED_PURCHASE_AUCTION, PROCEED_TO_BID, PURCHASE_TENDER_OFFLINE, TENDER_LOGIN, PURCHASE_AUCTION_LIST, PURCHASE_OFFLINE_AUCTION, REVERSE_AUCTION_ITEM, VIEW_AUCTION_DOCUMENTS, VIEW_AUCTION_ITEM_DETAIL, STAGETHREE, REJ_STAGE_TWO, GETCONTRACTORBYSTATE, GET_MASTER_DATA, ALL_DESIGNATION, GET_REGISTRATION_STATE, PARTNER_API_ENDPOINT, SAVE_CONTRACTOR_STAGE1, VERIFY_GST, VERIFY_ADHAR, SEND_ADHAROTP, SUBMIT_ENVELOPE_FILE_B, SUBMIT_ENVELOPE_FILE_A, SUBMIT_ENVELOPE_A, SUBMIT_ENVELOPE_B, VERIFY_ORGPAN, PURCHASE_AUCTION_PAGE, GET_TENDER_BY_ID } from "./ApiUrls"; +import { AUCTION_DOCUMENT_DOWNLOAD, DASHBOARD_COUNT, EMD_CHECK, FORARD_AUCTION_ITEM, GET_AUCTION_DETAILS, GET_MY_AUCTION, GET_MY_TENDER, GET_TENDER_DETAILS, LIVE_AUCTION, LIVE_TENDER, LOG_IN_URL, PROCEED_PURCHASE_AUCTION, PROCEED_TO_BID, PURCHASE_TENDER_OFFLINE, TENDER_LOGIN, PURCHASE_AUCTION_LIST, PURCHASE_OFFLINE_AUCTION, REVERSE_AUCTION_ITEM, VIEW_AUCTION_DOCUMENTS, VIEW_AUCTION_ITEM_DETAIL, STAGETHREE, REJ_STAGE_TWO, GETCONTRACTORBYSTATE, GET_MASTER_DATA, ALL_DESIGNATION, GET_REGISTRATION_STATE, PARTNER_API_ENDPOINT, SAVE_CONTRACTOR_STAGE1, VERIFY_GST, VERIFY_ADHAR, SEND_ADHAROTP, SUBMIT_ENVELOPE_FILE_B, SUBMIT_ENVELOPE_FILE_A, SUBMIT_ENVELOPE_A, SUBMIT_ENVELOPE_B, VERIFY_ORGPAN, PURCHASE_AUCTION_PAGE, GET_TENDER_BY_ID, GET_CONTRACTOR_PROFILE, CONTRACTOR_PROFILE_UPDATE } from "./ApiUrls"; import { apiCall } from "../../Axios/Axios"; // User @@ -129,6 +129,10 @@ export const fetchLiveTender = async (): Promise => { const data = await apiCall('get', `${LIVE_TENDER}`); return data } +export const fetchContractorProfile = async (): Promise => { + const data = await apiCall('get', `${GET_CONTRACTOR_PROFILE}`); + return data.data +} export const fetchTenderById = async (tenderId: string): Promise => { const data = await apiCall( 'get', @@ -159,7 +163,22 @@ export const verifyPanHandler = ( ); }; - +export const updateUserProfile = ( + payload: { + firstName: string, + middleName: string, + lastName: string, + mobileNo: string, + emailId: string, + fullname: string + } +): Promise => { + return apiCall( + 'put', + CONTRACTOR_PROFILE_UPDATE, + payload, + ); +}; export const fetchPurchaseAuctionList = async (payload: any): Promise => { const data = await apiCall('post', `${PURCHASE_AUCTION_LIST}`, payload); return data