development testing
This commit is contained in:
Generated
+37
-4
@@ -39,6 +39,7 @@
|
|||||||
"react-native-element-dropdown": "^2.12.4",
|
"react-native-element-dropdown": "^2.12.4",
|
||||||
"react-native-fs": "^2.20.0",
|
"react-native-fs": "^2.20.0",
|
||||||
"react-native-gesture-handler": "^2.30.0",
|
"react-native-gesture-handler": "^2.30.0",
|
||||||
|
"react-native-get-random-values": "^2.0.0",
|
||||||
"react-native-gifted-charts": "^1.4.70",
|
"react-native-gifted-charts": "^1.4.70",
|
||||||
"react-native-haptic-feedback": "^2.3.3",
|
"react-native-haptic-feedback": "^2.3.3",
|
||||||
"react-native-linear-gradient": "^2.8.3",
|
"react-native-linear-gradient": "^2.8.3",
|
||||||
@@ -56,6 +57,7 @@
|
|||||||
"redux-persist": "^6.0.0",
|
"redux-persist": "^6.0.0",
|
||||||
"sockjs-client": "^1.6.1",
|
"sockjs-client": "^1.6.1",
|
||||||
"text-encoding": "^0.7.0",
|
"text-encoding": "^0.7.0",
|
||||||
|
"uuid": "^13.0.0",
|
||||||
"xlsx": "^0.18.5",
|
"xlsx": "^0.18.5",
|
||||||
"yup": "^1.7.1"
|
"yup": "^1.7.1"
|
||||||
},
|
},
|
||||||
@@ -6736,6 +6738,15 @@
|
|||||||
"node": ">=8.3.0"
|
"node": ">=8.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/exceljs/node_modules/uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/execa": {
|
"node_modules/execa": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
@@ -6784,6 +6795,12 @@
|
|||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
|
"node_modules/fast-base64-decode": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/fast-csv": {
|
"node_modules/fast-csv": {
|
||||||
"version": "4.3.6",
|
"version": "4.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/fast-csv/-/fast-csv-4.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/fast-csv/-/fast-csv-4.3.6.tgz",
|
||||||
@@ -11160,6 +11177,18 @@
|
|||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-native-get-random-values": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-get-random-values/-/react-native-get-random-values-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-wx7/aPqsUIiWsG35D+MsUJd8ij96e3JKddklSdrdZUrheTx89gPtz3Q2yl9knBArj5u26Cl23T88ai+Q0vypdQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fast-base64-decode": "^1.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react-native": ">=0.81"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-native-gifted-charts": {
|
"node_modules/react-native-gifted-charts": {
|
||||||
"version": "1.4.70",
|
"version": "1.4.70",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -13102,12 +13131,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/uuid": {
|
"node_modules/uuid": {
|
||||||
"version": "8.3.2",
|
"version": "13.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz",
|
||||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
"integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==",
|
||||||
|
"funding": [
|
||||||
|
"https://github.com/sponsors/broofa",
|
||||||
|
"https://github.com/sponsors/ctavan"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
"uuid": "dist/bin/uuid"
|
"uuid": "dist-node/bin/uuid"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/v8-to-istanbul": {
|
"node_modules/v8-to-istanbul": {
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"react-native-element-dropdown": "^2.12.4",
|
"react-native-element-dropdown": "^2.12.4",
|
||||||
"react-native-fs": "^2.20.0",
|
"react-native-fs": "^2.20.0",
|
||||||
"react-native-gesture-handler": "^2.30.0",
|
"react-native-gesture-handler": "^2.30.0",
|
||||||
|
"react-native-get-random-values": "^2.0.0",
|
||||||
"react-native-gifted-charts": "^1.4.70",
|
"react-native-gifted-charts": "^1.4.70",
|
||||||
"react-native-haptic-feedback": "^2.3.3",
|
"react-native-haptic-feedback": "^2.3.3",
|
||||||
"react-native-linear-gradient": "^2.8.3",
|
"react-native-linear-gradient": "^2.8.3",
|
||||||
@@ -58,6 +59,7 @@
|
|||||||
"redux-persist": "^6.0.0",
|
"redux-persist": "^6.0.0",
|
||||||
"sockjs-client": "^1.6.1",
|
"sockjs-client": "^1.6.1",
|
||||||
"text-encoding": "^0.7.0",
|
"text-encoding": "^0.7.0",
|
||||||
|
"uuid": "^13.0.0",
|
||||||
"xlsx": "^0.18.5",
|
"xlsx": "^0.18.5",
|
||||||
"yup": "^1.7.1"
|
"yup": "^1.7.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
Pressable,
|
Pressable,
|
||||||
|
ActivityIndicator,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import colors from '../Color';
|
import colors from '../Color';
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@ type ConfirmDialogProps = {
|
|||||||
cancelText?: string;
|
cancelText?: string;
|
||||||
onConfirm: () => void;
|
onConfirm: () => void;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
loading:boolean
|
||||||
};
|
};
|
||||||
|
|
||||||
const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
|
const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
|
||||||
@@ -27,6 +29,7 @@ const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
|
|||||||
cancelText = 'Cancel',
|
cancelText = 'Cancel',
|
||||||
onConfirm,
|
onConfirm,
|
||||||
onClose,
|
onClose,
|
||||||
|
loading,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
@@ -59,7 +62,10 @@ const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
|
|||||||
onClose();
|
onClose();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text style={styles.confirmText}>{confirmText}</Text>
|
{ !loading ?<Text style={styles.confirmText}>{confirmText}</Text>:<ActivityIndicator
|
||||||
|
color={colors.primary}
|
||||||
|
size={30}
|
||||||
|
/>}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
|
|||||||
@@ -23,5 +23,6 @@ const NavigationString = {
|
|||||||
Profile:'Profile',
|
Profile:'Profile',
|
||||||
ViewTenderDetail:'ViewTenderDetail',
|
ViewTenderDetail:'ViewTenderDetail',
|
||||||
ResetPassword:'ResetPassword'
|
ResetPassword:'ResetPassword'
|
||||||
|
KycWebViewScreen:'KycWebViewScreen'
|
||||||
}
|
}
|
||||||
export default NavigationString
|
export default NavigationString
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
export const generateTransactionId = () => {
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
const dateTime =
|
||||||
|
now.getFullYear().toString() +
|
||||||
|
(now.getMonth() + 1).toString().padStart(2, '0') +
|
||||||
|
now.getDate().toString().padStart(2, '0') +
|
||||||
|
now.getHours().toString().padStart(2, '0') +
|
||||||
|
now.getMinutes().toString().padStart(2, '0') +
|
||||||
|
now.getSeconds().toString().padStart(2, '0');
|
||||||
|
|
||||||
|
const randomPart = Math.floor(1000 + Math.random() * 9000); // 4-digit random
|
||||||
|
|
||||||
|
return `TNX${dateTime}${randomPart}`;
|
||||||
|
};
|
||||||
@@ -32,7 +32,6 @@ export default function MainStack() {
|
|||||||
<Stack.Screen name={NavigationString.Signup} component={Screens.Signup} options={option} />
|
<Stack.Screen name={NavigationString.Signup} component={Screens.Signup} options={option} />
|
||||||
<Stack.Screen name={NavigationString.Onboarding} component={Screens.Onboarding} options={option} />
|
<Stack.Screen name={NavigationString.Onboarding} component={Screens.Onboarding} options={option} />
|
||||||
<Stack.Screen name={NavigationString.Login} component={Screens.Login} options={option} />
|
<Stack.Screen name={NavigationString.Login} component={Screens.Login} options={option} />
|
||||||
|
|
||||||
<Stack.Screen name={NavigationString.Home} component={BottomTab} options={option} />
|
<Stack.Screen name={NavigationString.Home} component={BottomTab} options={option} />
|
||||||
<Stack.Screen name={NavigationString.PurchaseList} component={Screens.PurchaseList} options={option} />
|
<Stack.Screen name={NavigationString.PurchaseList} component={Screens.PurchaseList} options={option} />
|
||||||
<Stack.Screen name={NavigationString.Emd} component={Screens.Emd} options={option} />
|
<Stack.Screen name={NavigationString.Emd} component={Screens.Emd} options={option} />
|
||||||
@@ -47,6 +46,8 @@ export default function MainStack() {
|
|||||||
<Stack.Screen name={NavigationString.Partnership} component={Screens.Partnership} options={option} />
|
<Stack.Screen name={NavigationString.Partnership} component={Screens.Partnership} options={option} />
|
||||||
<Stack.Screen name={NavigationString.LiveTenderDetail} component={Screens.LiveTenderDetail} options={option} />
|
<Stack.Screen name={NavigationString.LiveTenderDetail} component={Screens.LiveTenderDetail} options={option} />
|
||||||
<Stack.Screen name={NavigationString.ResetPassword} component={Screens.ResetPassword} options={option} />
|
<Stack.Screen name={NavigationString.ResetPassword} component={Screens.ResetPassword} options={option} />
|
||||||
|
<Stack.Screen name={NavigationString.ViewTenderDetail} component={Screens.ViewTenderDetail} options={option} />
|
||||||
|
<Stack.Screen name={NavigationString.KycWebViewScreen} component={Screens.KycWebViewScreen} options={option} />
|
||||||
</Stack.Navigator>
|
</Stack.Navigator>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+191
-86
@@ -5,7 +5,7 @@ import { useFetchLiveAuction, useFetchPurchaseAuction } from '../../Services/BBP
|
|||||||
import colors from '../../Constant/Color';
|
import colors from '../../Constant/Color';
|
||||||
import LiveAuction from './LiveAuction';
|
import LiveAuction from './LiveAuction';
|
||||||
import PurchaseAuction from './PurchaseAuction';
|
import PurchaseAuction from './PurchaseAuction';
|
||||||
import { ShoppingCart } from 'lucide-react-native';
|
import { ShoppingCart, Lock } from 'lucide-react-native';
|
||||||
import { useNavigation } from '@react-navigation/native';
|
import { useNavigation } from '@react-navigation/native';
|
||||||
import NavigationString from '../../Constant/NavigationString';
|
import NavigationString from '../../Constant/NavigationString';
|
||||||
import FontsFamily from '../../Constant/FontsFamily';
|
import FontsFamily from '../../Constant/FontsFamily';
|
||||||
@@ -21,6 +21,7 @@ const Auction = () => {
|
|||||||
const { data: liveAuctionData = {} }: any = useFetchLiveAuction();
|
const { data: liveAuctionData = {} }: any = useFetchLiveAuction();
|
||||||
const { data: purchaseAuctionData = {} } = useFetchPurchaseAuction();
|
const { data: purchaseAuctionData = {} } = useFetchPurchaseAuction();
|
||||||
const SelectedPurchaseList = useSelector((state: any) => state.selectPurchaseAuction);
|
const SelectedPurchaseList = useSelector((state: any) => state.selectPurchaseAuction);
|
||||||
|
const reduxToken = useSelector((state: any) => state.token?.token);
|
||||||
|
|
||||||
const liveCount = Array.isArray(liveAuctionData?.result)
|
const liveCount = Array.isArray(liveAuctionData?.result)
|
||||||
? liveAuctionData?.pages?.[0]?.totalCount
|
? liveAuctionData?.pages?.[0]?.totalCount
|
||||||
@@ -31,7 +32,6 @@ const Auction = () => {
|
|||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
const [selectedTab, setSelectedTab] = useState<'live' | 'purchase'>('live');
|
const [selectedTab, setSelectedTab] = useState<'live' | 'purchase'>('live');
|
||||||
|
|
||||||
const translateX = useRef(new Animated.Value(0)).current;
|
const translateX = useRef(new Animated.Value(0)).current;
|
||||||
|
|
||||||
const TAB_WIDTH = useMemo(() => {
|
const TAB_WIDTH = useMemo(() => {
|
||||||
@@ -48,97 +48,136 @@ const Auction = () => {
|
|||||||
}).start();
|
}).start();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Check if user is tender type
|
||||||
|
const isTenderUser = reduxToken?.userType?.toLowerCase() === 'tender';
|
||||||
|
|
||||||
|
// Render restricted access message
|
||||||
|
const renderRestrictedAccess = () => (
|
||||||
|
<View style={styles.restrictedContainer}>
|
||||||
|
<View style={styles.restrictedCard}>
|
||||||
|
<View style={styles.iconContainer}>
|
||||||
|
<Lock size={64} color={colors.primary} />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Text style={styles.restrictedTitle}>Auction Access Restricted</Text>
|
||||||
|
|
||||||
|
<Text style={styles.restrictedMessage}>
|
||||||
|
You are currently logged in as a Tender user. Auction features are not available for your account type.
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text style={styles.restrictedSubMessage}>
|
||||||
|
To access auction features, please login with an Auction user account.
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
style={styles.loginButton}
|
||||||
|
onPress={() => Navigation.navigate(NavigationString.Login)}
|
||||||
|
>
|
||||||
|
<Text style={styles.loginButtonText}>Switch to Auction Login</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<InsideHeader title="Auction" showArrow />
|
<InsideHeader title="Auction" showArrow />
|
||||||
|
|
||||||
<View style={styles.topRow}>
|
{isTenderUser ? (
|
||||||
<View
|
// Show restricted access message for tender users
|
||||||
style={[
|
renderRestrictedAccess()
|
||||||
styles.switchWrapper,
|
) : (
|
||||||
{
|
// Show normal auction UI for auction users
|
||||||
width: TAB_WIDTH * 2 + SWITCH_INSETS * 2,
|
<>
|
||||||
},
|
<View style={styles.topRow}>
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Animated.View
|
|
||||||
pointerEvents="none"
|
|
||||||
style={[
|
|
||||||
styles.activeTab,
|
|
||||||
{
|
|
||||||
width: TAB_WIDTH,
|
|
||||||
transform: [{ translateX }],
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TouchableOpacity
|
|
||||||
style={[styles.tab, { width: TAB_WIDTH }]}
|
|
||||||
activeOpacity={0.8}
|
|
||||||
onPress={() => onTabPress('live', 0)}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
styles.tabText,
|
|
||||||
selectedTab === 'live' && styles.activeText,
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
Live ({liveCount})
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
|
|
||||||
<TouchableOpacity
|
|
||||||
style={[styles.tab, { width: TAB_WIDTH }]}
|
|
||||||
activeOpacity={0.8}
|
|
||||||
onPress={() => onTabPress('purchase', 1)}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
styles.tabText,
|
|
||||||
selectedTab === 'purchase' && styles.activeText,
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
Purchased ({purchaseCount})
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View>
|
|
||||||
{SelectedPurchaseList.length ? (
|
|
||||||
<View
|
<View
|
||||||
style={{
|
style={[
|
||||||
borderWidth: 2,
|
styles.switchWrapper,
|
||||||
borderColor: colors.white,
|
{
|
||||||
backgroundColor: colors.primaryLight,
|
width: TAB_WIDTH * 2 + SWITCH_INSETS * 2,
|
||||||
position: 'absolute',
|
},
|
||||||
borderRadius: 50,
|
]}
|
||||||
zIndex: 20,
|
|
||||||
right: 0,
|
|
||||||
top: -10,
|
|
||||||
paddingHorizontal: 2,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<Text style={{ fontSize: 12, color: colors.black }}>
|
<Animated.View
|
||||||
{SelectedPurchaseList.length}
|
pointerEvents="none"
|
||||||
</Text>
|
style={[
|
||||||
</View>
|
styles.activeTab,
|
||||||
) : null}
|
{
|
||||||
<TouchableOpacity
|
width: TAB_WIDTH,
|
||||||
style={{
|
transform: [{ translateX }],
|
||||||
padding: 10,
|
},
|
||||||
backgroundColor: colors.primaryLight,
|
]}
|
||||||
borderRadius: 20,
|
/>
|
||||||
}}
|
|
||||||
onPress={() => {
|
|
||||||
Navigation.navigate(NavigationString.PurchaseList);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ShoppingCart size={22} color={colors.black} strokeWidth={2} />
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{selectedTab === 'live' ? <LiveAuction /> : <PurchaseAuction />}
|
<TouchableOpacity
|
||||||
|
style={[styles.tab, { width: TAB_WIDTH }]}
|
||||||
|
activeOpacity={0.8}
|
||||||
|
onPress={() => onTabPress('live', 0)}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
styles.tabText,
|
||||||
|
selectedTab === 'live' && styles.activeText,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
Live ({liveCount})
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.tab, { width: TAB_WIDTH }]}
|
||||||
|
activeOpacity={0.8}
|
||||||
|
onPress={() => onTabPress('purchase', 1)}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
styles.tabText,
|
||||||
|
selectedTab === 'purchase' && styles.activeText,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
Purchased ({purchaseCount})
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View>
|
||||||
|
{SelectedPurchaseList.length ? (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
borderWidth: 2,
|
||||||
|
borderColor: colors.white,
|
||||||
|
backgroundColor: colors.primaryLight,
|
||||||
|
position: 'absolute',
|
||||||
|
borderRadius: 50,
|
||||||
|
zIndex: 20,
|
||||||
|
right: 0,
|
||||||
|
top: -10,
|
||||||
|
paddingHorizontal: 2,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={{ fontSize: 12, color: colors.black }}>
|
||||||
|
{SelectedPurchaseList.length}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
) : null}
|
||||||
|
<TouchableOpacity
|
||||||
|
style={{
|
||||||
|
padding: 10,
|
||||||
|
backgroundColor: colors.primaryLight,
|
||||||
|
borderRadius: 20,
|
||||||
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
Navigation.navigate(NavigationString.PurchaseList);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ShoppingCart size={22} color={colors.black} strokeWidth={2} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{selectedTab === 'live' ? <LiveAuction /> : <PurchaseAuction />}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -191,4 +230,70 @@ const styles = StyleSheet.create({
|
|||||||
shadowRadius: 6,
|
shadowRadius: 6,
|
||||||
elevation: 3,
|
elevation: 3,
|
||||||
},
|
},
|
||||||
|
restrictedContainer: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
padding: 24,
|
||||||
|
backgroundColor: colors.lightGray,
|
||||||
|
},
|
||||||
|
restrictedCard: {
|
||||||
|
backgroundColor: colors.white,
|
||||||
|
borderRadius: 24,
|
||||||
|
padding: 32,
|
||||||
|
alignItems: 'center',
|
||||||
|
maxWidth: 400,
|
||||||
|
width: '100%',
|
||||||
|
|
||||||
|
},
|
||||||
|
iconContainer: {
|
||||||
|
width: 120,
|
||||||
|
height: 120,
|
||||||
|
borderRadius: 60,
|
||||||
|
backgroundColor: colors.primaryHighlight,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginBottom: 24,
|
||||||
|
},
|
||||||
|
restrictedTitle: {
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: '700',
|
||||||
|
color: colors.darkText,
|
||||||
|
textAlign: 'center',
|
||||||
|
marginBottom: 16,
|
||||||
|
fontFamily: FontsFamily.poppinsBold,
|
||||||
|
},
|
||||||
|
restrictedMessage: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: colors.grayText,
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: 24,
|
||||||
|
marginBottom: 12,
|
||||||
|
fontFamily: FontsFamily.poppinsRegular,
|
||||||
|
},
|
||||||
|
restrictedSubMessage: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: colors.grayText,
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: 22,
|
||||||
|
marginBottom: 32,
|
||||||
|
fontFamily: FontsFamily.poppinsRegular,
|
||||||
|
},
|
||||||
|
loginButton: {
|
||||||
|
backgroundColor: colors.primary,
|
||||||
|
paddingHorizontal: 32,
|
||||||
|
paddingVertical: 14,
|
||||||
|
borderRadius: 12,
|
||||||
|
shadowColor: colors.primary,
|
||||||
|
shadowOffset: { width: 0, height: 4 },
|
||||||
|
shadowOpacity: 0.3,
|
||||||
|
shadowRadius: 8,
|
||||||
|
elevation: 4,
|
||||||
|
},
|
||||||
|
loginButtonText: {
|
||||||
|
color: colors.white,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: '600',
|
||||||
|
fontFamily: FontsFamily.poppinsSemiBold,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
+80
-51
@@ -1,13 +1,15 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { View, Text, StyleSheet, Dimensions, FlatList, ActivityIndicator } from 'react-native';
|
import { View, Text, StyleSheet, Dimensions, FlatList, ActivityIndicator, Alert } from 'react-native';
|
||||||
import Animated, { useSharedValue, useAnimatedStyle, withDelay, withTiming } from 'react-native-reanimated';
|
import Animated, { useSharedValue, useAnimatedStyle, withDelay, withTiming } from 'react-native-reanimated';
|
||||||
import { Layers, Clock, ShoppingCart, X, FileText } from 'lucide-react-native';
|
import { Layers, Clock, ShoppingCart, X, FileText } from 'lucide-react-native';
|
||||||
import { Header } from '../../Component/Index';
|
import { Header } from '../../Component/Index';
|
||||||
import colors from '../../Constant/Color';
|
import colors from '../../Constant/Color';
|
||||||
import { useDashboard, useESetuAdharVarification } from '../../Services/BBPS/Hooks';
|
import { useDashboard, useESetuAdharVarification } from '../../Services/BBPS/Hooks';
|
||||||
import { log } from 'console';
|
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import ConfirmDialog from '../../Constant/Dialog/ConfirmDialog';
|
import ConfirmDialog from '../../Constant/Dialog/ConfirmDialog';
|
||||||
|
import { generateTransactionId } from '../../Helper/uniqueId';
|
||||||
|
import { useFocusEffect, useNavigation } from '@react-navigation/native';
|
||||||
|
import NavigationString from '../../Constant/NavigationString';
|
||||||
|
|
||||||
const { width } = Dimensions.get('window');
|
const { width } = Dimensions.get('window');
|
||||||
const CARD_WIDTH = (width - 48) / 2;
|
const CARD_WIDTH = (width - 48) / 2;
|
||||||
@@ -43,7 +45,6 @@ const StatCard = ({ item, index, isLoading }: any) => {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* VALUE / LOADER */}
|
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<ActivityIndicator
|
<ActivityIndicator
|
||||||
size="small"
|
size="small"
|
||||||
@@ -61,34 +62,49 @@ const StatCard = ({ item, index, isLoading }: any) => {
|
|||||||
|
|
||||||
const Home = () => {
|
const Home = () => {
|
||||||
const { data, isLoading } = useDashboard();
|
const { data, isLoading } = useDashboard();
|
||||||
|
const Navigation: any = useNavigation();
|
||||||
const user = useSelector((state: any) => state.token?.token);
|
const user = useSelector((state: any) => state.token?.token);
|
||||||
console.log("-=--",user)
|
const { mutateAsync: eSetuAdharVarification, isPending } = useESetuAdharVarification();
|
||||||
const { mutateAsync:eSetuAdharVarification } = useESetuAdharVarification();
|
|
||||||
const dashboard = data?.data || {};
|
const dashboard = data?.data || {};
|
||||||
const [esetu,setEsetu] = useState<boolean>();
|
const [showDialog, setShowDialog] = useState<boolean>(false);
|
||||||
useEffect(()=>{
|
const [isNavigating, setIsNavigating] = useState<boolean>(false);
|
||||||
if(user?.esetuVerified === 'Not Verified'){
|
useFocusEffect(()=>{
|
||||||
const payLoad= {
|
setIsNavigating(false)
|
||||||
contId: user,
|
})
|
||||||
transactionId: "string",
|
useEffect(() => {
|
||||||
udf1: "string",
|
if (user?.esetuVerified === 'Not Verified') {
|
||||||
udf2: "string",
|
setShowDialog(true);
|
||||||
udf3: "string",
|
}
|
||||||
udf4: "string",
|
}, []);
|
||||||
responseUrl: "string"
|
|
||||||
}
|
const handleProceedVerification = async () => {
|
||||||
setEsetu(true)
|
try {
|
||||||
eSetuAdharVarification(payLoad, {
|
setIsNavigating(true);
|
||||||
onSuccess: (res) => {
|
|
||||||
console.log(res)
|
const payload = {
|
||||||
}, onError: (err) => {
|
contId: user.id,
|
||||||
console.log(err, '-----auction item error');
|
transactionId: generateTransactionId(),
|
||||||
}
|
udf1: "23.77",
|
||||||
});
|
udf2: "77.34",
|
||||||
}else{
|
udf3: "string",
|
||||||
setEsetu(false)
|
udf4: "string",
|
||||||
}
|
};
|
||||||
},[user])
|
|
||||||
|
console.log("Payload:", payload);
|
||||||
|
|
||||||
|
const res = await eSetuAdharVarification(payload);
|
||||||
|
console.log("Verification response:", res);
|
||||||
|
|
||||||
|
setShowDialog(false);
|
||||||
|
|
||||||
|
Navigation.navigate(NavigationString.KycWebViewScreen, { res });
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.log("Verification error:", err);
|
||||||
|
Alert.alert('Error', 'Failed to initiate verification. Please try again.');
|
||||||
|
setIsNavigating(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const DASHBOARD_CARDS = [
|
const DASHBOARD_CARDS = [
|
||||||
{
|
{
|
||||||
@@ -119,7 +135,6 @@ console.log(res)
|
|||||||
icon: X,
|
icon: X,
|
||||||
color: '#DC2626',
|
color: '#DC2626',
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: 'Total Tenders',
|
title: 'Total Tenders',
|
||||||
value: 0,
|
value: 0,
|
||||||
@@ -153,18 +168,25 @@ console.log(res)
|
|||||||
return (
|
return (
|
||||||
<View style={styles.screen}>
|
<View style={styles.screen}>
|
||||||
<Header title="Dashboard" />
|
<Header title="Dashboard" />
|
||||||
<ConfirmDialog
|
|
||||||
visible={esetu as boolean}
|
<ConfirmDialog
|
||||||
title="Aadhaar Verification Required"
|
visible={showDialog}
|
||||||
message="To access features, please complete your Aadhaar verification."
|
title="Aadhaar Verification Required"
|
||||||
confirmText="Proceed"
|
message="To access features, please complete your Aadhaar verification."
|
||||||
cancelText="Cancel"
|
confirmText={isPending || isNavigating ? "Processing..." : "Proceed"}
|
||||||
onConfirm={() => {
|
cancelText="Cancel"
|
||||||
setEsetu(false);
|
onConfirm={handleProceedVerification}
|
||||||
|
onClose={() => !isPending && !isNavigating && setShowDialog(false)}
|
||||||
|
loading={isPending || isNavigating}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{isNavigating && (
|
||||||
|
<View style={styles.navigationOverlay}>
|
||||||
|
<ActivityIndicator size="large" color={colors.primary || '#2563EB'} />
|
||||||
|
<Text style={styles.loadingText}>Loading verification...</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
}}
|
|
||||||
onClose={() => setEsetu(false)}
|
|
||||||
/>
|
|
||||||
<FlatList
|
<FlatList
|
||||||
data={DASHBOARD_CARDS}
|
data={DASHBOARD_CARDS}
|
||||||
keyExtractor={(_, index) => index.toString()}
|
keyExtractor={(_, index) => index.toString()}
|
||||||
@@ -186,23 +208,19 @@ message="To access features, please complete your Aadhaar verification."
|
|||||||
|
|
||||||
export default Home;
|
export default Home;
|
||||||
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
screen: {
|
screen: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: colors.white,
|
backgroundColor: colors.white,
|
||||||
},
|
},
|
||||||
|
|
||||||
list: {
|
list: {
|
||||||
padding: 16,
|
padding: 16,
|
||||||
paddingBottom: 24,
|
paddingBottom: 24,
|
||||||
},
|
},
|
||||||
|
|
||||||
row: {
|
row: {
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
marginBottom: 16,
|
marginBottom: 16,
|
||||||
},
|
},
|
||||||
|
|
||||||
card: {
|
card: {
|
||||||
width: CARD_WIDTH,
|
width: CARD_WIDTH,
|
||||||
backgroundColor: '#FFFFFF',
|
backgroundColor: '#FFFFFF',
|
||||||
@@ -215,13 +233,11 @@ const styles = StyleSheet.create({
|
|||||||
shadowRadius: 8,
|
shadowRadius: 8,
|
||||||
elevation: 3,
|
elevation: 3,
|
||||||
},
|
},
|
||||||
|
|
||||||
header: {
|
header: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
alignItems: 'flex-start',
|
alignItems: 'flex-start',
|
||||||
},
|
},
|
||||||
|
|
||||||
title: {
|
title: {
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontWeight: '600',
|
fontWeight: '600',
|
||||||
@@ -229,7 +245,6 @@ const styles = StyleSheet.create({
|
|||||||
flex: 1,
|
flex: 1,
|
||||||
paddingRight: 8,
|
paddingRight: 8,
|
||||||
},
|
},
|
||||||
|
|
||||||
badge: {
|
badge: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
@@ -239,22 +254,36 @@ const styles = StyleSheet.create({
|
|||||||
paddingHorizontal: 8,
|
paddingHorizontal: 8,
|
||||||
paddingVertical: 4,
|
paddingVertical: 4,
|
||||||
},
|
},
|
||||||
|
|
||||||
badgeText: {
|
badgeText: {
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: '700',
|
fontWeight: '700',
|
||||||
},
|
},
|
||||||
|
|
||||||
value: {
|
value: {
|
||||||
fontSize: 28,
|
fontSize: 28,
|
||||||
fontWeight: '800',
|
fontWeight: '800',
|
||||||
color: '#111827',
|
color: '#111827',
|
||||||
marginTop: 5,
|
marginTop: 5,
|
||||||
},
|
},
|
||||||
|
|
||||||
desc: {
|
desc: {
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: '#6B7280',
|
color: '#6B7280',
|
||||||
marginTop: 6,
|
marginTop: 6,
|
||||||
},
|
},
|
||||||
|
navigationOverlay: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
zIndex: 999,
|
||||||
|
},
|
||||||
|
loadingText: {
|
||||||
|
marginTop: 12,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: '600',
|
||||||
|
color: '#374151',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,256 @@
|
|||||||
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
|
import { View, ActivityIndicator, StyleSheet, Text } from "react-native";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
import { WebView } from "react-native-webview";
|
||||||
|
import { CommonActions } from "@react-navigation/native";
|
||||||
|
import colors from "../../Constant/Color";
|
||||||
|
|
||||||
|
const SUCCESS_DELAY_MS = 5000; // 5 seconds
|
||||||
|
|
||||||
|
export const KycWebViewScreen = ({ route, navigation }: any) => {
|
||||||
|
const webRef = useRef<WebView>(null);
|
||||||
|
const pollTimerRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||||
|
const hasCompletedRef = useRef(false);
|
||||||
|
const successTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||||
|
|
||||||
|
const data = route.params ?? {};
|
||||||
|
const html = data.res.data;
|
||||||
|
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||||
|
const [loadError, setLoadError] = useState<boolean>(false);
|
||||||
|
const [showSuccessMessage, setShowSuccessMessage] = useState<boolean>(false);
|
||||||
|
const [countdown, setCountdown] = useState<number>(5);
|
||||||
|
const url = false;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
if (pollTimerRef.current) {
|
||||||
|
clearInterval(pollTimerRef.current);
|
||||||
|
}
|
||||||
|
if (successTimeoutRef.current) {
|
||||||
|
clearTimeout(successTimeoutRef.current);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const navigateToLogin = () => {
|
||||||
|
navigation.dispatch(
|
||||||
|
CommonActions.reset({
|
||||||
|
index: 0,
|
||||||
|
routes: [{ name: 'Login' }], // Adjust to your login screen route name
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const startSuccessCountdown = () => {
|
||||||
|
setShowSuccessMessage(true);
|
||||||
|
setCountdown(5);
|
||||||
|
|
||||||
|
let remainingSeconds = 5;
|
||||||
|
const countdownInterval = setInterval(() => {
|
||||||
|
remainingSeconds -= 1;
|
||||||
|
setCountdown(remainingSeconds);
|
||||||
|
|
||||||
|
if (remainingSeconds <= 0) {
|
||||||
|
clearInterval(countdownInterval);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
successTimeoutRef.current = setTimeout(() => {
|
||||||
|
clearInterval(countdownInterval);
|
||||||
|
navigateToLogin();
|
||||||
|
}, SUCCESS_DELAY_MS);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLoadStart = (event: any) => {
|
||||||
|
setIsLoading(true);
|
||||||
|
setLoadError(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLoadEnd = (event: any) => {
|
||||||
|
setIsLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleError = (event: any) => {
|
||||||
|
setIsLoading(false);
|
||||||
|
setLoadError(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNavigationStateChange = (navState: any) => {
|
||||||
|
if (
|
||||||
|
navState.title &&
|
||||||
|
navState.title.includes('E-KYC SETU - Verification Success') &&
|
||||||
|
!hasCompletedRef.current
|
||||||
|
) {
|
||||||
|
hasCompletedRef.current = true;
|
||||||
|
startSuccessCountdown();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const LoadingIndicator = () => (
|
||||||
|
<View style={styles.loadingContainer}>
|
||||||
|
<ActivityIndicator size="large" color={colors.primary || '#2563EB'} />
|
||||||
|
<Text style={styles.loadingText}>Loading KYC form...</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={{ flex: 1, backgroundColor: colors.white }}>
|
||||||
|
{url ? (
|
||||||
|
<WebView
|
||||||
|
ref={webRef}
|
||||||
|
source={{
|
||||||
|
uri: url,
|
||||||
|
baseUrl: "http://192.168.1.15:8080/",
|
||||||
|
}}
|
||||||
|
javaScriptEnabled
|
||||||
|
domStorageEnabled
|
||||||
|
startInLoadingState
|
||||||
|
originWhitelist={["*"]}
|
||||||
|
setSupportMultipleWindows={false}
|
||||||
|
onLoadStart={handleLoadStart}
|
||||||
|
onLoadEnd={handleLoadEnd}
|
||||||
|
onError={handleError}
|
||||||
|
onNavigationStateChange={handleNavigationStateChange}
|
||||||
|
renderLoading={() => <LoadingIndicator />}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<WebView
|
||||||
|
ref={webRef}
|
||||||
|
source={{
|
||||||
|
html: html ?? "<h3>No content</h3>",
|
||||||
|
baseUrl: "https://11.godemo.in/ESetuKYC/initiate/",
|
||||||
|
}}
|
||||||
|
javaScriptEnabled
|
||||||
|
domStorageEnabled
|
||||||
|
startInLoadingState
|
||||||
|
onLoadStart={handleLoadStart}
|
||||||
|
onLoadEnd={handleLoadEnd}
|
||||||
|
onError={handleError}
|
||||||
|
onNavigationStateChange={handleNavigationStateChange}
|
||||||
|
renderLoading={() => <LoadingIndicator />}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{isLoading && !showSuccessMessage && <LoadingIndicator />}
|
||||||
|
|
||||||
|
{showSuccessMessage && (
|
||||||
|
<View style={styles.successContainer}>
|
||||||
|
<View style={styles.successCard}>
|
||||||
|
<Text style={styles.successIcon}>✅</Text>
|
||||||
|
<Text style={styles.successTitle}>Verification Successful!</Text>
|
||||||
|
<Text style={styles.successMessage}>
|
||||||
|
Your KYC verification has been completed successfully.
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.countdownText}>
|
||||||
|
Redirecting in {countdown} seconds...
|
||||||
|
</Text>
|
||||||
|
<ActivityIndicator
|
||||||
|
size="small"
|
||||||
|
color={colors.primary || '#2563EB'}
|
||||||
|
style={{ marginTop: 16 }}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{loadError && (
|
||||||
|
<View style={styles.errorContainer}>
|
||||||
|
<Text style={styles.errorText}>Failed to load content</Text>
|
||||||
|
<Text style={styles.errorSubText}>Please try again</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default KycWebViewScreen;
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
loadingContainer: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: colors.white,
|
||||||
|
zIndex: 1,
|
||||||
|
},
|
||||||
|
loadingText: {
|
||||||
|
marginTop: 12,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: '600',
|
||||||
|
color: '#374151',
|
||||||
|
},
|
||||||
|
successContainer: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: 'rgba(255, 255, 255, 0.95)',
|
||||||
|
zIndex: 2,
|
||||||
|
padding: 24,
|
||||||
|
},
|
||||||
|
successCard: {
|
||||||
|
backgroundColor: '#FFFFFF',
|
||||||
|
borderRadius: 20,
|
||||||
|
padding: 32,
|
||||||
|
alignItems: 'center',
|
||||||
|
shadowColor: '#000',
|
||||||
|
shadowOffset: { width: 0, height: 4 },
|
||||||
|
shadowOpacity: 0.1,
|
||||||
|
shadowRadius: 12,
|
||||||
|
elevation: 8,
|
||||||
|
maxWidth: 340,
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
successIcon: {
|
||||||
|
fontSize: 64,
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
successTitle: {
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: '700',
|
||||||
|
color: '#16A34A',
|
||||||
|
marginBottom: 12,
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
successMessage: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: '#374151',
|
||||||
|
textAlign: 'center',
|
||||||
|
marginBottom: 20,
|
||||||
|
lineHeight: 24,
|
||||||
|
},
|
||||||
|
countdownText: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: '600',
|
||||||
|
color: '#2563EB',
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
errorContainer: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: colors.white,
|
||||||
|
zIndex: 1,
|
||||||
|
},
|
||||||
|
errorText: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: '700',
|
||||||
|
color: '#DC2626',
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
errorSubText: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: '#6B7280',
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -52,9 +52,14 @@ import {
|
|||||||
X,
|
X,
|
||||||
Save,
|
Save,
|
||||||
} from 'lucide-react-native';
|
} from 'lucide-react-native';
|
||||||
|
import { useFocusEffect, useNavigation } from '@react-navigation/native';
|
||||||
|
|
||||||
import { useContractorProfile, useUpdateUserProfile } from '../../Services/BBPS/Hooks';
|
import { useContractorProfile, useUpdateUserProfile, useESetuAdharVarification } from '../../Services/BBPS/Hooks';
|
||||||
import colors from '../../Constant/Color';
|
import colors from '../../Constant/Color';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import ConfirmDialog from '../../Constant/Dialog/ConfirmDialog';
|
||||||
|
import { generateTransactionId } from '../../Helper/uniqueId';
|
||||||
|
import NavigationString from '../../Constant/NavigationString';
|
||||||
|
|
||||||
const { width } = Dimensions.get('window');
|
const { width } = Dimensions.get('window');
|
||||||
|
|
||||||
@@ -102,10 +107,12 @@ interface ContractorData {
|
|||||||
|
|
||||||
interface ProfileHeaderProps {
|
interface ProfileHeaderProps {
|
||||||
data: ContractorData;
|
data: ContractorData;
|
||||||
|
displayName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface QuickStatsProps {
|
interface QuickStatsProps {
|
||||||
data: ContractorData;
|
data: ContractorData;
|
||||||
|
onAadhaarPress: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InfoSectionProps {
|
interface InfoSectionProps {
|
||||||
@@ -129,6 +136,7 @@ interface StatItem {
|
|||||||
label: string;
|
label: string;
|
||||||
value: string;
|
value: string;
|
||||||
color: string;
|
color: string;
|
||||||
|
onPress?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UpdateProfilePayload {
|
interface UpdateProfilePayload {
|
||||||
@@ -150,10 +158,65 @@ const isValidValue = (value: any): boolean => {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Helper function to check if section has any valid data
|
||||||
|
const hasSectionData = (values: any[]): boolean => {
|
||||||
|
return values.some(value => isValidValue(value));
|
||||||
|
};
|
||||||
|
|
||||||
// Main Component
|
// Main Component
|
||||||
const ProfileTab: React.FC = () => {
|
const ProfileTab: React.FC = () => {
|
||||||
const { data, refetch, isLoading, error } = useContractorProfile();
|
const { data, refetch, isLoading, error } = useContractorProfile();
|
||||||
|
const user = useSelector((state: any) => state.token?.token);
|
||||||
|
const Navigation: any = useNavigation();
|
||||||
|
const { mutateAsync: eSetuAdharVarification, isPending } = useESetuAdharVarification();
|
||||||
|
|
||||||
const [editModalVisible, setEditModalVisible] = useState(false);
|
const [editModalVisible, setEditModalVisible] = useState(false);
|
||||||
|
const [showDialog, setShowDialog] = useState<boolean>(false);
|
||||||
|
const [isNavigating, setIsNavigating] = useState<boolean>(false);
|
||||||
|
|
||||||
|
// Check if user is auction type
|
||||||
|
const isAuctionUser = user?.userType?.toLowerCase() === 'auction';
|
||||||
|
|
||||||
|
// Get display data based on user type
|
||||||
|
const displayName = isAuctionUser ? user?.fullName : data?.fullName;
|
||||||
|
const displayMobile = isAuctionUser ? user?.mobileNo : data?.mobileNo;
|
||||||
|
|
||||||
|
const handleAadhaarPress = () => {
|
||||||
|
if (user?.esetuVerified === 'Not Verified') {
|
||||||
|
setShowDialog(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useFocusEffect(()=>{
|
||||||
|
setIsNavigating(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleProceedVerification = async () => {
|
||||||
|
try {
|
||||||
|
setIsNavigating(true);
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
contId: user.id,
|
||||||
|
transactionId: generateTransactionId(),
|
||||||
|
udf1: "23.77",
|
||||||
|
udf2: "77.34",
|
||||||
|
udf3: "string",
|
||||||
|
udf4: "string",
|
||||||
|
responseUrl: "https://dev.procurelinc.in/"
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await eSetuAdharVarification(payload);
|
||||||
|
|
||||||
|
setShowDialog(false);
|
||||||
|
|
||||||
|
Navigation.navigate(NavigationString.KycWebViewScreen, { res });
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.log("Verification error:", err);
|
||||||
|
Alert.alert('Error', 'Failed to initiate verification. Please try again.');
|
||||||
|
setIsNavigating(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
@@ -199,78 +262,128 @@ const ProfileTab: React.FC = () => {
|
|||||||
windowSize={10}
|
windowSize={10}
|
||||||
>
|
>
|
||||||
{/* Header with Gradient */}
|
{/* Header with Gradient */}
|
||||||
<ProfileHeader data={data} />
|
<ProfileHeader data={data} displayName={displayName || data.fullName} />
|
||||||
|
|
||||||
{/* Quick Stats */}
|
{/* Quick Stats */}
|
||||||
<QuickStats data={data} />
|
<QuickStats data={data} onAadhaarPress={handleAadhaarPress} />
|
||||||
|
|
||||||
{/* Personal Information */}
|
{/* Personal Information - Always show */}
|
||||||
<InfoSection
|
<InfoSection
|
||||||
title="Personal Information"
|
title="Personal Information"
|
||||||
IconComponent={UserCircle}
|
IconComponent={UserCircle}
|
||||||
delay={0}
|
delay={0}
|
||||||
showEdit={true}
|
showEdit={!isAuctionUser}
|
||||||
onEdit={() => setEditModalVisible(true)}
|
onEdit={() => setEditModalVisible(true)}
|
||||||
>
|
>
|
||||||
<InfoRow label="Full Name" value={data.firstName+" "+data.middleName+" "+data.lastName} IconComponent={User} />
|
<InfoRow
|
||||||
|
label="Full Name"
|
||||||
|
value={isAuctionUser ? displayName : `${data.firstName} ${data.middleName} ${data.lastName}`.trim()}
|
||||||
|
IconComponent={User}
|
||||||
|
/>
|
||||||
<InfoRow label="Email" value={data.emailId} IconComponent={Mail} />
|
<InfoRow label="Email" value={data.emailId} IconComponent={Mail} />
|
||||||
<InfoRow
|
<InfoRow
|
||||||
label="Mobile"
|
label="Mobile"
|
||||||
value={`${data.dialCode} ${data.mobileNo}`}
|
value={isAuctionUser ? displayMobile : `${data.dialCode} ${data.mobileNo}`}
|
||||||
IconComponent={Phone}
|
IconComponent={Phone}
|
||||||
/>
|
/>
|
||||||
<InfoRow label="Designation" value={data.designation} IconComponent={Briefcase} />
|
<InfoRow label="Designation" value={data.designation} IconComponent={Briefcase} />
|
||||||
</InfoSection>
|
</InfoSection>
|
||||||
|
|
||||||
{/* Company Details */}
|
{/* Company Details - Only show if has data */}
|
||||||
<InfoSection title="Company Details" IconComponent={Building2} delay={0}>
|
{hasSectionData([
|
||||||
<InfoRow label="Company" value={data.company} IconComponent={Building} />
|
data.company,
|
||||||
<InfoRow label="Type" value={data.contractorType} IconComponent={Tag} />
|
data.contractorType,
|
||||||
<InfoRow label="Organization" value={data.contOrganization} IconComponent={Network} />
|
data.contOrganization,
|
||||||
<InfoRow label="Website" value={data.agentWebsite} IconComponent={Globe} />
|
data.agentWebsite,
|
||||||
<InfoRow label="Registration No" value={data.agentRegno} IconComponent={Award} />
|
data.agentRegno
|
||||||
</InfoSection>
|
]) && (
|
||||||
|
<InfoSection title="Company Details" IconComponent={Building2} delay={0}>
|
||||||
|
<InfoRow label="Company" value={data.company} IconComponent={Building} />
|
||||||
|
<InfoRow label="Type" value={data.contractorType} IconComponent={Tag} />
|
||||||
|
<InfoRow label="Organization" value={data.contOrganization} IconComponent={Network} />
|
||||||
|
<InfoRow label="Website" value={data.agentWebsite} IconComponent={Globe} />
|
||||||
|
<InfoRow label="Registration No" value={data.agentRegno} IconComponent={Award} />
|
||||||
|
</InfoSection>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Address Information */}
|
{/* Address Information - Only show if has data */}
|
||||||
<InfoSection title="Address Information" IconComponent={MapPin} delay={0}>
|
{hasSectionData([
|
||||||
<InfoRow label="Address" value={data.agentAddress} IconComponent={Home} />
|
data.agentAddress,
|
||||||
<InfoRow label="City" value={data.agentCity} IconComponent={Building2} />
|
data.agentCity,
|
||||||
<InfoRow label="State" value={data.agentState} IconComponent={Map} />
|
data.agentState,
|
||||||
<InfoRow label="Pincode" value={data.agentPincode} IconComponent={Mailbox} />
|
data.agentPincode
|
||||||
</InfoSection>
|
]) && (
|
||||||
|
<InfoSection title="Address Information" IconComponent={MapPin} delay={0}>
|
||||||
|
<InfoRow label="Address" value={data.agentAddress} IconComponent={Home} />
|
||||||
|
<InfoRow label="City" value={data.agentCity} IconComponent={Building2} />
|
||||||
|
<InfoRow label="State" value={data.agentState} IconComponent={Map} />
|
||||||
|
<InfoRow label="Pincode" value={data.agentPincode} IconComponent={Mailbox} />
|
||||||
|
</InfoSection>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Tax & Legal */}
|
{/* Tax & Legal - Only show if has data */}
|
||||||
<InfoSection title="Tax & Legal Information" IconComponent={FileText} delay={0}>
|
{hasSectionData([
|
||||||
<InfoRow label="PAN Number" value={data.orgPAN} IconComponent={CreditCard} />
|
data.orgPAN,
|
||||||
<InfoRow label="PAN Name" value={data.orgPANname} IconComponent={Type} />
|
data.orgPANname,
|
||||||
<InfoRow label="PAN DOB" value={data.orgPANdob} IconComponent={Calendar} />
|
data.orgPANdob,
|
||||||
<InfoRow label="GSTIN" value={data.gistnNo} IconComponent={Receipt} />
|
data.gistnNo,
|
||||||
<InfoRow label="Aadhar" value={data.comAadharNo} IconComponent={FileText} />
|
data.comAadharNo
|
||||||
</InfoSection>
|
]) && (
|
||||||
|
<InfoSection title="Tax & Legal Information" IconComponent={FileText} delay={0}>
|
||||||
|
<InfoRow label="PAN Number" value={data.orgPAN} IconComponent={CreditCard} />
|
||||||
|
<InfoRow label="PAN Name" value={data.orgPANname} IconComponent={Type} />
|
||||||
|
<InfoRow label="PAN DOB" value={data.orgPANdob} IconComponent={Calendar} />
|
||||||
|
<InfoRow label="GSTIN" value={data.gistnNo} IconComponent={Receipt} />
|
||||||
|
<InfoRow label="Aadhar" value={data.comAadharNo} IconComponent={FileText} />
|
||||||
|
</InfoSection>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Registration Status */}
|
{/* Registration Status - Only show if has data */}
|
||||||
<InfoSection title="Registration Details" IconComponent={ClipboardCheck} delay={0}>
|
{hasSectionData([
|
||||||
<InfoRow label="Class" value={data.contractorClass} IconComponent={Star} />
|
data.contractorClass,
|
||||||
<InfoRow label="Category" value={data.socialCategory} IconComponent={List} />
|
data.socialCategory,
|
||||||
<InfoRow label="MSME Status" value={data.msmeStatus} IconComponent={Factory} />
|
data.msmeStatus,
|
||||||
<InfoRow
|
data.expiryDate
|
||||||
label="Expiry Date"
|
]) && (
|
||||||
value={data.expiryDate}
|
<InfoSection title="Registration Details" IconComponent={ClipboardCheck} delay={0}>
|
||||||
IconComponent={CalendarClock}
|
<InfoRow label="Class" value={data.contractorClass} IconComponent={Star} />
|
||||||
valueColor={colors.warning}
|
<InfoRow label="Category" value={data.socialCategory} IconComponent={List} />
|
||||||
/>
|
<InfoRow label="MSME Status" value={data.msmeStatus} IconComponent={Factory} />
|
||||||
</InfoSection>
|
<InfoRow
|
||||||
|
label="Expiry Date"
|
||||||
|
value={data.expiryDate}
|
||||||
|
IconComponent={CalendarClock}
|
||||||
|
valueColor={colors.warning}
|
||||||
|
/>
|
||||||
|
</InfoSection>
|
||||||
|
)}
|
||||||
|
|
||||||
<View style={{ height: 40 }} />
|
<View style={{ height: 40 }} />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
{/* Edit Modal */}
|
{/* Edit Modal - Only for tender users */}
|
||||||
<EditProfileModal
|
{!isAuctionUser && (
|
||||||
visible={editModalVisible}
|
<EditProfileModal
|
||||||
onClose={() => setEditModalVisible(false)}
|
visible={editModalVisible}
|
||||||
data={data}
|
onClose={() => setEditModalVisible(false)}
|
||||||
onSuccess={refetch}
|
data={data}
|
||||||
|
onSuccess={refetch}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Aadhaar Verification Dialog */}
|
||||||
|
<ConfirmDialog
|
||||||
|
visible={showDialog}
|
||||||
|
title="Aadhaar Verification Required"
|
||||||
|
message="To access all features, please complete your Aadhaar verification."
|
||||||
|
confirmText={isPending || isNavigating ? "Processing..." : "Proceed"}
|
||||||
|
cancelText="Cancel"
|
||||||
|
onConfirm={handleProceedVerification}
|
||||||
|
onClose={() => !isPending && !isNavigating && setShowDialog(false)}
|
||||||
|
loading={isPending || isNavigating}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -302,7 +415,6 @@ const EditProfileModal: React.FC<EditProfileModalProps> = ({
|
|||||||
|
|
||||||
const updateProfileMutation = useUpdateUserProfile();
|
const updateProfileMutation = useUpdateUserProfile();
|
||||||
|
|
||||||
// Reset form when modal opens
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
setFormData({
|
setFormData({
|
||||||
@@ -340,7 +452,6 @@ const EditProfileModal: React.FC<EditProfileModalProps> = ({
|
|||||||
newErrors.mobileNo = 'Invalid mobile number';
|
newErrors.mobileNo = 'Invalid mobile number';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auto-generate fullname
|
|
||||||
const generatedFullName = `${formData.firstName} ${formData.middleName} ${formData.lastName}`.trim();
|
const generatedFullName = `${formData.firstName} ${formData.middleName} ${formData.lastName}`.trim();
|
||||||
setFormData(prev => ({ ...prev, fullname: generatedFullName }));
|
setFormData(prev => ({ ...prev, fullname: generatedFullName }));
|
||||||
|
|
||||||
@@ -375,7 +486,6 @@ const EditProfileModal: React.FC<EditProfileModalProps> = ({
|
|||||||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||||
>
|
>
|
||||||
<View style={styles.modalContent}>
|
<View style={styles.modalContent}>
|
||||||
{/* Header */}
|
|
||||||
<View style={styles.modalHeader}>
|
<View style={styles.modalHeader}>
|
||||||
<Text style={styles.modalTitle}>Edit Personal Information</Text>
|
<Text style={styles.modalTitle}>Edit Personal Information</Text>
|
||||||
<TouchableOpacity onPress={onClose} style={styles.closeButton}>
|
<TouchableOpacity onPress={onClose} style={styles.closeButton}>
|
||||||
@@ -383,9 +493,7 @@ const EditProfileModal: React.FC<EditProfileModalProps> = ({
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Form */}
|
|
||||||
<ScrollView style={styles.formContainer} showsVerticalScrollIndicator={false}>
|
<ScrollView style={styles.formContainer} showsVerticalScrollIndicator={false}>
|
||||||
{/* First Name */}
|
|
||||||
<View style={styles.inputGroup}>
|
<View style={styles.inputGroup}>
|
||||||
<Text style={styles.inputLabel}>First Name *</Text>
|
<Text style={styles.inputLabel}>First Name *</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
@@ -400,7 +508,6 @@ const EditProfileModal: React.FC<EditProfileModalProps> = ({
|
|||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Middle Name */}
|
|
||||||
<View style={styles.inputGroup}>
|
<View style={styles.inputGroup}>
|
||||||
<Text style={styles.inputLabel}>Middle Name</Text>
|
<Text style={styles.inputLabel}>Middle Name</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
@@ -412,7 +519,6 @@ const EditProfileModal: React.FC<EditProfileModalProps> = ({
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Last Name */}
|
|
||||||
<View style={styles.inputGroup}>
|
<View style={styles.inputGroup}>
|
||||||
<Text style={styles.inputLabel}>Last Name *</Text>
|
<Text style={styles.inputLabel}>Last Name *</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
@@ -427,7 +533,6 @@ const EditProfileModal: React.FC<EditProfileModalProps> = ({
|
|||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Email */}
|
|
||||||
<View style={styles.inputGroup}>
|
<View style={styles.inputGroup}>
|
||||||
<Text style={styles.inputLabel}>Email *</Text>
|
<Text style={styles.inputLabel}>Email *</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
@@ -444,7 +549,6 @@ const EditProfileModal: React.FC<EditProfileModalProps> = ({
|
|||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Mobile Number */}
|
|
||||||
<View style={styles.inputGroup}>
|
<View style={styles.inputGroup}>
|
||||||
<Text style={styles.inputLabel}>Mobile Number *</Text>
|
<Text style={styles.inputLabel}>Mobile Number *</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
@@ -462,7 +566,6 @@ const EditProfileModal: React.FC<EditProfileModalProps> = ({
|
|||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
{/* Footer Buttons */}
|
|
||||||
<View style={styles.modalFooter}>
|
<View style={styles.modalFooter}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[styles.button, styles.cancelButton]}
|
style={[styles.button, styles.cancelButton]}
|
||||||
@@ -494,7 +597,7 @@ const EditProfileModal: React.FC<EditProfileModalProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Profile Header Component - OPTIMIZED
|
// Profile Header Component - OPTIMIZED
|
||||||
const ProfileHeader: React.FC<ProfileHeaderProps> = React.memo(({ data }) => {
|
const ProfileHeader: React.FC<ProfileHeaderProps> = React.memo(({ data, displayName }) => {
|
||||||
const getInitials = (name: string): string => {
|
const getInitials = (name: string): string => {
|
||||||
if (!name || typeof name !== 'string' || name.trim().length === 0) {
|
if (!name || typeof name !== 'string' || name.trim().length === 0) {
|
||||||
const fallbackName = `${data.firstName || ''} ${data.lastName || ''}`.trim();
|
const fallbackName = `${data.firstName || ''} ${data.lastName || ''}`.trim();
|
||||||
@@ -536,7 +639,7 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = React.memo(({ data }) => {
|
|||||||
>
|
>
|
||||||
<View style={styles.avatarContainer}>
|
<View style={styles.avatarContainer}>
|
||||||
<View style={styles.avatar}>
|
<View style={styles.avatar}>
|
||||||
<Text style={styles.avatarText}>{getInitials(data.fullName)}</Text>
|
<Text style={styles.avatarText}>{getInitials(displayName)}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[styles.statusBadge, { backgroundColor: getStatusColor() }]}>
|
<View style={[styles.statusBadge, { backgroundColor: getStatusColor() }]}>
|
||||||
<View style={styles.statusDot} />
|
<View style={styles.statusDot} />
|
||||||
@@ -544,9 +647,7 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = React.memo(({ data }) => {
|
|||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Text style={styles.headerName}>
|
<Text style={styles.headerName}>
|
||||||
{data.fullName ||
|
{displayName || 'Unknown User'}
|
||||||
`${data.firstName} ${data.lastName}`.trim() ||
|
|
||||||
'Unknown User'}
|
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<View style={styles.roleBadge}>
|
<View style={styles.roleBadge}>
|
||||||
@@ -560,15 +661,18 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = React.memo(({ data }) => {
|
|||||||
|
|
||||||
ProfileHeader.displayName = 'ProfileHeader';
|
ProfileHeader.displayName = 'ProfileHeader';
|
||||||
|
|
||||||
// Quick Stats Component - OPTIMIZED
|
// Quick Stats Component - OPTIMIZED WITH TOUCHABLE AADHAAR
|
||||||
const QuickStats: React.FC<QuickStatsProps> = React.memo(({ data }) => {
|
const QuickStats: React.FC<QuickStatsProps> = React.memo(({ data, onAadhaarPress }) => {
|
||||||
|
const user = useSelector((state: any) => state.token?.token);
|
||||||
|
|
||||||
const stats: StatItem[] = useMemo(
|
const stats: StatItem[] = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
Icon: CheckCircle,
|
Icon: CheckCircle,
|
||||||
label: 'Status',
|
label: 'Aadhaar',
|
||||||
value: data.isActive,
|
value: user?.esetuVerified,
|
||||||
color: colors.success,
|
color: user?.esetuVerified === 'Not Verified' ? colors.error : colors.success,
|
||||||
|
onPress: onAadhaarPress,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Icon: ShieldCheck,
|
Icon: ShieldCheck,
|
||||||
@@ -583,20 +687,37 @@ const QuickStats: React.FC<QuickStatsProps> = React.memo(({ data }) => {
|
|||||||
color: colors.info,
|
color: colors.info,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[data.isActive, data.twoFactorAuthEnabled, data.registrationStatus]
|
[data.twoFactorAuthEnabled, data.registrationStatus, user?.esetuVerified, onAadhaarPress]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.statsContainer}>
|
<View style={styles.statsContainer}>
|
||||||
{stats.map((stat) => (
|
{stats.map((stat) => {
|
||||||
<View key={stat.label} style={styles.statCard}>
|
const CardContent = (
|
||||||
<stat.Icon size={28} color={stat.color} />
|
<View style={styles.statCard}>
|
||||||
<Text style={styles.statValue} numberOfLines={2}>
|
<stat.Icon size={28} color={stat.color} />
|
||||||
{stat.value}
|
<Text style={styles.statValue} numberOfLines={2}>
|
||||||
</Text>
|
{stat.value}
|
||||||
<Text style={styles.statLabel}>{stat.label}</Text>
|
</Text>
|
||||||
</View>
|
<Text style={styles.statLabel}>{stat.label}</Text>
|
||||||
))}
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
|
if (stat.onPress) {
|
||||||
|
return (
|
||||||
|
<TouchableOpacity
|
||||||
|
key={stat.label}
|
||||||
|
activeOpacity={0.7}
|
||||||
|
onPress={stat.onPress}
|
||||||
|
style={{ flex: 1 }}
|
||||||
|
>
|
||||||
|
{CardContent}
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <View key={stat.label} style={{ flex: 1 }}>{CardContent}</View>;
|
||||||
|
})}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -632,7 +753,6 @@ InfoSection.displayName = 'InfoSection';
|
|||||||
// Info Row Component - OPTIMIZED
|
// Info Row Component - OPTIMIZED
|
||||||
const InfoRow: React.FC<InfoRowProps> = React.memo(
|
const InfoRow: React.FC<InfoRowProps> = React.memo(
|
||||||
({ label, value, IconComponent, valueColor }) => {
|
({ label, value, IconComponent, valueColor }) => {
|
||||||
// Return null if value is not valid
|
|
||||||
if (!isValidValue(value)) {
|
if (!isValidValue(value)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -714,6 +834,7 @@ interface Styles {
|
|||||||
saveButton: ViewStyle;
|
saveButton: ViewStyle;
|
||||||
cancelButtonText: TextStyle;
|
cancelButtonText: TextStyle;
|
||||||
saveButtonText: TextStyle;
|
saveButtonText: TextStyle;
|
||||||
|
navigationOverlay: ViewStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create<Styles>({
|
const styles = StyleSheet.create<Styles>({
|
||||||
@@ -762,7 +883,6 @@ const styles = StyleSheet.create<Styles>({
|
|||||||
fontWeight: '600',
|
fontWeight: '600',
|
||||||
},
|
},
|
||||||
|
|
||||||
// Header Styles
|
|
||||||
headerGradient: {
|
headerGradient: {
|
||||||
paddingTop: Platform.OS === 'ios' ? 60 : 40,
|
paddingTop: Platform.OS === 'ios' ? 60 : 40,
|
||||||
paddingBottom: 30,
|
paddingBottom: 30,
|
||||||
@@ -840,7 +960,6 @@ const styles = StyleSheet.create<Styles>({
|
|||||||
fontWeight: '600',
|
fontWeight: '600',
|
||||||
},
|
},
|
||||||
|
|
||||||
// Stats Styles
|
|
||||||
statsContainer: {
|
statsContainer: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
marginHorizontal: 16,
|
marginHorizontal: 16,
|
||||||
@@ -873,7 +992,6 @@ const styles = StyleSheet.create<Styles>({
|
|||||||
marginTop: 4,
|
marginTop: 4,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Section Styles
|
|
||||||
section: {
|
section: {
|
||||||
marginHorizontal: 16,
|
marginHorizontal: 16,
|
||||||
marginTop: 24,
|
marginTop: 24,
|
||||||
@@ -924,7 +1042,6 @@ const styles = StyleSheet.create<Styles>({
|
|||||||
backgroundColor: colors.primaryHighlight,
|
backgroundColor: colors.primaryHighlight,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Info Row Styles
|
|
||||||
infoRow: {
|
infoRow: {
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
@@ -965,7 +1082,6 @@ const styles = StyleSheet.create<Styles>({
|
|||||||
lineHeight: 21,
|
lineHeight: 21,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Modal Styles
|
|
||||||
modalOverlay: {
|
modalOverlay: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||||
@@ -1057,6 +1173,17 @@ const styles = StyleSheet.create<Styles>({
|
|||||||
fontWeight: '600',
|
fontWeight: '600',
|
||||||
color: colors.white,
|
color: colors.white,
|
||||||
},
|
},
|
||||||
|
navigationOverlay: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
zIndex: 999,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default ProfileTab;
|
export default ProfileTab;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const Splash: React.FC = () => {
|
|||||||
const isFocused = useIsFocused();
|
const isFocused = useIsFocused();
|
||||||
const fadeAnim = useRef(new Animated.Value(0)).current;
|
const fadeAnim = useRef(new Animated.Value(0)).current;
|
||||||
const reduxToken = useSelector((state: any) => state.token?.token);
|
const reduxToken = useSelector((state: any) => state.token?.token);
|
||||||
console.log("user Token",reduxToken)
|
console.log("user Token", reduxToken)
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
const { mutateAsync: registrationStateMutate } = useRagistrationState();
|
const { mutateAsync: registrationStateMutate } = useRagistrationState();
|
||||||
const [isHydrated, setIsHydrated] = useState(false);
|
const [isHydrated, setIsHydrated] = useState(false);
|
||||||
@@ -66,11 +66,19 @@ const Splash: React.FC = () => {
|
|||||||
const handleGetData = async () => {
|
const handleGetData = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await registrationStateMutate();
|
const res = await registrationStateMutate();
|
||||||
console.log("ragister",res)
|
console.log("ragister", res)
|
||||||
if (res?.statusCode === 404 || res?.statusCode === 401) {
|
|
||||||
navigation.replace('Registration');
|
if ( res?.data?.message==="No Response From Server"&& res?.data?.success===false){
|
||||||
return;
|
navigation.reset({
|
||||||
|
index: 0,
|
||||||
|
routes: [{ name: NavigationString.Login }],
|
||||||
|
});
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
if (res?.statusCode === 404 || res?.statusCode === 401) {
|
||||||
|
navigation.replace('Registration');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (res?.statusCode === 200 && res?.data) {
|
if (res?.statusCode === 200 && res?.data) {
|
||||||
const { registrationStatus, contOtherId, contOrganization } = res.data;
|
const { registrationStatus, contOtherId, contOrganization } = res.data;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const EnvelopeCExcelPreview = (tenderData: any) => {
|
|||||||
const [data, setData] = useState<any[]>([]);
|
const [data, setData] = useState<any[]>([]);
|
||||||
const [columns, setColumns] = useState<string[]>([]);
|
const [columns, setColumns] = useState<string[]>([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
console.log("kllkl",tenderData)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadExcelFromApi();
|
loadExcelFromApi();
|
||||||
}, []);
|
}, []);
|
||||||
@@ -237,9 +237,9 @@ const EnvelopeCExcelPreview = (tenderData: any) => {
|
|||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
<TouchableOpacity style={styles.button} onPress={saveUpdatedExcel}>
|
{tenderData?.buttonEnable && <TouchableOpacity style={styles.button} onPress={saveUpdatedExcel}>
|
||||||
<Text style={styles.buttonText}>Save Updated Excel</Text>
|
<Text style={styles.buttonText}>Save Updated Excel</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ const ProceedToBidDetail = () => {
|
|||||||
const { data, refetch, isRefetching } = useProceedToBid(tenderDataId?.tenderId);
|
const { data, refetch, isRefetching } = useProceedToBid(tenderDataId?.tenderId);
|
||||||
const { data: tenderResponse, refetch: tenderRefetch }: any = useFetchTenderById(tenderDataId?.tenderId);
|
const { data: tenderResponse, refetch: tenderRefetch }: any = useFetchTenderById(tenderDataId?.tenderId);
|
||||||
const tenderData = tenderResponse?.data;
|
const tenderData = tenderResponse?.data;
|
||||||
|
console.log("dataopop",tenderData)
|
||||||
const [refreshing, setRefreshing] = React.useState(false);
|
const [refreshing, setRefreshing] = React.useState(false);
|
||||||
const [loading, setLoading] = React.useState(false);
|
const [loading, setLoading] = React.useState(false);
|
||||||
|
|
||||||
@@ -174,8 +175,8 @@ const ProceedToBidDetail = () => {
|
|||||||
<Text style={styles.sectionTitle}>Envelope Submission Status</Text>
|
<Text style={styles.sectionTitle}>Envelope Submission Status</Text>
|
||||||
<View style={styles.statusGrid}>
|
<View style={styles.statusGrid}>
|
||||||
<StatusIndicator status={tenderData?.envelopeASubmittStatus} label="Envelope A" />
|
<StatusIndicator status={tenderData?.envelopeASubmittStatus} label="Envelope A" />
|
||||||
<StatusIndicator status={tenderData?.envelopeBSubmittStatus} label="Envelope B" />
|
{tenderData?.showEB &&<StatusIndicator status={tenderData?.envelopeBSubmittStatus} label="Envelope B" />}
|
||||||
<StatusIndicator status={tenderData?.envelopeCSubmittStatus} label="Envelope C" />
|
{tenderData?.showEC &&<StatusIndicator status={tenderData?.envelopeCSubmittStatus} label="Envelope C" />}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
|||||||
+191
-85
@@ -13,7 +13,7 @@ import {
|
|||||||
useFetchPurchaseTender,
|
useFetchPurchaseTender,
|
||||||
} from '../../Services/BBPS/Hooks';
|
} from '../../Services/BBPS/Hooks';
|
||||||
import colors from '../../Constant/Color';
|
import colors from '../../Constant/Color';
|
||||||
import { ShoppingCart } from 'lucide-react-native';
|
import { ShoppingCart, Lock } from 'lucide-react-native';
|
||||||
import { useNavigation } from '@react-navigation/native';
|
import { useNavigation } from '@react-navigation/native';
|
||||||
import NavigationString from '../../Constant/NavigationString';
|
import NavigationString from '../../Constant/NavigationString';
|
||||||
import FontsFamily from '../../Constant/FontsFamily';
|
import FontsFamily from '../../Constant/FontsFamily';
|
||||||
@@ -33,6 +33,7 @@ const Tender = () => {
|
|||||||
const SelectedPurchaseList = useSelector(
|
const SelectedPurchaseList = useSelector(
|
||||||
(state: any) => state?.selectPurchaseTender,
|
(state: any) => state?.selectPurchaseTender,
|
||||||
);
|
);
|
||||||
|
const reduxToken = useSelector((state: any) => state.token?.token);
|
||||||
|
|
||||||
const liveCount = liveTenderData?.pages?.[0]?.totalCount || 0;
|
const liveCount = liveTenderData?.pages?.[0]?.totalCount || 0;
|
||||||
const purchaseCount = purchaseTenderData?.pages?.[0]?.totalCount || 0;
|
const purchaseCount = purchaseTenderData?.pages?.[0]?.totalCount || 0;
|
||||||
@@ -54,97 +55,136 @@ const Tender = () => {
|
|||||||
}).start();
|
}).start();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Check if user is auction type
|
||||||
|
const isAuctionUser = reduxToken?.userType?.toLowerCase() === 'auction';
|
||||||
|
|
||||||
|
// Render restricted access message
|
||||||
|
const renderRestrictedAccess = () => (
|
||||||
|
<View style={styles.restrictedContainer}>
|
||||||
|
<View style={styles.restrictedCard}>
|
||||||
|
<View style={styles.iconContainer}>
|
||||||
|
<Lock size={64} color={colors.primary} />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Text style={styles.restrictedTitle}>Tender Access Restricted</Text>
|
||||||
|
|
||||||
|
<Text style={styles.restrictedMessage}>
|
||||||
|
You are currently logged in as an Auction user. Tender features are not available for your account type.
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text style={styles.restrictedSubMessage}>
|
||||||
|
To access tender features, please login with a Tender user account.
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
style={styles.loginButton}
|
||||||
|
onPress={() => Navigation.navigate(NavigationString.Login)}
|
||||||
|
>
|
||||||
|
<Text style={styles.loginButtonText}>Switch to Tender Login</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<InsideHeader title="Tender" showArrow />
|
<InsideHeader title="Tender" showArrow />
|
||||||
|
|
||||||
<View style={styles.topRow}>
|
{isAuctionUser ? (
|
||||||
<View
|
// Show restricted access message for auction users
|
||||||
style={[
|
renderRestrictedAccess()
|
||||||
styles.switchWrapper,
|
) : (
|
||||||
{
|
// Show normal tender UI for tender users
|
||||||
width: TAB_WIDTH * 2 + SWITCH_INSETS * 2,
|
<>
|
||||||
},
|
<View style={styles.topRow}>
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Animated.View
|
|
||||||
pointerEvents="none"
|
|
||||||
style={[
|
|
||||||
styles.activeTab,
|
|
||||||
{
|
|
||||||
width: TAB_WIDTH,
|
|
||||||
transform: [{ translateX }],
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TouchableOpacity
|
|
||||||
style={[styles.tab, { width: TAB_WIDTH }]}
|
|
||||||
activeOpacity={0.8}
|
|
||||||
onPress={() => onTabPress('live', 0)}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
styles.tabText,
|
|
||||||
selectedTab === 'live' && styles.activeText,
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
Live ({liveCount})
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
|
|
||||||
<TouchableOpacity
|
|
||||||
style={[styles.tab, { width: TAB_WIDTH }]}
|
|
||||||
activeOpacity={0.8}
|
|
||||||
onPress={() => onTabPress('purchase', 1)}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
styles.tabText,
|
|
||||||
selectedTab === 'purchase' && styles.activeText,
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
Purchased ({purchaseCount})
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View>
|
|
||||||
{SelectedPurchaseList.length ? (
|
|
||||||
<View
|
<View
|
||||||
style={{
|
style={[
|
||||||
borderWidth: 2,
|
styles.switchWrapper,
|
||||||
borderColor: colors.white,
|
{
|
||||||
backgroundColor: colors.primaryLight,
|
width: TAB_WIDTH * 2 + SWITCH_INSETS * 2,
|
||||||
position: 'absolute',
|
},
|
||||||
borderRadius: 50,
|
]}
|
||||||
zIndex: 20,
|
|
||||||
right: 0,
|
|
||||||
top: -10,
|
|
||||||
paddingHorizontal: 2,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<Text style={{ fontSize: 12, color: colors.black }}>
|
<Animated.View
|
||||||
{SelectedPurchaseList.length}
|
pointerEvents="none"
|
||||||
</Text>
|
style={[
|
||||||
</View>
|
styles.activeTab,
|
||||||
) : null}
|
{
|
||||||
<TouchableOpacity
|
width: TAB_WIDTH,
|
||||||
style={{
|
transform: [{ translateX }],
|
||||||
padding: 10,
|
},
|
||||||
backgroundColor: colors.primaryLight,
|
]}
|
||||||
borderRadius: 20,
|
/>
|
||||||
}}
|
|
||||||
onPress={() => {
|
|
||||||
Navigation.navigate(NavigationString.PurchaseTenderList);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ShoppingCart size={22} color={colors.black} strokeWidth={2} />
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{selectedTab === 'live' ? <LiveTender /> : <PurchaseTenderAllList />}
|
<TouchableOpacity
|
||||||
|
style={[styles.tab, { width: TAB_WIDTH }]}
|
||||||
|
activeOpacity={0.8}
|
||||||
|
onPress={() => onTabPress('live', 0)}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
styles.tabText,
|
||||||
|
selectedTab === 'live' && styles.activeText,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
Live ({liveCount})
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.tab, { width: TAB_WIDTH }]}
|
||||||
|
activeOpacity={0.8}
|
||||||
|
onPress={() => onTabPress('purchase', 1)}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
styles.tabText,
|
||||||
|
selectedTab === 'purchase' && styles.activeText,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
Purchased ({purchaseCount})
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View>
|
||||||
|
{SelectedPurchaseList.length ? (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
borderWidth: 2,
|
||||||
|
borderColor: colors.white,
|
||||||
|
backgroundColor: colors.primaryLight,
|
||||||
|
position: 'absolute',
|
||||||
|
borderRadius: 50,
|
||||||
|
zIndex: 20,
|
||||||
|
right: 0,
|
||||||
|
top: -10,
|
||||||
|
paddingHorizontal: 2,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={{ fontSize: 12, color: colors.black }}>
|
||||||
|
{SelectedPurchaseList.length}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
) : null}
|
||||||
|
<TouchableOpacity
|
||||||
|
style={{
|
||||||
|
padding: 10,
|
||||||
|
backgroundColor: colors.primaryLight,
|
||||||
|
borderRadius: 20,
|
||||||
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
Navigation.navigate(NavigationString.PurchaseTenderList);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ShoppingCart size={22} color={colors.black} strokeWidth={2} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{selectedTab === 'live' ? <LiveTender /> : <PurchaseTenderAllList />}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -197,4 +237,70 @@ const styles = StyleSheet.create({
|
|||||||
shadowRadius: 6,
|
shadowRadius: 6,
|
||||||
elevation: 3,
|
elevation: 3,
|
||||||
},
|
},
|
||||||
|
restrictedContainer: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
padding: 24,
|
||||||
|
backgroundColor: colors.lightGray,
|
||||||
|
},
|
||||||
|
restrictedCard: {
|
||||||
|
backgroundColor: colors.white,
|
||||||
|
borderRadius: 24,
|
||||||
|
padding: 32,
|
||||||
|
alignItems: 'center',
|
||||||
|
maxWidth: 400,
|
||||||
|
width: '100%',
|
||||||
|
|
||||||
|
},
|
||||||
|
iconContainer: {
|
||||||
|
width: 120,
|
||||||
|
height: 120,
|
||||||
|
borderRadius: 60,
|
||||||
|
backgroundColor: colors.primaryHighlight,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginBottom: 24,
|
||||||
|
},
|
||||||
|
restrictedTitle: {
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: '700',
|
||||||
|
color: colors.darkText,
|
||||||
|
textAlign: 'center',
|
||||||
|
marginBottom: 16,
|
||||||
|
fontFamily: FontsFamily.poppinsBold,
|
||||||
|
},
|
||||||
|
restrictedMessage: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: colors.grayText,
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: 24,
|
||||||
|
marginBottom: 12,
|
||||||
|
fontFamily: FontsFamily.poppinsRegular,
|
||||||
|
},
|
||||||
|
restrictedSubMessage: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: colors.grayText,
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: 22,
|
||||||
|
marginBottom: 32,
|
||||||
|
fontFamily: FontsFamily.poppinsRegular,
|
||||||
|
},
|
||||||
|
loginButton: {
|
||||||
|
backgroundColor: colors.primary,
|
||||||
|
paddingHorizontal: 32,
|
||||||
|
paddingVertical: 14,
|
||||||
|
borderRadius: 12,
|
||||||
|
shadowColor: colors.primary,
|
||||||
|
shadowOffset: { width: 0, height: 4 },
|
||||||
|
shadowOpacity: 0.3,
|
||||||
|
shadowRadius: 8,
|
||||||
|
elevation: 4,
|
||||||
|
},
|
||||||
|
loginButtonText: {
|
||||||
|
color: colors.white,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: '600',
|
||||||
|
fontFamily: FontsFamily.poppinsSemiBold,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import {
|
|||||||
import ReactNativeBlobUtil from 'react-native-blob-util';
|
import ReactNativeBlobUtil from 'react-native-blob-util';
|
||||||
import { GET_DOCID } from '../../Services/BBPS/ApiUrls'
|
import { GET_DOCID } from '../../Services/BBPS/ApiUrls'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
|
import EnvelopeCExcelPreview from './Component/EnvelopeCExcelPreview'
|
||||||
|
|
||||||
const ViewTenderDetail = () => {
|
const ViewTenderDetail = () => {
|
||||||
const route: any = useRoute()
|
const route: any = useRoute()
|
||||||
@@ -122,7 +123,7 @@ const ViewTenderDetail = () => {
|
|||||||
</View>
|
</View>
|
||||||
|
|
||||||
{item.fieldValue && (
|
{item.fieldValue && (
|
||||||
<View style={styles.fieldRow}>
|
<View style={[styles.fieldRow,{backgroundColor:colors.lightGray,borderRadius:20,padding:10}]}>
|
||||||
<Type size={16} color={colors.gray} />
|
<Type size={16} color={colors.gray} />
|
||||||
<Text style={styles.fieldValue}>{item.fieldValue}</Text>
|
<Text style={styles.fieldValue}>{item.fieldValue}</Text>
|
||||||
</View>
|
</View>
|
||||||
@@ -143,15 +144,7 @@ const ViewTenderDetail = () => {
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<View style={styles.metaInfo}>
|
</View>
|
||||||
<Text style={styles.metaText}>
|
|
||||||
Type: {getLabelTypeText(item.labelTypeA || item.labelTypeB)}
|
|
||||||
</Text>
|
|
||||||
{item.docEnvelopeSeqId && (
|
|
||||||
<Text style={styles.metaText}>ID: {item.docEnvelopeSeqId}</Text>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
))}
|
))}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
@@ -276,19 +269,23 @@ const ViewTenderDetail = () => {
|
|||||||
<Text style={styles.sectionTitle}>Envelope C</Text>
|
<Text style={styles.sectionTitle}>Envelope C</Text>
|
||||||
</View>
|
</View>
|
||||||
{data?.data?.tenderEnvelopeCViewBidResDTO.map((item: any, index: number) => (
|
{data?.data?.tenderEnvelopeCViewBidResDTO.map((item: any, index: number) => (
|
||||||
|
<View>
|
||||||
<View key={index} style={styles.documentCard}>
|
<View key={index} style={styles.documentCard}>
|
||||||
<Folder size={40} color={colors.primary} />
|
<Folder size={40} color={colors.primary} />
|
||||||
<View style={styles.documentInfo}>
|
<View style={styles.documentInfo}>
|
||||||
<Text style={styles.documentName}>
|
<Text style={styles.documentName}>
|
||||||
{item.documentFileName || "Document"}
|
{item.documentFileName || "Document"}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={styles.documentMeta}>Department User ID: {item.deptUserId}</Text>
|
{/* <Text style={styles.documentMeta}>Department User ID: {item.deptUserId}</Text> */}
|
||||||
</View>
|
</View>
|
||||||
{item.documentFileName && (
|
{item.documentFileName && (
|
||||||
<TouchableOpacity style={styles.downloadButton}>
|
<TouchableOpacity style={styles.downloadButton}>
|
||||||
{/* <Download size={24} color={colors.primary} /> */}
|
{/* <Download size={24} color={colors.primary} /> */}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
</View>
|
||||||
|
<EnvelopeCExcelPreview tenderId={tender[0]} buttonEnable={false}/>
|
||||||
</View>
|
</View>
|
||||||
))}
|
))}
|
||||||
</View>
|
</View>
|
||||||
@@ -515,12 +512,12 @@ const styles = StyleSheet.create({
|
|||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginBottom: 12,
|
marginBottom:8,
|
||||||
},
|
},
|
||||||
labelName: {
|
labelName: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: '700',
|
fontWeight: '700',
|
||||||
color: colors.darkText,
|
color: colors.primary,
|
||||||
},
|
},
|
||||||
mandatoryTag: {
|
mandatoryTag: {
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
@@ -534,7 +531,7 @@ const styles = StyleSheet.create({
|
|||||||
fieldRow: {
|
fieldRow: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginTop: 8,
|
marginTop: 4,
|
||||||
},
|
},
|
||||||
fieldValue: {
|
fieldValue: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
|
|||||||
@@ -489,10 +489,12 @@ const TenderBidding = () => {
|
|||||||
title="Envelope C"
|
title="Envelope C"
|
||||||
envelopeType="C"
|
envelopeType="C"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
if (tenderData?.envelopeBSubmittStatus) {
|
if(tenderData?.showEB){ if (tenderData?.envelopeBSubmittStatus ) {
|
||||||
setActiveEnvelope('C')
|
setActiveEnvelope('C')
|
||||||
} else {
|
} else {
|
||||||
Alert.alert('Info', 'Submit Envelop B First')
|
Alert.alert('Info', 'Submit Envelop B First')
|
||||||
|
}}else{
|
||||||
|
setActiveEnvelope('C')
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -542,9 +544,9 @@ const TenderBidding = () => {
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
|
||||||
<EnvelopeCExcelPreview tenderId={tenderData} />
|
<EnvelopeCExcelPreview tenderId={tenderData} buttonEnable={true}/>
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
@@ -554,18 +556,23 @@ const TenderBidding = () => {
|
|||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={styles.primaryButton}
|
style={styles.primaryButton}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
if (!check) {
|
|
||||||
|
|
||||||
|
if (activeEnvelope === 'A') {
|
||||||
|
if (!check) {
|
||||||
Alert.alert('Info', 'check first terms & condition');
|
Alert.alert('Info', 'check first terms & condition');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activeEnvelope === 'A') {
|
|
||||||
handleSubmitEnvelopeA();
|
handleSubmitEnvelopeA();
|
||||||
} else if (activeEnvelope === 'B') {
|
} else if (activeEnvelope === 'B') {
|
||||||
|
if (!check) {
|
||||||
|
Alert.alert('Info', 'check first terms & condition');
|
||||||
|
return;
|
||||||
|
}
|
||||||
handleSubmitEnvelopeB();
|
handleSubmitEnvelopeB();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
// disabled={loading}
|
|
||||||
>
|
>
|
||||||
<Text style={styles.primaryButtonText}>
|
<Text style={styles.primaryButtonText}>
|
||||||
{loading ? <ActivityIndicator size={'small'} color={'#fff'} /> : `Submit Bid (${activeEnvelope})`}
|
{loading ? <ActivityIndicator size={'small'} color={'#fff'} /> : `Submit Bid (${activeEnvelope})`}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import Emd from "./Bidding/Emd";
|
|||||||
import StartBidding from "./Bidding/StartBidding";
|
import StartBidding from "./Bidding/StartBidding";
|
||||||
import StartReverseBidding from "./Bidding/StartReverseBidding";
|
import StartReverseBidding from "./Bidding/StartReverseBidding";
|
||||||
import Home from "./Home/Home";
|
import Home from "./Home/Home";
|
||||||
|
import KycWebViewScreen from "./Home/KycWebViewScreen";
|
||||||
import Login from "./Login/Login";
|
import Login from "./Login/Login";
|
||||||
import ResetPassword from "./Login/ResetPassword";
|
import ResetPassword from "./Login/ResetPassword";
|
||||||
import Onboarding from "./Onboarding/Onboarding";
|
import Onboarding from "./Onboarding/Onboarding";
|
||||||
@@ -44,6 +45,7 @@ const Screens = {
|
|||||||
LiveTenderDetail,
|
LiveTenderDetail,
|
||||||
ProfileTab,
|
ProfileTab,
|
||||||
ViewTenderDetail,
|
ViewTenderDetail,
|
||||||
ResetPassword
|
ResetPassword,
|
||||||
|
KycWebViewScreen
|
||||||
}
|
}
|
||||||
export default Screens
|
export default Screens
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import axios from "axios";
|
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, GET_CONTRACTOR_PROFILE, CONTRACTOR_PROFILE_UPDATE, ESETU_VARIFICATION, TENDER_BID_DETAIL } 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,
|
||||||
|
ESETU_VARIFICATION, TENDER_BID_DETAIL } from "./ApiUrls";
|
||||||
import { apiCall } from "../../Axios/Axios";
|
import { apiCall } from "../../Axios/Axios";
|
||||||
|
|
||||||
// User
|
// User
|
||||||
@@ -272,13 +273,14 @@ export const getRagistrationState = async (): Promise<any> => {
|
|||||||
|
|
||||||
|
|
||||||
export const eSetuAdharVarification = async (payLoad:any ): Promise<any> => {
|
export const eSetuAdharVarification = async (payLoad:any ): Promise<any> => {
|
||||||
|
console.log("klkllklklklk",payLoad)
|
||||||
const data = await apiCall<any>(
|
const data = await apiCall<any>(
|
||||||
'get',
|
'post',
|
||||||
`${ESETU_VARIFICATION}`,
|
`${ESETU_VARIFICATION}`,
|
||||||
payLoad,
|
payLoad,
|
||||||
{},
|
|
||||||
"application/x-www-form-urlencoded"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.log("ghghghghghhgg",data)
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user