Merge branch 'main' of https://git.zeptic.in/rohit/Procurelinc into etenderMerge
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
projectKey=procurelinc
|
||||||
|
serverUrl=http://localhost:9000
|
||||||
|
serverVersion=9.9.8.100196
|
||||||
|
dashboardUrl=http://localhost:9000/dashboard?id=procurelinc
|
||||||
|
ceTaskId=AZui1_IJunY9vPNeE5RI
|
||||||
|
ceTaskUrl=http://localhost:9000/api/ce/task?id=AZui1_IJunY9vPNeE5RI
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React from 'react';
|
||||||
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
||||||
import { Alert, Linking, LogBox, StatusBar, View } from 'react-native';
|
import { LogBox, StatusBar, View } from 'react-native';
|
||||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||||
import { AlertNotificationRoot } from 'react-native-alert-notification';
|
import { AlertNotificationRoot } from 'react-native-alert-notification';
|
||||||
import { PersistGate } from 'redux-persist/integration/react';
|
import { PersistGate } from 'redux-persist/integration/react';
|
||||||
@@ -8,13 +8,14 @@ import { Provider } from 'react-redux';
|
|||||||
import { persistor, store } from './src/Redux/Store.js';
|
import { persistor, store } from './src/Redux/Store.js';
|
||||||
import Routes from './src/Navigation/Routes.jsx';
|
import Routes from './src/Navigation/Routes.jsx';
|
||||||
import { NavigationContainer } from '@react-navigation/native';
|
import { NavigationContainer } from '@react-navigation/native';
|
||||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
||||||
import colors from './src/Constant/Color';
|
import colors from './src/Constant/Color';
|
||||||
import { TextEncoder } from 'text-encoding';
|
import { TextEncoder } from 'text-encoding';
|
||||||
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
LogBox.ignoreAllLogs(true);
|
LogBox.ignoreAllLogs(true);
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
|
const insets = useSafeAreaInsets()
|
||||||
global.TextEncoder = TextEncoder;
|
global.TextEncoder = TextEncoder;
|
||||||
return (
|
return (
|
||||||
<NavigationContainer >
|
<NavigationContainer >
|
||||||
@@ -23,11 +24,8 @@ const App = () => {
|
|||||||
<AlertNotificationRoot>
|
<AlertNotificationRoot>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<PersistGate persistor={persistor}>
|
<PersistGate persistor={persistor}>
|
||||||
{/* paddingTop: inset.top + 10, */}
|
<View style={{ flex: 1, backgroundColor: colors.white, paddingBottom: insets.bottom }}>
|
||||||
<View style={{ flex: 1, backgroundColor: colors.white }}>
|
<StatusBar barStyle="dark-content" />
|
||||||
<StatusBar
|
|
||||||
barStyle="dark-content"
|
|
||||||
/>
|
|
||||||
<Routes />
|
<Routes />
|
||||||
</View>
|
</View>
|
||||||
</PersistGate>
|
</PersistGate>
|
||||||
|
|||||||
Vendored
+3
@@ -8,3 +8,6 @@
|
|||||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
# Add any project specific keep options here:
|
# Add any project specific keep options here:
|
||||||
|
|
||||||
|
-keep class com.facebook.hermes.** { *; }
|
||||||
|
-keep class com.facebook.react.** { *; }
|
||||||
@@ -1,6 +1,14 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<!-- Android 12 and below -->
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||||
|
android:maxSdkVersion="28" />
|
||||||
|
|
||||||
|
<!-- Android 13+ -->
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".MainApplication"
|
android:name=".MainApplication"
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ import { AppRegistry } from 'react-native';
|
|||||||
import App from './App';
|
import App from './App';
|
||||||
import { name as appName } from './app.json';
|
import { name as appName } from './app.json';
|
||||||
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||||
|
import { Buffer } from 'buffer';
|
||||||
|
global.Buffer = Buffer;
|
||||||
const Root = () => (
|
const Root = () => (
|
||||||
<SafeAreaProvider>
|
<SafeAreaProvider>
|
||||||
<App />
|
<App />
|
||||||
|
|||||||
Generated
+586
-44
File diff suppressed because it is too large
Load Diff
+7
-1
@@ -22,6 +22,7 @@
|
|||||||
"@stomp/stompjs": "^7.2.1",
|
"@stomp/stompjs": "^7.2.1",
|
||||||
"@tanstack/react-query": "^5.90.12",
|
"@tanstack/react-query": "^5.90.12",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
|
"buffer": "^6.0.3",
|
||||||
"eslint-config-prettier": "^10.1.8",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-plugin-react": "^7.37.5",
|
"eslint-plugin-react": "^7.37.5",
|
||||||
"eslint-plugin-react-native": "^5.0.0",
|
"eslint-plugin-react-native": "^5.0.0",
|
||||||
@@ -33,9 +34,12 @@
|
|||||||
"react-native": "0.79.0",
|
"react-native": "0.79.0",
|
||||||
"react-native-alert-notification": "^0.4.2",
|
"react-native-alert-notification": "^0.4.2",
|
||||||
"react-native-app-intro-slider": "^4.0.4",
|
"react-native-app-intro-slider": "^4.0.4",
|
||||||
"react-native-bouncy-checkbox": "^4.1.3",
|
"react-native-blob-util": "^0.24.6",
|
||||||
|
"react-native-bouncy-checkbox": "^4.1.2",
|
||||||
"react-native-date-picker": "^5.0.13",
|
"react-native-date-picker": "^5.0.13",
|
||||||
"react-native-element-dropdown": "^2.12.4",
|
"react-native-element-dropdown": "^2.12.4",
|
||||||
|
"react-native-file-viewer": "^2.1.5",
|
||||||
|
"react-native-fs": "^2.20.0",
|
||||||
"react-native-gesture-handler": "^2.30.0",
|
"react-native-gesture-handler": "^2.30.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",
|
||||||
@@ -53,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",
|
||||||
|
"xlsx": "^0.18.5",
|
||||||
"yup": "^1.7.1"
|
"yup": "^1.7.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -74,6 +79,7 @@
|
|||||||
"eslint": "^8.19.0",
|
"eslint": "^8.19.0",
|
||||||
"jest": "^29.6.3",
|
"jest": "^29.6.3",
|
||||||
"prettier": "2.8.8",
|
"prettier": "2.8.8",
|
||||||
|
"react-native-bundle-visualizer": "^3.1.3",
|
||||||
"react-test-renderer": "19.0.0",
|
"react-test-renderer": "19.0.0",
|
||||||
"typescript": "5.0.4"
|
"typescript": "5.0.4"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Required project identifiers
|
||||||
|
sonar.projectKey=procurelinc
|
||||||
|
sonar.projectName=ProcureLinc
|
||||||
|
sonar.projectVersion=1.0
|
||||||
|
|
||||||
|
# Source configuration
|
||||||
|
sonar.sources=.
|
||||||
|
|
||||||
|
# SonarQube server
|
||||||
|
sonar.host.url=http://localhost:9000
|
||||||
|
|
||||||
|
# Authentication token
|
||||||
|
sonar.login=sqp_da89e447c964b6e91e142777097e25fa2f17a1cc
|
||||||
+1
-2
@@ -1,5 +1,4 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { NavigationString, showErrorAlert, Variable } from '../Constant/AllImports';
|
|
||||||
import { setToken } from '../Redux/Slices/Token';
|
import { setToken } from '../Redux/Slices/Token';
|
||||||
import { store } from '../Redux/Store';
|
import { store } from '../Redux/Store';
|
||||||
|
|
||||||
@@ -50,7 +49,7 @@ export const apiCall = async <R, D = {}>(
|
|||||||
return response.data;
|
return response.data;
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
const errorMessage = error?.response?.data?.error;
|
const errorMessage = error?.response?.data?.error;
|
||||||
{ error?.response?.data?.error && showErrorAlert(error?.response?.data?.error || '') }
|
console.log(errorMessage, '---------------------------api error message');
|
||||||
|
|
||||||
if (error?.response?.status === 401) {
|
if (error?.response?.status === 401) {
|
||||||
store.dispatch(setToken({}));
|
store.dispatch(setToken({}));
|
||||||
|
|||||||
@@ -1,12 +1,5 @@
|
|||||||
import React, { FC, useRef, useEffect } from 'react';
|
import React, { FC, useRef, useEffect } from 'react';
|
||||||
import {
|
import { StyleSheet, Text, View, TouchableOpacity, Animated, Platform } from 'react-native';
|
||||||
StyleSheet,
|
|
||||||
Text,
|
|
||||||
View,
|
|
||||||
TouchableOpacity,
|
|
||||||
Animated,
|
|
||||||
Platform,
|
|
||||||
} from 'react-native';
|
|
||||||
import LinearGradient from 'react-native-linear-gradient';
|
import LinearGradient from 'react-native-linear-gradient';
|
||||||
import { BlurView } from '@react-native-community/blur';
|
import { BlurView } from '@react-native-community/blur';
|
||||||
import colors from '../../Constant/Color';
|
import colors from '../../Constant/Color';
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import LottieView from 'lottie-react-native';
|
|||||||
interface CountdownTimerProps {
|
interface CountdownTimerProps {
|
||||||
endDate: string;
|
endDate: string;
|
||||||
myStyle?: any
|
myStyle?: any
|
||||||
size?: number // Expected format: "DD-MM-YYYY HH:mm:ss"
|
size?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const CountdownTimer: React.FC<CountdownTimerProps> = React.memo(({ endDate, myStyle = {}, size = 20 }) => {
|
const CountdownTimer: React.FC<CountdownTimerProps> = React.memo(({ endDate, myStyle = {}, size = 20 }) => {
|
||||||
const calculateTimeLeft = useCallback(() => {
|
const calculateTimeLeft = useCallback(() => {
|
||||||
if (!endDate) return null;
|
if (!endDate) return null;
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,5 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import {
|
import { View, Text, TouchableOpacity, Image, StyleSheet, Dimensions } from 'react-native';
|
||||||
View,
|
|
||||||
Text,
|
|
||||||
TouchableOpacity,
|
|
||||||
Image,
|
|
||||||
StyleSheet,
|
|
||||||
Dimensions,
|
|
||||||
} from 'react-native';
|
|
||||||
import LinearGradient from 'react-native-linear-gradient';
|
import LinearGradient from 'react-native-linear-gradient';
|
||||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
import { Menu } from 'lucide-react-native';
|
import { Menu } from 'lucide-react-native';
|
||||||
|
|||||||
@@ -1,12 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import { View, Text, TouchableOpacity, Image, StyleSheet, Dimensions } from 'react-native';
|
||||||
View,
|
|
||||||
Text,
|
|
||||||
TouchableOpacity,
|
|
||||||
Image,
|
|
||||||
StyleSheet,
|
|
||||||
Dimensions,
|
|
||||||
} from 'react-native';
|
|
||||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
import { ArrowLeft } from 'lucide-react-native';
|
import { ArrowLeft } from 'lucide-react-native';
|
||||||
import colors from '../../Constant/Color';
|
import colors from '../../Constant/Color';
|
||||||
@@ -23,7 +16,7 @@ interface HeaderProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const InsideHeader: React.FC<HeaderProps> = ({ title, showArrow = false }) => {
|
const InsideHeader: React.FC<HeaderProps> = ({ title, showArrow = false }) => {
|
||||||
const navigation:any = useNavigation();
|
const navigation: any = useNavigation();
|
||||||
const insets = useSafeAreaInsets();
|
const insets = useSafeAreaInsets();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { View, Text, StyleSheet, TouchableOpacity, Dimensions } from "react-native";
|
import { View, Text, StyleSheet, TouchableOpacity } from "react-native";
|
||||||
import LottieView from "lottie-react-native";
|
import LottieView from "lottie-react-native";
|
||||||
import LinearGradient from "react-native-linear-gradient";
|
import LinearGradient from "react-native-linear-gradient";
|
||||||
|
|
||||||
const { width } = Dimensions.get("window");
|
|
||||||
|
|
||||||
const InternetConnectivity = () => {
|
const InternetConnectivity = () => {
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
|
|||||||
@@ -1,42 +1,16 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import { View, Text, StyleSheet, TouchableOpacity, Dimensions, ScrollView, StatusBar } from 'react-native';
|
||||||
View,
|
|
||||||
Text,
|
|
||||||
StyleSheet,
|
|
||||||
TouchableOpacity,
|
|
||||||
Dimensions,
|
|
||||||
ScrollView,
|
|
||||||
StatusBar,
|
|
||||||
} from 'react-native';
|
|
||||||
import LottieView from 'lottie-react-native';
|
import LottieView from 'lottie-react-native';
|
||||||
import LinearGradient from 'react-native-linear-gradient';
|
import LinearGradient from 'react-native-linear-gradient';
|
||||||
import {
|
import { AlertCircle, Clock, RefreshCw, Activity } from 'lucide-react-native';
|
||||||
AlertCircle,
|
import colors from '../../Constant/Color';
|
||||||
Clock,
|
|
||||||
Server,
|
|
||||||
Calendar,
|
|
||||||
RefreshCw,
|
|
||||||
MessageCircle,
|
|
||||||
Twitter,
|
|
||||||
Activity,
|
|
||||||
MessageSquare,
|
|
||||||
Bell,
|
|
||||||
WifiOff,
|
|
||||||
} from 'lucide-react-native';
|
|
||||||
import Colors from '../../Styles/Color';
|
|
||||||
import FontsFamily from '../../Constant/FontsFamily';
|
import FontsFamily from '../../Constant/FontsFamily';
|
||||||
|
|
||||||
const {width} = Dimensions.get('window');
|
|
||||||
|
|
||||||
const ServerDown = () => {
|
const ServerDown = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<StatusBar
|
<StatusBar barStyle="dark-content" />
|
||||||
// translucent={true}
|
|
||||||
// backgroundColor="transparent"
|
|
||||||
barStyle="dark-content"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ScrollView
|
<ScrollView
|
||||||
contentContainerStyle={styles.scrollContainer}
|
contentContainerStyle={styles.scrollContainer}
|
||||||
showsVerticalScrollIndicator={false}>
|
showsVerticalScrollIndicator={false}>
|
||||||
@@ -81,12 +55,12 @@ const ServerDown = () => {
|
|||||||
<View style={styles.buttonGroup}>
|
<View style={styles.buttonGroup}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
activeOpacity={0.7}
|
activeOpacity={0.7}
|
||||||
onPress={() => {}}
|
onPress={() => { }}
|
||||||
style={styles.touchable}>
|
style={styles.touchable}>
|
||||||
<LinearGradient
|
<LinearGradient
|
||||||
colors={[Colors.appColourDark, Colors.appColourDarkDim]}
|
colors={[colors.primary, colors.primaryLight]}
|
||||||
start={{x: 0, y: 0}}
|
start={{ x: 0, y: 0 }}
|
||||||
end={{x: 1, y: 0}}
|
end={{ x: 1, y: 0 }}
|
||||||
style={styles.primaryButton}>
|
style={styles.primaryButton}>
|
||||||
<RefreshCw
|
<RefreshCw
|
||||||
size={20}
|
size={20}
|
||||||
@@ -140,9 +114,9 @@ const styles = StyleSheet.create({
|
|||||||
paddingVertical: 36,
|
paddingVertical: 36,
|
||||||
paddingHorizontal: 28,
|
paddingHorizontal: 28,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
shadowColor: Colors.appColourDark,
|
shadowColor: colors.primary,
|
||||||
shadowOpacity: 0.08,
|
shadowOpacity: 0.08,
|
||||||
shadowOffset: {width: 0, height: 12},
|
shadowOffset: { width: 0, height: 12 },
|
||||||
shadowRadius: 24,
|
shadowRadius: 24,
|
||||||
elevation: 10,
|
elevation: 10,
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
@@ -162,18 +136,18 @@ const styles = StyleSheet.create({
|
|||||||
width: 60,
|
width: 60,
|
||||||
height: 60,
|
height: 60,
|
||||||
borderRadius: 30,
|
borderRadius: 30,
|
||||||
backgroundColor: Colors.appColourDark,
|
backgroundColor: colors.primary,
|
||||||
opacity: 0.2,
|
opacity: 0.2,
|
||||||
},
|
},
|
||||||
statusDot: {
|
statusDot: {
|
||||||
width: 44,
|
width: 44,
|
||||||
height: 44,
|
height: 44,
|
||||||
borderRadius: 22,
|
borderRadius: 22,
|
||||||
backgroundColor: Colors.appColourDarkDim,
|
backgroundColor: colors.primary,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
shadowColor: Colors.appColourDark,
|
shadowColor: colors.primary,
|
||||||
shadowOffset: {width: 0, height: 4},
|
shadowOffset: { width: 0, height: 4 },
|
||||||
shadowOpacity: 0.3,
|
shadowOpacity: 0.3,
|
||||||
shadowRadius: 8,
|
shadowRadius: 8,
|
||||||
elevation: 6,
|
elevation: 6,
|
||||||
@@ -310,7 +284,7 @@ const styles = StyleSheet.create({
|
|||||||
touchable: {
|
touchable: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
shadowColor: '#FF6B6B',
|
shadowColor: '#FF6B6B',
|
||||||
shadowOffset: {width: 0, height: 4},
|
shadowOffset: { width: 0, height: 4 },
|
||||||
shadowOpacity: 0.3,
|
shadowOpacity: 0.3,
|
||||||
shadowRadius: 8,
|
shadowRadius: 8,
|
||||||
elevation: 6,
|
elevation: 6,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, ActivityIndicator } from 'react-native';
|
import { View, ActivityIndicator } from 'react-native';
|
||||||
|
|
||||||
interface LoaderType {
|
interface LoaderType {
|
||||||
size?: 'small' | 'large';
|
size?: 'small' | 'large';
|
||||||
color?: string;
|
color?: string;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { StyleSheet, TextInput, View, TextInputProps, StyleProp, TextStyle, ViewStyle, TouchableOpacity } from 'react-native';
|
import { StyleSheet, TextInput, View, TextInputProps, TouchableOpacity } from 'react-native';
|
||||||
import React, { ReactNode } from 'react';
|
import React from 'react';
|
||||||
import Icon from 'lucide-react-native';
|
|
||||||
|
|
||||||
type MyInputProps = {
|
type MyInputProps = {
|
||||||
icon?: string;
|
icon?: string;
|
||||||
@@ -16,7 +15,7 @@ type MyInputProps = {
|
|||||||
editable?: boolean;
|
editable?: boolean;
|
||||||
autoCapitalize?: TextInputProps['autoCapitalize'];
|
autoCapitalize?: TextInputProps['autoCapitalize'];
|
||||||
rightIcon?: string,
|
rightIcon?: string,
|
||||||
rightIconPress?:()=>void
|
rightIconPress?: () => void
|
||||||
} & TextInputProps;
|
} & TextInputProps;
|
||||||
|
|
||||||
const MyInput: React.FC<MyInputProps> = ({
|
const MyInput: React.FC<MyInputProps> = ({
|
||||||
@@ -67,23 +66,9 @@ const MyInput: React.FC<MyInputProps> = ({
|
|||||||
{
|
{
|
||||||
rightIcon ?
|
rightIcon ?
|
||||||
<TouchableOpacity onPress={rightIconPress}>
|
<TouchableOpacity onPress={rightIconPress}>
|
||||||
{/* <Icon
|
|
||||||
name={rightIcon}
|
|
||||||
size={18}
|
|
||||||
color={focused ? color.primary : '#aaa'}
|
|
||||||
style={styles.icon}
|
|
||||||
/> */}
|
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
: null}
|
: null}
|
||||||
{/* {isVarify ? (
|
|
||||||
<Icon
|
|
||||||
name="check-circle"
|
|
||||||
size={18}
|
|
||||||
color={color.success}
|
|
||||||
style={styles.icon}
|
|
||||||
/>
|
|
||||||
) : null} */}
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -101,7 +86,7 @@ const styles = StyleSheet.create({
|
|||||||
paddingHorizontal: 10,
|
paddingHorizontal: 10,
|
||||||
marginVertical: 10,
|
marginVertical: 10,
|
||||||
height: 55,
|
height: 55,
|
||||||
|
|
||||||
},
|
},
|
||||||
icon: {
|
icon: {
|
||||||
marginRight: 10,
|
marginRight: 10,
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
import { Filter, Search } from "lucide-react-native";
|
import { Filter, Search } from "lucide-react-native";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { View, Text, TextInput, StyleSheet, TouchableOpacity, Platform } from "react-native";
|
import { View, Text, TextInput, StyleSheet, TouchableOpacity, Platform } from "react-native";
|
||||||
import Animated, {
|
import Animated, { useAnimatedStyle, useSharedValue, withTiming, interpolateColor } from "react-native-reanimated";
|
||||||
useAnimatedStyle,
|
|
||||||
useSharedValue,
|
|
||||||
withTiming,
|
|
||||||
interpolateColor
|
|
||||||
} from "react-native-reanimated";
|
|
||||||
import colors from "../../Constant/Color";
|
import colors from "../../Constant/Color";
|
||||||
|
|
||||||
export interface SearchType {
|
export interface SearchType {
|
||||||
@@ -19,21 +14,14 @@ export interface SearchType {
|
|||||||
|
|
||||||
const AnimatedView = Animated.createAnimatedComponent(View);
|
const AnimatedView = Animated.createAnimatedComponent(View);
|
||||||
|
|
||||||
export const SearchInput: React.FC<SearchType> = ({
|
export const SearchInput: React.FC<SearchType> = ({ placeholder, onChange, label, filter = true, filterPress }) => {
|
||||||
placeholder,
|
|
||||||
onChange,
|
|
||||||
label,
|
|
||||||
filter = true,
|
|
||||||
filterPress
|
|
||||||
}) => {
|
|
||||||
const isFocused = useSharedValue(0);
|
const isFocused = useSharedValue(0);
|
||||||
|
|
||||||
// Animate border color and shadow based on focus
|
|
||||||
const inputContainerStyle = useAnimatedStyle(() => {
|
const inputContainerStyle = useAnimatedStyle(() => {
|
||||||
const borderColor = interpolateColor(
|
const borderColor = interpolateColor(
|
||||||
isFocused.value,
|
isFocused.value,
|
||||||
[0, 1],
|
[0, 1],
|
||||||
[colors.grayText + '50', colors.grayText] // Assuming colors.primary exists
|
[colors.grayText + '50', colors.grayText]
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -143,8 +143,6 @@ const SideDrawer: React.FC<Props> = ({ visible, onClose }) => {
|
|||||||
|
|
||||||
export default SideDrawer;
|
export default SideDrawer;
|
||||||
|
|
||||||
/* ================= Styles ================= */
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
modal: {
|
modal: {
|
||||||
margin: 0,
|
margin: 0,
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
import React, { useEffect, useRef } from 'react';
|
|
||||||
import { Animated, Text, StyleSheet } from 'react-native';
|
|
||||||
import colors from '../../Constant/Color';
|
|
||||||
|
|
||||||
interface AuctionItemProps {
|
|
||||||
item: any;
|
|
||||||
index: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const AuctionItem: React.FC<AuctionItemProps> = ({ item, index }) => {
|
|
||||||
const scale = useRef(new Animated.Value(0)).current;
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
Animated.spring(scale, {
|
|
||||||
toValue: 1,
|
|
||||||
friction: 8,
|
|
||||||
useNativeDriver: true,
|
|
||||||
delay: index * 50,
|
|
||||||
}).start();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Animated.View style={[styles.itemCard, { transform: [{ scale }] }]}>
|
|
||||||
<Text style={styles.itemTitle}>{item.title || `${item.auctionNumber}`}</Text>
|
|
||||||
<Text style={styles.itemDate}>End Date: {item.purchaseEnd || 'N/A'} </Text>
|
|
||||||
</Animated.View>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AuctionItem;
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
itemCard: {
|
|
||||||
backgroundColor: '#fff',
|
|
||||||
padding: 18,
|
|
||||||
borderRadius: 16,
|
|
||||||
marginBottom: 14,
|
|
||||||
shadowColor: '#000',
|
|
||||||
shadowOffset: { width: 0, height: 4 },
|
|
||||||
shadowOpacity: 0.12,
|
|
||||||
shadowRadius: 8,
|
|
||||||
elevation: 4,
|
|
||||||
},
|
|
||||||
itemTitle: {
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: '700',
|
|
||||||
marginBottom: 4,
|
|
||||||
color: '#020617',
|
|
||||||
},
|
|
||||||
itemDate: {
|
|
||||||
fontSize: 13,
|
|
||||||
color: '#64748b',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -10,6 +10,7 @@ const NavigationString = {
|
|||||||
StartBidding: 'StartBidding',
|
StartBidding: 'StartBidding',
|
||||||
PurchaseAuctionList:'PurchaseAuctionList',
|
PurchaseAuctionList:'PurchaseAuctionList',
|
||||||
StartReverseBidding:'StartReverseBidding',
|
StartReverseBidding:'StartReverseBidding',
|
||||||
|
// tender
|
||||||
PurchaseTenderList:'PurchaseTenderList',
|
PurchaseTenderList:'PurchaseTenderList',
|
||||||
ProceedToPurTender:'ProceedToPurTender',
|
ProceedToPurTender:'ProceedToPurTender',
|
||||||
TenderBidding:'TenderBidding',
|
TenderBidding:'TenderBidding',
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
export const format = {
|
||||||
|
// Internal helper to safely parse any input
|
||||||
|
parse: (date: string | Date) => {
|
||||||
|
if (!date) return null;
|
||||||
|
let d = date;
|
||||||
|
if (typeof date === 'string') {
|
||||||
|
// Replace IST or other known timezone abbreviations with UTC offset
|
||||||
|
d = date.replace('IST', '+0530');
|
||||||
|
}
|
||||||
|
return moment(d);
|
||||||
|
},
|
||||||
|
|
||||||
|
date1: (date: string | Date) => format.parse(date)?.format('DD-MM-YYYY'),
|
||||||
|
date2: (date: string | Date) => format.parse(date)?.format('YYYY-MM-DD'),
|
||||||
|
date3: (date: string | Date) => format.parse(date)?.format('MMMM Do, YYYY'),
|
||||||
|
date4: (date: string | Date) => format.parse(date)?.format('dddd, MMMM Do YYYY'),
|
||||||
|
date5: (date: string | Date) => format.parse(date)?.format('MM/DD/YYYY'),
|
||||||
|
date6: (date: string | Date) => format.parse(date)?.format('YYYY/MM/DD HH:mm'),
|
||||||
|
time1: (date: string | Date) => format.parse(date)?.format('hh:mm A'),
|
||||||
|
time2: (date: string | Date) => format.parse(date)?.format('HH:mm:ss'),
|
||||||
|
iso: (date: string | Date) => format.parse(date)?.toISOString(),
|
||||||
|
fromNow: (date: string | Date) => format.parse(date)?.fromNow(),
|
||||||
|
custom: (date: string | Date, formatStr: string) => format.parse(date)?.format(formatStr),
|
||||||
|
};
|
||||||
@@ -12,6 +12,7 @@ import * as LucideIcons from 'lucide-react-native';
|
|||||||
import Screens from '../Screens';
|
import Screens from '../Screens';
|
||||||
import colors from '../Constant/Color';
|
import colors from '../Constant/Color';
|
||||||
import NavigationString from '../Constant/NavigationString';
|
import NavigationString from '../Constant/NavigationString';
|
||||||
|
import EditableExcel from '../Screens/Tender/Component/EditableExcel';
|
||||||
|
|
||||||
const { width } = Dimensions.get('window');
|
const { width } = Dimensions.get('window');
|
||||||
const TAB_BAR_HEIGHT = 60;
|
const TAB_BAR_HEIGHT = 60;
|
||||||
@@ -24,6 +25,7 @@ const TabButton = ({ route, isFocused, onPress }: any) => {
|
|||||||
Home: { outline: "Home", filled: "Home" },
|
Home: { outline: "Home", filled: "Home" },
|
||||||
Auction: { outline: "Gavel", filled: "Gavel" },
|
Auction: { outline: "Gavel", filled: "Gavel" },
|
||||||
Tender: { outline: "FileText", filled: "FileText" },
|
Tender: { outline: "FileText", filled: "FileText" },
|
||||||
|
EditableExcel: { outline: "FileText", filled: "FileText" },
|
||||||
};
|
};
|
||||||
const IconName = LucideIcons[isFocused ? icons[route.name].filled : icons[route.name].outline];
|
const IconName = LucideIcons[isFocused ? icons[route.name].filled : icons[route.name].outline];
|
||||||
const scaleAnim = useRef(new Animated.Value(1)).current;
|
const scaleAnim = useRef(new Animated.Value(1)).current;
|
||||||
@@ -146,6 +148,7 @@ export default function BottomTab() {
|
|||||||
<Tab.Screen name="Home" component={Screens.Home} />
|
<Tab.Screen name="Home" component={Screens.Home} />
|
||||||
<Tab.Screen name={NavigationString.Auction} component={Screens.Auction} />
|
<Tab.Screen name={NavigationString.Auction} component={Screens.Auction} />
|
||||||
<Tab.Screen name={NavigationString.Tender} component={Screens.Tender} />
|
<Tab.Screen name={NavigationString.Tender} component={Screens.Tender} />
|
||||||
|
<Tab.Screen name={'EditableExcel'} component={EditableExcel} />
|
||||||
</Tab.Navigator>
|
</Tab.Navigator>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ export default function MainStack() {
|
|||||||
<Stack.Screen name={NavigationString.Registration} component={Screens.Registration} options={option} />
|
<Stack.Screen name={NavigationString.Registration} component={Screens.Registration} options={option} />
|
||||||
<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.StartReverseBidding} component={Screens.StartReverseBidding} options={option} />
|
||||||
|
|
||||||
</Stack.Navigator>
|
</Stack.Navigator>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ export interface AuctionItem {
|
|||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ DEFAULT = EMPTY ARRAY
|
|
||||||
const initialState: AuctionItem[] = [];
|
const initialState: AuctionItem[] = [];
|
||||||
|
|
||||||
export const selectPurchaseAuctionSlice = createSlice({
|
export const selectPurchaseAuctionSlice = createSlice({
|
||||||
|
|||||||
@@ -1,52 +1,40 @@
|
|||||||
import React, { useCallback, useState, useEffect } from 'react';
|
import React, { useCallback, useState, useEffect, useRef } from 'react';
|
||||||
import { View, FlatList, ActivityIndicator, RefreshControl, Text } from 'react-native';
|
import { View, FlatList, ActivityIndicator, RefreshControl, Text } from 'react-native';
|
||||||
import Animated, { FadeInDown, FadeOutUp } from 'react-native-reanimated';
|
import Animated, { FadeInDown, FadeOutUp } from 'react-native-reanimated';
|
||||||
import LiveAuctionTile from './LiveAuctionTile';
|
import LiveAuctionTile from './LiveAuctionTile';
|
||||||
import { useNavigation } from '@react-navigation/native';
|
|
||||||
import { useFetchLiveAuction } from '../../Services/BBPS/Hooks';
|
import { useFetchLiveAuction } from '../../Services/BBPS/Hooks';
|
||||||
import { SearchInput } from '../../Component/Serach/SeacrhInput';
|
import { SearchInput } from '../../Component/Serach/SeacrhInput';
|
||||||
import { Skelton } from '../../Component/Index';
|
import { Skelton } from '../../Component/Index';
|
||||||
import colors from '../../Constant/Color';
|
import colors from '../../Constant/Color';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { selectPurchaseAuctionSlice, togglePurchaseAuction } from '../../Redux/Slices/selectPurchaseAuction';
|
import { togglePurchaseAuction } from '../../Redux/Slices/selectPurchaseAuction';
|
||||||
import { apiCall } from '../../Axios/Axios';
|
import { apiCall } from '../../Axios/Axios';
|
||||||
import { GET_MY_AUCTION, LIVE_AUCTION } from '../../Services/BBPS/ApiUrls';
|
import { GET_MY_AUCTION } from '../../Services/BBPS/ApiUrls';
|
||||||
import moment from 'moment';
|
|
||||||
|
|
||||||
const LiveAuction = () => {
|
const LiveAuction = () => {
|
||||||
const navigation: any = useNavigation();
|
|
||||||
const Dispatch = useDispatch()
|
const Dispatch = useDispatch()
|
||||||
|
const onEndReachedCalledDuringMomentum = useRef(true);
|
||||||
const SelectedPurchaseList = useSelector((state: any) => state.selectPurchaseAuction);
|
const SelectedPurchaseList = useSelector((state: any) => state.selectPurchaseAuction);
|
||||||
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, isRefetching, refetch }: any = useFetchLiveAuction();
|
|
||||||
const [showRefreshBanner, setShowRefreshBanner] = useState(false);
|
const [showRefreshBanner, setShowRefreshBanner] = useState(false);
|
||||||
const [allBoolean, setAllBoolean] = useState({ liveAuctionData: [] })
|
const [allBoolean, setAllBoolean] = useState({ liveAuctionData: [] })
|
||||||
|
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, isRefetching, refetch, isPending }: any = useFetchLiveAuction();
|
||||||
|
|
||||||
useEffect(() => {
|
// My Methods
|
||||||
if (isRefetching) {
|
|
||||||
setShowRefreshBanner(true);
|
|
||||||
} else {
|
|
||||||
const timer = setTimeout(() => {
|
|
||||||
setShowRefreshBanner(false);
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
return () => clearTimeout(timer);
|
const getMyAuction = async () => {
|
||||||
|
try {
|
||||||
|
const res = await apiCall<any>('get', `${GET_MY_AUCTION}`,);
|
||||||
|
if (res?.statusCode === 200) {
|
||||||
|
const purchasedIds = new Set(res.data.map((item: any) => item.auctionId));
|
||||||
|
const filteredLive = data?.result.map((item: any) => ({ ...item, active: !purchasedIds.has(item.auctionId) }));
|
||||||
|
setAllBoolean(prev => ({ ...prev, liveAuctionData: filteredLive }));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('getMyAuction error', error);
|
||||||
|
} finally {
|
||||||
|
setAllBoolean(prev => ({ ...prev, isLoading: false }));
|
||||||
}
|
}
|
||||||
}, [isRefetching]);
|
};
|
||||||
|
|
||||||
const loadMore = useCallback(() => {
|
|
||||||
if (hasNextPage && !isFetchingNextPage) {
|
|
||||||
fetchNextPage();
|
|
||||||
}
|
|
||||||
}, [hasNextPage, isFetchingNextPage]);
|
|
||||||
|
|
||||||
const renderFooter = useCallback(() => {
|
|
||||||
if (!isFetchingNextPage) return null;
|
|
||||||
return (
|
|
||||||
<View style={{ paddingVertical: 12 }}>
|
|
||||||
<ActivityIndicator size="small" color={colors.primary} />
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}, [isFetchingNextPage]);
|
|
||||||
|
|
||||||
const renderItem = useCallback(
|
const renderItem = useCallback(
|
||||||
({ item, index }: any) => {
|
({ item, index }: any) => {
|
||||||
@@ -68,32 +56,35 @@ const LiveAuction = () => {
|
|||||||
[SelectedPurchaseList]
|
[SelectedPurchaseList]
|
||||||
);
|
);
|
||||||
|
|
||||||
const getMyAuction = async () => {
|
const loadMore = useCallback(() => {
|
||||||
try {
|
if (onEndReachedCalledDuringMomentum.current) return;
|
||||||
|
|
||||||
const res = await apiCall<any>('get', `${GET_MY_AUCTION}`,);
|
if (!hasNextPage || isFetchingNextPage) return;
|
||||||
|
|
||||||
if (res?.statusCode === 200) {
|
fetchNextPage();
|
||||||
const purchasedIds = new Set(
|
onEndReachedCalledDuringMomentum.current = true;
|
||||||
res.data.map((item: any) => item.auctionId),
|
}, [hasNextPage, isFetchingNextPage, fetchNextPage]);
|
||||||
);
|
|
||||||
|
|
||||||
const filteredLive = data?.result.map((item: any) => ({
|
const renderFooter = useCallback(() => {
|
||||||
...item,
|
if (!isFetchingNextPage) return null;
|
||||||
active: !purchasedIds.has(item.auctionId), // false if match, true otherwise
|
return (
|
||||||
}));
|
<View style={{ paddingVertical: 12 }}>
|
||||||
|
<ActivityIndicator size="small" color={colors.primary} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}, [isFetchingNextPage]);
|
||||||
|
|
||||||
setAllBoolean(prev => ({
|
useEffect(() => {
|
||||||
...prev,
|
if (isRefetching) {
|
||||||
liveAuctionData: filteredLive
|
setShowRefreshBanner(true);
|
||||||
}));
|
} else {
|
||||||
}
|
const timer = setTimeout(() => {
|
||||||
} catch (error) {
|
setShowRefreshBanner(false);
|
||||||
console.error('getMyAuction error', error);
|
}, 1000);
|
||||||
} finally {
|
|
||||||
setAllBoolean(prev => ({ ...prev, isLoading: false }));
|
return () => clearTimeout(timer);
|
||||||
}
|
}
|
||||||
};
|
}, [isRefetching]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data?.result?.length > 0) {
|
if (data?.result?.length > 0) {
|
||||||
@@ -148,27 +139,34 @@ const LiveAuction = () => {
|
|||||||
|
|
||||||
<FlatList
|
<FlatList
|
||||||
data={allBoolean.liveAuctionData ?? []}
|
data={allBoolean.liveAuctionData ?? []}
|
||||||
keyExtractor={(item: any) => String(item.auctionNumber)}
|
|
||||||
renderItem={renderItem}
|
renderItem={renderItem}
|
||||||
showsVerticalScrollIndicator={false}
|
showsVerticalScrollIndicator={false}
|
||||||
contentContainerStyle={{ paddingBottom: 50, paddingTop: 10 }}
|
contentContainerStyle={{ paddingBottom: 50, paddingTop: 10 }}
|
||||||
|
|
||||||
onEndReached={loadMore}
|
onEndReached={loadMore}
|
||||||
onEndReachedThreshold={0.2}
|
onEndReachedThreshold={0.1}
|
||||||
|
|
||||||
|
onMomentumScrollBegin={() => {
|
||||||
|
onEndReachedCalledDuringMomentum.current = false;
|
||||||
|
}}
|
||||||
|
|
||||||
ListFooterComponent={renderFooter}
|
ListFooterComponent={renderFooter}
|
||||||
|
|
||||||
refreshControl={
|
refreshControl={
|
||||||
<RefreshControl
|
<RefreshControl
|
||||||
refreshing={isRefetching}
|
refreshing={isRefetching}
|
||||||
onRefresh={refetch}
|
onRefresh={refetch}
|
||||||
tintColor="transparent" // Set to transparent if you only want your custom banner to show
|
tintColor="transparent"
|
||||||
colors={[colors.primary]}
|
colors={[colors.primary]}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|
||||||
initialNumToRender={6}
|
initialNumToRender={6}
|
||||||
maxToRenderPerBatch={6}
|
maxToRenderPerBatch={6}
|
||||||
windowSize={7}
|
windowSize={7}
|
||||||
removeClippedSubviews
|
removeClippedSubviews
|
||||||
updateCellsBatchingPeriod={50}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ const LiveAuctionTile: React.FC<LiveAuctionTileProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.cardWrapper}>
|
<View style={styles.cardWrapper}>
|
||||||
{/* Status Tag */}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
!showDetail ?
|
!showDetail ?
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { memo, useState } from 'react';
|
import React, { memo, useEffect, useState } from 'react';
|
||||||
import { View, Text, StyleSheet, TouchableOpacity, ScrollView, SafeAreaView, Platform, StatusBar } from 'react-native';
|
import { View, Text, StyleSheet, TouchableOpacity, ScrollView, SafeAreaView, Platform, StatusBar } from 'react-native';
|
||||||
import Modal from 'react-native-modal';
|
import Modal from 'react-native-modal';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
@@ -6,26 +6,29 @@ import { Briefcase, Calendar, FileText, Download, Eye, Layers, ArrowLeft, Clock
|
|||||||
import colors from '../../../Constant/Color';
|
import colors from '../../../Constant/Color';
|
||||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
import AuctionItemDetail from './AuctionItemDetail';
|
import AuctionItemDetail from './AuctionItemDetail';
|
||||||
|
import { useAucitonDocDownload, useAuctionItem, useGetAuciton, useGetAucitonDocument } from '../../../Services/BBPS/Hooks';
|
||||||
|
import ReactNativeBlobUtil from 'react-native-blob-util';
|
||||||
|
import { AUCTION_DOCUMENT_DOWNLOAD, ITEM_DOCUMENT_DOWNLOAD } from '../../../Services/BBPS/ApiUrls';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import { Loader } from '../../../Component/Index';
|
||||||
|
|
||||||
interface Props {
|
interface Props { visible: boolean; onClose: () => void; data?: any }
|
||||||
visible: boolean;
|
|
||||||
onClose: () => void;
|
|
||||||
data?: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
const AuctionFullDetail: React.FC<Props> = ({ visible, onClose, data }) => {
|
const AuctionFullDetail: React.FC<Props> = ({ visible, onClose, data }) => {
|
||||||
const inset = useSafeAreaInsets()
|
const inset = useSafeAreaInsets()
|
||||||
const [allBoolean, setAllBoolean] = useState({ showItemDetail: false })
|
const { data: auctionData, isLoading } = useGetAuciton({ auctionId: data?.auctionId })
|
||||||
|
const [aucitonDetail, setAuciotnDetail] = useState<any>(auctionData)
|
||||||
|
const [allBoolean, setAllBoolean] = useState({ showItemDetail: false, selectedItem: {}, fileLoading: false });
|
||||||
|
const { data: auctionDocuments } = useGetAucitonDocument({ auctionId: data?.auctionId })
|
||||||
|
const { mutate: downloadDocument, isPending } = useAucitonDocDownload()
|
||||||
|
const { mutate } = useAuctionItem()
|
||||||
const formatDate = (date?: string) => {
|
const formatDate = (date?: string) => {
|
||||||
if (!date) return '-';
|
if (!date) return '-';
|
||||||
return moment(date, 'DD-MM-YYYY HH:mm:ss').format('DD MMM YYYY, hh:mm A');
|
return moment(date, 'DD-MM-YYYY HH:mm:ss').format('DD MMM YYYY, hh:mm A');
|
||||||
};
|
};
|
||||||
|
|
||||||
const isLive = data?.purchaseEnd
|
const isLive = data?.purchaseEnd ? moment().isBefore(moment(data.purchaseEnd, 'DD-MM-YYYY HH:mm:ss')) : false;
|
||||||
? moment().isBefore(moment(data.purchaseEnd, 'DD-MM-YYYY HH:mm:ss'))
|
|
||||||
: false;
|
|
||||||
|
|
||||||
// Internal Components
|
|
||||||
const Section = ({ title, icon: Icon, children }: any) => (
|
const Section = ({ title, icon: Icon, children }: any) => (
|
||||||
<View style={styles.sectionContainer}>
|
<View style={styles.sectionContainer}>
|
||||||
<View style={styles.sectionHeader}>
|
<View style={styles.sectionHeader}>
|
||||||
@@ -43,6 +46,64 @@ const AuctionFullDetail: React.FC<Props> = ({ visible, onClose, data }) => {
|
|||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const handleDownload = async (id: number, fileName: string) => {
|
||||||
|
try {
|
||||||
|
setAllBoolean((prev: any) => ({ ...prev, fileLoading: true }));
|
||||||
|
const { dirs } = ReactNativeBlobUtil.fs;
|
||||||
|
|
||||||
|
// ✅ PUBLIC DOWNLOADS DIRECTORY
|
||||||
|
const path = `${dirs.DownloadDir}/${fileName}.pdf`;
|
||||||
|
|
||||||
|
console.log('📂 Saving to:', path);
|
||||||
|
|
||||||
|
const downloadUrl = `${AUCTION_DOCUMENT_DOWNLOAD}?documentId=${id}&isAmendment=false`;
|
||||||
|
console.log('🌐 Download URL:', downloadUrl);
|
||||||
|
|
||||||
|
const response = await ReactNativeBlobUtil.config({
|
||||||
|
fileCache: false, // important for public folder
|
||||||
|
addAndroidDownloads: {
|
||||||
|
useDownloadManager: true,
|
||||||
|
notification: true,
|
||||||
|
path,
|
||||||
|
mime: 'application/pdf',
|
||||||
|
title: `${fileName}.pdf`,
|
||||||
|
description: 'Downloading document',
|
||||||
|
mediaScannable: true, // 👈 makes it visible instantly
|
||||||
|
},
|
||||||
|
}).fetch('GET', downloadUrl, {
|
||||||
|
Accept: 'application/pdf',
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('✅ Download completed');
|
||||||
|
console.log('📦 Status:', response.info().status);
|
||||||
|
console.log('📦 Headers:', response.info().headers);
|
||||||
|
console.log('📍 Saved at:', path);
|
||||||
|
|
||||||
|
const stat = await ReactNativeBlobUtil.fs.stat(path);
|
||||||
|
console.log('📦 File size:', stat.size);
|
||||||
|
|
||||||
|
} catch (error: any) {
|
||||||
|
console.log('❌ Download failed');
|
||||||
|
console.log('❌ Error:', error?.message || error);
|
||||||
|
} finally {
|
||||||
|
setAllBoolean((prev: any) => ({ ...prev, fileLoading: false }));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
mutate({ auctionNumber: data?.auctionNumber, status: data?.auctionPattern }, {
|
||||||
|
onSuccess: (res) => {
|
||||||
|
setAuciotnDetail((prev: any) => ({ ...prev, auctionItems: res.data, auctionDocuments }))
|
||||||
|
}, onError: (err) => {
|
||||||
|
console.log(err, '-----auction item error');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [data.auctionNumber, auctionDocuments]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
isVisible={visible}
|
isVisible={visible}
|
||||||
@@ -94,12 +155,11 @@ const AuctionFullDetail: React.FC<Props> = ({ visible, onClose, data }) => {
|
|||||||
{/* 2. Work Description */}
|
{/* 2. Work Description */}
|
||||||
<Section title="Auction Details" icon={Briefcase}>
|
<Section title="Auction Details" icon={Briefcase}>
|
||||||
<View style={styles.grid}>
|
<View style={styles.grid}>
|
||||||
<InfoBox label="Auction Name" value={'Auction of cars'} />
|
<InfoBox label="Auction Name" value={auctionData?.auctionOfWork} />
|
||||||
<InfoBox label="Category Of Auction " value={'Live'} />
|
<InfoBox label="Category Of Auction " value={auctionData?.auctionCategories} />
|
||||||
<InfoBox label="Auto Time Increment " value={'yes'} />
|
<InfoBox label="Auction Fees (In Figure) " value={auctionData?.auctionFees} />
|
||||||
<InfoBox label="Auction Fees (In Figure) " value={'500'} />
|
<InfoBox label="Auction Fees (In Words)" value={auctionData?.auctionFeesInWord} />
|
||||||
<InfoBox label="Auction Fees (In Words)" value={'Five Hundred'} />
|
<InfoBox label="Auction Keyword" value={auctionData?.auctionKeywordName} />
|
||||||
<InfoBox label="Auction Keyword" value={'Dev Furniture, Furnture'} />
|
|
||||||
</View>
|
</View>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
@@ -129,68 +189,55 @@ const AuctionFullDetail: React.FC<Props> = ({ visible, onClose, data }) => {
|
|||||||
<View style={styles.tableWrapper}>
|
<View style={styles.tableWrapper}>
|
||||||
<View style={styles.tableHead}>
|
<View style={styles.tableHead}>
|
||||||
<Text style={[styles.tableLabel, { flex: 2 }]}>Item</Text>
|
<Text style={[styles.tableLabel, { flex: 2 }]}>Item</Text>
|
||||||
<Text style={styles.tableLabel}>Qty</Text>
|
<Text style={styles.tableLabel}>Time</Text>
|
||||||
<Text style={[styles.tableLabel, { textAlign: 'right' }]}>View</Text>
|
<Text style={[styles.tableLabel, { textAlign: 'right' }]}>View</Text>
|
||||||
</View>
|
</View>
|
||||||
{/* Dummy Item Row */}
|
{/* Dummy Item Row */}
|
||||||
<View style={styles.tableRow}>
|
{aucitonDetail?.auctionItems?.map((item: any, index: number) => (
|
||||||
<View style={{ flex: 2 }}>
|
<View style={styles.tableRow}>
|
||||||
<Text style={styles.itemMain}>Sick Sari / Laundry</Text>
|
<View style={{ flex: 2 }}>
|
||||||
<Text style={styles.itemSub}>Category: Sari</Text>
|
<Text style={styles.itemMain}>{item.productName}</Text>
|
||||||
|
<Text style={styles.itemSub}>Category: {item?.categoryName}</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.itemQty}>{item.timeDurationType}</Text>
|
||||||
|
<TouchableOpacity style={styles.actionIcon} onPress={() => { setAllBoolean((prev: any) => ({ ...prev, showItemDetail: true, selectedItem: item })) }}>
|
||||||
|
<Eye size={18} color={colors.primary} />
|
||||||
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
<Text style={styles.itemQty}>120,000</Text>
|
))}
|
||||||
<TouchableOpacity style={styles.actionIcon} onPress={() => { setAllBoolean((prev: any) => ({ ...prev, showItemDetail: true })) }}>
|
|
||||||
<Eye size={18} color={colors.primary} />
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
{/* 5. Downloads */}
|
{/* 5. Downloads */}
|
||||||
<Section title="Downloads" icon={Download}>
|
<Section title="Downloads" icon={Download}>
|
||||||
<TouchableOpacity style={styles.fileCard}>
|
{aucitonDetail?.auctionDocuments?.map((doc: any, index: number) => (
|
||||||
<View style={styles.fileIcon}><FileText size={20} color="#ef4444" /></View>
|
<TouchableOpacity style={styles.fileCard} onPress={() => {
|
||||||
<View style={{ flex: 1 }}>
|
handleDownload(
|
||||||
<Text style={styles.fileName}>Auction_Notice_Main.pdf</Text>
|
doc.auctionDocumentId,
|
||||||
<Text style={styles.fileSize}>1.2 MB • PDF</Text>
|
doc.fileName.replace('.pdf', '')
|
||||||
</View>
|
)
|
||||||
<Download size={20} color="#94a3b8" />
|
}}>
|
||||||
</TouchableOpacity>
|
<View style={styles.fileIcon}><FileText size={20} color="#ef4444" /></View>
|
||||||
|
<View style={{ flex: 1 }}>
|
||||||
|
<Text style={styles.fileName}>{doc.fileName}</Text>
|
||||||
|
</View>
|
||||||
|
{allBoolean.fileLoading ? (
|
||||||
|
<View >
|
||||||
|
<Loader size='small' color='#94a3b8' />
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
<Download size={20} color="#94a3b8" />
|
||||||
|
)}
|
||||||
|
|
||||||
|
</TouchableOpacity>
|
||||||
|
))}
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
{/* Sticky Footer */}
|
{allBoolean.showItemDetail && <AuctionItemDetail data={allBoolean.selectedItem} onClose={() => { setAllBoolean((prev: any) => ({ ...prev, showItemDetail: false })) }} visible={allBoolean.showItemDetail} />}
|
||||||
<View style={styles.footer}>
|
|
||||||
<TouchableOpacity
|
|
||||||
style={[styles.mainBtn, !isLive && styles.btnDisabled]}
|
|
||||||
disabled={!isLive}
|
|
||||||
>
|
|
||||||
<Text style={styles.mainBtnText}>
|
|
||||||
{isLive ? 'Add to Cart / Purchase' : 'Auction Closed'}
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<AuctionItemDetail
|
|
||||||
data={{
|
|
||||||
productName: "sick sari",
|
|
||||||
timeDuration: "112 YEAR",
|
|
||||||
category: "laundry",
|
|
||||||
subCategory: "sari",
|
|
||||||
reservePriceFig: "120000",
|
|
||||||
reservePriceWords: "One Lakh Twenty Thousand",
|
|
||||||
auctionStartFig: "120000",
|
|
||||||
auctionStartWords: "One Lakh Twenty Thousand",
|
|
||||||
bidVariationFig: "200",
|
|
||||||
bidVariationWords: "Two Hundred",
|
|
||||||
emdFig: "2000",
|
|
||||||
emdWords: "Two Thousand",
|
|
||||||
description: "Auction of cars",
|
|
||||||
documentName: "BBPS screens.pdf"
|
|
||||||
}} onClose={() => { setAllBoolean((prev: any) => ({ ...prev, showItemDetail: false })) }} visible={allBoolean.showItemDetail} />
|
|
||||||
</View>
|
</View>
|
||||||
</Modal>
|
</Modal >
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -242,7 +289,7 @@ const styles = StyleSheet.create({
|
|||||||
liveText: { fontSize: 11, fontWeight: '800', color: '#475569' },
|
liveText: { fontSize: 11, fontWeight: '800', color: '#475569' },
|
||||||
|
|
||||||
scrollView: { flex: 1, backgroundColor: '#f8fafc' },
|
scrollView: { flex: 1, backgroundColor: '#f8fafc' },
|
||||||
scrollContent: { padding: 16, paddingBottom: 100 },
|
scrollContent: { padding: 16, paddingBottom: 30 },
|
||||||
|
|
||||||
sectionContainer: {
|
sectionContainer: {
|
||||||
backgroundColor: '#fff',
|
backgroundColor: '#fff',
|
||||||
|
|||||||
@@ -1,79 +1,84 @@
|
|||||||
import React, { memo } from 'react';
|
import React, { memo, useState } from 'react';
|
||||||
import {
|
import { View, Text, StyleSheet, TouchableOpacity, ScrollView, Platform } from 'react-native';
|
||||||
View,
|
|
||||||
Text,
|
|
||||||
StyleSheet,
|
|
||||||
TouchableOpacity,
|
|
||||||
ScrollView,
|
|
||||||
SafeAreaView,
|
|
||||||
Platform,
|
|
||||||
StatusBar,
|
|
||||||
Dimensions
|
|
||||||
} from 'react-native';
|
|
||||||
import Modal from 'react-native-modal';
|
import Modal from 'react-native-modal';
|
||||||
import {
|
import { Package, IndianRupee, FileText, Download, ArrowLeft, Info, } from 'lucide-react-native';
|
||||||
X,
|
|
||||||
Package,
|
|
||||||
Clock,
|
|
||||||
Tag,
|
|
||||||
IndianRupee,
|
|
||||||
FileText,
|
|
||||||
Download,
|
|
||||||
ArrowLeft,
|
|
||||||
Info,
|
|
||||||
Layers,
|
|
||||||
ChevronRight
|
|
||||||
} from 'lucide-react-native';
|
|
||||||
import colors from '../../../Constant/Color';
|
import colors from '../../../Constant/Color';
|
||||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
|
import { useAucitonItemDetail } from '../../../Services/BBPS/Hooks';
|
||||||
|
import ReactNativeBlobUtil from 'react-native-blob-util';
|
||||||
|
import { AUCTION_ITEM_DOCUMENT_DOWNLOAD } from '../../../Services/BBPS/ApiUrls';
|
||||||
|
import { Loader } from '../../../Component/Index';
|
||||||
|
|
||||||
const { width } = Dimensions.get('window');
|
interface Props { visible: boolean; onClose: () => void; data?: any; }
|
||||||
|
|
||||||
// --- Exact Dummy Data Mapping ---
|
const Section = ({ title, icon: Icon, children }: any) => (
|
||||||
const ITEM_DUMMY_DATA = {
|
<View style={styles.sectionCard}>
|
||||||
productName: "sick sari",
|
<View style={styles.sectionHeader}>
|
||||||
timeDuration: "112 YEAR",
|
<View style={styles.iconCircle}>
|
||||||
category: "laundry",
|
<Icon size={18} color={colors.primary} strokeWidth={2.5} />
|
||||||
subCategory: "sari",
|
|
||||||
reservePriceFig: "120000",
|
|
||||||
reservePriceWords: "One Lakh Twenty Thousand",
|
|
||||||
auctionStartFig: "120000",
|
|
||||||
auctionStartWords: "One Lakh Twenty Thousand",
|
|
||||||
bidVariationFig: "200",
|
|
||||||
bidVariationWords: "Two Hundred",
|
|
||||||
emdFig: "2000",
|
|
||||||
emdWords: "Two Thousand",
|
|
||||||
description: "Auction of cars",
|
|
||||||
documentName: "BBPS screens.pdf"
|
|
||||||
};
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
visible: boolean;
|
|
||||||
onClose: () => void;
|
|
||||||
data?: typeof ITEM_DUMMY_DATA;
|
|
||||||
}
|
|
||||||
|
|
||||||
const AuctionItemDetail: React.FC<Props> = ({ visible, onClose, data = ITEM_DUMMY_DATA }) => {
|
|
||||||
const inset = useSafeAreaInsets()
|
|
||||||
const Section = ({ title, icon: Icon, children }: any) => (
|
|
||||||
<View style={styles.sectionCard}>
|
|
||||||
<View style={styles.sectionHeader}>
|
|
||||||
<View style={styles.iconCircle}>
|
|
||||||
<Icon size={18} color={colors.primary} strokeWidth={2.5} />
|
|
||||||
</View>
|
|
||||||
<Text style={styles.sectionTitle}>{title}</Text>
|
|
||||||
</View>
|
</View>
|
||||||
{children}
|
<Text style={styles.sectionTitle}>{title}</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
{children}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
const PriceTile = ({ label, fig, words, full = false }: any) => (
|
const PriceTile = ({ label, fig, words, full = false }: any) => (
|
||||||
<View style={[styles.priceTile, full ? { width: '100%' } : { width: '48%' }]}>
|
<View style={[styles.priceTile, full ? { width: '100%' } : { width: '48%' }]}>
|
||||||
<Text style={styles.label}>{label}</Text>
|
<Text style={styles.label}>{label}</Text>
|
||||||
<Text style={styles.priceFig}>₹{Number(fig).toLocaleString('en-IN')}</Text>
|
<Text style={styles.priceFig}>₹{Number(fig).toLocaleString('en-IN')}</Text>
|
||||||
<Text style={styles.priceWords}>{words}</Text>
|
<Text style={styles.priceWords}>{words}</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
const AuctionItemDetail: React.FC<Props> = ({ visible, onClose, data }) => {
|
||||||
|
const inset = useSafeAreaInsets()
|
||||||
|
const [allBoolean, setAllBoolean] = useState({ fileLoading: false });
|
||||||
|
const { data: itemData } = useAucitonItemDetail({ auctionItemId: data.id });
|
||||||
|
|
||||||
|
const handleDownload = async (id: number, fileName: string) => {
|
||||||
|
try {
|
||||||
|
setAllBoolean((prev: any) => ({ ...prev, fileLoading: true }));
|
||||||
|
const { dirs } = ReactNativeBlobUtil.fs;
|
||||||
|
|
||||||
|
// ✅ PUBLIC DOWNLOADS DIRECTORY
|
||||||
|
const path = `${dirs.DownloadDir}/${fileName}.pdf`;
|
||||||
|
|
||||||
|
console.log('📂 Saving to:', path);
|
||||||
|
|
||||||
|
const downloadUrl = `${AUCTION_ITEM_DOCUMENT_DOWNLOAD}?auctionItemId=${id}`;
|
||||||
|
console.log('🌐 Download URL:', downloadUrl);
|
||||||
|
|
||||||
|
const response = await ReactNativeBlobUtil.config({
|
||||||
|
fileCache: false, // important for public folder
|
||||||
|
addAndroidDownloads: {
|
||||||
|
useDownloadManager: true,
|
||||||
|
notification: true,
|
||||||
|
path,
|
||||||
|
mime: 'application/pdf',
|
||||||
|
title: `${fileName}.pdf`,
|
||||||
|
description: 'Downloading document',
|
||||||
|
mediaScannable: true, // 👈 makes it visible instantly
|
||||||
|
},
|
||||||
|
}).fetch('GET', downloadUrl, {
|
||||||
|
Accept: 'application/pdf',
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('✅ Download completed');
|
||||||
|
console.log('📦 Status:', response.info().status);
|
||||||
|
console.log('📦 Headers:', response.info().headers);
|
||||||
|
console.log('📍 Saved at:', path);
|
||||||
|
|
||||||
|
const stat = await ReactNativeBlobUtil.fs.stat(path);
|
||||||
|
console.log('📦 File size:', stat.size);
|
||||||
|
|
||||||
|
} catch (error: any) {
|
||||||
|
console.log('❌ Download failed');
|
||||||
|
console.log('❌ Error:', error?.message || error);
|
||||||
|
} finally {
|
||||||
|
setAllBoolean((prev: any) => ({ ...prev, fileLoading: false }));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
console.log(data, 'kkkkk---');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
@@ -106,72 +111,76 @@ const AuctionItemDetail: React.FC<Props> = ({ visible, onClose, data = ITEM_DUMM
|
|||||||
contentContainerStyle={styles.scrollContent}
|
contentContainerStyle={styles.scrollContent}
|
||||||
showsVerticalScrollIndicator={false}
|
showsVerticalScrollIndicator={false}
|
||||||
>
|
>
|
||||||
{/* Product Identity Card */}
|
|
||||||
<Section title="Product Specification" icon={Package}>
|
<Section title="Product Specification" icon={Package}>
|
||||||
<View style={styles.identityHeader}>
|
<View style={styles.identityHeader}>
|
||||||
<Text style={styles.productNameText}>{data.productName.toUpperCase()}</Text>
|
<Text style={styles.productNameText}>{data.productName.toUpperCase()}</Text>
|
||||||
<View style={styles.categoryBadge}>
|
<View style={styles.categoryBadge}>
|
||||||
<Text style={styles.categoryText}>{data.category}</Text>
|
<Text style={styles.categoryText}>{data.categoryName}</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={styles.specGrid}>
|
<View style={styles.specGrid}>
|
||||||
<View style={styles.specItem}>
|
<View style={styles.specItem}>
|
||||||
<Text style={styles.label}>Sub Category</Text>
|
<Text style={styles.label}>Sub Category</Text>
|
||||||
<Text style={styles.specValue}>{data.subCategory}</Text>
|
<Text style={styles.specValue}>{data.subCategoryName}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.specItem}>
|
<View style={styles.specItem}>
|
||||||
<Text style={styles.label}>Duration</Text>
|
<Text style={styles.label}>Duration</Text>
|
||||||
<Text style={styles.specValue}>{data.timeDuration}</Text>
|
<Text style={styles.specValue}>{data.timeDurationType}</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
{/* Pricing & Financials */}
|
|
||||||
<Section title="Reserve & Bid Values" icon={IndianRupee}>
|
<Section title="Reserve & Bid Values" icon={IndianRupee}>
|
||||||
<PriceTile
|
<PriceTile
|
||||||
label="Reserve Price"
|
label="Bidding Price"
|
||||||
fig={data.reservePriceFig}
|
fig={data.reservePrice || data.emdAmount}
|
||||||
words={data.reservePriceWords}
|
words={data.reservePriceInWords || data.emdAmountInWords}
|
||||||
full
|
full
|
||||||
/>
|
/>
|
||||||
<View style={styles.hDivider} />
|
<View style={styles.hDivider} />
|
||||||
<PriceTile
|
<PriceTile
|
||||||
label="Auction Start Value"
|
label="Auction Start Value"
|
||||||
fig={data.auctionStartFig}
|
fig={data.reservePrice || data.auctionStartValueFigure}
|
||||||
words={data.auctionStartWords}
|
words={data.reservePriceInWords || data.auctionStartValueWords}
|
||||||
full
|
full
|
||||||
/>
|
/>
|
||||||
<View style={styles.hDivider} />
|
<View style={styles.hDivider} />
|
||||||
<View style={styles.row}>
|
{/* <View style={styles.row}>
|
||||||
<PriceTile label="Bid Variation" fig={data.bidVariationFig} words={data.bidVariationWords} />
|
<PriceTile label="Bid Variation" fig={data.bidVariationFig} words={data.bidVariationWords} />
|
||||||
<PriceTile label="EMD Amount" fig={data.emdFig} words={data.emdWords} />
|
<PriceTile label="Auction Start Value" fig={data.auctionStartValue} words={data.auctionStartValueInWords
|
||||||
</View>
|
} />
|
||||||
|
</View> */}
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
{/* Description Card */}
|
|
||||||
<Section title="Brief Description" icon={Info}>
|
<Section title="Brief Description" icon={Info}>
|
||||||
<Text style={styles.descContent}>{data.description}</Text>
|
<Text style={styles.descContent}>{data.briefDescription}</Text>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
{/* Documents Card */}
|
{itemData?.length && <Section title="View Documents" icon={FileText}>
|
||||||
<Section title="View Documents" icon={FileText}>
|
|
||||||
<View style={styles.docTableHead}>
|
<View style={styles.docTableHead}>
|
||||||
<Text style={styles.tableLabel}>Sr No.</Text>
|
<Text style={styles.tableLabel}>Sr No.</Text>
|
||||||
<Text style={[styles.tableLabel, { flex: 2 }]}>Document Name</Text>
|
<Text style={[styles.tableLabel, { flex: 2 }]}>Document Name</Text>
|
||||||
<Text style={styles.tableLabel}>Action</Text>
|
<Text style={styles.tableLabel}>Action</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<TouchableOpacity style={styles.docRow} activeOpacity={0.7}>
|
{itemData?.map((doc: any, index: any) => (
|
||||||
<Text style={styles.docIndex}>1</Text>
|
<TouchableOpacity style={styles.docRow} activeOpacity={0.7} onPress={() => { handleDownload(doc.assetId, doc.fileName) }} key={doc.assetId}>
|
||||||
<View style={{ flex: 2 }}>
|
<Text style={styles.docIndex}>{index + 1}</Text>
|
||||||
<Text style={styles.docTitle} numberOfLines={1}>{data.documentName}</Text>
|
<View style={{ flex: 2 }}>
|
||||||
</View>
|
<Text style={styles.docTitle} numberOfLines={1}>{doc.fileName}</Text>
|
||||||
<View style={styles.downloadIconBox}>
|
</View>
|
||||||
<Download size={18} color={colors.primary} />
|
<View style={styles.downloadIconBox}>
|
||||||
</View>
|
{allBoolean.fileLoading ? (
|
||||||
</TouchableOpacity>
|
<View >
|
||||||
</Section>
|
<Loader size='small' color='#94a3b8' />
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
<Download size={20} color={colors.primary} />
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>))}
|
||||||
|
</Section>}
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { View, Text, FlatList, StyleSheet, TouchableOpacity, Alert } from 'react-native';
|
import { View, Text, FlatList, StyleSheet, TouchableOpacity, Alert } from 'react-native';
|
||||||
import { InsideHeader, Loader } from '../../Component/Index';
|
import { InsideHeader, Loader } from '../../Component/Index';
|
||||||
import colors from '../../Constant/Color';
|
import colors from '../../Constant/Color';
|
||||||
import { CreditCard, Calendar, User, DollarSign, ArrowRight } from 'lucide-react-native';
|
import { CreditCard, Calendar, User, DollarSign, ArrowRight } from 'lucide-react-native';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { useOfflineAuctionPurchase } from '../../Services/BBPS/Hooks';
|
import { useOfflineAuctionPurchase, usePurchaseAuctionList } from '../../Services/BBPS/Hooks';
|
||||||
import { showSuccessAlert } from '../../Constant/ShowDailog';
|
import { showSuccessAlert } from '../../Constant/ShowDailog';
|
||||||
import { clearPurchaseAuction } from '../../Redux/Slices/selectPurchaseAuction';
|
import { clearPurchaseAuction } from '../../Redux/Slices/selectPurchaseAuction';
|
||||||
import { CommonActions, useNavigation } from '@react-navigation/native';
|
import { CommonActions, useFocusEffect, useNavigation } from '@react-navigation/native';
|
||||||
import NavigationString from '../../Constant/NavigationString';
|
import NavigationString from '../../Constant/NavigationString';
|
||||||
|
import Skeleton from '../../Component/Skelton/Skelton';
|
||||||
|
|
||||||
const dummyAuctionList = [
|
const dummyAuctionList = [
|
||||||
{
|
{
|
||||||
@@ -23,40 +24,19 @@ const dummyAuctionList = [
|
|||||||
portalCharge: 100,
|
portalCharge: 100,
|
||||||
payableAmount: 3050,
|
payableAmount: 3050,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
auctionId: 2,
|
|
||||||
auctionNumber: 'AUC-2025-002',
|
|
||||||
auctionPattern: 'Two Stage',
|
|
||||||
auctionDispatchDate: '28 Feb 2025',
|
|
||||||
auctionDispatcherNumber: 'DISP-002',
|
|
||||||
auctionFees: 1800,
|
|
||||||
gst: 18,
|
|
||||||
gstAmount: 324,
|
|
||||||
portalCharge: 80,
|
|
||||||
payableAmount: 2204,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
auctionId: 3,
|
|
||||||
auctionNumber: 'AUC-2025-003',
|
|
||||||
auctionPattern: 'Single Stage',
|
|
||||||
auctionDispatchDate: '01 Mar 2025',
|
|
||||||
auctionDispatcherNumber: 'DISP-003',
|
|
||||||
auctionFees: 3200,
|
|
||||||
gst: 18,
|
|
||||||
gstAmount: 576,
|
|
||||||
portalCharge: 120,
|
|
||||||
payableAmount: 3896,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const PurchaseAuctionList = () => {
|
const PurchaseAuctionList = () => {
|
||||||
const Navigation = useNavigation()
|
const Navigation = useNavigation()
|
||||||
const Dispatch = useDispatch()
|
const Dispatch = useDispatch()
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [list, setList] = useState(dummyAuctionList);
|
const [list, setList] = useState([]);
|
||||||
const SelectedPurchaseList = useSelector((state: any) => state.selectPurchaseAuction);
|
const SelectedPurchaseList = useSelector((state: any) => state.selectPurchaseAuction);
|
||||||
|
|
||||||
|
const LoginUser = useSelector((state: any) => state.token.token);
|
||||||
const { mutate, isPending } = useOfflineAuctionPurchase()
|
const { mutate, isPending } = useOfflineAuctionPurchase()
|
||||||
|
const { mutate: purchaseListMutation, isPending: purchaseListPending } = usePurchaseAuctionList();
|
||||||
|
|
||||||
const calculateTotalAmount = (item: any) => {
|
const calculateTotalAmount = (item: any) => {
|
||||||
const gstAmount =
|
const gstAmount =
|
||||||
(Number(item.auctionFees) + Number(item.portalCharge)) *
|
(Number(item.auctionFees) + Number(item.portalCharge)) *
|
||||||
@@ -69,7 +49,7 @@ const PurchaseAuctionList = () => {
|
|||||||
|
|
||||||
const handleOfflinePurchase = async () => {
|
const handleOfflinePurchase = async () => {
|
||||||
const body = {
|
const body = {
|
||||||
auctionDetails: SelectedPurchaseList.map((b: any) => ({
|
auctionDetails: list.map((b: any) => ({
|
||||||
auctionDispatchDate: b?.auctionDispatchDate,
|
auctionDispatchDate: b?.auctionDispatchDate,
|
||||||
auctionDispatcherNumber: b?.auctionDispatcherNumber,
|
auctionDispatcherNumber: b?.auctionDispatcherNumber,
|
||||||
auctionFees: b?.auctionFees,
|
auctionFees: b?.auctionFees,
|
||||||
@@ -156,16 +136,37 @@ const PurchaseAuctionList = () => {
|
|||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getPurchaseList = () => {
|
||||||
|
const auctionNumbers: string[] = SelectedPurchaseList.map(
|
||||||
|
(item: { auctionNumber: string }) => item.auctionNumber
|
||||||
|
);
|
||||||
|
purchaseListMutation({ auctionNumbers, contractorId: LoginUser.contractorId }, {
|
||||||
|
onSuccess: (res) => {
|
||||||
|
if (res.statusCode == 200) {
|
||||||
|
setList(res.data)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
console.log(error, "=================purchase list error");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
useFocusEffect(
|
||||||
|
React.useCallback(() => {
|
||||||
|
getPurchaseList()
|
||||||
|
}, [SelectedPurchaseList])
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{ flex: 1, backgroundColor: colors.white }}>
|
<View style={{ flex: 1, backgroundColor: colors.white }}>
|
||||||
<InsideHeader title="Purchase List" showArrow />
|
<InsideHeader title="Purchase List" showArrow />
|
||||||
<View style={styles.screen}>
|
<View style={styles.screen}>
|
||||||
<FlatList
|
{purchaseListPending ? <Skeleton /> : <FlatList
|
||||||
data={SelectedPurchaseList}
|
data={list}
|
||||||
renderItem={renderItem}
|
renderItem={renderItem}
|
||||||
keyExtractor={(item) => item.auctionId.toString()}
|
keyExtractor={(item) => item.auctionId.toString()}
|
||||||
contentContainerStyle={styles.container}
|
contentContainerStyle={styles.container}
|
||||||
/>
|
/>}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={styles.bottomButtonContainer}>
|
<View style={styles.bottomButtonContainer}>
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ const PurchaseAuctionTile = ({ item, onPressDetails, onStartBidding, buttonEnabl
|
|||||||
const statusColor = isAuctionEnd ? '#EF4444' : buttonEnable ? colors.primary : '#94A3B8';
|
const statusColor = isAuctionEnd ? '#EF4444' : buttonEnable ? colors.primary : '#94A3B8';
|
||||||
|
|
||||||
const lightStatusBg = isAuctionEnd ? '#FEF2F2' : buttonEnable ? '#EFF6FF' : '#F8FAFC';
|
const lightStatusBg = isAuctionEnd ? '#FEF2F2' : buttonEnable ? '#EFF6FF' : '#F8FAFC';
|
||||||
console.log(item?.keyDates?.auctionBidding?.endDateTime, 'kk');
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{ flex: 1 }}>
|
<View style={{ flex: 1 }}>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const PurchaseList = () => {
|
|||||||
{/* Header */}
|
{/* Header */}
|
||||||
<View style={styles.header}>
|
<View style={styles.header}>
|
||||||
<Text style={styles.heading}>Purchase List</Text>
|
<Text style={styles.heading}>Purchase List</Text>
|
||||||
<Info size={20} color="#0F172A" />
|
{/* <Info size={20} color="#0F172A" /> */}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Cards */}
|
{/* Cards */}
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
import React, { memo, useCallback, useRef } from 'react';
|
import React, { memo, useCallback, useRef, useState } from 'react';
|
||||||
import { View, Text, TouchableOpacity, StyleSheet, Platform } from 'react-native';
|
import { View, Text, TouchableOpacity, StyleSheet, Platform, TextInput, Alert } from 'react-native';
|
||||||
import Animated, { FadeInUp, Layout, interpolate, useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated';
|
import Animated, { FadeInUp, Layout, interpolate, useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated';
|
||||||
import colors from '../../../Constant/Color';
|
import colors from '../../../Constant/Color';
|
||||||
import AuctionItemDetail from '../../Auction/Modal/AuctionItemDetail';
|
import AuctionItemDetail from '../../Auction/Modal/AuctionItemDetail';
|
||||||
import MainStyle from '../../../Styles/MainStyle';
|
import MainStyle from '../../../Styles/MainStyle';
|
||||||
|
import { Loader } from '../../../Component/Index';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import axios from 'axios';
|
||||||
|
import Variables from '../../../Constant/Variable';
|
||||||
|
import { showErrorAlert, showSuccessAlert } from '../../../Constant/ShowDailog';
|
||||||
|
|
||||||
const BiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid, SelectedAuction }: any) => {
|
const BiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid, SelectedAuction, allBoolean, setAllBoolean }: any) => {
|
||||||
const [showDetail, setShowDetail] = React.useState(false);
|
const Token = useSelector((state: any) => state.token.token)
|
||||||
|
const [showDetail, setShowDetail] = useState(false);
|
||||||
|
const [value, setValue] = useState(`${item.bidAmount}`);
|
||||||
|
const [allState, setAllState] = useState({ isLoading: false })
|
||||||
const isMin = bidValue <= item.bidAmount;
|
const isMin = bidValue <= item.bidAmount;
|
||||||
|
|
||||||
// 🔒 Persist expand state safely
|
// 🔒 Persist expand state safely
|
||||||
@@ -26,6 +34,11 @@ const BiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid, Selec
|
|||||||
opacity: interpolate(animation.value, [0, 0.5, 1], [0, 0, 1]),
|
opacity: interpolate(animation.value, [0, 0.5, 1], [0, 0, 1]),
|
||||||
marginTop: interpolate(animation.value, [0, 1], [0, 15]),
|
marginTop: interpolate(animation.value, [0, 1], [0, 15]),
|
||||||
}));
|
}));
|
||||||
|
const bodyStyle2 = useAnimatedStyle(() => ({
|
||||||
|
height: interpolate(animation.value, [0, 1], [0, 100]),
|
||||||
|
opacity: interpolate(animation.value, [0, 0.5, 1], [0, 0, 1]),
|
||||||
|
marginTop: interpolate(animation.value, [0, 1], [0, 15]),
|
||||||
|
}));
|
||||||
|
|
||||||
const arrowStyle = useAnimatedStyle(() => ({
|
const arrowStyle = useAnimatedStyle(() => ({
|
||||||
transform: [
|
transform: [
|
||||||
@@ -34,6 +47,53 @@ const BiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid, Selec
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
}));
|
}));
|
||||||
|
const MAX_VALUE = Number(item.bidAmount);
|
||||||
|
|
||||||
|
const handleChange = (text: string) => {
|
||||||
|
let cleaned = text.replace(/[^0-9.]/g, '');
|
||||||
|
if ((cleaned.match(/\./g) || []).length > 1) return;
|
||||||
|
setValue(cleaned);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const oneTimePlaceBid = async () => {
|
||||||
|
try {
|
||||||
|
if (Number(value) < MAX_VALUE) {
|
||||||
|
showErrorAlert("Enter the greather vlaue to current bid value")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
setAllState((prev: any) => ({ ...prev, isLoading: true }))
|
||||||
|
const payload = {
|
||||||
|
itemId: item.id,
|
||||||
|
bidAmount: Number(value),
|
||||||
|
auctionId: SelectedAuction.auctionId,
|
||||||
|
contractorId: Token.contractorId,
|
||||||
|
fullName: Token.fullName,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const res = await axios.post(
|
||||||
|
`${Variables.socketUrl}bidding/placeBidForAuction`,
|
||||||
|
[payload],
|
||||||
|
{ headers: { Authentication: `Bearer ${Token.token}` } }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (res.data.statusCode === 200) {
|
||||||
|
showSuccessAlert(res.data.message);
|
||||||
|
}
|
||||||
|
setAllBoolean((prev: any) => ({ ...prev, reload: !prev.reload }))
|
||||||
|
} catch (error) {
|
||||||
|
if (axios.isAxiosError(error)) {
|
||||||
|
showErrorAlert(error.response?.data.message)
|
||||||
|
} else {
|
||||||
|
console.log('UNKNOWN ERROR:', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
setAllState((prev: any) => ({ ...prev, isLoading: false }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// console.log(item, 'jkjjj');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
@@ -80,7 +140,7 @@ const BiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid, Selec
|
|||||||
<View style={styles.priceRow}>
|
<View style={styles.priceRow}>
|
||||||
<View>
|
<View>
|
||||||
<Text style={styles.label}>Current Bid</Text>
|
<Text style={styles.label}>Current Bid</Text>
|
||||||
<Text style={styles.mainPrice}>₹{item?.bidAmount}</Text>
|
<Text style={styles.mainPrice}>₹{item?.bidAmount || item.auctionStartValueFigure}</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={{ alignItems: 'flex-end' }}>
|
<View style={{ alignItems: 'flex-end' }}>
|
||||||
@@ -92,12 +152,12 @@ const BiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid, Selec
|
|||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* COLLAPSIBLE BODY */}
|
{/* COLLAPSIBLE BODY */}
|
||||||
<Animated.View style={[styles.collapsibleContainer, bodyStyle]}>
|
<Animated.View style={[styles.collapsibleContainer, (!allBoolean.rebid && item.contractorId == undefined) ? bodyStyle : bodyStyle2]}>
|
||||||
<View style={styles.divider} />
|
<View style={styles.divider} />
|
||||||
|
|
||||||
<Text style={styles.bidLabel}>Set Your Bid</Text>
|
<Text style={styles.bidLabel}>Set Your Bid</Text>
|
||||||
|
|
||||||
<View style={styles.stepperContainer}>
|
{!allBoolean.oneTimeBid && <View style={styles.stepperContainer}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={onDecrease}
|
onPress={onDecrease}
|
||||||
disabled={isMin}
|
disabled={isMin}
|
||||||
@@ -114,16 +174,30 @@ const BiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid, Selec
|
|||||||
<TouchableOpacity onPress={onIncrease} style={styles.stepBtn}>
|
<TouchableOpacity onPress={onIncrease} style={styles.stepBtn}>
|
||||||
<Text style={styles.stepText}>+</Text>
|
<Text style={styles.stepText}>+</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>}
|
||||||
|
{
|
||||||
|
(allBoolean.oneTimeBid || allBoolean.rebid) && <View style={styles.inputBox2}>
|
||||||
|
<Text style={styles.currency2}>₹</Text>
|
||||||
|
|
||||||
<TouchableOpacity
|
<TextInput
|
||||||
style={styles.submitBtn}
|
value={value}
|
||||||
onPress={onPlaceBid}
|
onChangeText={handleChange}
|
||||||
// activeOpacity={0.85}
|
keyboardType="decimal-pad"
|
||||||
|
placeholder="0.00"
|
||||||
|
style={styles.input}
|
||||||
|
placeholderTextColor="#94A3B8"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
}
|
||||||
|
|
||||||
|
{(!allBoolean.rebid && item.contractorId == undefined) ? <TouchableOpacity
|
||||||
|
style={[styles.submitBtn]}
|
||||||
|
onPress={(allBoolean.oneTimeBid || allBoolean.rebid) ? oneTimePlaceBid : onPlaceBid}
|
||||||
>
|
>
|
||||||
<Text style={styles.submitBtnText}>Confirm Bid</Text>
|
{
|
||||||
</TouchableOpacity>
|
allState.isLoading ? <Loader size='small' color={colors.white} /> : <Text style={styles.submitBtnText}>Confirm Bid</Text>
|
||||||
|
}
|
||||||
|
</TouchableOpacity> : null}
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
:
|
:
|
||||||
@@ -135,7 +209,31 @@ const BiddingCard = ({ item, bidValue, onIncrease, onDecrease, onPlaceBid, Selec
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default memo(BiddingCard);
|
export default memo(BiddingCard);
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
inputBox2: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: '#F1F5F9',
|
||||||
|
borderRadius: 12,
|
||||||
|
height: 45,
|
||||||
|
paddingHorizontal: 12,
|
||||||
|
width: '100%',
|
||||||
|
marginBottom: 20
|
||||||
|
},
|
||||||
|
currency2: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#64748B',
|
||||||
|
marginRight: 4,
|
||||||
|
},
|
||||||
|
input: {
|
||||||
|
flex: 1,
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: '700',
|
||||||
|
color: '#0F172A',
|
||||||
|
width: '100%'
|
||||||
|
},
|
||||||
card: {
|
card: {
|
||||||
backgroundColor: '#FFF',
|
backgroundColor: '#FFF',
|
||||||
borderRadius: 24,
|
borderRadius: 24,
|
||||||
|
|||||||
+163
-17
@@ -12,9 +12,12 @@ import { useNavigation } from '@react-navigation/native';
|
|||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { useAuctionItem, useEmdCheck } from '../../Services/BBPS/Hooks';
|
import { useAuctionItem, useEmdCheck } from '../../Services/BBPS/Hooks';
|
||||||
import { apiCall } from '../../Axios/Axios';
|
import { apiCall } from '../../Axios/Axios';
|
||||||
import { AUCTION_ITEM_SUBMIT, CHECK_TECHNICAL_DOCUMENTAION, GET_TECHNICAL_DOCUMENTAION } from '../../Services/BBPS/ApiUrls';
|
import { AUCITON_SINGLE_EMD, AUCTION_ITEM_SUBMIT, CHECK_TECHNICAL_DOCUMENTAION, GET_AUCTION_DETAILS, GET_TECHNICAL_DOCUMENTAION } from '../../Services/BBPS/ApiUrls';
|
||||||
import TemplateFormModal from './Component/TemplateFormModal';
|
import TemplateFormModal from './Component/TemplateFormModal';
|
||||||
import { SelectedItem } from './Type/BidType';
|
import { SelectedItem } from './Type/BidType';
|
||||||
|
import FontsFamily from '../../Constant/FontsFamily';
|
||||||
|
import { all } from 'axios';
|
||||||
|
import { showSuccessAlert } from '../../Constant/ShowDailog';
|
||||||
|
|
||||||
|
|
||||||
const Emd = () => {
|
const Emd = () => {
|
||||||
@@ -22,7 +25,7 @@ const Emd = () => {
|
|||||||
const SelectedAuction = useSelector((state: any) => state.auction.auction)
|
const SelectedAuction = useSelector((state: any) => state.auction.auction)
|
||||||
const [selectedItems, setSelectedItems] = useState<SelectedItem[]>([]);
|
const [selectedItems, setSelectedItems] = useState<SelectedItem[]>([]);
|
||||||
const [acceptedPolicy, setAcceptedPolicy] = useState(false);
|
const [acceptedPolicy, setAcceptedPolicy] = useState(false);
|
||||||
const [allBoolean, setAllBoolean] = useState({ isSubmitEmdLoading: false, isEmdComplete: false, auctionItems: [], technicalDocumentStatus: false, selectTemplate: {}, technicalDocModalVisible: false })
|
const [allBoolean, setAllBoolean]: any = useState({ isSubmitEmdLoading: false, isEmdComplete: false, auctionItems: [], technicalDocumentStatus: false, selectTemplate: {}, technicalDocModalVisible: false, emdType: false, fileName: '', file: {} })
|
||||||
const { mutate } = useEmdCheck()
|
const { mutate } = useEmdCheck()
|
||||||
const { mutate: AuctionItemMutate, isPending } = useAuctionItem()
|
const { mutate: AuctionItemMutate, isPending } = useAuctionItem()
|
||||||
|
|
||||||
@@ -63,8 +66,15 @@ const Emd = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const pickFileSingle = async () => {
|
||||||
|
try {
|
||||||
|
const res = await pick({ type: ['application/pdf'] });
|
||||||
|
const file = res[0];
|
||||||
|
setAllBoolean((prev: any) => ({ ...prev, file: { name: file.name ?? 'document.pdf', uri: file.uri, type: 'application/pdf' } }))
|
||||||
|
} catch {
|
||||||
|
console.log('Pick cancelled');
|
||||||
|
}
|
||||||
|
};
|
||||||
/* ---------------- Render Item ---------------- */
|
/* ---------------- Render Item ---------------- */
|
||||||
const renderItem = ({ item }: any) => {
|
const renderItem = ({ item }: any) => {
|
||||||
const selected = isSelected(item.id);
|
const selected = isSelected(item.id);
|
||||||
@@ -202,15 +212,33 @@ const Emd = () => {
|
|||||||
setAllBoolean((prev: any) => ({ ...prev, isLoading: false }))
|
setAllBoolean((prev: any) => ({ ...prev, isLoading: false }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const getAuction = async () => {
|
||||||
|
const selectedRes = await apiCall<any>('get', GET_AUCTION_DETAILS, {}, { id: SelectedAuction.auctionId });
|
||||||
|
const emdType = String(selectedRes.data.emd)
|
||||||
|
.trim()
|
||||||
|
.replace(/\s+/g, ' ')
|
||||||
|
.toLowerCase();
|
||||||
|
|
||||||
|
|
||||||
|
if (selectedRes.statusCode == 200 && emdType === 'auction wise') {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const AlreadyEmdCheck = async () => {
|
const AlreadyEmdCheck = async () => {
|
||||||
try {
|
try {
|
||||||
mutate({ auctionNumber: SelectedAuction.auctionNumber }, {
|
mutate({ auctionNumber: SelectedAuction.auctionNumber }, {
|
||||||
onSuccess: (res => {
|
onSuccess: (async (res) => {
|
||||||
console.log(SelectedAuction.auctionNumber, res , SelectedAuction,'iiiiiiiiiiiiiiiiiiiiiiiii');
|
|
||||||
|
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
|
|
||||||
if (res.message == 'No EMD Documents') {
|
if (res.message == 'No EMD Documents') {
|
||||||
|
const result = await getAuction()
|
||||||
|
if (result) {
|
||||||
|
setAllBoolean((prev: any) => ({ ...prev, emdType: true }))
|
||||||
|
return
|
||||||
|
}
|
||||||
setAllBoolean((prev: any) => ({ ...prev, isEmdComplete: false }))
|
setAllBoolean((prev: any) => ({ ...prev, isEmdComplete: false }))
|
||||||
getAuctionItem()
|
getAuctionItem()
|
||||||
} else {
|
} else {
|
||||||
@@ -308,7 +336,53 @@ const Emd = () => {
|
|||||||
getTemplateDocumentation()
|
getTemplateDocumentation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const singleEmdSubmit = async () => {
|
||||||
|
try {
|
||||||
|
setAllBoolean((prev: any) => ({ ...prev, isSubmitEmdLoading: true }))
|
||||||
|
|
||||||
|
if (!acceptedPolicy) {
|
||||||
|
Alert.alert('Policy Required', 'Please accept terms');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const formData = new FormData();
|
||||||
|
|
||||||
|
formData.append('auctionId', SelectedAuction.auctionId);
|
||||||
|
formData.append('productImageName', allBoolean.fileName);
|
||||||
|
formData.append('files', allBoolean.file);
|
||||||
|
|
||||||
|
const response = await apiCall<any>(
|
||||||
|
'post',
|
||||||
|
AUCITON_SINGLE_EMD,
|
||||||
|
formData,
|
||||||
|
{},
|
||||||
|
'multipart/form-data'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response?.statusCode === 200) {
|
||||||
|
showSuccessAlert(response.message || 'EMD submitted successfully');
|
||||||
|
if (SelectedAuction.auctionPattern === 'Forward') {
|
||||||
|
Navigation.navigate(NavigationString.StartBidding)
|
||||||
|
} else {
|
||||||
|
Navigation.navigate(NavigationString.StartReverseBidding)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
if (error?.response) {
|
||||||
|
console.log('Server error:', error.response.data);
|
||||||
|
} else if (error?.request) {
|
||||||
|
console.log('Network error:', error.request);
|
||||||
|
} else {
|
||||||
|
console.log('Error message:', error.message);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setAllBoolean((prev: any) => ({ ...prev, isSubmitEmdLoading: false }))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// getAuction()
|
||||||
AlreadyEmdCheck()
|
AlreadyEmdCheck()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
@@ -324,16 +398,24 @@ const Emd = () => {
|
|||||||
<Skelton />
|
<Skelton />
|
||||||
) : allBoolean.isEmdComplete ? (
|
) : allBoolean.isEmdComplete ? (
|
||||||
<EmdComplete onNext={EmdContinueHandle} />
|
<EmdComplete onNext={EmdContinueHandle} />
|
||||||
) : <>
|
) : allBoolean.emdType ? <View style={{ flex: 1 }}>
|
||||||
<FlatList
|
<View style={styles.container2}>
|
||||||
data={allBoolean.auctionItems}
|
<Text style={{ color: colors.black, fontSize: 17, fontFamily: FontsFamily.poppinsSemiBold }}>Document Name</Text>
|
||||||
keyExtractor={(item: any) => item.auctionId}
|
<TextInput
|
||||||
renderItem={renderItem}
|
style={styles.input2}
|
||||||
contentContainerStyle={{ paddingBottom: 170 }}
|
placeholder="Enter document name...."
|
||||||
/>
|
value={allBoolean.fileName}
|
||||||
|
editable={true}
|
||||||
|
placeholderTextColor={colors.grayText}
|
||||||
|
onChangeText={(text) => { setAllBoolean((prev: any) => ({ ...prev, fileName: text })) }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TouchableOpacity style={styles.button} onPress={() => { pickFileSingle() }}>
|
||||||
|
<Text style={styles.buttonText}>{allBoolean?.file?.name ? allBoolean?.file?.name : 'Choose File'}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
<View style={styles.bottom}>
|
<View style={styles.bottom}>
|
||||||
{/* <BouncyCheckbox
|
<BouncyCheckbox
|
||||||
size={18}
|
size={18}
|
||||||
fillColor={colors.primary}
|
fillColor={colors.primary}
|
||||||
iconStyle={{ borderRadius: 5, borderWidth: 1.5, borderColor: colors.primary }}
|
iconStyle={{ borderRadius: 5, borderWidth: 1.5, borderColor: colors.primary }}
|
||||||
@@ -342,7 +424,41 @@ const Emd = () => {
|
|||||||
onPress={() => setAcceptedPolicy(p => !p)}
|
onPress={() => setAcceptedPolicy(p => !p)}
|
||||||
text="I agree to Terms & Privacy Policy"
|
text="I agree to Terms & Privacy Policy"
|
||||||
textStyle={styles.policyText}
|
textStyle={styles.policyText}
|
||||||
/> */}
|
/>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[
|
||||||
|
styles.submitBtn,
|
||||||
|
!acceptedPolicy && styles.disabled,
|
||||||
|
]}
|
||||||
|
onPress={singleEmdSubmit}
|
||||||
|
disabled={!acceptedPolicy}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
allBoolean.isSubmitEmdLoading ? <Loader size='small' color={colors.white} /> : <Text style={styles.submitText}>Submit EMD</Text>
|
||||||
|
}
|
||||||
|
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View> : <>
|
||||||
|
<FlatList
|
||||||
|
data={allBoolean.auctionItems}
|
||||||
|
keyExtractor={(item: any) => item.auctionId}
|
||||||
|
renderItem={renderItem}
|
||||||
|
contentContainerStyle={{ paddingBottom: 170 }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<View style={styles.bottom}>
|
||||||
|
<BouncyCheckbox
|
||||||
|
size={18}
|
||||||
|
fillColor={colors.primary}
|
||||||
|
iconStyle={{ borderRadius: 5, borderWidth: 1.5, borderColor: colors.primary }}
|
||||||
|
innerIconStyle={{ borderRadius: 5 }}
|
||||||
|
isChecked={acceptedPolicy}
|
||||||
|
onPress={() => setAcceptedPolicy(p => !p)}
|
||||||
|
text="I agree to Terms & Privacy Policy"
|
||||||
|
textStyle={styles.policyText}
|
||||||
|
/>
|
||||||
|
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[
|
style={[
|
||||||
@@ -370,9 +486,29 @@ export default Emd;
|
|||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingHorizontal: 10
|
// paddingHorizontal: 10,
|
||||||
|
backgroundColor: colors.white
|
||||||
},
|
},
|
||||||
|
container2: {
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
paddingVertical: 10,
|
||||||
|
backgroundColor: colors.white,
|
||||||
|
elevation: 2,
|
||||||
|
borderRadius: 10,
|
||||||
|
marginTop: 20,
|
||||||
|
marginHorizontal: 10
|
||||||
|
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
backgroundColor: colors.primary,
|
||||||
|
padding: 12,
|
||||||
|
borderRadius: 6,
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
buttonText: {
|
||||||
|
color: '#fff',
|
||||||
|
fontWeight: '600',
|
||||||
|
},
|
||||||
card: {
|
card: {
|
||||||
backgroundColor: '#FFFFFF',
|
backgroundColor: '#FFFFFF',
|
||||||
marginHorizontal: 5,
|
marginHorizontal: 5,
|
||||||
@@ -434,6 +570,16 @@ const styles = StyleSheet.create({
|
|||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: colors.black
|
color: colors.black
|
||||||
},
|
},
|
||||||
|
input2: {
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: '#CBD5E1',
|
||||||
|
borderRadius: 14,
|
||||||
|
padding: 12,
|
||||||
|
backgroundColor: '#FFFFFF',
|
||||||
|
fontSize: 14,
|
||||||
|
color: colors.black,
|
||||||
|
marginBottom: 20
|
||||||
|
},
|
||||||
|
|
||||||
uploadBtn: {
|
uploadBtn: {
|
||||||
marginTop: 12,
|
marginTop: 12,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { useWebSocketService } from '../../socket/Socket';
|
|||||||
import Variables from '../../Constant/Variable';
|
import Variables from '../../Constant/Variable';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { apiCall } from '../../Axios/Axios';
|
import { apiCall } from '../../Axios/Axios';
|
||||||
import { FORWARD_AUCTION_ITEM, REVERSE_AUCTION_ITEM, SELECTED_AUCTION_ITEM } from '../../Services/BBPS/ApiUrls';
|
import { AUCTION_ONE_TIME_BID, FORWARD_AUCTION_ITEM, GET_AUCTION_DETAILS, REVERSE_AUCTION_ITEM, SELECTED_AUCTION_ITEM } from '../../Services/BBPS/ApiUrls';
|
||||||
import BiddingCard from './Component/BiddingCard';
|
import BiddingCard from './Component/BiddingCard';
|
||||||
import { CommonActions, useFocusEffect, useNavigation } from '@react-navigation/native';
|
import { CommonActions, useFocusEffect, useNavigation } from '@react-navigation/native';
|
||||||
import NavigationString from '../../Constant/NavigationString';
|
import NavigationString from '../../Constant/NavigationString';
|
||||||
@@ -20,7 +20,7 @@ const StartBidding = () => {
|
|||||||
const Navigation: any = useNavigation()
|
const Navigation: any = useNavigation()
|
||||||
const [items, setItems] = useState<any>([]);
|
const [items, setItems] = useState<any>([]);
|
||||||
const [bidValues, setBidValues] = useState<Record<number, number>>({});
|
const [bidValues, setBidValues] = useState<Record<number, number>>({});
|
||||||
const [allBoolean, setAllBoolean] = useState({ showSuccess: false, showDialog: false, bidPayload: {} })
|
const [allBoolean, setAllBoolean] = useState({ showSuccess: false, showDialog: false, bidPayload: {}, oneTimeBid: false, rebid: false, reload: false })
|
||||||
const { subscribe, createRoom, placeBid } = useWebSocketService(
|
const { subscribe, createRoom, placeBid } = useWebSocketService(
|
||||||
Variables.webSocketUrl,
|
Variables.webSocketUrl,
|
||||||
() => console.log('Connected!'),
|
() => console.log('Connected!'),
|
||||||
@@ -28,6 +28,25 @@ const StartBidding = () => {
|
|||||||
loginUser.token,
|
loginUser.token,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getAuction = async () => {
|
||||||
|
const selectedRes = await apiCall<any>('get', GET_AUCTION_DETAILS, {}, { id: SelectedAuction.auctionId });
|
||||||
|
if (selectedRes.statusCode == 200 && selectedRes.data.contractorId.length) {
|
||||||
|
setAllBoolean((prev: any) => ({ ...prev, oneTimeBid: true }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const getOneTimeBidValue = async () => {
|
||||||
|
try {
|
||||||
|
const selectedRes = await apiCall<any>('get', AUCTION_ONE_TIME_BID, {}, { auctionId: SelectedAuction.auctionId });
|
||||||
|
if (selectedRes.statusCode == 200) {
|
||||||
|
return selectedRes.data
|
||||||
|
} else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
const getAllAcutionItems = async () => {
|
const getAllAcutionItems = async () => {
|
||||||
try {
|
try {
|
||||||
const payload = { auctionNumber: SelectedAuction.auctionNumber };
|
const payload = { auctionNumber: SelectedAuction.auctionNumber };
|
||||||
@@ -36,13 +55,9 @@ const StartBidding = () => {
|
|||||||
if (SelectedAuction.auctionPattern === 'Forward') {
|
if (SelectedAuction.auctionPattern === 'Forward') {
|
||||||
const res = await apiCall<any>('get', FORWARD_AUCTION_ITEM, {}, payload);
|
const res = await apiCall<any>('get', FORWARD_AUCTION_ITEM, {}, payload);
|
||||||
if (res?.statusCode === 200) auctionItem = res.data || [];
|
if (res?.statusCode === 200) auctionItem = res.data || [];
|
||||||
} else {
|
|
||||||
const res = await apiCall<any>('get', REVERSE_AUCTION_ITEM, {}, payload);
|
|
||||||
if (res?.statusCode === 200) auctionItem = res.data || [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedRes = await apiCall<any>('get', SELECTED_AUCTION_ITEM, {}, payload);
|
const selectedRes = await apiCall<any>('get', SELECTED_AUCTION_ITEM, {}, payload);
|
||||||
console.log(selectedRes,'jhhhhhhhhhh');
|
|
||||||
|
|
||||||
const uniqueArray: number[] = Array.from(
|
const uniqueArray: number[] = Array.from(
|
||||||
new Set(selectedRes?.data || [])
|
new Set(selectedRes?.data || [])
|
||||||
@@ -52,47 +67,96 @@ console.log(selectedRes,'jhhhhhhhhhh');
|
|||||||
uniqueArray.includes(item.id)
|
uniqueArray.includes(item.id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (SelectedAuction.auctionCategories == 'Live') {
|
||||||
|
const result = await createRoom(SelectedAuction.auctionNumber);
|
||||||
|
|
||||||
const result = await createRoom(SelectedAuction.auctionNumber);
|
subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, data => {
|
||||||
|
console.log('🔥 BID UPDATE:', data);
|
||||||
subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, data => {
|
|
||||||
console.log('🔥 BID UPDATE:', data);
|
|
||||||
});
|
|
||||||
|
|
||||||
const bidAmountMap2 = new Map<number, { bidAmount: number; contractorId: number }>();
|
|
||||||
|
|
||||||
(result || []).forEach((r: any) => {
|
|
||||||
bidAmountMap2.set(r.auctionItemId, {
|
|
||||||
bidAmount: r.bidAmount,
|
|
||||||
contractorId: r.contractorId,
|
|
||||||
});
|
});
|
||||||
});
|
const bidAmountMap2 = new Map<number, { bidAmount: number; contractorId: number }>();
|
||||||
|
|
||||||
|
(result || []).forEach((r: any) => {
|
||||||
|
bidAmountMap2.set(r.auctionItemId, {
|
||||||
|
bidAmount: r.bidAmount,
|
||||||
|
contractorId: r.contractorId,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// Check One Time bid enable butoon
|
||||||
|
if (SelectedAuction.auctionCategories != 'Live') {
|
||||||
|
const myBid = result.find(
|
||||||
|
(bid: any) => bid.contractorId === loginUser.contractorId
|
||||||
|
);
|
||||||
|
|
||||||
|
if (myBid) {
|
||||||
|
setAllBoolean((prev: any) => ({ ...prev, oneTimeBid: true }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const bidAmountMap = new Map<number, number>();
|
const bidAmountMap = new Map<number, number>();
|
||||||
|
|
||||||
(result || []).forEach((r: any) => {
|
(result || []).forEach((r: any) => {
|
||||||
bidAmountMap.set(r.auctionItemId, r.bidAmount);
|
bidAmountMap.set(r.auctionItemId, r.bidAmount);
|
||||||
});
|
});
|
||||||
|
|
||||||
const updatedFilteredItems = filteredItems.map(item => {
|
const updatedFilteredItems = filteredItems.map(item => {
|
||||||
const bidData = bidAmountMap2.get(item.id);
|
const bidData = bidAmountMap2.get(item.id);
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
bidAmount: bidData?.bidAmount ?? item.auctionStartValueFigure,
|
bidAmount: bidData?.bidAmount ?? item.auctionStartValueFigure,
|
||||||
bidAvilable: bidData?.bidAmount ?? 0,
|
bidAvilable: bidData?.bidAmount ?? 0,
|
||||||
me: bidData?.contractorId == loginUser.contractorId ? true : false
|
me: bidData?.contractorId == loginUser.contractorId ? true : false
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialBids: Record<number, number> = {};
|
const initialBids: Record<number, number> = {};
|
||||||
updatedFilteredItems.forEach(item => {
|
updatedFilteredItems.forEach(item => {
|
||||||
initialBids[item.id] = item.bidAmount;
|
initialBids[item.id] = item.bidAmount;
|
||||||
});
|
});
|
||||||
setBidValues(initialBids);
|
setBidValues(initialBids);
|
||||||
setItems(updatedFilteredItems);
|
setItems(updatedFilteredItems);
|
||||||
|
} else {
|
||||||
|
let result = []
|
||||||
|
if (SelectedAuction.rebidAllowed) {
|
||||||
|
setAllBoolean((prev: any) => ({ ...prev, rebid: true }))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SelectedAuction.auctionCategories != 'Live') {
|
||||||
|
result = await getOneTimeBidValue()
|
||||||
|
}
|
||||||
|
const bidMap = new Map<number, any>();
|
||||||
|
|
||||||
|
result.forEach((bid: any) => {
|
||||||
|
bidMap.set(bid.auctionItemId, bid);
|
||||||
|
});
|
||||||
|
const mergedData = auctionItem.map((item: any) => {
|
||||||
|
const bid = bidMap.get(item.id);
|
||||||
|
|
||||||
|
if (!bid) {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
bidAmount: item.auctionStartValueFigure,
|
||||||
|
contractorId: item.contractorId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
bidAmount: bid.bidAmount,
|
||||||
|
bidId: bid.bidId,
|
||||||
|
contractorId: bid.contractorId,
|
||||||
|
contractorName: bid.contractorName,
|
||||||
|
me: bid.contractorId === loginUser.contractorId,
|
||||||
|
bidTime: bid.bidTime,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const initialBids: Record<number, number> = {};
|
||||||
|
mergedData.forEach(item => {
|
||||||
|
initialBids[item.id] = item.bidAmount;
|
||||||
|
});
|
||||||
|
setBidValues(initialBids);
|
||||||
|
setItems(mergedData)
|
||||||
|
setBidValues(initialBids);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching auction items:', error);
|
console.error('Error fetching auction items:', error);
|
||||||
}
|
}
|
||||||
@@ -122,11 +186,14 @@ console.log(selectedRes,'jhhhhhhhhhh');
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (SelectedAuction.auctionCategories == 'One-time') {
|
||||||
|
getAuction()
|
||||||
|
}
|
||||||
getAllAcutionItems();
|
getAllAcutionItems();
|
||||||
subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, (data) => { });
|
subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, (data) => { });
|
||||||
}, []);
|
}, [allBoolean.reload]);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initial: Record<number, number> = {};
|
const initial: Record<number, number> = {};
|
||||||
@@ -233,6 +300,8 @@ console.log(selectedRes,'jhhhhhhhhhh');
|
|||||||
return () => subscription.remove();
|
return () => subscription.remove();
|
||||||
}, [Navigation])
|
}, [Navigation])
|
||||||
);
|
);
|
||||||
|
// console.log(bidValues, 'jjfdlsjfldsjfl');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<InsideHeader title="Bidding Panel" showArrow />
|
<InsideHeader title="Bidding Panel" showArrow />
|
||||||
@@ -261,9 +330,11 @@ console.log(selectedRes,'jhhhhhhhhhh');
|
|||||||
onDecrease={() => handleUpdate(item.id, -item.bidVariationValue)}
|
onDecrease={() => handleUpdate(item.id, -item.bidVariationValue)}
|
||||||
onPlaceBid={() => { submitBid(item) }}
|
onPlaceBid={() => { submitBid(item) }}
|
||||||
SelectedAuction={SelectedAuction}
|
SelectedAuction={SelectedAuction}
|
||||||
|
allBoolean={allBoolean}
|
||||||
|
setAllBoolean={setAllBoolean}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
contentContainerStyle={{ padding: 16 }}
|
contentContainerStyle={{ padding: 16, paddingBottom: 300 }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{allBoolean.showSuccess && (
|
{allBoolean.showSuccess && (
|
||||||
|
|||||||
@@ -1,30 +1,9 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import {
|
import { View, Text, StyleSheet, Dimensions, FlatList, ActivityIndicator } from 'react-native';
|
||||||
View,
|
import Animated, { useSharedValue, useAnimatedStyle, withDelay, withTiming } from 'react-native-reanimated';
|
||||||
Text,
|
import { Layers, Clock, ShoppingCart, X, FileText } from 'lucide-react-native';
|
||||||
StyleSheet,
|
|
||||||
Dimensions,
|
|
||||||
FlatList,
|
|
||||||
ActivityIndicator,
|
|
||||||
} from 'react-native';
|
|
||||||
import Animated, {
|
|
||||||
useSharedValue,
|
|
||||||
useAnimatedStyle,
|
|
||||||
withDelay,
|
|
||||||
withTiming,
|
|
||||||
} from 'react-native-reanimated';
|
|
||||||
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 { useWebSocketService } from '../../socket/Socket';
|
|
||||||
import Variables from '../../Constant/Variable';
|
|
||||||
import { useFocusEffect } from '@react-navigation/native';
|
|
||||||
import { useDashboard } from '../../Services/BBPS/Hooks';
|
import { useDashboard } from '../../Services/BBPS/Hooks';
|
||||||
|
|
||||||
const { width } = Dimensions.get('window');
|
const { width } = Dimensions.get('window');
|
||||||
@@ -142,17 +121,6 @@ const Home = () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
/* ---------------- WebSocket ---------------- */
|
|
||||||
const { connect } = useWebSocketService(
|
|
||||||
Variables.webSocketUrl,
|
|
||||||
() => console.log('WebSocket Connected'),
|
|
||||||
error => console.log('WebSocket Error:', error),
|
|
||||||
);
|
|
||||||
|
|
||||||
useFocusEffect(() => {
|
|
||||||
connect();
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.screen}>
|
<View style={styles.screen}>
|
||||||
<Header title="Dashboard" />
|
<Header title="Dashboard" />
|
||||||
|
|||||||
@@ -0,0 +1,187 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import {
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
ScrollView,
|
||||||
|
TouchableOpacity,
|
||||||
|
StyleSheet,
|
||||||
|
ActivityIndicator,
|
||||||
|
Alert,
|
||||||
|
} from 'react-native';
|
||||||
|
import RNFS from 'react-native-fs';
|
||||||
|
import * as XLSX from 'xlsx';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const EXCEL_API_URL = 'https://procurelinc.in/EProcurementSB/eTendering/getEnvelopeCTemplate/tenderId';
|
||||||
|
|
||||||
|
const EnvelopeCExcelPreview = () => {
|
||||||
|
const [data, setData] = useState<any[]>([]);
|
||||||
|
const [columns, setColumns] = useState<string[]>([]);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadExcelFromApi();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// 📥 FETCH EXCEL BLOB + READ
|
||||||
|
const loadExcelFromApi = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
const urlWithParams = `${EXCEL_API_URL}?tenderId=2479`;
|
||||||
|
|
||||||
|
// ⬇️ Fetch Excel as blob
|
||||||
|
const response = await axios.get(urlWithParams, {
|
||||||
|
responseType: 'arraybuffer',
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJBQklOVE9QUE85NkBHTUFJTC5DT00iLCJpYXQiOjE3Njc5MzgzMDMsImV4cCI6MTc2Nzk3NDMwM30.NiT5iOIdQH0y8TutLfLVp9ApQIAI3NHbkmRjb1fl-JlGxeyX21n3oPGvU6sDw_uU9iTZHI183e2FH_IL2sZYpQ`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log(response, '--------------------------------------');
|
||||||
|
|
||||||
|
// ⬇️ Save file locally
|
||||||
|
const filePath = `${RNFS.DocumentDirectoryPath}/envelopeC.xlsx`;
|
||||||
|
const buffer = Buffer.from(response.data, 'binary'); // convert arraybuffer to buffer
|
||||||
|
await RNFS.writeFile(filePath, buffer.toString('base64'), 'base64');
|
||||||
|
|
||||||
|
// 📖 Read Excel
|
||||||
|
const workbook = XLSX.readFile(filePath);
|
||||||
|
const sheet = workbook.Sheets[workbook.SheetNames[0]];
|
||||||
|
const jsonData: any[] = XLSX.utils.sheet_to_json(sheet, { defval: '' });
|
||||||
|
|
||||||
|
setData(jsonData);
|
||||||
|
setColumns(Object.keys(jsonData[0] || {}));
|
||||||
|
} catch (error: any) {
|
||||||
|
console.log('Excel load error:', error);
|
||||||
|
Alert.alert('Error', error.message || 'Unable to load Excel');
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ✏️ UPDATE CELL
|
||||||
|
const updateCell = (rowIndex: number, key: string, value: string) => {
|
||||||
|
const updated = [...data];
|
||||||
|
updated[rowIndex][key] = value;
|
||||||
|
setData(updated);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 💾 SAVE UPDATED EXCEL (LOCAL)
|
||||||
|
const saveUpdatedExcel = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
const worksheet = XLSX.utils.json_to_sheet(data);
|
||||||
|
const workbook = XLSX.utils.book_new();
|
||||||
|
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
|
||||||
|
|
||||||
|
const base64Excel = XLSX.write(workbook, { bookType: 'xlsx', type: 'base64' });
|
||||||
|
const updatedPath = `${RNFS.DocumentDirectoryPath}/envelopeC_updated.xlsx`;
|
||||||
|
|
||||||
|
await RNFS.writeFile(updatedPath, base64Excel, 'base64');
|
||||||
|
|
||||||
|
Alert.alert('Success', 'Updated Excel saved successfully');
|
||||||
|
console.log('Saved at:', updatedPath);
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Save error:', error);
|
||||||
|
Alert.alert('Error', 'Failed to save Excel');
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return (
|
||||||
|
<View style={styles.loader}>
|
||||||
|
<ActivityIndicator size="large" />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Text style={styles.title}>Envelope-C Excel Preview</Text>
|
||||||
|
|
||||||
|
<ScrollView horizontal>
|
||||||
|
<View>
|
||||||
|
{/* HEADER */}
|
||||||
|
<View style={styles.row}>
|
||||||
|
{columns.map(col => (
|
||||||
|
<Text key={col} style={styles.headerCell}>
|
||||||
|
{col}
|
||||||
|
</Text>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* DATA */}
|
||||||
|
<ScrollView style={{ maxHeight: 420 }}>
|
||||||
|
{data.map((row, rowIndex) => (
|
||||||
|
<View key={rowIndex} style={styles.row}>
|
||||||
|
{columns.map(key => (
|
||||||
|
<TextInput
|
||||||
|
key={key}
|
||||||
|
value={String(row[key])}
|
||||||
|
style={styles.cell}
|
||||||
|
onChangeText={text => updateCell(rowIndex, key, text)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<TouchableOpacity style={styles.button} onPress={saveUpdatedExcel}>
|
||||||
|
<Text style={styles.buttonText}>Save Updated Excel</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EnvelopeCExcelPreview;
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
padding: 16,
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
},
|
||||||
|
loader: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: '700',
|
||||||
|
marginBottom: 10,
|
||||||
|
},
|
||||||
|
row: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
},
|
||||||
|
headerCell: {
|
||||||
|
minWidth: 140,
|
||||||
|
padding: 10,
|
||||||
|
backgroundColor: '#f1f5f9',
|
||||||
|
borderWidth: 1,
|
||||||
|
fontWeight: '700',
|
||||||
|
},
|
||||||
|
cell: {
|
||||||
|
minWidth: 140,
|
||||||
|
padding: 10,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: '#cbd5e1',
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
marginTop: 15,
|
||||||
|
backgroundColor: '#2563eb',
|
||||||
|
padding: 14,
|
||||||
|
borderRadius: 8,
|
||||||
|
},
|
||||||
|
buttonText: {
|
||||||
|
color: '#fff',
|
||||||
|
textAlign: 'center',
|
||||||
|
fontWeight: '600',
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -57,8 +57,8 @@ const LiveTender = () => {
|
|||||||
tenderOfWork={item.departmentName}
|
tenderOfWork={item.departmentName}
|
||||||
tenderFees={item.documentFees}
|
tenderFees={item.documentFees}
|
||||||
tenderNumber={item.tenderNumber}
|
tenderNumber={item.tenderNumber}
|
||||||
// onPurchasePress={() => { Dispatch(togglePurchaseTender(item)) }}
|
onPurchasePress={() => { Dispatch(togglePurchaseTender(item)) }}
|
||||||
// onDetailsPress={() => navigation.navigate('LiveTenderDetail', {item})}
|
onDetailsPress={() => navigation.navigate('LiveTenderDetail', { item })}
|
||||||
/>
|
/>
|
||||||
},
|
},
|
||||||
[SelectedPurchaseList]
|
[SelectedPurchaseList]
|
||||||
@@ -104,7 +104,7 @@ const LiveTender = () => {
|
|||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Refreshing auctions
|
Refreshing Tender
|
||||||
</Text>
|
</Text>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
)}
|
)}
|
||||||
@@ -122,7 +122,7 @@ const LiveTender = () => {
|
|||||||
<RefreshControl
|
<RefreshControl
|
||||||
refreshing={isRefetching}
|
refreshing={isRefetching}
|
||||||
onRefresh={refetch}
|
onRefresh={refetch}
|
||||||
tintColor="transparent" // Set to transparent if you only want your custom banner to show
|
tintColor="transparent"
|
||||||
colors={[colors.primary]}
|
colors={[colors.primary]}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,97 +1,94 @@
|
|||||||
import { StyleSheet, Text, View, ScrollView, StatusBar, TouchableOpacity } from 'react-native'
|
import { StyleSheet, Text, View, ScrollView, TouchableOpacity } from 'react-native';
|
||||||
import React from 'react'
|
import React from 'react';
|
||||||
import { InsideHeader } from '../../Component/Index'
|
import { InsideHeader } from '../../Component/Index';
|
||||||
import colors from '../../Constant/Color'
|
import colors from '../../Constant/Color';
|
||||||
import { useNavigation, useRoute } from '@react-navigation/native'
|
import { useNavigation, useRoute } from '@react-navigation/native';
|
||||||
import { useProceedToBid } from '../../Services/BBPS/Hooks'
|
import { useProceedToBid } from '../../Services/BBPS/Hooks';
|
||||||
|
import { format } from '../../Helper/DateFormat';
|
||||||
|
import FontsFamily from '../../Constant/FontsFamily';
|
||||||
|
|
||||||
const ProceedToBidDetail = () => {
|
const ProceedToBidDetail = () => {
|
||||||
// Sample data based on your JSON
|
const route: any = useRoute();
|
||||||
const route = useRoute()
|
|
||||||
const tenderData = route.params?.tender;
|
const tenderData = route.params?.tender;
|
||||||
const {data, refetch} = useProceedToBid(tenderData?.tenderId);
|
const navigation = useNavigation<any>();
|
||||||
|
const { data, refetch } = useProceedToBid(tenderData?.tenderId);
|
||||||
const navigation = useNavigation<any>()
|
|
||||||
// Format date from array
|
|
||||||
|
|
||||||
const handleStartBidding = () => {
|
const handleStartBidding = () => {
|
||||||
refetch();
|
refetch();
|
||||||
if (data) {
|
if (data) {
|
||||||
navigation.navigate('TenderBidding', { tenderData: tenderData , bidData: data.data });
|
navigation.navigate('TenderBidding', { tenderData: tenderData, bidData: data.data });
|
||||||
}
|
}
|
||||||
}
|
|
||||||
const formatDate = (dateArray: any[]) => {
|
|
||||||
if (!dateArray || dateArray.length < 3) return "N/A";
|
|
||||||
const [year, month, day, hour = 0, minute = 0] = dateArray;
|
|
||||||
return `${day.toString().padStart(2, '0')}/${month.toString().padStart(2, '0')}/${year} ${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Status indicator component
|
// Status indicator component
|
||||||
const StatusIndicator = ({ status, label }) => (
|
const StatusIndicator = ({ status, label }: { status: any, label: string }) => (
|
||||||
<View style={styles.statusContainer}>
|
<View style={styles.statusContainer}>
|
||||||
<View style={[styles.statusDot, { backgroundColor: status ? colors.success : colors.error }]} />
|
<View style={[styles.statusDot, { backgroundColor: status ? colors.success : colors.error }]} />
|
||||||
<Text style={[styles.statusText, { color: status ? colors.success : colors.error }]}>
|
<Text style={[styles.statusText, { color: status ? colors.success : colors.error, fontFamily: FontsFamily.poppinsSemiBold }]}>
|
||||||
{label}: {status ? "Submitted" : "Not Submitted"}
|
{label}: {status ? "Submitted" : "Not Submitted"}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
// Envelope log card component
|
// Envelope log card component
|
||||||
const EnvelopeLogCard = ({ log, title }) => (
|
const EnvelopeLogCard = ({ log, title }: { log: any, title: string }) => {
|
||||||
<View style={styles.envelopeCard}>
|
|
||||||
<View style={styles.cardHeader}>
|
return (
|
||||||
<Text style={styles.cardTitle}>{title}</Text>
|
<View style={styles.envelopeCard}>
|
||||||
<View style={[styles.envelopeBadge, { backgroundColor: colors.primary }]}>
|
<View style={styles.cardHeader}>
|
||||||
<Text style={styles.envelopeBadgeText}>{log?.envelope}</Text>
|
<Text style={[styles.cardTitle, { fontFamily: FontsFamily.poppinsSemiBold }]}>{title}</Text>
|
||||||
|
<View style={[styles.envelopeBadge, { backgroundColor: colors.primary }]}>
|
||||||
|
<Text style={[styles.envelopeBadgeText, { fontFamily: FontsFamily.poppinsSemiBold }]}>{log?.envelope}</Text>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
|
||||||
|
|
||||||
<View style={styles.logDetailRow}>
|
|
||||||
<Text style={styles.label}>Activity:</Text>
|
|
||||||
<Text style={styles.value}>{log?.activity}</Text>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View style={styles.logDetailRow}>
|
|
||||||
<Text style={styles.label}>Date & Time:</Text>
|
|
||||||
<Text style={styles.value}>{log?.dateTime}</Text>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View style={styles.logDetailRow}>
|
|
||||||
<Text style={styles.label}>System Info:</Text>
|
|
||||||
<Text style={styles.value}>{log?.osName} / {log?.browserName}</Text>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View style={styles.logDetailRow}>
|
|
||||||
<Text style={styles.label}>IP Address:</Text>
|
|
||||||
<Text style={styles.value}>{log?.ipAddress}</Text>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View style={styles.logDetailRow}>
|
|
||||||
<Text style={styles.label}>Status Message:</Text>
|
|
||||||
<Text style={[styles.value, styles.successText]}>{log?.logMessage}</Text>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{log?.headingMsg && (
|
|
||||||
<View style={styles.logDetailRow}>
|
<View style={styles.logDetailRow}>
|
||||||
<Text style={styles.label}>Heading:</Text>
|
<Text style={[styles.label, { fontFamily: FontsFamily.poppinsMedium }]}>Activity:</Text>
|
||||||
<Text style={styles.value}>{log?.headingMsg}</Text>
|
<Text style={[styles.value, { fontFamily: FontsFamily.poppinsRegular }]}>{log?.activity}</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
|
||||||
</View>
|
<View style={styles.logDetailRow}>
|
||||||
);
|
<Text style={[styles.label, { fontFamily: FontsFamily.poppinsMedium }]}>Date & Time:</Text>
|
||||||
|
<Text style={[styles.value, { fontFamily: FontsFamily.poppinsRegular }]}>{format.date6(log?.dateTime)}</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.logDetailRow}>
|
||||||
|
<Text style={[styles.label, { fontFamily: FontsFamily.poppinsMedium }]}>System Info:</Text>
|
||||||
|
<Text style={[styles.value, { fontFamily: FontsFamily.poppinsRegular }]}>{log?.osName} / {log?.browserName}</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.logDetailRow}>
|
||||||
|
<Text style={[styles.label, { fontFamily: FontsFamily.poppinsMedium }]}>IP Address:</Text>
|
||||||
|
<Text style={[styles.value, { fontFamily: FontsFamily.poppinsRegular }]}>{log?.ipAddress}</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.logDetailRow}>
|
||||||
|
<Text style={[styles.label, { fontFamily: FontsFamily.poppinsMedium }]}>Status Message:</Text>
|
||||||
|
<Text style={[styles.value, styles.successText, { fontFamily: FontsFamily.poppinsSemiBold }]}>{log?.logMessage}</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{log?.headingMsg && (
|
||||||
|
<View style={styles.logDetailRow}>
|
||||||
|
<Text style={[styles.label, { fontFamily: FontsFamily.poppinsMedium }]}>Heading:</Text>
|
||||||
|
<Text style={[styles.value, { fontFamily: FontsFamily.poppinsRegular }]}>{log?.headingMsg}</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Information row component
|
// Information row component
|
||||||
const InfoRow = ({ label, value, isHighlighted = false }) => (
|
const InfoRow = ({ label, value, isHighlighted = false }: { label: string, value: string, isHighlighted?: boolean }) => (
|
||||||
<View style={styles.infoRow}>
|
<View style={styles.infoRow}>
|
||||||
<Text style={styles.infoLabel}>{label}:</Text>
|
<Text style={[styles.infoLabel, { fontFamily: FontsFamily.poppinsMedium }]}>{label}:</Text>
|
||||||
<Text style={[styles.infoValue, isHighlighted && styles.highlightedValue]}>{value}</Text>
|
<Text style={[styles.infoValue, isHighlighted && styles.highlightedValue, { fontFamily: FontsFamily.poppinsSemiBold }]}>{value}</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
// Feature chip component
|
// Feature chip component
|
||||||
const FeatureChip = ({ label, enabled }) => (
|
const FeatureChip = ({ label, enabled }: { label: string, enabled: boolean }) => (
|
||||||
<View style={[styles.chip, { backgroundColor: enabled ? colors.successLight : colors.lightGray }]}>
|
<View style={[styles.chip, { backgroundColor: enabled ? colors.successLight : colors.lightGray }]}>
|
||||||
<Text style={[styles.chipText, { color: enabled ? colors.success : colors.darkGray }]}>
|
<Text style={[styles.chipText, { color: enabled ? colors.success : colors.darkGray, fontFamily: FontsFamily.poppinsSemiBold }]}>
|
||||||
{label} {enabled ? '✓' : '✗'}
|
{label} {enabled ? '✓' : '✗'}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
@@ -99,42 +96,41 @@ const ProceedToBidDetail = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{ flex: 1, backgroundColor: colors.white }}>
|
<View style={{ flex: 1, backgroundColor: colors.white }}>
|
||||||
<StatusBar backgroundColor={colors.primary} barStyle="light-content" />
|
|
||||||
<InsideHeader title="Tender Detail" showArrow />
|
<InsideHeader title="Tender Detail" showArrow />
|
||||||
|
|
||||||
<ScrollView style={styles.container} showsVerticalScrollIndicator={false}>
|
<ScrollView style={styles.container} showsVerticalScrollIndicator={false} contentContainerStyle={{ paddingBottom: 100 }}>
|
||||||
{/* Tender Header Section */}
|
{/* Tender Header */}
|
||||||
<View style={styles.headerCard}>
|
<View style={styles.headerCard}>
|
||||||
<View style={styles.tenderHeader}>
|
<View style={styles.tenderHeader}>
|
||||||
<View>
|
<View>
|
||||||
<Text style={styles.tenderNumber}>{tenderData?.tenderNumber}</Text>
|
<Text style={[styles.tenderNumber, { fontFamily: FontsFamily.poppinsSemiBold }]}>{tenderData.tenderNumber}</Text>
|
||||||
<Text style={styles.tenderId}>ID: {tenderData?.tenderId}</Text>
|
<Text style={[styles.tenderId, { fontFamily: FontsFamily.poppinsRegular }]}>ID: {tenderData.tenderId}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[styles.statusBadge, { backgroundColor: tenderData?.biddingStatus ? colors.success : colors.warning }]}>
|
<View style={[styles.statusBadge, { backgroundColor: tenderData.biddingStatus ? colors.success : colors.warning }]}>
|
||||||
<Text style={styles.statusBadgeText}>
|
<Text style={[styles.statusBadgeText, { fontFamily: FontsFamily.poppinsSemiBold }]}>
|
||||||
{tenderData?.biddingStatus ? "Active" : "Inactive"}
|
{tenderData.biddingStatus ? "Active" : "Inactive"}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Text style={styles.workDescription}>{tenderData?.nameofWork}</Text>
|
<Text style={[styles.workDescription, { fontFamily: FontsFamily.poppinsRegular }]} numberOfLines={1}>{tenderData.nameofWork}</Text>
|
||||||
|
|
||||||
<View style={styles.headerInfoRow}>
|
<View style={styles.headerInfoRow}>
|
||||||
<View style={styles.headerInfoItem}>
|
<View style={styles.headerInfoItem}>
|
||||||
<Text style={styles.headerInfoLabel}>NIT No.</Text>
|
<Text style={[styles.headerInfoLabel, { fontFamily: FontsFamily.poppinsMedium }]}>NIT No.</Text>
|
||||||
<Text style={styles.headerInfoValue}>{tenderData?.nitNo}</Text>
|
<Text style={[styles.headerInfoValue, { fontFamily: FontsFamily.poppinsSemiBold }]}>{tenderData.nitNo}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.separator} />
|
<View style={styles.separator} />
|
||||||
<View style={styles.headerInfoItem}>
|
<View style={styles.headerInfoItem}>
|
||||||
<Text style={styles.headerInfoLabel}>EMD Amount</Text>
|
<Text style={[styles.headerInfoLabel, { fontFamily: FontsFamily.poppinsMedium }]}>EMD Amount</Text>
|
||||||
<Text style={styles.headerInfoValue}>₹{tenderData?.emdInFig}</Text>
|
<Text style={[styles.headerInfoValue, { fontFamily: FontsFamily.poppinsSemiBold }]}>₹{tenderData.emdInFig}</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Envelope Submission Status */}
|
{/* Envelope Status */}
|
||||||
<View style={styles.section}>
|
<View style={styles.section}>
|
||||||
<Text style={styles.sectionTitle}>Envelope Submission Status</Text>
|
<Text style={[styles.sectionTitle, { color: colors.black }]}>{`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" />
|
<StatusIndicator status={tenderData?.envelopeBSubmittStatus} label="Envelope B" />
|
||||||
@@ -142,19 +138,19 @@ const ProceedToBidDetail = () => {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Envelope Logs */}
|
{/* Logs */}
|
||||||
{tenderData?.envelopeA_Logs && (
|
{tenderData.envelopeA_Logs && (
|
||||||
<View style={styles.section}>
|
<View style={styles.section}>
|
||||||
<Text style={styles.sectionTitle}>Submission Logs</Text>
|
<Text style={[styles.sectionTitle, { color: colors.black }]}>Submission Logs</Text>
|
||||||
<EnvelopeLogCard log={tenderData?.envelopeA_Logs} title="Envelope A Submission" />
|
<EnvelopeLogCard log={tenderData.envelopeA_Logs} title="Envelope A Submission" />
|
||||||
<EnvelopeLogCard log={tenderData?.envelopeB_Logs} title="Envelope B Submission" />
|
<EnvelopeLogCard log={tenderData.envelopeB_Logs} title="Envelope B Submission" />
|
||||||
<EnvelopeLogCard log={tenderData?.envelopeC_Logs} title="Envelope C Submission" />
|
<EnvelopeLogCard log={tenderData.envelopeC_Logs} title="Envelope C Submission" />
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Tender Details */}
|
{/* Tender Details */}
|
||||||
<View style={styles.section}>
|
<View style={styles.section}>
|
||||||
<Text style={styles.sectionTitle}>Tender Details</Text>
|
<Text style={[styles.sectionTitle, { color: colors.black }]}>Tender Details</Text>
|
||||||
<View style={styles.detailsCard}>
|
<View style={styles.detailsCard}>
|
||||||
<InfoRow label="Envelope Type" value={tenderData?.envelopeType} />
|
<InfoRow label="Envelope Type" value={tenderData?.envelopeType} />
|
||||||
<InfoRow label="Tender Stages" value={tenderData?.tenderStages} />
|
<InfoRow label="Tender Stages" value={tenderData?.tenderStages} />
|
||||||
@@ -164,24 +160,24 @@ const ProceedToBidDetail = () => {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Time Period */}
|
{/* Submission Time */}
|
||||||
<View style={styles.section}>
|
<View style={styles.section}>
|
||||||
<Text style={styles.sectionTitle}>Submission Time Period</Text>
|
<Text style={[styles.sectionTitle, { color: colors.black }]}>Submission Time Period</Text>
|
||||||
<View style={styles.timeCard}>
|
<View style={styles.timeCard}>
|
||||||
<View style={styles.timeRow}>
|
<View style={styles.timeRow}>
|
||||||
<Text style={styles.timeLabel}>Starts On:</Text>
|
<Text style={[styles.timeLabel, { fontFamily: FontsFamily.poppinsSemiBold }]}>Starts On:</Text>
|
||||||
<Text style={styles.timeValue}>{formatDate(tenderData?.submittedStartDate)}</Text>
|
<Text style={[styles.timeValue, { fontFamily: FontsFamily.poppinsSemiBold }]}>{format.date6(tenderData.submittedStartDate)}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.timeRow}>
|
<View style={styles.timeRow}>
|
||||||
<Text style={styles.timeLabel}>Ends On:</Text>
|
<Text style={[styles.timeLabel, { fontFamily: FontsFamily.poppinsSemiBold }]}>Ends On:</Text>
|
||||||
<Text style={styles.timeValue}>{formatDate(tenderData?.submittedEndDate)}</Text>
|
<Text style={[styles.timeValue, { fontFamily: FontsFamily.poppinsSemiBold }]}>{format.date6(tenderData.submittedEndDate)}</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Feature Flags */}
|
{/* Feature Chips */}
|
||||||
<View style={styles.section}>
|
<View style={styles.section}>
|
||||||
<Text style={styles.sectionTitle}>Available Features</Text>
|
<Text style={[styles.sectionTitle, { color: colors.black }]}>Available Features</Text>
|
||||||
<View style={styles.chipsContainer}>
|
<View style={styles.chipsContainer}>
|
||||||
<FeatureChip label="View Bid" enabled={tenderData?.viewBid} />
|
<FeatureChip label="View Bid" enabled={tenderData?.viewBid} />
|
||||||
<FeatureChip label="Proceed to Bid" enabled={tenderData?.proceedtoBid} />
|
<FeatureChip label="Proceed to Bid" enabled={tenderData?.proceedtoBid} />
|
||||||
@@ -192,362 +188,93 @@ const ProceedToBidDetail = () => {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Final Status */}
|
{/* Overall Status */}
|
||||||
<View style={styles.finalStatusCard}>
|
<View style={styles.finalStatusCard}>
|
||||||
<Text style={styles.finalStatusTitle}>Overall Status</Text>
|
<Text style={[styles.finalStatusTitle, { fontFamily: FontsFamily.poppinsSemiBold }]}>Overall Status</Text>
|
||||||
<View style={styles.finalStatusRow}>
|
<View style={styles.finalStatusRow}>
|
||||||
<Text style={styles.finalStatusLabel}>All Envelopes Submitted:</Text>
|
<Text style={[styles.finalStatusLabel, { fontFamily: FontsFamily.poppinsMedium }]}>All Envelopes Submitted:</Text>
|
||||||
<Text style={[styles.finalStatusValue,
|
<Text style={[styles.finalStatusValue, {
|
||||||
{
|
color: tenderData.envelopeASubmittStatus && tenderData.envelopeBSubmittStatus && tenderData.envelopeCSubmittStatus
|
||||||
color: tenderData?.envelopeASubmittStatus && tenderData?.envelopeBSubmittStatus && tenderData?.envelopeCSubmittStatus
|
? colors.success : colors.error, fontFamily: FontsFamily.poppinsSemiBold
|
||||||
? colors.success : colors.error
|
|
||||||
}]}>
|
}]}>
|
||||||
{tenderData?.envelopeASubmittStatus && tenderData?.envelopeBSubmittStatus && tenderData?.envelopeCSubmittStatus
|
{tenderData.envelopeASubmittStatus && tenderData.envelopeBSubmittStatus && tenderData.envelopeCSubmittStatus ? "COMPLETED" : "PENDING"}
|
||||||
? "COMPLETED" : "PENDING"}
|
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.finalStatusRow}>
|
<View style={styles.finalStatusRow}>
|
||||||
<Text style={styles.finalStatusLabel}>Bidding Status:</Text>
|
<Text style={[styles.finalStatusLabel, { fontFamily: FontsFamily.poppinsMedium }]}>Bidding Status:</Text>
|
||||||
<Text style={[styles.finalStatusValue,
|
<Text style={[styles.finalStatusValue, { color: tenderData.biddingStatus ? colors.success : colors.error, fontFamily: FontsFamily.poppinsSemiBold }]}>
|
||||||
{ color: tenderData?.biddingStatus ? colors.success : colors.error }]}>
|
{tenderData.biddingStatus ? "ACTIVE" : "CLOSED"}
|
||||||
{tenderData?.biddingStatus ? "ACTIVE" : "CLOSED"}
|
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={styles.footerSpace} />
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
|
{/* Footer */}
|
||||||
|
|
||||||
<View style={styles.footer}>
|
<View style={styles.footer}>
|
||||||
{
|
{
|
||||||
tenderData?.proceedtoBid && !tenderData?.viewBid && tenderData?.biddingStatus && tenderData?.bidWithdrawStatus === false ? (
|
tenderData?.proceedtoBid && !tenderData?.viewBid && tenderData?.biddingStatus && tenderData?.bidWithdrawStatus === false ? (
|
||||||
|
|
||||||
<TouchableOpacity style={styles.proceedButton} onPress={handleStartBidding}>
|
<TouchableOpacity style={styles.proceedButton} onPress={handleStartBidding}>
|
||||||
<Text style={styles.proceedButtonText}>Start Bidding</Text>
|
<Text style={[styles.proceedButtonText, { fontFamily: FontsFamily.poppinsSemiBold }]}>Start Bidding</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
) : <Text style={[styles.footerText, { fontFamily: FontsFamily.poppinsMedium }]}>One time bidding is completed</Text>
|
||||||
) : <Text style={styles.footerText}>One time bidding is completed</Text>
|
}
|
||||||
} </View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
)
|
export default ProceedToBidDetail;
|
||||||
}
|
|
||||||
|
|
||||||
export default ProceedToBidDetail
|
|
||||||
|
|
||||||
|
// Styles remain mostly unchanged but improved shadows, spacing, and rounded corners
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: { flex: 1, padding: 16 },
|
||||||
flex: 1,
|
headerCard: { backgroundColor: colors.white, borderRadius: 14, padding: 20, marginBottom: 20, borderLeftWidth: 4, borderLeftColor: colors.primary, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 5, elevation: 5 },
|
||||||
padding: 16,
|
tenderHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 12 },
|
||||||
marginBottom: 60,
|
tenderNumber: { fontSize: 22, fontWeight: 'bold', color: colors.primary },
|
||||||
},
|
tenderId: { fontSize: 14, color: colors.darkGray, marginTop: 4 },
|
||||||
headerCard: {
|
statusBadge: { paddingHorizontal: 12, paddingVertical: 6, borderRadius: 20 },
|
||||||
backgroundColor: colors.primaryLight,
|
statusBadgeText: { color: colors.white, fontWeight: '600', fontSize: 12 },
|
||||||
borderRadius: 12,
|
workDescription: { fontSize: 13, color: colors.black, marginBottom: 16, fontFamily: FontsFamily.poppinsMedium },
|
||||||
padding: 20,
|
headerInfoRow: { flexDirection: 'row', alignItems: 'center', backgroundColor: colors.lightestGray, borderRadius: 8, padding: 12 },
|
||||||
marginBottom: 20,
|
headerInfoItem: { flex: 1, alignItems: 'center' },
|
||||||
borderLeftWidth: 4,
|
headerInfoLabel: { fontSize: 12, color: colors.darkGray, marginBottom: 4 },
|
||||||
borderLeftColor: colors.primary,
|
headerInfoValue: { fontSize: 16, fontWeight: '600', color: colors.primary },
|
||||||
},
|
separator: { width: 1, height: 30, backgroundColor: colors.lightGray },
|
||||||
tenderHeader: {
|
section: { marginBottom: 20 },
|
||||||
flexDirection: 'row',
|
sectionTitle: { fontSize: 18, fontWeight: '600', marginBottom: 12, paddingLeft: 4 },
|
||||||
justifyContent: 'space-between',
|
statusGrid: { backgroundColor: colors.white, borderRadius: 14, padding: 16, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 5, elevation: 3 },
|
||||||
alignItems: 'center',
|
statusContainer: { flexDirection: 'row', alignItems: 'center', marginBottom: 12 },
|
||||||
marginBottom: 12,
|
statusDot: { width: 12, height: 12, borderRadius: 6, marginRight: 10 },
|
||||||
},
|
statusText: { fontSize: 15, fontWeight: '500' },
|
||||||
tenderNumber: {
|
envelopeCard: { backgroundColor: colors.white, borderRadius: 14, padding: 16, marginBottom: 12, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.05, shadowRadius: 4, elevation: 2 },
|
||||||
fontSize: 22,
|
cardHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 },
|
||||||
fontWeight: 'bold',
|
cardTitle: { fontSize: 16, fontWeight: '600', color: colors.black },
|
||||||
color: colors.primary,
|
envelopeBadge: { paddingHorizontal: 10, paddingVertical: 4, borderRadius: 12 },
|
||||||
},
|
envelopeBadgeText: { color: colors.white, fontWeight: 'bold', fontSize: 12 },
|
||||||
tenderId: {
|
logDetailRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 },
|
||||||
fontSize: 14,
|
label: { fontSize: 14, color: colors.black, flex: 1, fontFamily: FontsFamily.poppinsSemiBold },
|
||||||
color: colors.darkGray,
|
value: { fontSize: 14, color: colors.darkText, flex: 2, textAlign: 'right' },
|
||||||
marginTop: 4,
|
successText: { color: colors.success, fontWeight: '600' },
|
||||||
},
|
detailsCard: { backgroundColor: colors.white, borderRadius: 14, padding: 16, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.05, shadowRadius: 4, elevation: 3 },
|
||||||
statusBadge: {
|
infoRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingVertical: 10, borderBottomWidth: 1, borderBottomColor: colors.lightestGray },
|
||||||
paddingHorizontal: 12,
|
infoLabel: { fontSize: 14, color: colors.black, fontFamily: FontsFamily.poppinsSemiBold },
|
||||||
paddingVertical: 6,
|
infoValue: { fontSize: 15, fontWeight: '500', color: colors.darkText },
|
||||||
borderRadius: 20,
|
highlightedValue: { color: colors.success, fontWeight: '600' },
|
||||||
},
|
timeCard: { backgroundColor: colors.white, borderRadius: 14, padding: 16, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.05, shadowRadius: 4, elevation: 3 },
|
||||||
statusBadgeText: {
|
timeRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingVertical: 12, borderBottomWidth: 1, borderBottomColor: colors.lightestGray },
|
||||||
color: colors.white,
|
timeLabel: { fontSize: 15, color: colors.black, },
|
||||||
fontWeight: '600',
|
timeValue: { fontSize: 15, color: colors.grayText, },
|
||||||
fontSize: 12,
|
chipsContainer: { flexDirection: 'row', flexWrap: 'wrap', gap: 10 },
|
||||||
},
|
chip: { paddingHorizontal: 16, paddingVertical: 8, borderRadius: 20, marginBottom: 8 },
|
||||||
workDescription: {
|
chipText: { fontSize: 14, fontWeight: '500' },
|
||||||
fontSize: 16,
|
finalStatusCard: { backgroundColor: colors.white, borderRadius: 14, padding: 20, marginTop: 10, borderWidth: 2, borderColor: colors.primary, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 5, elevation: 5 },
|
||||||
color: colors.darkText,
|
finalStatusTitle: { fontSize: 18, fontWeight: 'bold', marginBottom: 16, textAlign: 'center' },
|
||||||
lineHeight: 22,
|
finalStatusRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12, paddingVertical: 8, borderBottomWidth: 1, borderBottomColor: 'rgba(0,0,0,0.1)' },
|
||||||
marginBottom: 16,
|
finalStatusLabel: { fontSize: 14, color: colors.black, fontFamily: FontsFamily.poppinsSemiBold },
|
||||||
},
|
finalStatusValue: { fontSize: 13, },
|
||||||
headerInfoRow: {
|
footer: { position: 'absolute', bottom: 0, left: 0, right: 0, backgroundColor: colors.white, padding: 16, borderTopWidth: 1, borderTopColor: colors.lightGray, elevation: 10 },
|
||||||
flexDirection: 'row',
|
proceedButton: { backgroundColor: colors.primary, paddingVertical: 14, borderRadius: 30, alignItems: 'center' },
|
||||||
alignItems: 'center',
|
proceedButtonText: { color: colors.white, fontSize: 16, fontWeight: '600' },
|
||||||
backgroundColor: colors.white,
|
footerText: { textAlign: 'center', color: colors.darkGray, fontSize: 14 },
|
||||||
borderRadius: 8,
|
});
|
||||||
padding: 12,
|
|
||||||
},
|
|
||||||
headerInfoItem: {
|
|
||||||
flex: 1,
|
|
||||||
alignItems: 'center',
|
|
||||||
},
|
|
||||||
headerInfoLabel: {
|
|
||||||
fontSize: 12,
|
|
||||||
color: colors.darkGray,
|
|
||||||
marginBottom: 4,
|
|
||||||
},
|
|
||||||
headerInfoValue: {
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: '600',
|
|
||||||
color: colors.primary,
|
|
||||||
},
|
|
||||||
separator: {
|
|
||||||
width: 1,
|
|
||||||
height: 30,
|
|
||||||
backgroundColor: colors.lightGray,
|
|
||||||
},
|
|
||||||
section: {
|
|
||||||
marginBottom: 20,
|
|
||||||
},
|
|
||||||
sectionTitle: {
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: '600',
|
|
||||||
color: colors.primary,
|
|
||||||
marginBottom: 12,
|
|
||||||
paddingLeft: 4,
|
|
||||||
},
|
|
||||||
statusGrid: {
|
|
||||||
backgroundColor: colors.white,
|
|
||||||
borderRadius: 12,
|
|
||||||
padding: 16,
|
|
||||||
shadowColor: '#000',
|
|
||||||
shadowOffset: { width: 0, height: 2 },
|
|
||||||
shadowOpacity: 0.1,
|
|
||||||
shadowRadius: 4,
|
|
||||||
elevation: 3,
|
|
||||||
},
|
|
||||||
statusContainer: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
marginBottom: 12,
|
|
||||||
},
|
|
||||||
statusDot: {
|
|
||||||
width: 12,
|
|
||||||
height: 12,
|
|
||||||
borderRadius: 6,
|
|
||||||
marginRight: 10,
|
|
||||||
},
|
|
||||||
statusText: {
|
|
||||||
fontSize: 15,
|
|
||||||
fontWeight: '500',
|
|
||||||
},
|
|
||||||
envelopeCard: {
|
|
||||||
backgroundColor: colors.white,
|
|
||||||
borderRadius: 12,
|
|
||||||
padding: 16,
|
|
||||||
marginBottom: 12,
|
|
||||||
borderWidth: 1,
|
|
||||||
borderColor: colors.lightGray,
|
|
||||||
},
|
|
||||||
cardHeader: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
alignItems: 'center',
|
|
||||||
marginBottom: 12,
|
|
||||||
},
|
|
||||||
cardTitle: {
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: '600',
|
|
||||||
color: colors.primary,
|
|
||||||
},
|
|
||||||
envelopeBadge: {
|
|
||||||
paddingHorizontal: 10,
|
|
||||||
paddingVertical: 4,
|
|
||||||
borderRadius: 12,
|
|
||||||
},
|
|
||||||
envelopeBadgeText: {
|
|
||||||
color: colors.white,
|
|
||||||
fontWeight: 'bold',
|
|
||||||
fontSize: 12,
|
|
||||||
},
|
|
||||||
logDetailRow: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
alignItems: 'center',
|
|
||||||
marginBottom: 8,
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
fontSize: 14,
|
|
||||||
color: colors.darkGray,
|
|
||||||
flex: 1,
|
|
||||||
},
|
|
||||||
value: {
|
|
||||||
fontSize: 14,
|
|
||||||
color: colors.darkText,
|
|
||||||
fontWeight: '500',
|
|
||||||
flex: 2,
|
|
||||||
textAlign: 'right',
|
|
||||||
},
|
|
||||||
successText: {
|
|
||||||
color: colors.success,
|
|
||||||
fontWeight: '600',
|
|
||||||
},
|
|
||||||
detailsCard: {
|
|
||||||
backgroundColor: colors.white,
|
|
||||||
borderRadius: 12,
|
|
||||||
padding: 16,
|
|
||||||
shadowColor: '#000',
|
|
||||||
shadowOffset: { width: 0, height: 2 },
|
|
||||||
shadowOpacity: 0.1,
|
|
||||||
shadowRadius: 4,
|
|
||||||
elevation: 3,
|
|
||||||
},
|
|
||||||
infoRow: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
alignItems: 'center',
|
|
||||||
paddingVertical: 10,
|
|
||||||
borderBottomWidth: 1,
|
|
||||||
borderBottomColor: colors.lightestGray,
|
|
||||||
},
|
|
||||||
infoLabel: {
|
|
||||||
fontSize: 14,
|
|
||||||
color: colors.darkGray,
|
|
||||||
},
|
|
||||||
infoValue: {
|
|
||||||
fontSize: 15,
|
|
||||||
fontWeight: '500',
|
|
||||||
color: colors.darkText,
|
|
||||||
},
|
|
||||||
highlightedValue: {
|
|
||||||
color: colors.success,
|
|
||||||
fontWeight: '600',
|
|
||||||
},
|
|
||||||
timeCard: {
|
|
||||||
backgroundColor: colors.white,
|
|
||||||
borderRadius: 12,
|
|
||||||
padding: 16,
|
|
||||||
shadowColor: '#000',
|
|
||||||
shadowOffset: { width: 0, height: 2 },
|
|
||||||
shadowOpacity: 0.1,
|
|
||||||
shadowRadius: 4,
|
|
||||||
elevation: 3,
|
|
||||||
},
|
|
||||||
timeRow: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
alignItems: 'center',
|
|
||||||
paddingVertical: 12,
|
|
||||||
borderBottomWidth: 1,
|
|
||||||
borderBottomColor: colors.lightestGray,
|
|
||||||
},
|
|
||||||
timeLabel: {
|
|
||||||
fontSize: 15,
|
|
||||||
color: colors.darkGray,
|
|
||||||
fontWeight: '500',
|
|
||||||
},
|
|
||||||
timeValue: {
|
|
||||||
fontSize: 15,
|
|
||||||
color: colors.primary,
|
|
||||||
fontWeight: '600',
|
|
||||||
},
|
|
||||||
chipsContainer: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
gap: 10,
|
|
||||||
},
|
|
||||||
chip: {
|
|
||||||
paddingHorizontal: 16,
|
|
||||||
paddingVertical: 8,
|
|
||||||
borderRadius: 20,
|
|
||||||
marginBottom: 8,
|
|
||||||
},
|
|
||||||
chipText: {
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: '500',
|
|
||||||
},
|
|
||||||
finalStatusCard: {
|
|
||||||
backgroundColor: colors.primaryLight,
|
|
||||||
borderRadius: 12,
|
|
||||||
padding: 20,
|
|
||||||
marginTop: 10,
|
|
||||||
borderWidth: 2,
|
|
||||||
borderColor: colors.primary,
|
|
||||||
},
|
|
||||||
finalStatusTitle: {
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: 'bold',
|
|
||||||
color: colors.primary,
|
|
||||||
marginBottom: 16,
|
|
||||||
textAlign: 'center',
|
|
||||||
},
|
|
||||||
finalStatusRow: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
alignItems: 'center',
|
|
||||||
marginBottom: 12,
|
|
||||||
paddingVertical: 8,
|
|
||||||
borderBottomWidth: 1,
|
|
||||||
borderBottomColor: 'rgba(0, 0, 0, 0.1)',
|
|
||||||
},
|
|
||||||
finalStatusLabel: {
|
|
||||||
fontSize: 16,
|
|
||||||
color: colors.darkText,
|
|
||||||
fontWeight: '500',
|
|
||||||
},
|
|
||||||
finalStatusValue: {
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: 'bold',
|
|
||||||
},
|
|
||||||
footerSpace: {
|
|
||||||
height: 30,
|
|
||||||
},
|
|
||||||
success: {
|
|
||||||
color: colors.success,
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
color: colors.error,
|
|
||||||
},
|
|
||||||
primary: {
|
|
||||||
color: colors.primary,
|
|
||||||
},
|
|
||||||
warning: {
|
|
||||||
color: colors.warning,
|
|
||||||
},
|
|
||||||
successLight: {
|
|
||||||
backgroundColor: colors.successLight,
|
|
||||||
},
|
|
||||||
lightGray: {
|
|
||||||
backgroundColor: colors.lightGray,
|
|
||||||
},
|
|
||||||
footer: {
|
|
||||||
position: 'absolute',
|
|
||||||
bottom: 0,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
backgroundColor: colors.white,
|
|
||||||
padding: 16,
|
|
||||||
borderTopWidth: 1,
|
|
||||||
borderTopColor: colors.lightGray,
|
|
||||||
elevation: 10,
|
|
||||||
},
|
|
||||||
proceedButton: {
|
|
||||||
backgroundColor: colors.primary,
|
|
||||||
paddingVertical: 14,
|
|
||||||
borderRadius: 30,
|
|
||||||
alignItems: 'center',
|
|
||||||
},
|
|
||||||
proceedButtonText: {
|
|
||||||
color: colors.white,
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: '600',
|
|
||||||
},
|
|
||||||
footerText: {
|
|
||||||
textAlign: 'center',
|
|
||||||
color: colors.darkGray,
|
|
||||||
fontSize: 14,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,29 +1,14 @@
|
|||||||
import React, { use, useEffect } from 'react';
|
import React, { use, useEffect } from 'react';
|
||||||
import {
|
import { View, Text, StyleSheet, TouchableOpacity, Platform } from 'react-native';
|
||||||
View,
|
import Animated, { FadeInUp, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
|
||||||
Text,
|
|
||||||
StyleSheet,
|
|
||||||
TouchableOpacity,
|
|
||||||
Platform,
|
|
||||||
Alert,
|
|
||||||
} from 'react-native';
|
|
||||||
import Animated, {
|
|
||||||
FadeInUp,
|
|
||||||
useAnimatedStyle,
|
|
||||||
useSharedValue,
|
|
||||||
withTiming,
|
|
||||||
} from 'react-native-reanimated';
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import CountdownTimer from '../../Component/Counter/CountdownTimer';
|
import CountdownTimer from '../../Component/Counter/CountdownTimer';
|
||||||
import colors from '../../Constant/Color';
|
import colors from '../../Constant/Color';
|
||||||
import { useFetchTenderById, useProceedToBid } from '../../Services/BBPS/Hooks';
|
import { useFetchTenderById } from '../../Services/BBPS/Hooks';
|
||||||
import { useNavigation } from '@react-navigation/native';
|
import { useNavigation } from '@react-navigation/native';
|
||||||
import TenderFullDetail from './Modal/TenderFullDetail';
|
import TenderFullDetail from './Modal/TenderFullDetail';
|
||||||
|
|
||||||
const PurchaseTenderTile = ({
|
const PurchaseTenderTile = ({ item, onPressDetails }: any) => {
|
||||||
item,
|
|
||||||
onPressDetails,
|
|
||||||
}: any) => {
|
|
||||||
const scale = useSharedValue(1);
|
const scale = useSharedValue(1);
|
||||||
const elevation = useSharedValue(8);
|
const elevation = useSharedValue(8);
|
||||||
const navigation = useNavigation<any>();
|
const navigation = useNavigation<any>();
|
||||||
@@ -36,15 +21,6 @@ const PurchaseTenderTile = ({
|
|||||||
const { data: tenderResponse, }: any = useFetchTenderById(item?.tenderId);
|
const { data: tenderResponse, }: any = useFetchTenderById(item?.tenderId);
|
||||||
const tender = tenderResponse?.data;
|
const tender = tenderResponse?.data;
|
||||||
|
|
||||||
// console.log("item my : ", item)
|
|
||||||
|
|
||||||
{
|
|
||||||
if (item?.nitNumber == 'TN/111') {
|
|
||||||
console.log("tender item : ", item?.nitNumber)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlePressIn = () => {
|
const handlePressIn = () => {
|
||||||
scale.value = withTiming(0.97, { duration: 120 });
|
scale.value = withTiming(0.97, { duration: 120 });
|
||||||
elevation.value = withTiming(3, { duration: 120 });
|
elevation.value = withTiming(3, { duration: 120 });
|
||||||
@@ -61,11 +37,6 @@ const PurchaseTenderTile = ({
|
|||||||
const lightStatusBg = isLive ? '#EFF6FF' : '#F8FAFC';
|
const lightStatusBg = isLive ? '#EFF6FF' : '#F8FAFC';
|
||||||
const [showDetail, setShowDetail] = React.useState(false);
|
const [showDetail, setShowDetail] = React.useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if(item?.tenderNumber == 'TN/210'){
|
|
||||||
console.log("tender item : ", item)
|
|
||||||
}
|
|
||||||
}, [item]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Animated.View
|
<Animated.View
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ const Screens = {
|
|||||||
Emd,
|
Emd,
|
||||||
StartBidding,
|
StartBidding,
|
||||||
PurchaseAuctionList,
|
PurchaseAuctionList,
|
||||||
|
StartReverseBidding,
|
||||||
PurchaseTenderList,
|
PurchaseTenderList,
|
||||||
ProceedToPurTender,
|
ProceedToPurTender,
|
||||||
TenderBidding,
|
TenderBidding,
|
||||||
|
|||||||
@@ -62,7 +62,13 @@ const ITEM_DOCUMENT_DOWNLOAD = `${BASE_URL_Auction}api/auction/home/downloadDocu
|
|||||||
|
|
||||||
// Rohit
|
// Rohit
|
||||||
const DASHBOARD_COUNT = `${BASE_URL_Auction}api/auction/home/dashboard/counts`
|
const DASHBOARD_COUNT = `${BASE_URL_Auction}api/auction/home/dashboard/counts`
|
||||||
const AUCTION_ONE_TIME_BID =`${BASE_URL_Auction}api/bidding/getBidForAuction`
|
const AUCTION_ONE_TIME_BID = `${BASE_URL_Auction}api/bidding/getBidForAuction`
|
||||||
|
const AUCITON_SINGLE_EMD = `${BASE_URL_Auction}api/auction/addEMDDocumentsAuctionWise`
|
||||||
|
const PURCHASE_AUCTION_LIST = `${BASE_URL_Auction}api/auction/proceedToPurchase`
|
||||||
|
const VIEW_AUCTION_ITEM_DETAIL = `${BASE_URL_Auction}api/auction/home/viewDocumentsForAuctionItemDetails`
|
||||||
|
const VIEW_AUCTION_DOCUMENTS = `${BASE_URL_Auction}api/auction/viewDocumentsForAuction`
|
||||||
|
const AUCTION_DOCUMENT_DOWNLOAD = `${BASE_URL_Auction}api/auction/home/downloadDocumentForAuction`
|
||||||
|
const AUCTION_ITEM_DOCUMENT_DOWNLOAD = `${BASE_URL_Auction}api/auction/home/downloadDocument/auctionItemId`
|
||||||
|
|
||||||
|
|
||||||
//tender
|
//tender
|
||||||
@@ -78,9 +84,15 @@ const SUBMIT_ENVELOPE_FILE_B = `${BASE_URL}tenderBidding/addDocumentsEnvelopeB?r
|
|||||||
|
|
||||||
export {
|
export {
|
||||||
// Rohit
|
// Rohit
|
||||||
|
VIEW_AUCTION_ITEM_DETAIL,
|
||||||
|
AUCTION_ITEM_DOCUMENT_DOWNLOAD,
|
||||||
|
AUCTION_DOCUMENT_DOWNLOAD,
|
||||||
|
VIEW_AUCTION_DOCUMENTS,
|
||||||
|
AUCITON_SINGLE_EMD,
|
||||||
DASHBOARD_COUNT,
|
DASHBOARD_COUNT,
|
||||||
AUCTION_ONE_TIME_BID,
|
AUCTION_ONE_TIME_BID,
|
||||||
ITEM_DOCUMENT_DOWNLOAD,
|
ITEM_DOCUMENT_DOWNLOAD,
|
||||||
|
PURCHASE_AUCTION_LIST,
|
||||||
ITEM_DETAIL,
|
ITEM_DETAIL,
|
||||||
TECHNICAL_DOCUMENT_SUBMIT,
|
TECHNICAL_DOCUMENT_SUBMIT,
|
||||||
TECHNICAL_VALUE_SUBMIT,
|
TECHNICAL_VALUE_SUBMIT,
|
||||||
|
|||||||
+13
-10
@@ -62,6 +62,7 @@ export const useFetchLiveTender = () => {
|
|||||||
queryFn: () => fetchLiveTender()
|
queryFn: () => fetchLiveTender()
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useFetchPurchaseAuction = () => {
|
export const useFetchPurchaseAuction = () => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: ['fetchPurchaseAuction',],
|
queryKey: ['fetchPurchaseAuction',],
|
||||||
@@ -69,25 +70,28 @@ export const useFetchPurchaseAuction = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const useFetchLiveAuction = () => {
|
export const useFetchLiveAuction = () => {
|
||||||
return useInfiniteQuery<any>({
|
return useInfiniteQuery<any>({
|
||||||
queryKey: ['fetchLiveAuction',],
|
queryKey: ['fetchLiveAuction'],
|
||||||
queryFn: ({ pageParam = 1 }) =>
|
queryFn: ({ pageParam = 0 }) =>
|
||||||
fetchLiveAuction({
|
fetchLiveAuction({
|
||||||
page: pageParam,
|
page: pageParam,
|
||||||
size: 10,
|
size: 10,
|
||||||
}),
|
}),
|
||||||
initialPageParam: 1,
|
initialPageParam: 0,
|
||||||
getNextPageParam: (lastPage) => {
|
|
||||||
const { page, size, totalCount } = lastPage;
|
getNextPageParam: (lastPage, allPages) => {
|
||||||
|
const { size, totalCount } = lastPage;
|
||||||
const totalPages = Math.ceil(totalCount / size);
|
const totalPages = Math.ceil(totalCount / size);
|
||||||
const nextPage = page + 1;
|
const nextPage = allPages.length;
|
||||||
return nextPage < totalPages ? nextPage : undefined;
|
return nextPage < totalPages ? nextPage : undefined;
|
||||||
},
|
},
|
||||||
select: (data) => {
|
|
||||||
|
|
||||||
const mergedResults = data.pages.flatMap((page: any) => page.data ?? []);
|
select: (data) => {
|
||||||
|
const mergedResults = data.pages.flatMap(
|
||||||
|
(page: any) => page?.data ?? []
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...data,
|
...data,
|
||||||
result: mergedResults,
|
result: mergedResults,
|
||||||
@@ -97,7 +101,6 @@ export const useFetchLiveAuction = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Auction Purchase offline
|
// Auction Purchase offline
|
||||||
|
|
||||||
export const useOfflineAuctionPurchase = () => {
|
export const useOfflineAuctionPurchase = () => {
|
||||||
|
|||||||
+21
-191
@@ -1,5 +1,5 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { ALL_DESIGNATION, DASHBOARD_COUNT, EMD_CHECK, FORARD_AUCTION_ITEM, GET_MASTER_DATA, GET_MY_AUCTION, GET_MY_TENDER, GET_REGISTRATION_STATE, GET_TENDER_DETAILS, GETCONTRACTORBYSTATE, LIVE_AUCTION, LIVE_TENDER, LOG_IN_URL, PARTNER_API_ENDPOINT, PROCEED_PURCHASE_AUCTION, PROCEED_TO_BID, PURCHASE_OFFLINE_AUCTION, PURCHASE_TENDER_OFFLINE, SUBMIT_ENVELOPE_A, SUBMIT_ENVELOPE_B, SUBMIT_ENVELOPE_FILE_A, SUBMIT_ENVELOPE_FILE_B, REJ_STAGE_TWO, REVERSE_AUCTION_ITEM, SAVE_CONTRACTOR_STAGE1, SEND_ADHAROTP, STAGETHREE, TENDER_LOGIN, VERIFY_ADHAR, VERIFY_GST,VERIFY_ORGPAN } 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 } from "./ApiUrls";
|
||||||
import { apiCall } from "../../Axios/Axios";
|
import { apiCall } from "../../Axios/Axios";
|
||||||
|
|
||||||
// User
|
// User
|
||||||
@@ -24,31 +24,14 @@ type City = { id: number; name: string };
|
|||||||
|
|
||||||
export const userLogin = async (payload: { emailAdd: string, password: string }): Promise<any> => {
|
export const userLogin = async (payload: { emailAdd: string, password: string }): Promise<any> => {
|
||||||
try {
|
try {
|
||||||
// const response = await axios.post(LOG_IN_URL, { ...payload, divice: "mobileApp" });
|
const response = await axios.post(LOG_IN_URL, { ...payload, divice: "mobileApp" });
|
||||||
const response = await axios.post(TENDER_LOGIN, { ...payload, device: "mobileApp" });
|
// const response = await axios.post(TENDER_LOGIN, { ...payload, device: "mobileApp" });
|
||||||
return response.data;
|
|
||||||
} catch (error: any) {
|
|
||||||
throw error.response?.data || error.message;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
export const userAuctionLogin = async (payload: { emailAdd: string, password: string }): Promise<any> => {
|
|
||||||
try {
|
|
||||||
const response = await axios.post(LOG_IN_URL, { ...payload, device: "mobileApp" });
|
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
throw error.response?.data || error.message;
|
throw error.response?.data || error.message;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const registerContractor = async (payload: any): Promise<any> => {
|
|
||||||
console.log("registerContractor payload : ", payload)
|
|
||||||
try {
|
|
||||||
const response = await axios.post(SAVE_CONTRACTOR_STAGE1, { ...payload, device: "mobileApp" });
|
|
||||||
return response.data;
|
|
||||||
} catch (error: any) {
|
|
||||||
throw error.response?.data || error.message;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
export const fetchDashboard = async (): Promise<any> => {
|
export const fetchDashboard = async (): Promise<any> => {
|
||||||
const data = await apiCall<any>('get', `${DASHBOARD_COUNT}`);
|
const data = await apiCall<any>('get', `${DASHBOARD_COUNT}`);
|
||||||
return data
|
return data
|
||||||
@@ -59,7 +42,7 @@ export const fetchPurchaseAuction = async (): Promise<any> => {
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
export const fetchLiveAuction = async (payload: any): Promise<any> => {
|
export const fetchLiveAuction = async (payload: any): Promise<any> => {
|
||||||
const data = await apiCall<any>('get', `${LIVE_AUCTION}`, {}, { payload });
|
const data = await apiCall<any>('get', `${LIVE_AUCTION}`, {}, payload);
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,179 +129,26 @@ export const proceedToBid = async (tenderId: string): Promise<any> => {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getDesignation = async (): Promise<any> => {
|
|
||||||
const data = await axios.get(ALL_DESIGNATION).then((response) => response.data);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getRagistrationState = async (): Promise<any> => {
|
|
||||||
const data = await apiCall<any>(
|
|
||||||
'get',
|
|
||||||
`${GET_REGISTRATION_STATE}`
|
|
||||||
);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
export const fetchPurchaseAuctionList = async (payload: any): Promise<any> => {
|
||||||
////////////////////////////////////////////////////////////////////
|
const data = await apiCall<any>('post', `${PURCHASE_AUCTION_LIST}`, payload);
|
||||||
|
|
||||||
export const fetchMasterData = async (): Promise<any> => {
|
|
||||||
const data = await apiCall<any>(
|
|
||||||
'get',
|
|
||||||
`${GET_MASTER_DATA}`
|
|
||||||
);
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export const fetchCityDropdown = async (stateId: number): Promise<any> => {
|
|
||||||
const res = await apiCall<{ statusCode: number; data: City[] }>(
|
|
||||||
'get',
|
|
||||||
`${GETCONTRACTORBYSTATE}?stateId=${stateId}`,
|
|
||||||
);
|
|
||||||
console.log("--",res)
|
|
||||||
if (res.statusCode !== 200 || !res.data) {
|
|
||||||
throw new Error('Failed load cities');
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.data.map(item => ({
|
|
||||||
label: item.name,
|
|
||||||
value: item.id,
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const verifyPanHandler = (
|
|
||||||
payload: {
|
|
||||||
dob: string;
|
|
||||||
name: string;
|
|
||||||
panNumber: string;
|
|
||||||
}
|
|
||||||
): Promise<any> => {
|
|
||||||
return apiCall<any>(
|
|
||||||
'post',
|
|
||||||
VERIFY_ORGPAN,
|
|
||||||
payload,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export const sendAadhaarOtp = (
|
|
||||||
payload: any
|
|
||||||
): Promise<any> => {
|
|
||||||
return apiCall<any>('post', SEND_ADHAROTP, payload);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export type VerifyAadhaarOtpPayload = {
|
|
||||||
otp: string;
|
|
||||||
refNumber: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const verifyAadhaarOtp = (
|
|
||||||
payload: {
|
|
||||||
otp: string;
|
|
||||||
refNumber: string;
|
|
||||||
}
|
|
||||||
): Promise<any> => {
|
|
||||||
return apiCall<any>(
|
|
||||||
'post',
|
|
||||||
VERIFY_ADHAR,
|
|
||||||
payload,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export type VerifyGstPayload = {
|
|
||||||
gstNumber: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const verifyGstNumber = (
|
|
||||||
payload: {
|
|
||||||
gstNumber: string;
|
|
||||||
}
|
|
||||||
): Promise<any> => {
|
|
||||||
return apiCall<any>(
|
|
||||||
'post',
|
|
||||||
VERIFY_GST,
|
|
||||||
payload,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
export const contractorStageTwoSubmit = (
|
|
||||||
fileData: any
|
|
||||||
): Promise<any> => {
|
|
||||||
return apiCall<any>(
|
|
||||||
'post',
|
|
||||||
REJ_STAGE_TWO,
|
|
||||||
fileData,
|
|
||||||
undefined,
|
|
||||||
'multipart/form-data'
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const contractorStageThreeSubmit = (
|
|
||||||
payload: any
|
|
||||||
): Promise<any> => {
|
|
||||||
return apiCall<any>(
|
|
||||||
'post',
|
|
||||||
STAGETHREE,
|
|
||||||
payload,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const partnerShipSubmit = (
|
|
||||||
payload: any
|
|
||||||
): Promise<any> => {
|
|
||||||
return apiCall<any>(
|
|
||||||
'post',
|
|
||||||
PARTNER_API_ENDPOINT,
|
|
||||||
payload,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const submitEnvelopeA = async (payload: any) => {
|
|
||||||
console.log('SUBMIT ENVELOPE A API CALLED', payload)
|
|
||||||
const { data } = await apiCall<any>('post', SUBMIT_ENVELOPE_A, payload)
|
|
||||||
console.log("data : ", data)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
export const submitEnvelopeB = async (payload: any) => {
|
|
||||||
console.log('SUBMIT ENVELOPE B API CALLED', payload)
|
|
||||||
const { data } = await apiCall<any>('post', SUBMIT_ENVELOPE_B, payload)
|
|
||||||
console.log("data : ", data)
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getAuction = async (payload: any) => {
|
||||||
export const uploadEnvelopeFile = async ({
|
const selectedRes = await apiCall<any>('get', GET_AUCTION_DETAILS, {}, { id: payload.auctionId });
|
||||||
activeEnvelope,
|
return selectedRes.data;
|
||||||
file,
|
|
||||||
payload,
|
|
||||||
}: UploadArgs) => {
|
|
||||||
const formData = new FormData()
|
|
||||||
|
|
||||||
formData.append('files', {
|
|
||||||
uri: file.uri,
|
|
||||||
name: file.name,
|
|
||||||
type: file.type,
|
|
||||||
} as any)
|
|
||||||
|
|
||||||
formData.append('requestDto', JSON.stringify(payload))
|
|
||||||
|
|
||||||
const url =
|
|
||||||
activeEnvelope === 'B' ? SUBMIT_ENVELOPE_FILE_B : SUBMIT_ENVELOPE_FILE_A
|
|
||||||
|
|
||||||
const data = await apiCall('post', url, formData, {
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'multipart/form-data',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
return data
|
|
||||||
}
|
}
|
||||||
|
export const viewAuctionItemDocuments = async (payload: { auctionItemId: number }) => {
|
||||||
|
const selectedRes = await apiCall<any>('get', VIEW_AUCTION_ITEM_DETAIL, {}, payload);
|
||||||
|
return selectedRes.data;
|
||||||
|
}
|
||||||
|
export const viewAuctionDocuments = async (payload: { auctionId: number }) => {
|
||||||
|
const selectedRes = await apiCall<any>('get', VIEW_AUCTION_DOCUMENTS, {}, payload);
|
||||||
|
return selectedRes.data;
|
||||||
|
}
|
||||||
|
export const viewAuctionDocumentDownload = async (payload: { documentId: number, isAmendment: boolean }) => {
|
||||||
|
const selectedRes = await apiCall<any>('get', AUCTION_DOCUMENT_DOWNLOAD, {}, payload);
|
||||||
|
return selectedRes.data;
|
||||||
|
}
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 44 KiB |
@@ -1,5 +1,5 @@
|
|||||||
// import React, { useCallback, useEffect, useState } from 'react';
|
// import React, { useCallback, useEffect, useState } from 'react';
|
||||||
// import { View, FlatList, StyleSheet, Platform, Alert, BackHandler, Text, ToastAndroid } from 'react-native';
|
// import { View, FlatList, StyleSheet, Platform, Alert, BackHandler, Text } from 'react-native';
|
||||||
// import LottieView from 'lottie-react-native';
|
// import LottieView from 'lottie-react-native';
|
||||||
// import { InsideHeader } from '../../Component/Index';
|
// import { InsideHeader } from '../../Component/Index';
|
||||||
// import colors from '../../Constant/Color';
|
// import colors from '../../Constant/Color';
|
||||||
@@ -36,12 +36,13 @@
|
|||||||
// if (SelectedAuction.auctionPattern === 'Forward') {
|
// if (SelectedAuction.auctionPattern === 'Forward') {
|
||||||
// const res = await apiCall<any>('get', FORWARD_AUCTION_ITEM, {}, payload);
|
// const res = await apiCall<any>('get', FORWARD_AUCTION_ITEM, {}, payload);
|
||||||
// if (res?.statusCode === 200) auctionItem = res.data || [];
|
// if (res?.statusCode === 200) auctionItem = res.data || [];
|
||||||
// } else if(SelectedAuction.auctionPattern === 'Reverse') {
|
// } else {
|
||||||
// const res = await apiCall<any>('get', REVERSE_AUCTION_ITEM, {}, payload);
|
// const res = await apiCall<any>('get', REVERSE_AUCTION_ITEM, {}, payload);
|
||||||
// if (res?.statusCode === 200) auctionItem = res.data || [];
|
// if (res?.statusCode === 200) auctionItem = res.data || [];
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// const selectedRes = await apiCall<any>('get', SELECTED_AUCTION_ITEM, {}, payload);
|
// const selectedRes = await apiCall<any>('get', SELECTED_AUCTION_ITEM, {}, payload);
|
||||||
|
// console.log(selectedRes, 'jhhhhhhhhhh');
|
||||||
|
|
||||||
// const uniqueArray: number[] = Array.from(
|
// const uniqueArray: number[] = Array.from(
|
||||||
// new Set(selectedRes?.data || [])
|
// new Set(selectedRes?.data || [])
|
||||||
@@ -98,7 +99,7 @@
|
|||||||
// };
|
// };
|
||||||
|
|
||||||
// subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, async (message) => {
|
// subscribe(`/topic/room/${SelectedAuction.auctionNumber}`, async (message) => {
|
||||||
|
// // console.log('RAW MESSAGE:', message[message.length - 1]);
|
||||||
// const result = message[message.length - 1]
|
// const result = message[message.length - 1]
|
||||||
|
|
||||||
// const updatedBidItem = (prev: any[]) =>
|
// const updatedBidItem = (prev: any[]) =>
|
||||||
@@ -160,6 +161,7 @@
|
|||||||
// {
|
// {
|
||||||
// text: 'Submit',
|
// text: 'Submit',
|
||||||
// onPress: () => {
|
// onPress: () => {
|
||||||
|
|
||||||
// placeBidSubmit(payload);
|
// placeBidSubmit(payload);
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
@@ -180,7 +182,6 @@
|
|||||||
// : item
|
// : item
|
||||||
// );
|
// );
|
||||||
|
|
||||||
// // ToastAndroid.show(result.message, ToastAndroid.SHORT)
|
|
||||||
// // setItems(updatedBidItem);
|
// // setItems(updatedBidItem);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user