first commit
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { View, Text, Image, Platform, ImageBackground } from 'react-native';
|
||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||
import IMAGES from '../../../constants/Images';
|
||||
import { styles } from './style';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import CustomTextInput from '../../../components/CustomTextInput';
|
||||
import CustomButton from '../../../components/CustomButton';
|
||||
import Loader from '../../../constants/Loader';
|
||||
import { ApiURL } from '../../../api/ApiConstant';
|
||||
import { toastError, toastSuccess } from '../../../constants/Toast';
|
||||
import axios from 'axios';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { GlobalTheme } from '../../../theme';
|
||||
import Geolocation from '@react-native-community/geolocation';
|
||||
|
||||
|
||||
const Login = ({ navigation }) => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const dispatch = useDispatch();
|
||||
const [username, setUsername] = useState('');
|
||||
|
||||
|
||||
// geo loc
|
||||
useEffect(() => {
|
||||
Geolocation.getCurrentPosition(info => console.log("Location infoooo====>", JSON.stringify(info)));
|
||||
}, [])
|
||||
// end geo loc
|
||||
|
||||
|
||||
const onSubmit = () => {
|
||||
setLoading(true);
|
||||
getOTP();
|
||||
};
|
||||
|
||||
const getOTP = async () => {
|
||||
try {
|
||||
const params = {
|
||||
"UserId": username
|
||||
};
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: ApiURL.getotpApi,
|
||||
headers: {
|
||||
'api_key': '9a1f056fecb84eaf8eb4152dda22ab0501955c4f9bbe7daa8780740459fdde7a',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: params
|
||||
};
|
||||
|
||||
const response = await axios.request(config);
|
||||
const res = response.data || [];
|
||||
console.log('OTP is ===> ', res?.SendOTP);
|
||||
if (res?.SendOTP[0].OTP === '0' || res?.SendOTP[0].OTP === 0) {
|
||||
setLoading(false);
|
||||
toastError("Alert", "Invalid User");
|
||||
} else {
|
||||
toastSuccess("Alert", res?.SendOTP[0]?.Messages);
|
||||
navigation.navigate('VerifyOTP', { username: username });
|
||||
setLoading(false);
|
||||
}
|
||||
// console.log('getotpApi res==>', JSON.stringify(res?.SendOTP[0]));
|
||||
} catch (error) {
|
||||
console.log("❌ OTP API error:", error);
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<KeyboardAwareScrollView keyboardShouldPersistTaps="handled" enableOnAndroid={true} contentContainerStyle={{ justifyContent: 'center', flexGrow: 1, marginTop: 0 }} style={styles.container}>
|
||||
<View style={{ backgroundColor: GlobalTheme.colors.primary, height: 40 }} />
|
||||
<Image style={styles.appLogo} source={IMAGES.AuthTopBGNew} resizeMode='contain' />
|
||||
<View style={styles.card}>
|
||||
<Text style={styles.loginTitle}>Login</Text>
|
||||
<CustomTextInput
|
||||
label="Username"
|
||||
placeholder="Enter username"
|
||||
value={username}
|
||||
onChangeText={setUsername}
|
||||
containerStyle={styles.inputWrapper}
|
||||
/>
|
||||
<CustomButton onPress={() => onSubmit()} title={'Continue'} style={styles.btnbg} textstyle={styles.btntext} />
|
||||
<ImageBackground source={IMAGES.AuthBottomBG} style={styles.AuthBottomBG} >
|
||||
<Text style={{ position: 'absolute', textAlign: 'center', alignContent: 'center', alignSelf: 'center', bottom: 0, color: GlobalTheme.colors.gray }}> Copyright CPM India - 2025</Text>
|
||||
{/* <Image source={IMAGES.Logo} style={styles.footerImage} resizeMode="contain"/> */}
|
||||
</ImageBackground>
|
||||
</View>
|
||||
</KeyboardAwareScrollView>
|
||||
<Loader visible={loading} loadingtext={'Loading ...'} />
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
|
||||
export default Login;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<<<<<<< HEAD
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import { GlobalTheme, Screen } from '../../../theme';
|
||||
@@ -33,3 +34,87 @@ export const styles = StyleSheet.create({
|
||||
}
|
||||
|
||||
});
|
||||
=======
|
||||
import { StyleSheet, Dimensions } from 'react-native';
|
||||
import { GlobalTheme } from '../../../theme';
|
||||
import { normalize } from '../../../utilis/responsive';
|
||||
const { width, height } = Dimensions.get('window');
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: GlobalTheme.colors.primary,
|
||||
},
|
||||
logoContainer: {
|
||||
width: '100%',
|
||||
},
|
||||
appLogo: {
|
||||
height: normalize(170),
|
||||
width: '100%',
|
||||
resizeMode: 'contain',
|
||||
},
|
||||
titleContainer: {
|
||||
alignSelf: 'center',
|
||||
marginBottom: normalize(10),
|
||||
},
|
||||
titleText: {
|
||||
fontSize: normalize(20),
|
||||
fontWeight: 'bold',
|
||||
color: GlobalTheme.colors.black,
|
||||
},
|
||||
card: {
|
||||
backgroundColor: GlobalTheme.colors.white,
|
||||
borderTopLeftRadius: GlobalTheme.borderRadius.xxlg || normalize(20),
|
||||
borderTopRightRadius: GlobalTheme.borderRadius.xxlg || normalize(20),
|
||||
padding: normalize(20),
|
||||
width: width,
|
||||
alignSelf: 'center',
|
||||
// marginTop: normalize(30),
|
||||
shadowColor: '#000',
|
||||
shadowOpacity: 0.05,
|
||||
shadowOffset: { width: 0, height: 4 },
|
||||
shadowRadius: 8,
|
||||
elevation: 4,
|
||||
flex: 1,
|
||||
},
|
||||
btnbg: {
|
||||
backgroundColor: GlobalTheme.colors.secondary,
|
||||
borderRadius: GlobalTheme.borderRadius.md,
|
||||
marginTop: normalize(30),
|
||||
paddingVertical: normalize(12),
|
||||
alignItems: 'center',
|
||||
},
|
||||
btntext: {
|
||||
color: GlobalTheme.colors.white,
|
||||
fontSize: normalize(GlobalTheme.typography.fontSize.small),
|
||||
fontWeight: GlobalTheme.typography.fontWeight.regular,
|
||||
},
|
||||
footer: {
|
||||
marginTop: normalize(60),
|
||||
alignItems: 'center',
|
||||
},
|
||||
footerImage: {
|
||||
width: '100%',
|
||||
height: normalize(80),
|
||||
resizeMode: 'contain',
|
||||
marginTop : normalize(160),
|
||||
},
|
||||
AuthBottomBG: {
|
||||
width: '100%',
|
||||
resizeMode: 'contain',
|
||||
height: normalize(300),
|
||||
justifyContent: 'center',
|
||||
},
|
||||
loginTitle: {
|
||||
color: GlobalTheme.colors.black,
|
||||
fontSize: normalize(GlobalTheme.typography.fontSize.large),
|
||||
fontWeight: GlobalTheme.typography.fontWeight.medium,
|
||||
textAlign: 'center',
|
||||
marginBottom: normalize(20),
|
||||
},
|
||||
mainContainer: {
|
||||
flex: 1,
|
||||
backgroundColor: '#EAF0FF',
|
||||
},
|
||||
});
|
||||
>>>>>>> dabur-store-dna
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { View, Text, Image, Platform, ImageBackground, TextInput } from 'react-native';
|
||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||
import IMAGES from '../../../constants/Images';
|
||||
import { styles } from './style';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import CustomButton from '../../../components/CustomButton';
|
||||
import Loader from '../../../constants/Loader';
|
||||
import { ApiURL } from '../../../api/ApiConstant';
|
||||
import { toastError, toastSuccess } from '../../../constants/Toast';
|
||||
import axios from 'axios';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { GlobalTheme } from '../../../theme';
|
||||
import Geolocation from '@react-native-community/geolocation';
|
||||
|
||||
|
||||
const Project = ({ navigation }) => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const dispatch = useDispatch();
|
||||
const [username, setUsername] = useState('');
|
||||
|
||||
|
||||
// geo loc
|
||||
useEffect(() => {
|
||||
Geolocation.getCurrentPosition(info => console.log("Location infoooo====>", JSON.stringify(info)));
|
||||
}, [])
|
||||
// end geo loc
|
||||
|
||||
|
||||
const onSubmit = () => {
|
||||
// setLoading(true);
|
||||
// getOTP();
|
||||
navigation.navigate("Login")
|
||||
};
|
||||
|
||||
const getOTP = async () => {
|
||||
try {
|
||||
const params = {
|
||||
"UserId": username
|
||||
};
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: ApiURL.getotpApi,
|
||||
headers: {
|
||||
'api_key': '9a1f056fecb84eaf8eb4152dda22ab0501955c4f9bbe7daa8780740459fdde7a',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: params
|
||||
};
|
||||
|
||||
const response = await axios.request(config);
|
||||
const res = response.data || [];
|
||||
console.log('OTP is ===> ', res?.SendOTP);
|
||||
if (res?.SendOTP[0].OTP === '0' || res?.SendOTP[0].OTP === 0) {
|
||||
setLoading(false);
|
||||
toastError("Alert", "Invalid User");
|
||||
} else {
|
||||
toastSuccess("Alert", res?.SendOTP[0]?.Messages);
|
||||
navigation.navigate('VerifyOTP', { username: username });
|
||||
setLoading(false);
|
||||
}
|
||||
// console.log('getotpApi res==>', JSON.stringify(res?.SendOTP[0]));
|
||||
} catch (error) {
|
||||
console.log("❌ OTP API error:", error);
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<KeyboardAwareScrollView keyboardShouldPersistTaps="handled" enableOnAndroid={true} contentContainerStyle={{ justifyContent: 'center', flexGrow: 1, marginTop: 0 }} style={styles.container}>
|
||||
{/* <View style={{ backgroundColor: GlobalTheme.colors.primary, height: 40 }} /> */}
|
||||
<Image style={styles.performicsLogo} source={IMAGES.PerformicsLogo} resizeMode='contain' />
|
||||
<Image style={styles.appLogo} source={IMAGES.projectIdImg} resizeMode='contain' />
|
||||
<View style={styles.card}>
|
||||
<View style={{marginTop:25}}>
|
||||
<Text style={[styles.loginTitle, { fontSize: 15, color: '#555555', marginBottom: 10 }]}>Hey There</Text>
|
||||
<Text style={styles.loginTitle}>Enter Your Project Id</Text>
|
||||
</View>
|
||||
|
||||
<View style={{ marginTop: 20, height: 50, backgroundColor: '#eee', borderRadius: 10 }}>
|
||||
<TextInput
|
||||
style={{ height: 50, paddingHorizontal: 15 }}
|
||||
placeholder='Enter Project Id'
|
||||
placeholderTextColor={'gray'}
|
||||
keyboardType='numeric'
|
||||
/>
|
||||
</View>
|
||||
|
||||
<CustomButton onPress={() => onSubmit()} title={'Next'} style={styles.btnbg} textstyle={styles.btntext} />
|
||||
<ImageBackground source={IMAGES.AuthBottomBG} style={styles.AuthBottomBG} >
|
||||
<Text style={{ position: 'absolute', textAlign: 'center', alignContent: 'center', alignSelf: 'center', bottom: 20, color: GlobalTheme.colors.gray }}> Copyright CPM India - 2025</Text>
|
||||
</ImageBackground>
|
||||
</View>
|
||||
</KeyboardAwareScrollView>
|
||||
<Loader visible={loading} loadingtext={'Loading ...'} />
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
|
||||
export default Project;
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import { StyleSheet, Dimensions } from 'react-native';
|
||||
import { GlobalTheme } from '../../../theme';
|
||||
import { normalize } from '../../../utilis/responsive';
|
||||
const { width, height } = Dimensions.get('window');
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: "#fff",
|
||||
},
|
||||
logoContainer: {
|
||||
width: '100%',
|
||||
},
|
||||
appLogo: {
|
||||
height: normalize(180),
|
||||
width: '100%',
|
||||
resizeMode: 'contain',
|
||||
marginTop: 30,
|
||||
},
|
||||
performicsLogo: {
|
||||
height: normalize(50),
|
||||
width: '55%',
|
||||
resizeMode: 'contain',
|
||||
alignSelf: 'center',
|
||||
marginTop:10,
|
||||
},
|
||||
titleContainer: {
|
||||
alignSelf: 'center',
|
||||
marginBottom: normalize(10),
|
||||
},
|
||||
titleText: {
|
||||
fontSize: normalize(20),
|
||||
fontWeight: 'bold',
|
||||
color: GlobalTheme.colors.black,
|
||||
},
|
||||
card: {
|
||||
padding: normalize(25),
|
||||
width: width,
|
||||
alignSelf: 'center',
|
||||
// marginTop: normalize(30),
|
||||
shadowColor: '#000',
|
||||
shadowOpacity: 0.05,
|
||||
shadowOffset: { width: 0, height: 4 },
|
||||
shadowRadius: 8,
|
||||
// elevation: 4,
|
||||
flex: 1,
|
||||
},
|
||||
btnbg: {
|
||||
backgroundColor: GlobalTheme.colors.secondary,
|
||||
borderRadius: GlobalTheme.borderRadius.md,
|
||||
marginTop: normalize(30),
|
||||
paddingVertical: normalize(12),
|
||||
alignItems: 'center',
|
||||
},
|
||||
btntext: {
|
||||
color: GlobalTheme.colors.white,
|
||||
fontSize: normalize(GlobalTheme.typography.fontSize.small),
|
||||
fontWeight: GlobalTheme.typography.fontWeight.regular,
|
||||
},
|
||||
footer: {
|
||||
marginTop: normalize(60),
|
||||
alignItems: 'center',
|
||||
},
|
||||
footerImage: {
|
||||
width: '100%',
|
||||
height: normalize(80),
|
||||
resizeMode: 'contain',
|
||||
marginTop: normalize(160),
|
||||
},
|
||||
AuthBottomBG: {
|
||||
width: '100%',
|
||||
resizeMode: 'contain',
|
||||
height: normalize(210),
|
||||
justifyContent: 'center',
|
||||
},
|
||||
loginTitle: {
|
||||
color: GlobalTheme.colors.black,
|
||||
fontSize: normalize(GlobalTheme.typography.fontSize.small),
|
||||
fontWeight: GlobalTheme.typography.fontWeight.medium,
|
||||
textAlign: 'center',
|
||||
marginBottom: normalize(20),
|
||||
},
|
||||
mainContainer: {
|
||||
flex: 1,
|
||||
backgroundColor: '#EAF0FF',
|
||||
},
|
||||
});
|
||||
@@ -1,3 +1,4 @@
|
||||
<<<<<<< HEAD
|
||||
import {View, Text, Image, Dimensions, StyleSheet} from 'react-native';
|
||||
import React, {useEffect} from 'react';
|
||||
import IMAGES from '../../../constants/Images';
|
||||
@@ -97,3 +98,104 @@ const styles = StyleSheet.create({
|
||||
//borderWidth:1
|
||||
},
|
||||
});
|
||||
=======
|
||||
import { View, Text, Image, Dimensions, StyleSheet } from 'react-native';
|
||||
import React, { useEffect } from 'react';
|
||||
import IMAGES from '../../../constants/Images';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { setUser } from '../../../redux/slices/userSlice';
|
||||
|
||||
const SplashScreen = ({ navigation }) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
checkLoginStatus();
|
||||
}, []);
|
||||
|
||||
const checkLoginStatus = async () => {
|
||||
try {
|
||||
const isuserlogin = await AsyncStorage.getItem('@Dabur_DNA_User');
|
||||
console.log("isuserlogin", isuserlogin)
|
||||
const parsedUser = JSON.parse(isuserlogin);
|
||||
if (isuserlogin) {
|
||||
dispatch(setUser(parsedUser));
|
||||
setTimeout(() => {
|
||||
navigation.reset({
|
||||
index: 0,
|
||||
routes: [{ name: 'Welcome' }],
|
||||
});
|
||||
}, 1000);
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
navigation.reset({
|
||||
index: 0,
|
||||
routes: [{ name: 'Login' }],
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error checking login status:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.backgroundContainer}>
|
||||
<Image
|
||||
source={IMAGES.splashFullImg}
|
||||
resizeMode="stretch"
|
||||
style={styles.backdrop}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.overlay}>
|
||||
<Image style={styles.logo} source={IMAGES.AppLogo} />
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default SplashScreen;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
backgroundContainer: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
overlay: {
|
||||
opacity: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
logo: {
|
||||
backgroundColor: 'rgba(0,0,0,0)',
|
||||
height: 200,
|
||||
width: 200,
|
||||
overflow: 'hidden',
|
||||
resizeMode: 'contain',
|
||||
marginTop: 5,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
backdrop: {
|
||||
flex: 1,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
headline: {
|
||||
fontSize: 18,
|
||||
textAlign: 'center',
|
||||
backgroundColor: 'black',
|
||||
color: 'white',
|
||||
//borderWidth:1
|
||||
},
|
||||
});
|
||||
>>>>>>> dabur-store-dna
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<<<<<<< HEAD
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { View, Text, Image, Alert, TouchableOpacity } from 'react-native';
|
||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||
@@ -122,3 +123,224 @@ const VerifyOTP = ({ navigation }) => {
|
||||
};
|
||||
|
||||
export default VerifyOTP;
|
||||
=======
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { View, Text, Image, TouchableOpacity, ImageBackground } from 'react-native';
|
||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { OtpInput } from "react-native-otp-entry";
|
||||
import CustomButton from '../../../components/CustomButton';
|
||||
import Background from '../../../components/Background';
|
||||
import IMAGES from '../../../constants/Images';
|
||||
import { GlobalTheme } from '../../../theme';
|
||||
import { styles } from './style';
|
||||
import { toastError, toastSuccess } from '../../../constants/Toast';
|
||||
import Loader from '../../../constants/Loader';
|
||||
import { ApiURL } from '../../../api/ApiConstant';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import { setUser } from '../../../redux/slices/userSlice';
|
||||
import axios from 'axios';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
|
||||
const VerifyOTP = ({ navigation, route }) => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const dispatch = useDispatch();
|
||||
const [otp, setOTP] = useState('');
|
||||
const [timer, setTimer] = useState(300); // 5 minutes = 300 seconds
|
||||
const [showResend, setShowResend] = useState(false);
|
||||
|
||||
const username = route.params.username;
|
||||
|
||||
useEffect(() => {
|
||||
if (timer === 0) {
|
||||
setShowResend(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const interval = setInterval(() => {
|
||||
setTimer(prev => prev - 1);
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, [timer]);
|
||||
|
||||
const formatTime = (secs) => {
|
||||
const minutes = Math.floor(secs / 60);
|
||||
const seconds = secs % 60;
|
||||
return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
|
||||
};
|
||||
|
||||
const handle_validate = () => {
|
||||
if (otp.length < 6) {
|
||||
toastError('Alert', "Please enter 6 digit PIN");
|
||||
} else {
|
||||
onSubmit();
|
||||
}
|
||||
}
|
||||
|
||||
const resendOTP = async () => {
|
||||
try {
|
||||
const params = {
|
||||
"UserId": username
|
||||
}
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: ApiURL.getotpApi,
|
||||
headers: {
|
||||
'api_key': '9a1f056fecb84eaf8eb4152dda22ab0501955c4f9bbe7daa8780740459fdde7a',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: params
|
||||
};
|
||||
const response = await axios.request(config);
|
||||
const res = response.data || [];
|
||||
// console.log('storeSearchApi====>', res);
|
||||
if (res?.SendOTP[0].OTP === '0' || res?.SendOTP[0].OTP === 0) {
|
||||
toastError("Alert", res?.SendOTP[0]?.Messages)
|
||||
} else {
|
||||
toastSuccess("Alert", res?.SendOTP[0]?.Messages)
|
||||
navigation.navigate('VerifyOTP', { username: username });
|
||||
}
|
||||
// console.log('getotpApi res==>', JSON.stringify(res?.SendOTP[0]));
|
||||
// setLoading(false)
|
||||
} catch (error) {
|
||||
// setLoading(false)
|
||||
console.log("❌ Filter API error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const resend_OTP = () => {
|
||||
setTimer(300);
|
||||
setShowResend(false);
|
||||
toastSuccess('Resend OTP Successfully.')
|
||||
resendOTP();
|
||||
}
|
||||
|
||||
const onSubmit = () => {
|
||||
setLoading(true)
|
||||
VerifyOTP();
|
||||
setTimeout(() => {
|
||||
setLoading(false)
|
||||
}, 100);
|
||||
}
|
||||
|
||||
const VerifyOTP = async () => {
|
||||
try {
|
||||
const params = {
|
||||
"UserId": username,
|
||||
"OTP": otp
|
||||
}
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: ApiURL.verifyotpApi,
|
||||
headers: {
|
||||
'api_key': '9a1f056fecb84eaf8eb4152dda22ab0501955c4f9bbe7daa8780740459fdde7a',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: params
|
||||
};
|
||||
|
||||
const response = await axios.request(config);
|
||||
const res = response.data || [];
|
||||
|
||||
if (res?.AuthenticateOTP[0].Message == 'OTP is matched') {
|
||||
toastSuccess("Alert", res?.AuthenticateOTP[0]?.Message || "Alert", "Login Successfully.")
|
||||
await AsyncStorage.setItem('@Dabur_DNA_User', JSON.stringify(res?.AuthenticateOTP[0]));
|
||||
dispatch(setUser(res?.AuthenticateOTP[0]));
|
||||
navigation.reset({ index: 0, routes: [{ name: 'Welcome' }] })
|
||||
} else {
|
||||
toastError("Alert", res?.AuthenticateOTP[0]?.Message);
|
||||
}
|
||||
} catch (error) {
|
||||
// setLoading(false)
|
||||
console.log("❌ Filter API error:", error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<TouchableOpacity onPress={() => navigation.goBack()}>
|
||||
<View style={styles.backTextView}>
|
||||
<Image source={IMAGES.leftArrowIcon} style={styles.iconStyle} />
|
||||
<Text style={styles.backIconText}>Back</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<KeyboardAwareScrollView keyboardShouldPersistTaps="handled" enableOnAndroid={true} style={styles.container} contentContainerStyle={{ justifyContent: 'center', flex: 1 }}>
|
||||
<View style={{ backgroundColor: GlobalTheme.colors.primary, height: 40 }} />
|
||||
<Image style={styles.appLogo} source={IMAGES.AuthTopBGNew} resizeMode='contain' />
|
||||
<View style={styles.card}>
|
||||
<View style={styles.titleContainer}>
|
||||
<Text style={styles.titleText}>Enter the OTP sent to your {"\n"} registered contact</Text>
|
||||
</View>
|
||||
<View style={{ marginTop: 50 }}>
|
||||
<OtpInput
|
||||
numberOfDigits={6}
|
||||
focusColor={GlobalTheme.colors.primary}
|
||||
autoFocus={false}
|
||||
hideStick={true}
|
||||
placeholder=""
|
||||
blurOnFilled={true}
|
||||
disabled={false}
|
||||
type="numeric"
|
||||
secureTextEntry={false}
|
||||
focusStickBlinkingDuration={500}
|
||||
// onFocus={() => console.log("Focused")}
|
||||
// onBlur={() => console.log("Blurred")}
|
||||
onTextChange={(text) => setOTP(text)}
|
||||
onFilled={(text) => {
|
||||
setOTP(text);
|
||||
console.log(`OTP is ${text}`);
|
||||
}}
|
||||
textInputProps={{
|
||||
accessibilityLabel: "One-Time Password",
|
||||
}}
|
||||
textProps={{
|
||||
accessibilityRole: "text",
|
||||
accessibilityLabel: "OTP digit",
|
||||
allowFontScaling: false,
|
||||
}}
|
||||
theme={{
|
||||
containerStyle: styles.container,
|
||||
pinCodeContainerStyle: styles.pinCodeContainer,
|
||||
pinCodeTextStyle: styles.pinCodeText,
|
||||
focusStickStyle: styles.focusStick,
|
||||
focusedPinCodeContainerStyle: styles.activePinCodeContainer,
|
||||
placeholderTextStyle: styles.placeholderText,
|
||||
filledPinCodeContainerStyle: styles.filledPinCodeContainer,
|
||||
disabledPinCodeContainerStyle: styles.disabledPinCodeContainer,
|
||||
}}
|
||||
/>
|
||||
|
||||
</View>
|
||||
<View style={{ marginTop: 100}}>
|
||||
<CustomButton onPress={handle_validate} title={'Verify'} style={styles.btnbg} textstyle={styles.btntext} />
|
||||
</View>
|
||||
|
||||
<View style={{ alignItems: 'center', marginTop: 20 }}>
|
||||
{!showResend ? (
|
||||
<Text style={{ color: GlobalTheme.colors.darkGray }}>Resend OTP in {formatTime(timer)}</Text>
|
||||
) : (
|
||||
<TouchableOpacity onPress={resend_OTP}>
|
||||
<Text style={styles.resendOTP} >
|
||||
Resend OTP
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<ImageBackground source={IMAGES.AuthBottomBG} style={styles.AuthBottomBG} >
|
||||
{/* <Image source={IMAGES.Logo} style={styles.footerImage} resizeMode="contain"/> */}
|
||||
<Text style={{ position : 'absolute', textAlign:'center', alignContent:'center',alignSelf:'center', bottom:0 , color : GlobalTheme.colors.gray}}> Copyright CPM India - 2025</Text>
|
||||
</ImageBackground>
|
||||
</View>
|
||||
|
||||
</KeyboardAwareScrollView>
|
||||
<Loader visible={loading} />
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
|
||||
export default VerifyOTP;
|
||||
>>>>>>> dabur-store-dna
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<<<<<<< HEAD
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import { GlobalTheme, Screen } from '../../../theme';
|
||||
@@ -99,3 +100,154 @@ export const styles = StyleSheet.create({
|
||||
}
|
||||
|
||||
});
|
||||
=======
|
||||
import { Dimensions, StyleSheet } from 'react-native';
|
||||
import { GlobalTheme, Screen } from '../../../theme';
|
||||
import { normalize } from '../../../utilis/responsive';
|
||||
|
||||
const { width, height } = Dimensions.get('window');
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
container: {
|
||||
// flex: 1,
|
||||
// paddingHorizontal: 5
|
||||
flex: 1,
|
||||
backgroundColor: GlobalTheme.colors.primary,
|
||||
},
|
||||
logoContainer: {
|
||||
alignItems: 'center',
|
||||
},
|
||||
appLogo: {
|
||||
height: normalize(170),
|
||||
width: '100%',
|
||||
resizeMode: 'contain',
|
||||
marginTop: 40
|
||||
},
|
||||
titleContainer: {
|
||||
alignSelf: 'center',
|
||||
},
|
||||
titleText: {
|
||||
fontSize: 18,
|
||||
fontWeight: '500',
|
||||
color: GlobalTheme.colors.black,
|
||||
textAlign: 'center'
|
||||
},
|
||||
btnbg: {
|
||||
backgroundColor: GlobalTheme.colors.secondary, borderRadius: GlobalTheme.borderRadius.md
|
||||
},
|
||||
btntext: {
|
||||
color: GlobalTheme.colors.white,
|
||||
fontSize: GlobalTheme.typography.fontSize.medium
|
||||
},
|
||||
otp_inputStyle: {
|
||||
textAlign: 'center',
|
||||
backgroundColor: 'red',
|
||||
width: 100,
|
||||
borderRadius: 4,
|
||||
paddingVertical: 10,
|
||||
paddingHorizontal: 15,
|
||||
height: 50,
|
||||
color: 'red',
|
||||
marginBottom: 10,
|
||||
marginRight: 10,
|
||||
fontSize: 25,
|
||||
},
|
||||
// OTP
|
||||
pinCodeContainer: {
|
||||
width: 45,
|
||||
height: 55,
|
||||
borderWidth: 1,
|
||||
borderColor: '#D8E3F1',
|
||||
borderRadius: 8,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
activePinCodeContainer: {
|
||||
borderColor: GlobalTheme.colors.primary,
|
||||
borderWidth: 2,
|
||||
},
|
||||
filledPinCodeContainer: {
|
||||
backgroundColor: '#D8E3F1',
|
||||
},
|
||||
disabledPinCodeContainer: {
|
||||
backgroundColor: '#f0f0f0',
|
||||
borderColor: '#ddd',
|
||||
},
|
||||
pinCodeText: {
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold',
|
||||
color: '#333',
|
||||
},
|
||||
focusStick: {
|
||||
height: 2,
|
||||
width: 20,
|
||||
backgroundColor: GlobalTheme.colors.primary,
|
||||
marginTop: 4,
|
||||
},
|
||||
placeholderText: {
|
||||
color: '#aaa',
|
||||
fontSize: 18,
|
||||
},
|
||||
resendText: {
|
||||
color: GlobalTheme.colors.primary,
|
||||
fontWeight: 'bold',
|
||||
fontSize: 14,
|
||||
marginTop: 20,
|
||||
textAlign: 'center',
|
||||
},
|
||||
timerText: {
|
||||
color: 'gray',
|
||||
fontSize: 14,
|
||||
marginTop: 20,
|
||||
textAlign: 'center',
|
||||
},
|
||||
resendOTP: {
|
||||
color: GlobalTheme.colors.secondary, fontWeight: GlobalTheme.typography.fontWeight.medium, fontSize: GlobalTheme.typography.fontSize.small
|
||||
},
|
||||
iconStyle: {
|
||||
height: 20,
|
||||
width: 20,
|
||||
resizeMode: 'contain',
|
||||
tintColor: GlobalTheme.colors.white
|
||||
},
|
||||
backIconText: { fontSize: GlobalTheme.typography.fontSize.small, color: GlobalTheme.colors.white, fontWeight: GlobalTheme.typography.fontWeight.medium, marginLeft: 8 },
|
||||
backTextView: {
|
||||
flexDirection: 'row', alignItems: 'center', paddingTop: 20, paddingHorizontal: 10
|
||||
},
|
||||
card: {
|
||||
backgroundColor: GlobalTheme.colors.white,
|
||||
borderTopLeftRadius: GlobalTheme.borderRadius.xxlg || normalize(20),
|
||||
borderTopRightRadius: GlobalTheme.borderRadius.xxlg || normalize(20),
|
||||
padding: normalize(20),
|
||||
width: width,
|
||||
alignSelf: 'center',
|
||||
// marginTop: normalize(30),
|
||||
shadowColor: '#000',
|
||||
shadowOpacity: 0.05,
|
||||
shadowOffset: { width: 0, height: 4 },
|
||||
shadowRadius: 8,
|
||||
elevation: 4,
|
||||
flex: 1,
|
||||
minHeight : height * 0.7
|
||||
},
|
||||
footer: {
|
||||
marginTop: 60,
|
||||
alignItems: 'center',
|
||||
},
|
||||
footerImage: {
|
||||
width: '100%',
|
||||
height: normalize(80),
|
||||
resizeMode: 'contain',
|
||||
marginTop: normalize(160),
|
||||
},
|
||||
AuthBottomBG: {
|
||||
width: '100%',
|
||||
resizeMode: 'contain',
|
||||
height: normalize(270),
|
||||
justifyContent: 'center',
|
||||
marginTop: normalize(-40),
|
||||
},
|
||||
|
||||
});
|
||||
>>>>>>> dabur-store-dna
|
||||
|
||||
@@ -0,0 +1,406 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { View, Text, TouchableOpacity, ScrollView, Image, Modal, Platform, StyleSheet, Alert } from 'react-native';
|
||||
import { useRoute, useNavigation } from '@react-navigation/native';
|
||||
import { post } from '../../../api/ApiService';
|
||||
import IMAGES from '../../../constants/Images';
|
||||
import { GlobalTheme } from '../../../theme';
|
||||
import Loader from '../../../constants/Loader';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { toastError } from '../../../constants/Toast';
|
||||
|
||||
const Details = () => {
|
||||
|
||||
const route = useRoute();
|
||||
const navigation = useNavigation();
|
||||
|
||||
const { selectedDetails = [], storeData, year, month, mainTabIndex } = route.params || {};
|
||||
const [modalGraphData, setModalGraphData] = useState({});
|
||||
const [activePromoTab, setActivePromoTab] = useState('Executed');
|
||||
const [allCatData, setAllCatData] = useState([])
|
||||
const [selectedCategoryData, setSelectedCategoryData] = useState([]);
|
||||
const [categoryModalVisible, setCategoryModalVisible] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedDetails.length > 0) {
|
||||
fetchDetailGraphs(selectedDetails);
|
||||
}
|
||||
}, [selectedDetails]);
|
||||
|
||||
useEffect(() => {
|
||||
getAllCatData();
|
||||
}, [])
|
||||
|
||||
const getAllCatData = () => {
|
||||
let data = {
|
||||
parameters: {
|
||||
projectid: 41654,
|
||||
year: year,
|
||||
monthno: month,
|
||||
storeid: storeData?.StoreId
|
||||
},
|
||||
}
|
||||
|
||||
const apiUrl = mainTabIndex === 0
|
||||
? 'https://dax.parinaam.in/execute/dabur/detmtd/oos_sku_list_for_all_visits_mtd'
|
||||
: 'https://dax.parinaam.in/execute/dabur/detlsv/oos_sku_list_on_lsv';
|
||||
|
||||
post(apiUrl, data)
|
||||
.then(res => {
|
||||
setAllCatData(res?.data);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('Error =>', err);
|
||||
});
|
||||
}
|
||||
|
||||
const fetchDetailGraphs = async (detailPages) => {
|
||||
try {
|
||||
const resultMap = {};
|
||||
for (let item of detailPages) {
|
||||
const response = await post(item.GraphUrl, {
|
||||
parameters: {
|
||||
projectid: 41654,
|
||||
year: year,
|
||||
monthno: month,
|
||||
storeid: storeData?.StoreId
|
||||
},
|
||||
});
|
||||
resultMap[item.GraphUrl] = response?.data || [];
|
||||
}
|
||||
setModalGraphData(resultMap);
|
||||
} catch (error) {
|
||||
console.log("❌ Error fetching detail graphs:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const showCategoryDetails = (data) => {
|
||||
setCategoryModalVisible(!categoryModalVisible)
|
||||
// Filter SKUs from allCatData where the category name matches
|
||||
const filteredCategory = allCatData.filter(item =>
|
||||
item.Product_CategoryCategory_Name === data.Product_CategoryCategory_Name
|
||||
);
|
||||
// Save for display
|
||||
setSelectedCategoryData(filteredCategory);
|
||||
}
|
||||
|
||||
const isOSATab = selectedDetails.some(item => item.GraphTitle === "OSA - Category");
|
||||
|
||||
return (
|
||||
<SafeAreaView style={{ flex: 1, backgroundColor: '#113F8C' }}>
|
||||
<View style={{ flex: 1, backgroundColor: '#fff' }}>
|
||||
{/* Header */}
|
||||
<View style={styled.header}>
|
||||
<TouchableOpacity onPress={() => navigation.goBack()} style={{ padding: 5 }}>
|
||||
<Image source={IMAGES.backIcon} style={{ height: 20, width: 20, tintColor: '#fff' }} />
|
||||
</TouchableOpacity>
|
||||
<Text style={{ color: '#fff', fontSize: 20, fontWeight: 'bold' }}>Details</Text>
|
||||
<View style={{ width: 25 }} /> {/* spacer */}
|
||||
</View>
|
||||
|
||||
<ScrollView style={{ padding: 20 }}>
|
||||
{selectedDetails.map((detail, index) => {
|
||||
const values = modalGraphData[detail.GraphUrl] || [];
|
||||
|
||||
if (!modalGraphData[detail.GraphUrl]) {
|
||||
return (
|
||||
<View key={index} style={{ flex: 1, marginBottom: 20 }}>
|
||||
<Loader visible={true} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
switch (detail.GraphType) {
|
||||
case 'Table':
|
||||
// Check if it's the Promotion table
|
||||
const isPromotionTable =
|
||||
values.length > 0 &&
|
||||
values[0].hasOwnProperty('Product_CategoryCategory_Name') &&
|
||||
values[0].hasOwnProperty('Promotion_MasterPromotion_Definition');
|
||||
|
||||
if (isPromotionTable) {
|
||||
// Filter data based on active tab
|
||||
const filteredValues = values.filter(row =>
|
||||
activePromoTab === 'Executed'
|
||||
? row.Executed?.toLowerCase() === 'yes'
|
||||
: row.Executed?.toLowerCase() === 'no'
|
||||
);
|
||||
// Group data by Product_CategoryCategory_Name
|
||||
const groupedData = filteredValues.reduce((acc, curr) => {
|
||||
const category = curr.Product_CategoryCategory_Name || 'Unknown';
|
||||
if (!acc[category]) acc[category] = [];
|
||||
acc[category].push(curr);
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
return (
|
||||
<View key={index} style={{ marginBottom: 10 }}>
|
||||
|
||||
{/* Horizontal Tabs - show once at top */}
|
||||
{index === 0 && ( // ensures only first promotion table renders the toggle
|
||||
<View style={{ flexDirection: 'row', marginBottom: 20 }}>
|
||||
{['Executed', 'Not Executed'].map(tab => {
|
||||
const isSelected = activePromoTab === tab;
|
||||
return (
|
||||
<TouchableOpacity
|
||||
key={tab}
|
||||
onPress={() => setActivePromoTab(tab)}
|
||||
style={{
|
||||
flex: 1,
|
||||
paddingVertical: 10,
|
||||
backgroundColor: isSelected ? '#113F8C' : '#E3EBF8',
|
||||
borderRadius: 8,
|
||||
marginHorizontal: 5,
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: isSelected ? '#fff' : '#000', fontWeight: '600' }}>
|
||||
{tab}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* No data message */}
|
||||
<View style={{}}>
|
||||
{filteredValues.length === 0 ? (
|
||||
<View style={{ marginTop: 0, backgroundColor: 'red' }} />
|
||||
) : (
|
||||
Object.keys(groupedData).map((categoryName, catIdx) => (
|
||||
<View key={catIdx} style={{ marginBottom: 20, }}>
|
||||
{/* Category Header */}
|
||||
<View style={{ backgroundColor: '#E8F0FF', padding: 8, borderRadius: 6 }}>
|
||||
<Text style={{ fontSize: 15, fontWeight: '700', color: '#113F8C' }}>
|
||||
{String(categoryName)}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* Table Header */}
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
backgroundColor: '#f5f5f5',
|
||||
paddingVertical: 8,
|
||||
paddingHorizontal: 9,
|
||||
borderTopLeftRadius: 8,
|
||||
borderTopRightRadius: 8,
|
||||
marginTop: 5
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: '#000', fontWeight: 'bold', width: '80%' }}>
|
||||
Definition
|
||||
</Text>
|
||||
<Text style={{ color: '#000', fontWeight: 'bold', width: '20%', textAlign: 'center' }}>
|
||||
Executed
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* Table Rows */}
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: '#fff',
|
||||
paddingHorizontal: 10,
|
||||
borderBottomLeftRadius: 8,
|
||||
borderBottomRightRadius: 8,
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 1 },
|
||||
shadowOpacity: 0.1,
|
||||
shadowRadius: 2,
|
||||
elevation: 2
|
||||
}}
|
||||
>
|
||||
{groupedData[categoryName].map((row, rowIdx) => (
|
||||
<View
|
||||
key={rowIdx}
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
paddingVertical: 8,
|
||||
borderBottomWidth: rowIdx === groupedData[categoryName].length - 1 ? 0 : 1,
|
||||
borderColor: '#eee'
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: '#000', width: '80%' }}>
|
||||
{String(row.Promotion_MasterPromotion_Definition) || '-'}
|
||||
</Text>
|
||||
<Text style={{ color: '#000', width: '20%', textAlign: 'center' }}>
|
||||
{row.Executed || '-'}
|
||||
</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
))
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
let displayKey = null;
|
||||
let presentKey = null;
|
||||
if (values.length > 0) {
|
||||
const presentKeys = Object.keys(values[0]).filter(k =>
|
||||
(typeof values[0][k] === 'string' && ['Yes', 'No'].includes(values[0][k])) ||
|
||||
typeof values[0][k] === 'boolean' ||
|
||||
typeof values[0][k] === 'number'
|
||||
);
|
||||
presentKey = presentKeys.length > 0 ? presentKeys[0] : null;
|
||||
const displayKeys = Object.keys(values[0]).filter(k => k !== presentKey && typeof values[0][k] === 'string');
|
||||
displayKey = displayKeys.length > 0 ? displayKeys[0] : null;
|
||||
}
|
||||
|
||||
return (
|
||||
<View key={index} style={{ marginBottom: 30 }}>
|
||||
<Text style={{ color: '#000', fontSize: 16, fontWeight: '600', marginBottom: 10 }}>
|
||||
{detail.GraphTitle}
|
||||
|
||||
</Text>
|
||||
<View style={styled.categoryHeader}>
|
||||
<Text style={{ color: '#000', fontWeight: 'bold', width: '80%' }}>
|
||||
{displayKey ? displayKey.replace(/_/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2') : ''}
|
||||
</Text>
|
||||
<Text style={{ color: '#000', fontWeight: 'bold', width: '20%', textAlign: 'center' }}>
|
||||
{presentKey ? presentKey.replace(/_/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2') : ''}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={styled.itemContainer}>
|
||||
{values.map((row, idx) => {
|
||||
const presentKeys = Object.keys(row).filter(k =>
|
||||
(typeof row[k] === 'string' && ['Yes', 'No'].includes(row[k])) ||
|
||||
typeof row[k] === 'boolean' ||
|
||||
typeof row[k] === 'number'
|
||||
);
|
||||
const presentKey = presentKeys.length > 0 ? presentKeys[0] : null;
|
||||
const displayKeys = Object.keys(row).filter(k => k !== presentKey && typeof row[k] === 'string');
|
||||
const displayKey = displayKeys.length > 0 ? displayKeys[0] : null;
|
||||
|
||||
return (
|
||||
<View
|
||||
key={idx}
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
paddingVertical: 8,
|
||||
borderBottomWidth: idx === values.length - 1 ? 0 : 1,
|
||||
borderColor: '#eee',
|
||||
}}>
|
||||
<Text style={{ color: '#000', width: '80%' }}>{row[displayKey] || '--'}</Text>
|
||||
<TouchableOpacity disabled={isOSATab ? false : true}
|
||||
onPress={() => {
|
||||
if (row[presentKey] == 100 || row[presentKey] == '100') {
|
||||
toastError('Alert', 'No Data Available')
|
||||
} else {
|
||||
showCategoryDetails(row)
|
||||
}
|
||||
}}
|
||||
style={{ width: '20%', }}>
|
||||
<Text style={{ color: '#113F8C', textAlign: 'center', fontWeight: '500' }}>
|
||||
{presentKey ? (
|
||||
typeof row[presentKey] === 'string' && ['Yes', 'No'].includes(row[presentKey]) ? row[presentKey] :
|
||||
typeof row[presentKey] === 'boolean' ? (row[presentKey] ? 'Yes' : 'No') :
|
||||
typeof row[presentKey] === 'number' ? row[presentKey].toFixed(2) : row[presentKey] || '-'
|
||||
) : '-'}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<View key={index} style={{ marginBottom: 20 }}>
|
||||
<Text>Unsupported GraphType: {detail.GraphType}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
})}
|
||||
</ScrollView>
|
||||
|
||||
<Modal
|
||||
visible={categoryModalVisible}
|
||||
animationType="slide"
|
||||
onRequestClose={() => setCategoryModalVisible(false)}
|
||||
>
|
||||
<View style={{ flex: 1, }}>
|
||||
{/* Header */}
|
||||
<View style={{ height: Platform.OS === 'ios' ? 55 : 0, backgroundColor: '#113F8C' }} />
|
||||
|
||||
<View style={{ width: '100%', backgroundColor: '#113F8C', borderBottomWidth: 1, borderColor: 'gray', padding: 5, paddingHorizontal: 20, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<View style={{ width: '93%', alignItems: 'center' }}>
|
||||
<Text style={{ color: '#fff', fontSize: 20, fontWeight: 'bold', marginBottom: 10, alignSelf: 'center' }}>{selectedCategoryData[0]?.Product_CategoryCategory_Name || 'Category'}</Text>
|
||||
</View>
|
||||
<TouchableOpacity onPress={() => setCategoryModalVisible(false)} style={{ width: '7%', alignItems: 'center' }}>
|
||||
<Image source={IMAGES.crossIcon} style={{ height: 25, width: 25, resizeMode: 'contain' }} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* SKU List */}
|
||||
<ScrollView contentContainerStyle={{ padding: 15 }}>
|
||||
{/* <Text style={{ color: '#000', fontSize: 16, fontWeight: 'bold', marginBottom: 5 }}>OOS SKU details</Text> */}
|
||||
{selectedCategoryData.map((item, idx) => (
|
||||
<View
|
||||
key={idx}
|
||||
style={{
|
||||
marginTop: 2,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
paddingVertical: 8,
|
||||
borderBottomWidth: idx === selectedCategoryData.length - 1 ? 0 : 1,
|
||||
borderColor: '#eee',
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: '#000', width: '80%' }}>
|
||||
{item.Product_MasterProduct_Name}
|
||||
</Text>
|
||||
{/* <Text style={{ color: '#000', width: '20%', textAlign: 'center' }}>
|
||||
{item['#_of_OOS_SKU_for_all_visits']}
|
||||
</Text> */}
|
||||
</View>
|
||||
))}
|
||||
</ScrollView>
|
||||
</View>
|
||||
</Modal>
|
||||
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
|
||||
const styled = StyleSheet.create({
|
||||
header: {
|
||||
width: '100%',
|
||||
backgroundColor: '#113F8C',
|
||||
padding: 10,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center'
|
||||
},
|
||||
categoryHeader: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
backgroundColor: '#EDEDED',
|
||||
paddingVertical: 8,
|
||||
paddingHorizontal: 10,
|
||||
borderTopLeftRadius: 8,
|
||||
borderTopRightRadius: 8,
|
||||
},
|
||||
itemContainer: {
|
||||
backgroundColor: '#fff',
|
||||
paddingHorizontal: 10,
|
||||
borderBottomLeftRadius: 8,
|
||||
borderBottomRightRadius: 8,
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 1 },
|
||||
shadowOpacity: 0.1,
|
||||
shadowRadius: 2,
|
||||
elevation: 2
|
||||
}
|
||||
})
|
||||
|
||||
export default Details;
|
||||
@@ -0,0 +1,431 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { View, Text, TouchableOpacity, ScrollView, Image, Modal, Platform, StyleSheet, Alert } from 'react-native';
|
||||
import { useRoute, useNavigation } from '@react-navigation/native';
|
||||
import { post } from '../../../api/ApiService';
|
||||
import IMAGES from '../../../constants/Images';
|
||||
import { GlobalTheme } from '../../../theme';
|
||||
import Loader from '../../../constants/Loader';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { toastError } from '../../../constants/Toast';
|
||||
|
||||
const Details = () => {
|
||||
|
||||
const route = useRoute();
|
||||
const navigation = useNavigation();
|
||||
|
||||
const { selectedDetails = [], storeData, year, month, mainTabIndex } = route.params || {};
|
||||
const [modalGraphData, setModalGraphData] = useState({});
|
||||
const [activePromoTab, setActivePromoTab] = useState('Executed');
|
||||
const [allCatData, setAllCatData] = useState([])
|
||||
const [selectedCategoryData, setSelectedCategoryData] = useState([]);
|
||||
const [categoryModalVisible, setCategoryModalVisible] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedDetails.length > 0) {
|
||||
fetchDetailGraphs(selectedDetails);
|
||||
}
|
||||
}, [selectedDetails]);
|
||||
|
||||
useEffect(() => {
|
||||
getAllCatData();
|
||||
}, [])
|
||||
|
||||
const getAllCatData = () => {
|
||||
let data = {
|
||||
parameters: {
|
||||
projectid: 41654,
|
||||
year: year,
|
||||
monthno: month,
|
||||
storeid: storeData?.StoreId
|
||||
},
|
||||
}
|
||||
|
||||
const apiUrl = mainTabIndex === 0
|
||||
? 'https://dax.parinaam.in/execute/dabur/detmtd/oos_sku_list_for_all_visits_mtd'
|
||||
: 'https://dax.parinaam.in/execute/dabur/detlsv/oos_sku_list_on_lsv';
|
||||
|
||||
post(apiUrl, data)
|
||||
.then(res => {
|
||||
setAllCatData(res?.data);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('Error =>', err);
|
||||
});
|
||||
}
|
||||
|
||||
const fetchDetailGraphs = async (detailPages) => {
|
||||
try {
|
||||
const resultMap = {};
|
||||
for (let item of detailPages) {
|
||||
const response = await post(item.GraphUrl, {
|
||||
parameters: {
|
||||
projectid: 41654,
|
||||
year: year,
|
||||
monthno: month,
|
||||
storeid: storeData?.StoreId
|
||||
},
|
||||
});
|
||||
resultMap[item.GraphUrl] = response?.data || [];
|
||||
}
|
||||
setModalGraphData(resultMap);
|
||||
} catch (error) {
|
||||
console.log("❌ Error fetching detail graphs:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const showCategoryDetails = (data) => {
|
||||
setCategoryModalVisible(!categoryModalVisible)
|
||||
// Filter SKUs from allCatData where the category name matches
|
||||
const filteredCategory = allCatData.filter(item =>
|
||||
item.Product_CategoryCategory_Name === data.Product_CategoryCategory_Name
|
||||
);
|
||||
// Save for display
|
||||
setSelectedCategoryData(filteredCategory);
|
||||
}
|
||||
|
||||
const isOSATab = selectedDetails.some(item => item.GraphTitle === "OSA - Category");
|
||||
console.log('isOSATab----',isOSATab);
|
||||
|
||||
|
||||
return (
|
||||
<SafeAreaView style={{ flex: 1, backgroundColor: '#113F8C' }}>
|
||||
<View style={{ flex: 1, backgroundColor: '#fff' }}>
|
||||
{/* Header */}
|
||||
<View style={styled.header}>
|
||||
<TouchableOpacity onPress={() => navigation.goBack()} style={{ padding: 5 }}>
|
||||
<Image source={IMAGES.backIcon} style={{ height: 20, width: 20, tintColor: '#fff' }} />
|
||||
</TouchableOpacity>
|
||||
<Text style={{ color: '#fff', fontSize: 20, fontWeight: 'bold' }}>Details</Text>
|
||||
<View style={{ width: 25 }} />
|
||||
|
||||
</View>
|
||||
|
||||
<ScrollView style={{ padding: 20 }}>
|
||||
{selectedDetails && selectedDetails.length > 0 ? selectedDetails.map((detail, index) => {
|
||||
const values = modalGraphData[detail.GraphUrl] || [];
|
||||
|
||||
if (!modalGraphData[detail.GraphUrl]) {
|
||||
return (
|
||||
<View key={index} style={{ flex: 1, marginBottom: 20 }}>
|
||||
<Loader visible={true} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
switch (detail.GraphType) {
|
||||
case 'Table':
|
||||
// Check if it's the Promotion table
|
||||
const isPromotionTable =
|
||||
values.length > 0 &&
|
||||
values[0].hasOwnProperty('Product_CategoryCategory_Name') &&
|
||||
values[0].hasOwnProperty('Promotion_MasterPromotion_Definition');
|
||||
|
||||
if (isPromotionTable) {
|
||||
// Filter data based on active tab
|
||||
const filteredValues = values.filter(row =>
|
||||
activePromoTab === 'Executed'
|
||||
? row.Executed?.toLowerCase() === 'yes'
|
||||
: row.Executed?.toLowerCase() === 'no'
|
||||
);
|
||||
// Group data by Product_CategoryCategory_Name
|
||||
const groupedData = filteredValues.reduce((acc, curr) => {
|
||||
const category = curr.Product_CategoryCategory_Name || 'Unknown';
|
||||
if (!acc[category]) acc[category] = [];
|
||||
acc[category].push(curr);
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
return (
|
||||
<View key={index} style={{ marginBottom: 10 }}>
|
||||
{/* Horizontal Tabs - show once at top */}
|
||||
{index === 0 && ( // ensures only first promotion table renders the toggle
|
||||
<View style={{ flexDirection: 'row', marginBottom: 20 }}>
|
||||
{['Executed', 'Not Executed'].map(tab => {
|
||||
const isSelected = activePromoTab === tab;
|
||||
return (
|
||||
<TouchableOpacity
|
||||
key={tab}
|
||||
onPress={() => setActivePromoTab(tab)}
|
||||
style={{
|
||||
flex: 1,
|
||||
paddingVertical: 10,
|
||||
backgroundColor: isSelected ? '#113F8C' : '#E3EBF8',
|
||||
borderRadius: 8,
|
||||
marginHorizontal: 5,
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: isSelected ? '#fff' : '#000', fontWeight: '600' }}>
|
||||
{tab}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* No data message */}
|
||||
<View style={{}}>
|
||||
{filteredValues.length === 0 ? (
|
||||
<View style={{ marginTop: 0, backgroundColor: 'red' }} />
|
||||
) : (
|
||||
Object.keys(groupedData).map((categoryName, catIdx) => (
|
||||
<View key={catIdx} style={{ marginBottom: 20 }}>
|
||||
{/* Category Header */}
|
||||
<View style={{ backgroundColor: '#E8F0FF', padding: 8, borderRadius: 6 }}>
|
||||
<Text style={{ fontSize: 15, fontWeight: '700', color: '#113F8C' }}>
|
||||
{String(categoryName)}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* Table Header */}
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
backgroundColor: '#f5f5f5',
|
||||
paddingVertical: 8,
|
||||
paddingHorizontal: 9,
|
||||
borderTopLeftRadius: 8,
|
||||
borderTopRightRadius: 8,
|
||||
marginTop: 5
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: '#000', fontWeight: 'bold', width: '80%' }}>
|
||||
Definition
|
||||
</Text>
|
||||
<Text style={{ color: '#000', fontWeight: 'bold', width: '20%', textAlign: 'center' }}>
|
||||
Executed
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* Table Rows */}
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: '#fff',
|
||||
paddingHorizontal: 10,
|
||||
borderBottomLeftRadius: 8,
|
||||
borderBottomRightRadius: 8,
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 1 },
|
||||
shadowOpacity: 0.1,
|
||||
shadowRadius: 2,
|
||||
elevation: 2
|
||||
}}
|
||||
>
|
||||
{groupedData[categoryName].map((row, rowIdx) => (
|
||||
<View
|
||||
key={rowIdx}
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
paddingVertical: 8,
|
||||
borderBottomWidth: rowIdx === groupedData[categoryName].length - 1 ? 0 : 1,
|
||||
borderColor: '#eee'
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: '#000', width: '80%' }}>
|
||||
{String(row.Promotion_MasterPromotion_Definition) || '-'}
|
||||
</Text>
|
||||
<Text style={{ color: '#000', width: '20%', textAlign: 'center' }}>
|
||||
{row.Executed || '-'}
|
||||
</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
))
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
let displayKey = null;
|
||||
let presentKey = null;
|
||||
if (values.length > 0) {
|
||||
const presentKeys = Object.keys(values[0]).filter(k =>
|
||||
(typeof values[0][k] === 'string' && ['Yes', 'No'].includes(values[0][k])) ||
|
||||
typeof values[0][k] === 'boolean' ||
|
||||
typeof values[0][k] === 'number'
|
||||
);
|
||||
presentKey = presentKeys.length > 0 ? presentKeys[0] : null;
|
||||
const displayKeys = Object.keys(values[0]).filter(k => k !== presentKey && typeof values[0][k] === 'string');
|
||||
displayKey = displayKeys.length > 0 ? displayKeys[0] : null;
|
||||
}
|
||||
|
||||
return (
|
||||
<View key={index} style={{ marginBottom: 30 }}>
|
||||
|
||||
<Text style={{ marginTop: 10, color: '#000', fontSize: 16, fontWeight: '600', marginBottom: 10 }}>
|
||||
{detail.GraphTitle}
|
||||
|
||||
</Text>
|
||||
<View style={styled.categoryHeader}>
|
||||
<Text style={{ color: '#000', fontWeight: 'bold', width: '80%' }}>
|
||||
{displayKey ? displayKey.replace(/_/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2') : ''}
|
||||
</Text>
|
||||
<Text style={{ color: '#000', fontWeight: 'bold', width: '20%', textAlign: 'center' }}>
|
||||
{presentKey ? presentKey.replace(/_/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2') : ''}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={styled.itemContainer}>
|
||||
{values.map((row, idx) => {
|
||||
const presentKeys = Object.keys(row).filter(k =>
|
||||
(typeof row[k] === 'string' && ['Yes', 'No'].includes(row[k])) ||
|
||||
typeof row[k] === 'boolean' ||
|
||||
typeof row[k] === 'number'
|
||||
);
|
||||
const presentKey = presentKeys.length > 0 ? presentKeys[0] : null;
|
||||
const displayKeys = Object.keys(row).filter(k => k !== presentKey && typeof row[k] === 'string');
|
||||
const displayKey = displayKeys.length > 0 ? displayKeys[0] : null;
|
||||
|
||||
return (
|
||||
<View
|
||||
key={idx}
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
paddingVertical: 8,
|
||||
borderBottomWidth: idx === values.length - 1 ? 0 : 1,
|
||||
borderColor: '#eee',
|
||||
}}>
|
||||
<Text style={{ color: '#000', width: '80%' }}>{row[displayKey] || '--'}</Text>
|
||||
|
||||
<TouchableOpacity disabled={isOSATab ? false : true}
|
||||
onPress={() => {
|
||||
if (row[presentKey] == 100 || row[presentKey] == '100') {
|
||||
toastError('Alert', 'No Data Available')
|
||||
} else {
|
||||
showCategoryDetails(row)
|
||||
}
|
||||
}}
|
||||
style={{ width: '20%', }}>
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||
<Text style={{ color: '#113F8C', textAlign: 'center', fontWeight: '500' }}>
|
||||
{presentKey ? (
|
||||
typeof row[presentKey] === 'string' && ['Yes', 'No'].includes(row[presentKey]) ? row[presentKey] :
|
||||
typeof row[presentKey] === 'boolean' ? (row[presentKey] ? 'Yes' : 'No') :
|
||||
typeof row[presentKey] === 'number' ? row[presentKey].toFixed(2) : row[presentKey] || '-'
|
||||
) : '-'}
|
||||
</Text>
|
||||
{ isOSATab && row[presentKey] != 100 || isOSATab && row[presentKey] != '100'? <Image source={IMAGES.rightArrowIcon} style={{marginLeft:6, height: 12, width: 12, resizeMode: 'contain' }} /> :null}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<View key={index} style={{ marginBottom: 20 }}>
|
||||
<Text>Unsupported GraphType: {detail.GraphType}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}) :
|
||||
<Loader visible={true} />
|
||||
}
|
||||
</ScrollView>
|
||||
|
||||
<Modal
|
||||
visible={categoryModalVisible}
|
||||
animationType="slide"
|
||||
onRequestClose={() => setCategoryModalVisible(false)}
|
||||
>
|
||||
<View style={{ flex: 1, }}>
|
||||
{/* Header */}
|
||||
<View style={{ height: Platform.OS === 'ios' ? 55 : 0, backgroundColor: '#113F8C' }} />
|
||||
|
||||
<View style={{ width: '100%', backgroundColor: '#113F8C', borderBottomWidth: 1, borderColor: 'gray', padding: 5, paddingHorizontal: 20, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<View style={{ width: '93%', alignItems: 'center' }}>
|
||||
<Text style={{ color: '#fff', fontSize: 20, fontWeight: 'bold', marginBottom: 10, alignSelf: 'center' }}>{selectedCategoryData[0]?.Product_CategoryCategory_Name || 'Category'}</Text>
|
||||
</View>
|
||||
<TouchableOpacity onPress={() => setCategoryModalVisible(false)} style={{ width: '7%', alignItems: 'center' }}>
|
||||
<Image source={IMAGES.crossIcon} style={{ height: 25, width: 25, resizeMode: 'contain' }} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<View style={{ borderTopLeftRadius: 10, borderTopRightRadius: 10, marginTop: 15, marginHorizontal: 15, backgroundColor: '#eee', padding: 10, borderWidth: 1, borderColor: 'gray' }}>
|
||||
<Text style={{ color: '#000', fontSize: 16, fontWeight: '500' }}>{'Out of Stock SKUs:'}</Text>
|
||||
</View>
|
||||
|
||||
{/* SKU List */}
|
||||
<ScrollView contentContainerStyle={{
|
||||
marginHorizontal: 15,
|
||||
borderBottomWidth: 0.5,
|
||||
borderLeftWidth: 0.5,
|
||||
borderRightWidth: 0.5,
|
||||
borderColor: 'gray',
|
||||
borderBottomEndRadius: 10,
|
||||
borderBottomLeftRadius: 10,
|
||||
}}>
|
||||
{/* <Text style={{ color: '#000', fontSize: 16, fontWeight: 'bold', marginBottom: 5 }}>OOS SKU details</Text> */}
|
||||
{selectedCategoryData.map((item, idx) => (
|
||||
<View
|
||||
key={idx}
|
||||
style={{
|
||||
marginTop: 2,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
paddingVertical: 8,
|
||||
borderBottomWidth: idx === selectedCategoryData.length - 1 ? 0 : 1,
|
||||
borderColor: '#eee',
|
||||
|
||||
}}
|
||||
>
|
||||
<View style={{ flexDirection: 'row' }}>
|
||||
<Text style={{ color: '#000', marginLeft: 10 }}>{idx + 1}. </Text>
|
||||
<Text style={{ color: '#000', }}>
|
||||
{item.Product_MasterProduct_Name}
|
||||
</Text>
|
||||
</View>
|
||||
{/* <Text style={{ color: '#000', width: '20%', textAlign: 'center' }}>
|
||||
{item['#_of_OOS_SKU_for_all_visits']}
|
||||
</Text> */}
|
||||
</View>
|
||||
))}
|
||||
</ScrollView>
|
||||
</View>
|
||||
</Modal>
|
||||
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
|
||||
const styled = StyleSheet.create({
|
||||
header: {
|
||||
width: '100%',
|
||||
backgroundColor: '#113F8C',
|
||||
padding: 10,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center'
|
||||
},
|
||||
categoryHeader: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
backgroundColor: '#EDEDED',
|
||||
paddingVertical: 8,
|
||||
paddingHorizontal: 10,
|
||||
borderTopLeftRadius: 8,
|
||||
borderTopRightRadius: 8,
|
||||
},
|
||||
itemContainer: {
|
||||
backgroundColor: '#fff',
|
||||
paddingHorizontal: 10,
|
||||
borderBottomLeftRadius: 8,
|
||||
borderBottomRightRadius: 8,
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 1 },
|
||||
shadowOpacity: 0.1,
|
||||
shadowRadius: 2,
|
||||
elevation: 2
|
||||
}
|
||||
})
|
||||
|
||||
export default Details;
|
||||
@@ -0,0 +1,318 @@
|
||||
{
|
||||
"subTabs": [
|
||||
{
|
||||
"TabId": 1,
|
||||
"TabName": "PSS Score",
|
||||
"TabRow": 1,
|
||||
"TabCol": 1
|
||||
},
|
||||
{
|
||||
"TabId": 2,
|
||||
"TabName": "SOS Actual",
|
||||
"TabRow": 1,
|
||||
"TabCol": 2
|
||||
},
|
||||
{
|
||||
"TabId": 3,
|
||||
"TabName": "SOS Compliance",
|
||||
"TabRow": 1,
|
||||
"TabCol": 3
|
||||
},
|
||||
{
|
||||
"TabId": 4,
|
||||
"TabName": "OSA",
|
||||
"TabRow": 1,
|
||||
"TabCol": 4
|
||||
},
|
||||
{
|
||||
"TabId": 5,
|
||||
"TabName": "Asset",
|
||||
"TabRow": 1,
|
||||
"TabCol": 5
|
||||
},
|
||||
{
|
||||
"TabId": 6,
|
||||
"TabName": "Promotion",
|
||||
"TabRow": 1,
|
||||
"TabCol": 6
|
||||
}
|
||||
],
|
||||
"graphDetails": [
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 1,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "PSS Score",
|
||||
"GraphUrl": "http://localhost:3000/MTD/PSSScore",
|
||||
"GraphBackground": "#F4EAFF",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 2,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "SOS Actual",
|
||||
"GraphUrl": "http://localhost:3000/MTD/SOSActual",
|
||||
"GraphBackground": "#FFF3ED",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 3,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "SOS Compliance",
|
||||
"GraphUrl": "http://localhost:3000/MTD/SOSCompliance",
|
||||
"GraphBackground": "#FFFEF0",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 4,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "OSA",
|
||||
"GraphUrl": "http://localhost:3000/MTD/OSA",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 5,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Asset",
|
||||
"GraphUrl": "http://localhost:3000/MTD/Asset",
|
||||
"GraphBackground": "#EBECFF",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 6,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Promotion",
|
||||
"GraphUrl": "http://localhost:3000/MTD/Promotion",
|
||||
"GraphBackground": "#FFFEF0",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 2,
|
||||
"GraphId": 1,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "SOS Actual",
|
||||
"GraphUrl": "http://localhost:3000/MTD/SOSActual",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 2,
|
||||
"GraphId": 2,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "SOS Actual Trend",
|
||||
"GraphUrl": "http://localhost:3000/MTD/SOSActualTrend",
|
||||
"GraphBackground": "#F4EAFF",
|
||||
"GraphOptions": {
|
||||
"axisX": "month",
|
||||
"axisY": "score",
|
||||
"labelShow": 1,
|
||||
"barColors": [
|
||||
"#ffaa11",
|
||||
"#ffbb11",
|
||||
"#ffcc11"
|
||||
],
|
||||
"gridLinesH": 1,
|
||||
"gridLinesV": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"TabId": 3,
|
||||
"GraphId": 3,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "SOS Compliance",
|
||||
"GraphUrl": "http://localhost:3000/MTD/SOSActual",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 3,
|
||||
"GraphId": 4,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "SOS Compliance Trend",
|
||||
"GraphUrl": "http://localhost:3000/MTD/SOSActualTrend",
|
||||
"GraphBackground": "#fff",
|
||||
"GraphOptions": {
|
||||
"axisX": "month",
|
||||
"axisY": "score",
|
||||
"labelShow": 1,
|
||||
"barColors": [
|
||||
"#ffaa11",
|
||||
"#ffbb11",
|
||||
"#ffcc11"
|
||||
],
|
||||
"gridLinesH": 1,
|
||||
"gridLinesV": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"TabId": 5,
|
||||
"GraphId": 5,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Asset",
|
||||
"GraphUrl": "http://localhost:3000/MTD/SOSActual",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
|
||||
},
|
||||
{
|
||||
"TabId": 5,
|
||||
"GraphId": 6,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "Asset Details",
|
||||
"GraphUrl": "http://localhost:3000/MTD/SOSActual",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 4,
|
||||
"GraphId": 7,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "OSA",
|
||||
"GraphUrl": "http://localhost:3000/MTD/SOSActual",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 4,
|
||||
"GraphId": 8,
|
||||
"GraphType": "PieChart",
|
||||
"GraphTitle": "OSA",
|
||||
"GraphUrl": "http://localhost:3000/MTD/SOSActual",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 6,
|
||||
"GraphId": 9,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Promotion",
|
||||
"GraphUrl": "http://localhost:3000/MTD/SOSActual",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 6,
|
||||
"GraphId": 10,
|
||||
"GraphType": "LineChart",
|
||||
"GraphTitle": "Promotion",
|
||||
"GraphUrl": "http://localhost:3000/MTD/SOSActual",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"TabId": 3,
|
||||
"GraphId": 3,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "SOS Compliance",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/SOS_Compliance_Perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 1,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 3,
|
||||
"GraphId": 3,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "SOS Compliance - Category",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/sos_sompliance_perc_on_category",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 3,
|
||||
"GraphId": 4,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "SOS Compliance Trend",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/sos_compliance_trend_perc_mtd",
|
||||
"GraphBackground": "#fff",
|
||||
"GraphOptions": {
|
||||
"axisX": "month",
|
||||
"axisY": "score",
|
||||
"labelShow": 1,
|
||||
"barColors": [
|
||||
"#11a4ff",
|
||||
"#0ea3e3",
|
||||
"#0b9ddb"
|
||||
],
|
||||
"gridLinesH": 1,
|
||||
"gridLinesV": 1
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"TabId": 3,
|
||||
"GraphId": 3,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "SOS Compliance",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/sos_compliance_lsv_perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 1,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 3,
|
||||
"GraphId": 3,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "SOS Actual - Category",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detlsv/sos_compliance_lsv_perc_on_category",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 3,
|
||||
"GraphId": 4,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "SOS Compliance Trend",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/sos_compliance_trend_lsv_perc",
|
||||
"GraphBackground": "#fff",
|
||||
"GraphOptions": {
|
||||
"axisX": "month",
|
||||
"axisY": "score",
|
||||
"labelShow": 1,
|
||||
"barColors": [
|
||||
"#11a4ff",
|
||||
"#0ea3e3",
|
||||
"#0b9ddb"
|
||||
],
|
||||
"gridLinesH": 1,
|
||||
"gridLinesV": 1
|
||||
}
|
||||
},
|
||||
@@ -0,0 +1,906 @@
|
||||
import { View, Text, StyleSheet, Image, TouchableOpacity, Dimensions, TextInput, ScrollView, FlatList, Button, Alert, Modal, TouchableWithoutFeedback, StatusBar } from 'react-native'
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import RBSheet from 'react-native-raw-bottom-sheet';
|
||||
import { styles } from './style';
|
||||
import LinearGradient from 'react-native-linear-gradient';
|
||||
import CustomHeader from '../../../components/CustomHeader';
|
||||
import IMAGES from '../../../constants/Images';
|
||||
import CustomButton from '../../../components/CustomButton';
|
||||
import CustomDropdown from '../../../components/CustomDropdown';
|
||||
import { GlobalTheme } from '../../../theme';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
|
||||
import displayData from './display.json'
|
||||
import { BarChart, LineChart, PieChart } from 'react-native-chart-kit';
|
||||
import { getDownloadJson } from '../../../constants/function';
|
||||
import db, { getAllFromTable } from '../../../constants/database';
|
||||
import { post } from '../../../api/ApiService';
|
||||
import { ApiURL } from '../../../api/ApiConstant';
|
||||
|
||||
import mainDisplayJson from './mainDisplay.json'
|
||||
|
||||
const Dashboard = (props) => {
|
||||
|
||||
const { navigation } = props;
|
||||
const screenHeight = Dimensions.get('screen').height;
|
||||
const screenWidth = Dimensions.get('screen').width;
|
||||
const refRBSheet = useRef();
|
||||
const [isStoreSelected, setIsStoreSelected] = useState(false)
|
||||
const [searchResult, setSearchResult] = useState(false)
|
||||
const [storeData, setStoreData] = useState({})
|
||||
const [mainTab, setMainTab] = useState('mtd')
|
||||
const [activeTab, setActiveTab] = useState(displayData?.subTabs?.[0]?.TabId || 1)
|
||||
const [state, setState] = useState(null);
|
||||
const [year, setYear] = useState(null)
|
||||
const [month, setMonth] = useState(null)
|
||||
const [city, setCity] = useState(null);
|
||||
const [asmArea, setAsmArea] = useState(null);
|
||||
const scrollViewRef = useRef(null);
|
||||
const [showButton, setShowButton] = useState(false);
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
|
||||
|
||||
// Handle scroll event to show/hide button
|
||||
const handleScroll = (event) => {
|
||||
const offsetY = event.nativeEvent.contentOffset.y;
|
||||
setShowButton(offsetY > 0); // Show button only if not at the top
|
||||
};
|
||||
|
||||
const openBottomSheet = () => {
|
||||
refRBSheet.current.open()
|
||||
}
|
||||
|
||||
const onSelectStore = (item) => {
|
||||
setStoreData(item)
|
||||
setIsStoreSelected(true)
|
||||
refRBSheet.current.close()
|
||||
}
|
||||
|
||||
const data = [
|
||||
{ label: 'Delhi', value: '1' },
|
||||
{ label: 'Mumbai', value: '2' },
|
||||
];
|
||||
const cityData = [
|
||||
{ label: 'Okhla', value: '1' },
|
||||
{ label: 'Kalkaji', value: '2' },
|
||||
{ label: 'South Ex.', value: '3' },
|
||||
];
|
||||
const storeJson = [
|
||||
{
|
||||
id: 1,
|
||||
name: "Banarasi & Sons",
|
||||
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||
status: "pending"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Gupta store & Sons",
|
||||
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||
status: "completed"
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "Bansal General store",
|
||||
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||
status: "completed"
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "Mohan Mahalaxmi store",
|
||||
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||
status: "completed"
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "Chawla Store",
|
||||
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||
status: "completed"
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "Chawla Store",
|
||||
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||
status: "completed"
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: "Chawla Store",
|
||||
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||
status: "completed"
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: "Chawla Store",
|
||||
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||
status: "completed"
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: "Chawla Store",
|
||||
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||
status: "completed"
|
||||
},
|
||||
|
||||
|
||||
];
|
||||
const visitedStoreData = [
|
||||
{
|
||||
id: 1,
|
||||
name: "Chawla Store",
|
||||
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||
status: "pending"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Mohan Mahalaxmi store",
|
||||
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||
status: "completed"
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "Bansal General store",
|
||||
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||
status: "completed"
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "Bansal General store",
|
||||
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||
status: "completed"
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "Bansal General store",
|
||||
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||
status: "completed"
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "Bansal General store",
|
||||
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||
status: "completed"
|
||||
},
|
||||
|
||||
];
|
||||
const monthData = [
|
||||
{ label: 'January', value: '1' },
|
||||
{ label: 'February', value: '2' },
|
||||
{ label: 'March', value: '3' },
|
||||
{ label: 'April', value: '4' },
|
||||
{ label: 'May', value: '5' },
|
||||
{ label: 'June', value: '6' },
|
||||
{ label: 'July', value: '7' },
|
||||
{ label: 'August', value: '8' },
|
||||
{ label: 'September', value: '9' },
|
||||
{ label: 'October', value: '10' },
|
||||
{ label: 'November', value: '11' },
|
||||
{ label: 'December', value: '12' },
|
||||
];
|
||||
const yearData = [
|
||||
{ label: '2025', value: '2025' },
|
||||
{ label: '2024', value: '2024' },
|
||||
{ label: '2023', value: '2023' },
|
||||
{ label: '2022', value: '2022' },
|
||||
{ label: '2021', value: '2021' },
|
||||
{ label: '2020', value: '2020' },
|
||||
{ label: '2019', value: '2019' },
|
||||
{ label: '2018', value: '2018' },
|
||||
{ label: '2017', value: '2017' },
|
||||
{ label: '2016', value: '2016' },
|
||||
{ label: '2015', value: '2015' },
|
||||
];
|
||||
const assetData = [
|
||||
{
|
||||
"section": "Asset%",
|
||||
"data": [
|
||||
{ "display": "Real Endcap", "present": "No" },
|
||||
{ "display": "Honey Parasite", "present": "Yes" },
|
||||
{ "display": "Odonil Floor Stack", "present": "YHes" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"section": "Additional Visibility",
|
||||
"data": [
|
||||
{ "display": "Active 1 Ltr Endcap", "present": "Yes" },
|
||||
{ "display": "Chyawanprash Stack", "present": "Yes" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"section": "Promotion",
|
||||
"data": [
|
||||
{ "display": "Activ 100% Juice", "present": "Yes" },
|
||||
{ "display": "Airfresher", "present": "No" },
|
||||
{ "display": "BABY CARE", "present": "No" },
|
||||
{ "display": "Chyawanprash", "present": "No" },
|
||||
{ "display": "Hair Oil", "present": "No" },
|
||||
]
|
||||
}
|
||||
]
|
||||
const PieData = [
|
||||
{
|
||||
name: "Seoul",
|
||||
population: 21500000,
|
||||
color: "rgba(131, 167, 234, 1)",
|
||||
legendFontColor: "#7F7F7F",
|
||||
legendFontSize: 15
|
||||
},
|
||||
{
|
||||
name: "Toronto",
|
||||
population: 2800000,
|
||||
color: "#F00",
|
||||
legendFontColor: "#7F7F7F",
|
||||
legendFontSize: 15
|
||||
},
|
||||
{
|
||||
name: "Beijing",
|
||||
population: 527612,
|
||||
color: "red",
|
||||
legendFontColor: "#7F7F7F",
|
||||
legendFontSize: 15
|
||||
},
|
||||
{
|
||||
name: "New York",
|
||||
population: 8538000,
|
||||
color: "#ffffff",
|
||||
legendFontColor: "#7F7F7F",
|
||||
legendFontSize: 15
|
||||
},
|
||||
{
|
||||
name: "Moscow",
|
||||
population: 11920000,
|
||||
color: "rgb(0, 0, 255)",
|
||||
legendFontColor: "#7F7F7F",
|
||||
legendFontSize: 15
|
||||
}
|
||||
];
|
||||
|
||||
const barData = {
|
||||
labels: ["Jan", "Feb", "March", "April",],
|
||||
datasets: [
|
||||
{
|
||||
data: [20, 45, 28, 80]
|
||||
}
|
||||
]
|
||||
};
|
||||
const chartConfig = {
|
||||
backgroundColor: '#ffffff',
|
||||
backgroundGradientFrom: '#ffffff',
|
||||
backgroundGradientTo: '#ffffff',
|
||||
fillShadowGradientFrom: '#FF8C61', // For bar colors
|
||||
fillShadowGradientTo: '#FF8C61',
|
||||
fillShadowGradientFromOpacity: 1,
|
||||
fillShadowGradientToOpacity: 1,
|
||||
decimalPlaces: 0,
|
||||
color: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`, // Text color
|
||||
labelColor: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
|
||||
// barPercentage: 0.5,
|
||||
barPercentage: 1,
|
||||
|
||||
};
|
||||
|
||||
const onSelectSubTab = (item) => {
|
||||
setActiveTab(item?.TabId)
|
||||
}
|
||||
|
||||
const filteredGraphs = displayData?.graphDetails?.filter(graph => graph.TabId === activeTab);
|
||||
const firstItem = filteredGraphs?.[0];
|
||||
const restItems = filteredGraphs?.slice(1);
|
||||
|
||||
const renderItem = ({ item }) => {
|
||||
switch (item.GraphType) {
|
||||
case "ScoreCard":
|
||||
return (
|
||||
<View style={[styles.percentBox, { backgroundColor: item.GraphBackground }]}>
|
||||
<Text style={styles.boxText}>{item.GraphTitle}</Text>
|
||||
<Text style={[styles.boxText, { fontWeight: '500', fontSize: 24, marginTop: 10 }]}>{"45%"}</Text>
|
||||
</View>
|
||||
);
|
||||
|
||||
case "BarGraph":
|
||||
const barData = {
|
||||
labels: ["Jan", "Feb", "Mar", "Apr"],
|
||||
datasets: [{ data: [35, 45, 20, 55] }]
|
||||
};
|
||||
return (
|
||||
<View style={{ padding: 10, backgroundColor: '', borderRadius: 8 }}>
|
||||
<Text style={{ fontSize: 16, fontWeight: '600', marginBottom: 10 }}>
|
||||
SOS Compliance Trend
|
||||
</Text>
|
||||
<BarChart
|
||||
data={barData}
|
||||
width={screenWidth - 40}
|
||||
height={220}
|
||||
yAxisSuffix="%"
|
||||
chartConfig={chartConfig}
|
||||
fromZero
|
||||
showValuesOnTopOfBars
|
||||
withInnerLines
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
||||
case "Table":
|
||||
return (
|
||||
<View style={{ flex: 1, }}>
|
||||
<ScrollView>
|
||||
<View style={{ flexDirection: 'row', borderWidth: 1, borderColor: '#EAEAEA', alignItems: 'center', alignSelf: 'flex-start', padding: 5, borderRadius: 15 }}>
|
||||
<TouchableOpacity
|
||||
style={[styles.subTab, { backgroundColor: '#113F8C' }]}>
|
||||
<Text style={[styles.tabText, { color: "#fff" }]}>{'Asset'}</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
style={[styles.subTab, { backgroundColor: '#113F8C' }]}>
|
||||
<Text style={[styles.tabText, { color: "#fff" }]}>{'Asset Details'}</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
</View>
|
||||
|
||||
{assetData && assetData.map((table, index) => (
|
||||
<View key={index} style={{ marginTop: 10 }}>
|
||||
<Text style={{ fontSize: 16, color: '#000', fontWeight: '500' }}>{table.section}</Text>
|
||||
|
||||
<View style={{ marginTop: 5, backgroundColor: '#fff', elevation: 5, padding: 10, borderRadius: 10 }}>
|
||||
<View style={{ flexDirection: 'row', borderBottomWidth: 1, borderColor: '#E0E0E0', paddingBottom: 7, }}>
|
||||
<Text style={{ width: '50%', color: '#676767', fontSize: 14 }}>Display</Text>
|
||||
<Text style={{ width: '50%', color: '#676767', fontSize: 14 }}>Present</Text>
|
||||
</View>
|
||||
{
|
||||
table && table.data.map((item) => (
|
||||
<View style={{ marginTop: 3, flexDirection: 'row', paddingBottom: 7, borderBottomWidth: 1, borderColor: '#E0E0E0', }}>
|
||||
<Text style={{ width: '50%', color: '#000', fontSize: 14, }}>{item.display}</Text>
|
||||
<Text style={{ width: '50%', color: '#000', fontSize: 14, }}>{item?.present}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
))}
|
||||
<View style={{ marginBottom: 500 }} />
|
||||
</ScrollView>
|
||||
</View>
|
||||
)
|
||||
|
||||
case "LineChart":
|
||||
return (
|
||||
<View style={{ flex: 1, }}>
|
||||
<Text>Bezier Line Chart</Text>
|
||||
<LineChart
|
||||
data={{
|
||||
labels: ["January", "February", "March", "April", "May", "June"],
|
||||
datasets: [
|
||||
{
|
||||
data: [
|
||||
Math.random() * 100,
|
||||
Math.random() * 100,
|
||||
Math.random() * 100,
|
||||
Math.random() * 100,
|
||||
Math.random() * 100,
|
||||
Math.random() * 100
|
||||
]
|
||||
}
|
||||
]
|
||||
}}
|
||||
width={Dimensions.get("window").width} // from react-native
|
||||
height={220}
|
||||
yAxisLabel="$"
|
||||
yAxisSuffix="k"
|
||||
yAxisInterval={1} // optional, defaults to 1
|
||||
chartConfig={{
|
||||
backgroundColor: "#e26a00",
|
||||
backgroundGradientFrom: "lgray",
|
||||
backgroundGradientTo: "lightblue",
|
||||
decimalPlaces: 2, // optional, defaults to 2dp
|
||||
color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
|
||||
labelColor: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
|
||||
style: {
|
||||
borderRadius: 16
|
||||
},
|
||||
propsForDots: {
|
||||
r: "6",
|
||||
strokeWidth: "2",
|
||||
stroke: "#ffa726"
|
||||
}
|
||||
}}
|
||||
bezier
|
||||
style={{
|
||||
marginVertical: 8,
|
||||
borderRadius: 16
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
case "PieChart":
|
||||
return (
|
||||
<View style={{ flex: 1, }}>
|
||||
<PieChart
|
||||
data={PieData}
|
||||
width={screenWidth}
|
||||
height={220}
|
||||
chartConfig={chartConfig}
|
||||
accessor={"population"}
|
||||
backgroundColor={"transparent"}
|
||||
paddingLeft={"15"}
|
||||
center={[10, 50]}
|
||||
absolute
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
|
||||
default:
|
||||
return (
|
||||
<View style={[styles.percentBox, { backgroundColor: "#f8d7da", padding: 10, marginVertical: 5 }]}>
|
||||
<Text style={[styles.boxText, { color: "#721c24" }]}>
|
||||
Unsupported Graph Type: {item.GraphType}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// download data
|
||||
useEffect(() => {
|
||||
const init = async () => {
|
||||
await getData(); // <-- Only dynamic live data
|
||||
};
|
||||
init();
|
||||
|
||||
getTabData()
|
||||
|
||||
}, []);
|
||||
|
||||
// Insert fallback mock data if empty
|
||||
const insertMasterSurveyQuestion = (data_arr = []) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!Array.isArray(data_arr) || data_arr.length === 0) {
|
||||
resolve(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const escape = str => (str || '').toString().replace(/'/g, "''");
|
||||
|
||||
const values = data_arr.map(item => {
|
||||
const {
|
||||
MenuId, SurveyId, SurveyName, CategoryId, Category, CategorySequence,
|
||||
QuestionId, Question, QuestionType, QuestionImageAllow, QEnable,
|
||||
LengthValidation, MinLength, MaxLength, OTP, DateRange, QuestionSequence,
|
||||
AnswerId, Answer, ImageAllow1, ImageAllow2, Image1Mandatory, Image2Mandatory,
|
||||
QuestionImageMandatory, EnableQuestion, DisableQuestion, AnswerSequence,
|
||||
ShowCat, SubCategoryId, SubCategory, SubCategorySequence,
|
||||
QuestionTypeNew, CalFormula, RefImage, QuestionRefImage
|
||||
} = item;
|
||||
|
||||
return `(
|
||||
'${MenuId}', '${SurveyId}', '${escape(SurveyName)}', '${CategoryId}', '${escape(Category)}',
|
||||
'${CategorySequence}', '${QuestionId}', '${escape(Question)}', '${escape(QuestionType)}',
|
||||
'${QuestionImageAllow ? 1 : 0}', '${QEnable ? 1 : 0}', '${LengthValidation ? 1 : 0}',
|
||||
'${MinLength}', '${MaxLength}', '${OTP ? 1 : 0}', '${escape(DateRange)}',
|
||||
'${QuestionSequence}', '${AnswerId}', '${escape(Answer)}',
|
||||
'${ImageAllow1 ? 1 : 0}', '${ImageAllow2 ? 1 : 0}', '${Image1Mandatory ? 1 : 0}',
|
||||
'${Image2Mandatory ? 1 : 0}', '${QuestionImageMandatory ? 1 : 0}',
|
||||
'${escape(EnableQuestion)}', '${escape(DisableQuestion)}', '${AnswerSequence}',
|
||||
'${ShowCat ? 1 : 0}', '${SubCategoryId}', '${escape(SubCategory)}',
|
||||
'${SubCategorySequence}', '${escape(QuestionTypeNew)}', '${escape(CalFormula)}',
|
||||
'${escape(RefImage)}', '${escape(QuestionRefImage)}'
|
||||
)`;
|
||||
});
|
||||
|
||||
const sql = `
|
||||
INSERT INTO FeedbackCategory (
|
||||
MenuId, SurveyId, SurveyName, CategoryId, Category, CategorySequence,
|
||||
QuestionId, Question, QuestionType, QuestionImageAllow, QEnable,
|
||||
LengthValidation, MinLength, MaxLength, OTP, DateRange, QuestionSequence,
|
||||
AnswerId, Answer, ImageAllow1, ImageAllow2, Image1Mandatory, Image2Mandatory,
|
||||
QuestionImageMandatory, EnableQuestion, DisableQuestion, AnswerSequence,
|
||||
ShowCat, SubCategoryId, SubCategory, SubCategorySequence,
|
||||
QuestionTypeNew, CalFormula, RefImage,QuestionRefImage
|
||||
) VALUES ${values.join(',')}
|
||||
`;
|
||||
|
||||
db.transaction(tx => {
|
||||
tx.executeSql(`DELETE FROM FeedbackCategory`, [], () => {
|
||||
tx.executeSql(sql, [], () => {
|
||||
console.log('FeedbackCategory inserted successfully');
|
||||
resolve(true);
|
||||
}, (err) => {
|
||||
console.log('Insert error in FeedbackCategory:', err);
|
||||
reject(err);
|
||||
});
|
||||
}, (err) => {
|
||||
console.log('Delete error before insert FeedbackCategory:', err);
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
async function getData() {
|
||||
try {
|
||||
const data1 = {
|
||||
Downloadtype: "Master_SurveyQuestion",
|
||||
Param1: "",
|
||||
Param2: "",
|
||||
username: "testmer",
|
||||
};
|
||||
|
||||
const url = "https://di1.parinaam.in/Webservice/GenericService.svc/DownloadJson";
|
||||
console.log("Downloading from:", url, data1);
|
||||
|
||||
const res = await getDownloadJson(url, data1);
|
||||
console.log('Response:', res);
|
||||
|
||||
if (res?.Master_SurveyQuestion?.length) {
|
||||
const data = res.Master_SurveyQuestion || [];
|
||||
console.log("Inserting downloaded data into FeedbackCategory...");
|
||||
const all = await getAllFromTable('FeedbackCategory');
|
||||
if (all?.length === 0) {
|
||||
console.log("Table empty. Inserting fallback mock data...");
|
||||
await insertMasterSurveyQuestion(data);
|
||||
} else {
|
||||
console.log("FeedbackCategory table already has data.");
|
||||
}
|
||||
} else {
|
||||
console.log("No Master_SurveyQuestion data found in response");
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("Dashboard feedback survey download error:", err);
|
||||
}
|
||||
}
|
||||
// end download data.
|
||||
|
||||
const getTabData = () => {
|
||||
let params = {
|
||||
"parameters": {
|
||||
"projectid": 41654,
|
||||
"year": 2025,
|
||||
"monthno": 6,
|
||||
"storeid": 2702
|
||||
}
|
||||
}
|
||||
post(ApiURL.pssscoreApi, params)
|
||||
.then(res => {
|
||||
console.log('psscoreApi res==>', res);
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView style={{ flex: 1, backgroundColor: GlobalTheme.colors.primary }}>
|
||||
<View style={{ flex: 1, backgroundColor: '#fff' }}>
|
||||
{!isStoreSelected ?
|
||||
<CustomHeader
|
||||
title=" Dashboard"
|
||||
rightIcon={IMAGES.menuIcon}
|
||||
onRightPress={() => setModalVisible(true)}
|
||||
/>
|
||||
:
|
||||
<CustomHeader
|
||||
title="Dashboard"
|
||||
leftIcon={IMAGES.backIcon}
|
||||
onLeftPress={() => setIsStoreSelected(false)}
|
||||
rightIcon={IMAGES.menuIcon}
|
||||
onRightPress={() => setModalVisible(true)}
|
||||
|
||||
/>
|
||||
}
|
||||
|
||||
{/* MAIN DASHBOARD */}
|
||||
{!isStoreSelected ? (
|
||||
<View style={{ flex: 1 }} >
|
||||
|
||||
<TouchableOpacity onPress={() => openBottomSheet()} activeOpacity={0.8} style={styles.selectCard}>
|
||||
<Image source={IMAGES.reportIcon} style={styles.iconStyle} />
|
||||
<Text style={styles.storeText}> Select Store:</Text>
|
||||
<Image source={IMAGES.downIcon} style={{ height: 20, width: 20, resizeMode: 'contain' }} />
|
||||
</TouchableOpacity>
|
||||
<Text style={styles.selectStoreText}>Select a store to view it's data.</Text>
|
||||
|
||||
<LinearGradient
|
||||
colors={['#D8E7FF', '#FFFFFF',]}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 1 }}
|
||||
style={styles.storeGredient}>
|
||||
|
||||
<View style={styles.todayStoreCard}>
|
||||
|
||||
<View style={{ marginLeft: 5, flexDirection: 'row', padding: 10, alignItems: 'center' }}>
|
||||
<View style={{ backgroundColor: '#E3EBF8', padding: 5, borderRadius: 7 }}>
|
||||
<Image source={IMAGES.storeIcon} style={{ height: 18, width: 18 }} />
|
||||
</View>
|
||||
<Text style={styles.todayStoreText}>Today's store</Text>
|
||||
</View>
|
||||
<View style={{ borderBottomWidth: 1.5, borderColor: '#E3EBF8' }} />
|
||||
|
||||
<View style={[styles.row, { paddingHorizontal: 10 }]}>
|
||||
<View style={{ width: '48%', alignItems: 'center' }}>
|
||||
<Text style={{ color: '#000', fontSize: 20, fontWeight: 'bold' }}>1</Text>
|
||||
<Text style={{ color: '#808CA3', fontSize: 15, fontWeight: '400' }}>View</Text>
|
||||
</View>
|
||||
<View style={{ borderWidth: 1, height: 50, borderColor: '#E3EBF8' }} />
|
||||
<View style={{ width: '48%', alignItems: 'center' }}>
|
||||
<Text style={{ color: '#000', fontSize: 20, fontWeight: 'bold', textAlign: 'right' }}>2</Text>
|
||||
<Text style={{ color: '#808CA3', fontSize: 15, fontWeight: '400', textAlign: 'right' }}>Feedback</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<ScrollView showsVerticalScrollIndicator={false}>
|
||||
<View style={{ marginTop: 5, marginHorizontal: 10 }}>
|
||||
{visitedStoreData && visitedStoreData.map(store => (
|
||||
<TouchableOpacity onPress={() => navigation.navigate("FeedbackCategories")}
|
||||
key={store.id} style={styles.storeCard}>
|
||||
<View style={[styles.row, { margin: 0 }]}>
|
||||
<Text style={styles.cardTextBold}>{store.name}</Text>
|
||||
{store?.status === 'completed' ?
|
||||
<Image source={IMAGES.greenTick} style={{ height: 20, width: 20 }} />
|
||||
:
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||
<View style={{ backgroundColor: '#FFF8CD', padding: 5, paddingHorizontal: 7, borderRadius: 15 }}>
|
||||
<Text style={{ color: 'orange', fontSize: 13, fontWeight: '500' }}>Pending</Text>
|
||||
</View>
|
||||
<Image source={IMAGES.rightArrowIcon} style={{ marginLeft: 10, height: 20, width: 20, resizeMode: 'contain', tintColor: '#97ADD6' }} />
|
||||
</View>
|
||||
}
|
||||
</View>
|
||||
<Text style={styles.cardText}>{store.address}</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
))}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
|
||||
|
||||
|
||||
</LinearGradient>
|
||||
</View>
|
||||
) : (
|
||||
// STORE DASHBOARD
|
||||
<View style={styles.mainContainer}>
|
||||
<View style={styles.row}>
|
||||
<View style={styles.selectedStoreText}>
|
||||
<Text style={styles.storeNameText}> {storeData?.name}</Text>
|
||||
<TouchableOpacity onPress={() => openBottomSheet()} style={styles.filterIcon}>
|
||||
<Image source={IMAGES.filterIcon} style={{ height: 18, width: 18 }} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<TouchableOpacity onPress={() => navigation.navigate('StoreInfo')} style={{ width: '25%', alignItems: 'flex-end' }}>
|
||||
<Text style={styles.storeInfoText}>Store info</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* Year & Month Selector */}
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center', marginHorizontal: 10, marginTop: 5 }}>
|
||||
<View style={{ width: 100, }}>
|
||||
<CustomDropdown
|
||||
data={yearData}
|
||||
value={year}
|
||||
placeholder='Year'
|
||||
onChange={item => setYear(item.value)}
|
||||
containerStyle={styles.yearDropDown}
|
||||
/>
|
||||
</View>
|
||||
<View style={{ width: 120, marginHorizontal: 10, }}>
|
||||
<CustomDropdown
|
||||
data={monthData}
|
||||
value={month}
|
||||
placeholder='Month'
|
||||
onChange={item => setMonth(item.value)}
|
||||
containerStyle={[styles.yearDropDown, { width: 120 }]}
|
||||
/>
|
||||
</View>
|
||||
<CustomButton title={'Show'}
|
||||
style={styles.btnbg}
|
||||
textstyle={styles.btntext}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.seperator} />
|
||||
|
||||
{/* Main Tab */}
|
||||
<View style={{ flexDirection: 'row' }}>
|
||||
<TouchableOpacity onPress={() => setMainTab('mtd')}
|
||||
style={[styles.mtdTab, { borderBottomWidth: mainTab === 'mtd' ? 3 : 0, backgroundColor: mainTab === 'mtd' ? '#EFF6FF' : '#fff' }]} >
|
||||
<Text style={[styles.mtdTabText, { color: mainTab === 'mtd' ? '#113F8C' : '#000', }]}>MTD</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={() => setMainTab('lastVisit')}
|
||||
style={[styles.mtdTab, { borderBottomWidth: mainTab === 'lastVisit' ? 3 : 0, backgroundColor: mainTab === 'lastVisit' ? '#EFF6FF' : '#fff' }]} >
|
||||
<Text style={[styles.mtdTabText, { color: mainTab === 'lastVisit' ? '#113F8C' : '#000' }]}>Last Visit</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* <View style={{ flexDirection: 'row' }}>
|
||||
|
||||
{mainDisplayJson && mainDisplayJson?.Tabs.map((item, index) => (
|
||||
<TouchableOpacity onPress={() => setMainTab('mtd')}
|
||||
style={[styles.mtdTab, { borderBottomWidth: mainTab === 'mtd' ? 3 : 0, backgroundColor: mainTab === 'mtd' ? '#EFF6FF' : '#fff' }]} >
|
||||
<Text style={[styles.mtdTabText, { color: mainTab === 'mtd' ? '#113F8C' : '#000', }]}>MTD</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
|
||||
</View> */}
|
||||
|
||||
|
||||
|
||||
{/* Sub Tab */}
|
||||
<View style={styles.subTabView}>
|
||||
<FlatList
|
||||
data={displayData?.subTabs}
|
||||
horizontal
|
||||
keyExtractor={(item) => item.TabId}
|
||||
showsHorizontalScrollIndicator={false}
|
||||
contentContainerStyle={{ paddingHorizontal: 10 }}
|
||||
renderItem={({ item }) => {
|
||||
const isSelected = activeTab === item.TabId;
|
||||
return (
|
||||
<TouchableOpacity onPress={() => onSelectSubTab(item)}
|
||||
style={[styles.subTab, { backgroundColor: isSelected ? '#113F8C' : '#fff' }]}>
|
||||
<Text style={[styles.tabText, { color: isSelected ? "#fff" : "#000" }]}>{item.TabName}</Text>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* Boxes */}
|
||||
<View style={{ margin: 10 }}>
|
||||
{/* First full-width item */}
|
||||
{firstItem && (
|
||||
<View style={[styles.percentBox, { backgroundColor: firstItem.GraphBackground, width: '100%', elevation: 0 },]}>
|
||||
<Text style={styles.boxText}>{firstItem.GraphTitle}</Text>
|
||||
<Text style={[styles.boxText, { fontWeight: '500', fontSize: 24, marginTop: 10 }]}>{"45%"}</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<FlatList
|
||||
data={restItems}
|
||||
keyExtractor={(item, index) => `${item.GraphId}-${index}`}
|
||||
renderItem={renderItem}
|
||||
numColumns={2}
|
||||
columnWrapperStyle={{ justifyContent: 'space-between', marginTop: 10 }}
|
||||
contentContainerStyle={{ paddingHorizontal: 2, paddingVertical: 2 }}
|
||||
showsVerticalScrollIndicator={false}
|
||||
/>
|
||||
|
||||
</View>
|
||||
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* Pop-up Modal */}
|
||||
<Modal transparent visible={modalVisible} animationType="fade" >
|
||||
<TouchableOpacity style={styles.modalOverlay} activeOpacity={0.1} onPress={() => setModalVisible(false)}>
|
||||
<View style={styles.modalContainer}>
|
||||
<TouchableOpacity onPress={() => { navigation.navigate('FeedbackCategories'), setModalVisible(false) }} style={{ padding: 15 }}>
|
||||
<Text style={{}}>Feedback and Rating</Text>
|
||||
</TouchableOpacity>
|
||||
<View style={{ borderBottomWidth: 1, borderColor: '#D8E3F1' }} />
|
||||
<TouchableOpacity onPress={() => setModalVisible(false)} style={{ padding: 15 }}>
|
||||
<Text style={{}}>Dashboard</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</Modal>
|
||||
|
||||
{/* Bottom Sheet */}
|
||||
<RBSheet
|
||||
ref={refRBSheet}
|
||||
useNativeDriver={true}
|
||||
customStyles={{
|
||||
wrapper: {
|
||||
backgroundColor: 'rgba(0,0,0,0.2)',
|
||||
},
|
||||
container: {
|
||||
height: '86%',
|
||||
backgroundColor: '#fff',
|
||||
borderTopLeftRadius: 20,
|
||||
borderTopRightRadius: 20,
|
||||
paddingBottom: 10,
|
||||
},
|
||||
draggableIcon: {
|
||||
backgroundColor: 'gray',
|
||||
},
|
||||
|
||||
}}
|
||||
customModalProps={{
|
||||
animationType: 'slide',
|
||||
statusBarTranslucent: true,
|
||||
|
||||
}}
|
||||
customAvoidingViewProps={{
|
||||
enabled: false,
|
||||
}}>
|
||||
<View style={{ flex: 1, }}>
|
||||
<View style={styles.header}>
|
||||
<Text style={{ color: '#000', fontWeight: '500', fontSize: 16 }}>Select Store</Text>
|
||||
<TouchableOpacity onPress={() => refRBSheet.current.close()}>
|
||||
<Image source={IMAGES.crossIcon} style={styles.iconStyle} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={{ marginVertical: 0, borderBottomWidth: 1, borderColor: '#ccc' }} />
|
||||
|
||||
<ScrollView showsVerticalScrollIndicator={false}
|
||||
ref={scrollViewRef}
|
||||
onScroll={handleScroll} >
|
||||
<View style={{ flex: 1, margin: 15, }}>
|
||||
<View style={[styles.row, {}]}>
|
||||
<Text style={styles.dropHeaderText}>State</Text>
|
||||
<Text style={styles.dropHeaderText}> City</Text>
|
||||
<Text style={styles.dropHeaderText}> ASM Area</Text>
|
||||
</View>
|
||||
|
||||
{/* Dropdown */}
|
||||
<View style={{ marginTop: 5, flexDirection: 'row', alignItems: 'center' }}>
|
||||
<CustomDropdown
|
||||
data={data}
|
||||
value={state}
|
||||
onChange={item => setState(item.value)}
|
||||
containerStyle={{ flex: 1, }}
|
||||
/>
|
||||
<CustomDropdown
|
||||
data={cityData}
|
||||
value={city}
|
||||
onChange={item => setCity(item.value)}
|
||||
containerStyle={{ flex: 1, marginHorizontal: 10 }}
|
||||
/>
|
||||
<CustomDropdown
|
||||
data={cityData}
|
||||
value={asmArea}
|
||||
onChange={item => setAsmArea(item.value)}
|
||||
containerStyle={{ flex: 1, }}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={[styles.searchBox, { marginTop: 20 }]}>
|
||||
{/* <Image source={IMAGES.searchIcon} style={{ height: 15, width: 15 }} /> */}
|
||||
<TextInput
|
||||
style={styles.inputStyle}
|
||||
placeholder='Search store...'
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={{ marginTop: 20 }}>
|
||||
<CustomButton title={'Apply'} onPress={() => setSearchResult(!searchResult)}
|
||||
style={{ backgroundColor: GlobalTheme.colors.secondary, borderRadius: GlobalTheme.borderRadius.md }}
|
||||
textstyle={{ color: GlobalTheme.colors.white, fontSize: GlobalTheme.typography.fontSize.medium }}
|
||||
/>
|
||||
</View>
|
||||
{searchResult ?
|
||||
<View style={{ marginBottom: 70 }}>
|
||||
<View style={{ marginTop: 20 }}>
|
||||
<Text style={{ color: '#000', fontSize: 14 }}>11 Store</Text>
|
||||
</View>
|
||||
|
||||
{storeJson && storeJson.map(store => (
|
||||
<TouchableOpacity onPress={() => onSelectStore(store)}
|
||||
key={store.id} style={styles.storeCard}>
|
||||
<Text style={styles.cardTextBold}>{store.name}</Text>
|
||||
<Text style={styles.cardText}>{store.address}</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
))}
|
||||
|
||||
|
||||
</View>
|
||||
: null
|
||||
}
|
||||
|
||||
|
||||
|
||||
</View>
|
||||
</ScrollView>
|
||||
{showButton && (
|
||||
<TouchableOpacity style={styles.floatingBtn} onPress={() => { scrollViewRef.current?.scrollTo({ y: 0, animated: true }) }}>
|
||||
<Image source={IMAGES.upArrow} style={{ height: 15, width: 15 }} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
|
||||
</View>
|
||||
|
||||
</RBSheet>
|
||||
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
||||
|
||||
export default Dashboard
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,631 @@
|
||||
{
|
||||
"Tabs": [
|
||||
{
|
||||
"MainTabId": 1,
|
||||
"MainTabName": "MTD",
|
||||
"MainTabData": {
|
||||
"subTabs": [
|
||||
{
|
||||
"TabId": 1,
|
||||
"TabName": "PSS Score",
|
||||
"TabRow": 1,
|
||||
"TabCol": 1
|
||||
},
|
||||
{
|
||||
"TabId": 2,
|
||||
"TabName": "PSS Trend",
|
||||
"TabRow": 1,
|
||||
"TabCol": 2
|
||||
},
|
||||
{
|
||||
"TabId": 3,
|
||||
"TabName": "SOS Actual",
|
||||
"TabRow": 1,
|
||||
"TabCol": 2
|
||||
},
|
||||
{
|
||||
"TabId": 4,
|
||||
"TabName": "OSA",
|
||||
"TabRow": 1,
|
||||
"TabCol": 4
|
||||
},
|
||||
{
|
||||
"TabId": 5,
|
||||
"TabName": "Asset",
|
||||
"TabRow": 1,
|
||||
"TabCol": 5
|
||||
},
|
||||
{
|
||||
"TabId": 6,
|
||||
"TabName": "Promotion",
|
||||
"TabRow": 1,
|
||||
"TabCol": 6
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
|
||||
"graphDetails": [
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 1,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "PSS Score",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/pssscore",
|
||||
"GraphBackground": "#C3D7FF",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 2,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "SOS Actual",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/SOS_Actual_Perc",
|
||||
"GraphBackground": "#E2C8FE",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 4,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "OSA",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/OSA_Perc",
|
||||
"GraphBackground": "#FFF9A1",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 5,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Asset",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/Asset_Perc",
|
||||
"GraphBackground": "#A2F3DE",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 6,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Promotion",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/Promotion_Perc",
|
||||
"GraphBackground": "#BFC2FF",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"TabId": 2,
|
||||
"GraphId": 1,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "PSS Score",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/SOS_Actual_Perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 0,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 2,
|
||||
"GraphId": 1,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "PSS - Category",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/sos_actual_perc_on_category",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 2,
|
||||
"GraphId": 2,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "PSS Trend",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/sos_actual_trend_perc_mtd",
|
||||
"GraphBackground": "#F4EAFF",
|
||||
"GraphOptions": {
|
||||
"axisX": "month",
|
||||
"axisY": "score",
|
||||
"labelShow": 1,
|
||||
"barColors": [
|
||||
"#11a4ff",
|
||||
"#0ea3e3",
|
||||
"#0b9ddb"
|
||||
],
|
||||
"gridLinesH": 0,
|
||||
"gridLinesV": 0
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"TabId": 3,
|
||||
"GraphId": 3,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "SOS Actual",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/SOS_Actual_Perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 1,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 2,
|
||||
"GraphId": 1,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "SOS - Category",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/sos_actual_perc_on_category",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 3,
|
||||
"GraphId": 4,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "SOS Actual Trend",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/sos_actual_trend_perc_mtd",
|
||||
"GraphBackground": "#F4EAFF",
|
||||
"GraphOptions": {
|
||||
"axisX": "month",
|
||||
"axisY": "score",
|
||||
"labelShow": 1,
|
||||
"barColors": [
|
||||
"#11a4ff",
|
||||
"#0ea3e3",
|
||||
"#0b9ddb"
|
||||
],
|
||||
"gridLinesH": 0,
|
||||
"gridLinesV": 0
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"TabId": 4,
|
||||
"GraphId": 5,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "OSA",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/OSA_Perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 1,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 3,
|
||||
"GraphId": 3,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "OSA - Category",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/osa_perc_on_category",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 4,
|
||||
"GraphId": 6,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "OSA",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/osa_trend_perc_mtd",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"TabId": 5,
|
||||
"GraphId": 7,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Asset",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/Asset_Perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 1,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 5,
|
||||
"GraphId": 5,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "Visibility",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/asset_availability_mtd",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 5,
|
||||
"GraphId": 5,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "Additional Visibility",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/additional_visibility_mtd",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 5,
|
||||
"GraphId": 8,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "Asset Details",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/asset_trend_perc_mtd",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
|
||||
{
|
||||
"TabId": 6,
|
||||
"GraphId": 9,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Promotion",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/Promotion_Perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 1,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 6,
|
||||
"GraphId": 9,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "Promotion Not Executed",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/promotion_not_executed_mtd",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 6,
|
||||
"GraphId": 10,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "Promotion executed",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/promotion_executed_mtd",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 6,
|
||||
"GraphId": 11,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "Promotion",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/promotion_trend_perc_mtd",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"MainTabId": 2,
|
||||
"MainTabName": "Last Visit",
|
||||
"MainTabData": {
|
||||
"subTabs": [
|
||||
{
|
||||
"TabId": 1,
|
||||
"TabName": "PSS Score",
|
||||
"TabRow": 1,
|
||||
"TabCol": 1
|
||||
},
|
||||
{
|
||||
"TabId": 2,
|
||||
"TabName": "SOS Actual",
|
||||
"TabRow": 1,
|
||||
"TabCol": 2
|
||||
},
|
||||
{
|
||||
"TabId": 4,
|
||||
"TabName": "OSA",
|
||||
"TabRow": 1,
|
||||
"TabCol": 4
|
||||
},
|
||||
{
|
||||
"TabId": 5,
|
||||
"TabName": "Asset",
|
||||
"TabRow": 1,
|
||||
"TabCol": 5
|
||||
},
|
||||
{
|
||||
"TabId": 6,
|
||||
"TabName": "Promotion",
|
||||
"TabRow": 1,
|
||||
"TabCol": 6
|
||||
}
|
||||
],
|
||||
"graphDetails": [
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 1,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "PSS Score",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/PSS_Score_LSV_Perc",
|
||||
"GraphBackground": "#E2C8FE",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 2,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "SOS Actual",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/sos_actual_lsv_perc",
|
||||
"GraphBackground": "#E2C8FE",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 4,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "OSA",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/osa_lsv_perc",
|
||||
"GraphBackground": "#FFF9A1",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 5,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Asset",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/asset_lsv_perc",
|
||||
"GraphBackground": "#A2F3DE",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 6,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Promotion",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/promotion_lsv_perc",
|
||||
"GraphBackground": "#BFC2FF",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"TabId": 2,
|
||||
"GraphId": 1,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "PSS Score",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/SOS_Actual_Perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 0,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 2,
|
||||
"GraphId": 1,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "PSS - Category",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/sos_actual_perc_on_category",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"TabId": 2,
|
||||
"GraphId": 2,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "PSS Trend",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/sos_actual_trend_perc_mtd",
|
||||
"GraphBackground": "#F4EAFF",
|
||||
"GraphOptions": {
|
||||
"axisX": "month",
|
||||
"axisY": "score",
|
||||
"labelShow": 1,
|
||||
"barColors": [
|
||||
"#11a4ff",
|
||||
"#0ea3e3",
|
||||
"#0b9ddb"
|
||||
],
|
||||
"gridLinesH": 0,
|
||||
"gridLinesV": 0
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"TabId": 3,
|
||||
"GraphId": 3,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "SOS Actual",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/sos_actual_lsv_perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 1,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 2,
|
||||
"GraphId": 1,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "SOS Actual - Category",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detlsv/sos_actual_lsv_perc_on_category",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 3,
|
||||
"GraphId": 4,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "SOS Actual Trend",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/sos_actual_trend_lsv_perc",
|
||||
"GraphBackground": "#F4EAFF",
|
||||
"GraphOptions": {
|
||||
"axisX": "month",
|
||||
"axisY": "score",
|
||||
"labelShow": 1,
|
||||
"barColors": [
|
||||
"#11a4ff",
|
||||
"#0ea3e3",
|
||||
"#0b9ddb"
|
||||
],
|
||||
"gridLinesH": 1,
|
||||
"gridLinesV": 1
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"TabId": 4,
|
||||
"GraphId": 5,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "OSA",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/osa_lsv_perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 1,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 4,
|
||||
"GraphId": 7,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "OSA - Category",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detlsv/osa_lsv_perc_on_category",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 4,
|
||||
"GraphId": 6,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "OSA Trend",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/osa_trend_lsv_perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
|
||||
{
|
||||
"TabId": 5,
|
||||
"GraphId": 7,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Asset",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/asset_lsv_perc",
|
||||
"GraphBa ckground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 1,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 5,
|
||||
"GraphId": 5,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "Visibility",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/asset_availability_lsv",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 5,
|
||||
"GraphId": 5,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "Additional Visibility",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/additional_visibility_lsv",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 5,
|
||||
"GraphId": 8,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "Asset Trend",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/asset_trend_lsv_perc",
|
||||
"GraphBackground": "#fff",
|
||||
"GraphOptions": {
|
||||
"axisX": "month",
|
||||
"axisY": "score",
|
||||
"labelShow": 1,
|
||||
"barColors": [
|
||||
"#11a4ff",
|
||||
"#0ea3e3",
|
||||
"#0b9ddb"
|
||||
],
|
||||
"gridLinesH": 1,
|
||||
"gridLinesV": 1
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"TabId": 6,
|
||||
"GraphId": 9,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Promotion",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/promotion_lsv_perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 1,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 6,
|
||||
"GraphId": 9,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "Promotion Not Executed",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detlsv/promotion_not_executed_lsv",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 6,
|
||||
"GraphId": 10,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "Promotion executed",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detlsv/promotion_executed_lsv",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 6,
|
||||
"GraphId": 11,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "Promotion",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/promotion_trend_lsv_perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,638 @@
|
||||
{
|
||||
"Tabs": [
|
||||
{
|
||||
"MainTabId": 1,
|
||||
"MainTabName": "MTD",
|
||||
"MainTabData": {
|
||||
"subTabs": [
|
||||
{
|
||||
"TabId": 1,
|
||||
"TabName": "PSS Score",
|
||||
"TabRow": 1,
|
||||
"TabCol": 1
|
||||
},
|
||||
{
|
||||
"TabId": 2,
|
||||
"TabName": "PSS Trend",
|
||||
"TabRow": 1,
|
||||
"TabCol": 2
|
||||
},
|
||||
{
|
||||
"TabId": 3,
|
||||
"TabName": "SOS Actual",
|
||||
"TabRow": 1,
|
||||
"TabCol": 2
|
||||
},
|
||||
{
|
||||
"TabId": 4,
|
||||
"TabName": "OSA",
|
||||
"TabRow": 1,
|
||||
"TabCol": 4
|
||||
},
|
||||
{
|
||||
"TabId": 5,
|
||||
"TabName": "Asset",
|
||||
"TabRow": 1,
|
||||
"TabCol": 5
|
||||
},
|
||||
{
|
||||
"TabId": 6,
|
||||
"TabName": "Promotion",
|
||||
"TabRow": 1,
|
||||
"TabCol": 6
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
|
||||
"graphDetails": [
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 1,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "PSS Score",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/pssscore",
|
||||
"GraphBackground": "#C3D7FF",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 2,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "SOS Actual",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/SOS_Actual_Perc",
|
||||
"GraphBackground": "#E2C8FE",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 4,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "OSA",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/OSA_Perc",
|
||||
"GraphBackground": "#FFF9A1",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 5,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Asset",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/Asset_Perc",
|
||||
"GraphBackground": "#A2F3DE",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 6,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Promotion",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/Promotion_Perc",
|
||||
"GraphBackground": "#BFC2FF",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"TabId": 2,
|
||||
"GraphId": 1,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "PSS Score",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/pssscore",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 0,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 2,
|
||||
"GraphId": 1,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "PSS - Category",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/sos_actual_perc_on_category",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 2,
|
||||
"GraphId": 2,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "PSS Trend",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/pss_trend_perc_mtd_O",
|
||||
"GraphBackground": "#F4EAFF",
|
||||
"GraphOptions": {
|
||||
"axisX": "month",
|
||||
"axisY": "score",
|
||||
"labelShow": 1,
|
||||
"barColors": [
|
||||
"#11a4ff",
|
||||
"#0ea3e3",
|
||||
"#0b9ddb"
|
||||
],
|
||||
"gridLinesH": 0,
|
||||
"gridLinesV": 0
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"TabId": 3,
|
||||
"GraphId": 3,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "SOS Actual",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/SOS_Actual_Perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 1,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 2,
|
||||
"GraphId": 1,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "SOS - Category",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/sos_actual_perc_on_category",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 3,
|
||||
"GraphId": 4,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "SOS Actual Trend",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/sos_actual_trend_perc_mtd_O",
|
||||
"GraphBackground": "#F4EAFF",
|
||||
"GraphOptions": {
|
||||
"axisX": "month",
|
||||
"axisY": "score",
|
||||
"labelShow": 1,
|
||||
"barColors": [
|
||||
"#11a4ff",
|
||||
"#0ea3e3",
|
||||
"#0b9ddb"
|
||||
],
|
||||
"gridLinesH": 0,
|
||||
"gridLinesV": 0
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"TabId": 4,
|
||||
"GraphId": 5,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "OSA",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/OSA_Perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 1,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 3,
|
||||
"GraphId": 3,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "OSA - Category",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/osa_perc_on_category",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 4,
|
||||
"GraphId": 6,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "OSA",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/osa_trend_perc_mtd_O",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"TabId": 5,
|
||||
"GraphId": 7,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Asset",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/Asset_Perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 1,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 5,
|
||||
"GraphId": 5,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "Visibility",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/asset_availability_mtd",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 5,
|
||||
"GraphId": 5,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "Additional Visibility",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/additional_visibility_mtd",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 5,
|
||||
"GraphId": 8,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "Asset Details",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/asset_trend_perc_mtd_O",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
|
||||
{
|
||||
"TabId": 6,
|
||||
"GraphId": 9,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Promotion",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/Promotion_Perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 1,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 6,
|
||||
"GraphId": 9,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "Promotion Not Executed",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/promotion_not_executed_mtd",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 6,
|
||||
"GraphId": 10,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "Promotion executed",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/promotion_executed_mtd",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 6,
|
||||
"GraphId": 11,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "Promotion",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/promotion_trend_perc_mtd_O",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"MainTabId": 2,
|
||||
"MainTabName": "Last Visit",
|
||||
"MainTabData": {
|
||||
"subTabs": [
|
||||
{
|
||||
"TabId": 1,
|
||||
"TabName": "PSS Score",
|
||||
"TabRow": 1,
|
||||
"TabCol": 1
|
||||
},
|
||||
{
|
||||
"TabId": 2,
|
||||
"TabName": "PSS Trend",
|
||||
"TabRow": 1,
|
||||
"TabCol": 2
|
||||
},
|
||||
|
||||
{
|
||||
"TabId": 3,
|
||||
"TabName": "SOS Actual",
|
||||
"TabRow": 1,
|
||||
"TabCol": 2
|
||||
},
|
||||
{
|
||||
"TabId": 4,
|
||||
"TabName": "OSA",
|
||||
"TabRow": 1,
|
||||
"TabCol": 4
|
||||
},
|
||||
{
|
||||
"TabId": 5,
|
||||
"TabName": "Asset",
|
||||
"TabRow": 1,
|
||||
"TabCol": 5
|
||||
},
|
||||
{
|
||||
"TabId": 6,
|
||||
"TabName": "Promotion",
|
||||
"TabRow": 1,
|
||||
"TabCol": 6
|
||||
}
|
||||
],
|
||||
"graphDetails": [
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 1,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "PSS Score",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/PSS_Score_LSV_Perc",
|
||||
"GraphBackground": "#E2C8FE",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 2,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "SOS Actual",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/sos_actual_lsv_perc",
|
||||
"GraphBackground": "#E2C8FE",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 4,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "OSA",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/osa_lsv_perc",
|
||||
"GraphBackground": "#FFF9A1",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 5,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Asset",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/asset_lsv_perc",
|
||||
"GraphBackground": "#A2F3DE",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 1,
|
||||
"GraphId": 6,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Promotion",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/promotion_lsv_perc",
|
||||
"GraphBackground": "#BFC2FF",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"TabId": 2,
|
||||
"GraphId": 1,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "PSS Score",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/PSS_Score_LSV_Perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 0,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 2,
|
||||
"GraphId": 1,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "PSS - Category",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/sos_actual_perc_on_category",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"TabId": 2,
|
||||
"GraphId": 2,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "PSS Trend",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/pss_trend_perc_lsv_O",
|
||||
"GraphBackground": "#F4EAFF",
|
||||
"GraphOptions": {
|
||||
"axisX": "month",
|
||||
"axisY": "score",
|
||||
"labelShow": 1,
|
||||
"barColors": [
|
||||
"#11a4ff",
|
||||
"#0ea3e3",
|
||||
"#0b9ddb"
|
||||
],
|
||||
"gridLinesH": 0,
|
||||
"gridLinesV": 0
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"TabId": 3,
|
||||
"GraphId": 3,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "SOS Actual",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/sos_actual_lsv_perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 1,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 2,
|
||||
"GraphId": 1,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "SOS Actual - Category",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detlsv/sos_actual_lsv_perc_on_category",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 3,
|
||||
"GraphId": 4,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "SOS Actual Trend",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/sos_actual_trend_lsv_perc_O",
|
||||
"GraphBackground": "#F4EAFF",
|
||||
"GraphOptions": {
|
||||
"axisX": "month",
|
||||
"axisY": "score",
|
||||
"labelShow": 1,
|
||||
"barColors": [
|
||||
"#11a4ff",
|
||||
"#0ea3e3",
|
||||
"#0b9ddb"
|
||||
],
|
||||
"gridLinesH": 1,
|
||||
"gridLinesV": 1
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"TabId": 4,
|
||||
"GraphId": 5,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "OSA",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/osa_lsv_perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 1,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 4,
|
||||
"GraphId": 7,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "OSA - Category",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detlsv/osa_lsv_perc_on_category",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 4,
|
||||
"GraphId": 6,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "OSA Trend",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/osa_trend_lsv_perc_O",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
|
||||
{
|
||||
"TabId": 5,
|
||||
"GraphId": 7,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Asset",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/asset_lsv_perc",
|
||||
"GraphBa ckground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 1,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 5,
|
||||
"GraphId": 5,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "Visibility",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/asset_availability_lsv",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 5,
|
||||
"GraphId": 5,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "Additional Visibility",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/additional_visibility_lsv",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 5,
|
||||
"GraphId": 8,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "Asset Trend",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/asset_trend_lsv_perc_O",
|
||||
"GraphBackground": "#fff",
|
||||
"GraphOptions": {
|
||||
"axisX": "month",
|
||||
"axisY": "score",
|
||||
"labelShow": 1,
|
||||
"barColors": [
|
||||
"#11a4ff",
|
||||
"#0ea3e3",
|
||||
"#0b9ddb"
|
||||
],
|
||||
"gridLinesH": 1,
|
||||
"gridLinesV": 1
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"TabId": 6,
|
||||
"GraphId": 9,
|
||||
"GraphType": "ScoreCard",
|
||||
"GraphTitle": "Promotion",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/promotion_lsv_perc",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {},
|
||||
"clickable": 1,
|
||||
"DetailsPage": [
|
||||
{
|
||||
"TabId": 6,
|
||||
"GraphId": 9,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "Promotion Not Executed",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detlsv/promotion_not_executed_lsv",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
},
|
||||
{
|
||||
"TabId": 6,
|
||||
"GraphId": 10,
|
||||
"GraphType": "Table",
|
||||
"GraphTitle": "Promotion executed",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detlsv/promotion_executed_lsv",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"TabId": 6,
|
||||
"GraphId": 11,
|
||||
"GraphType": "BarGraph",
|
||||
"GraphTitle": "Promotion",
|
||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/promotion_trend_lsv_perc_O",
|
||||
"GraphBackground": "#ECFFFA",
|
||||
"GraphOptions": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,381 @@
|
||||
import { Platform, StyleSheet } from 'react-native';
|
||||
import { GlobalTheme, Screen } from '../../../theme';
|
||||
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
// backgroundColor: GlobalTheme.colors.white,
|
||||
paddingHorizontal: 10,
|
||||
// justifyContent:'center'
|
||||
},
|
||||
logoContainer: {
|
||||
alignItems: 'center',
|
||||
},
|
||||
appLogo: {
|
||||
height: 200,
|
||||
width: 200,
|
||||
resizeMode: 'contain',
|
||||
},
|
||||
appMaskLogo: {
|
||||
resizeMode: 'stretch',
|
||||
width: Screen.screenHeight * 0.9,
|
||||
height: Screen.screenHeight * 0.33,
|
||||
},
|
||||
titleContainer: {
|
||||
alignSelf: 'center',
|
||||
// marginTop: 15,
|
||||
},
|
||||
titleText: {
|
||||
fontSize: 25,
|
||||
fontWeight: 'bold',
|
||||
color: GlobalTheme.colors.black,
|
||||
},
|
||||
subtitleText: {
|
||||
fontSize: 15,
|
||||
color: '#1F2128',
|
||||
marginBottom: 14,
|
||||
fontWeight: '600',
|
||||
alignSelf: 'center',
|
||||
width: '80%',
|
||||
textAlign: 'center',
|
||||
},
|
||||
subtitleHighlight: {
|
||||
color: '#2381E9',
|
||||
},
|
||||
headerStyle: {
|
||||
height: '8%',
|
||||
backgroundColor: '#113F8C',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingHorizontal: 15
|
||||
},
|
||||
headerText: {
|
||||
color: GlobalTheme.colors.white,
|
||||
fontSize: GlobalTheme.typography.fontSize.medium,
|
||||
fontWeight: '600'
|
||||
},
|
||||
headerDotBtn: {
|
||||
backgroundColor: '#295398',
|
||||
flexDirection: 'row',
|
||||
paddingHorizontal: 5,
|
||||
alignItems: 'center',
|
||||
borderRadius: 10
|
||||
},
|
||||
selectCard: {
|
||||
backgroundColor: '#FFFFFF',
|
||||
borderRadius: 30,
|
||||
elevation: 7,
|
||||
padding: 15,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginTop: 15,
|
||||
marginHorizontal: 15,
|
||||
borderWidth: 1.5,
|
||||
borderColor: '#C9DAFF'
|
||||
},
|
||||
iconStyle: {
|
||||
height: 25,
|
||||
width: 25,
|
||||
},
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
margin: 15,
|
||||
},
|
||||
dropdown: {
|
||||
flex: 1,
|
||||
borderWidth: 1,
|
||||
borderColor: '#ccc',
|
||||
borderRadius: 8,
|
||||
paddingHorizontal: 10,
|
||||
marginHorizontal: 4,
|
||||
height: 45,
|
||||
},
|
||||
row: {
|
||||
margin: 10,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center'
|
||||
},
|
||||
inputStyle: {
|
||||
paddingHorizontal: 7,
|
||||
width: '100%',
|
||||
color: '#000'
|
||||
// backgroundColor:'red'
|
||||
},
|
||||
searchBox: {
|
||||
height: 45,
|
||||
borderWidth: 1,
|
||||
borderColor: '#ccc',
|
||||
borderRadius: 10,
|
||||
marginTop: 10,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: 10
|
||||
},
|
||||
storeNameText: {
|
||||
color: '#000',
|
||||
fontWeight: '500',
|
||||
fontSize: 16
|
||||
},
|
||||
storeCard: {
|
||||
backgroundColor: '#fff',
|
||||
borderWidth: 1,
|
||||
borderColor: '#DFDFDF',
|
||||
marginTop: 10,
|
||||
padding: 10,
|
||||
paddingHorizontal: 12,
|
||||
borderRadius: 20,
|
||||
// elevation: 2
|
||||
},
|
||||
cardTextBold: {
|
||||
fontSize: 16,
|
||||
color: '#000',
|
||||
fontWeight: '500',
|
||||
flexWrap: 'wrap',
|
||||
width: '72%'
|
||||
},
|
||||
cardText: {
|
||||
marginTop: 2,
|
||||
fontSize: 14,
|
||||
color: '#494949',
|
||||
fontWeight: '400'
|
||||
},
|
||||
dropHeaderText: {
|
||||
width: '50%',
|
||||
color: '#000',
|
||||
fontWeight: '400',
|
||||
fontSize: 14
|
||||
},
|
||||
selectStoreText: {
|
||||
fontSize: 15,
|
||||
color: '#808CA3',
|
||||
fontWeight: '400',
|
||||
alignSelf: 'center',
|
||||
marginTop: 5
|
||||
},
|
||||
storeText: {
|
||||
color: '#000',
|
||||
fontSize: 15,
|
||||
fontWeight: '500',
|
||||
marginLeft: 10
|
||||
},
|
||||
todayStoreText: {
|
||||
marginLeft: 10,
|
||||
color: '#2357C6',
|
||||
fontSize: 16,
|
||||
fontWeight: '500'
|
||||
},
|
||||
storeGredient: {
|
||||
flex: 1,
|
||||
padding: 10,
|
||||
marginTop: 15,
|
||||
borderTopLeftRadius: 25,
|
||||
borderTopRightRadius: 25
|
||||
},
|
||||
todayStoreCard: {
|
||||
flex: 1,
|
||||
// width:'95%',
|
||||
backgroundColor: '#fff',
|
||||
borderRadius: 25,
|
||||
paddingBottom: 10,
|
||||
marginRight: Platform.OS === 'ios' ? 20 : 0,
|
||||
// width:'100%'
|
||||
},
|
||||
|
||||
mainContainer: {
|
||||
flex: 1,
|
||||
},
|
||||
selectedStoreText: {
|
||||
width: '75%',
|
||||
borderWidth: 1.5,
|
||||
borderColor: '#D8E3F1',
|
||||
borderRadius: 10,
|
||||
padding: 7,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
},
|
||||
filterIcon: {
|
||||
backgroundColor: '#D8E3F1',
|
||||
padding: 5,
|
||||
borderRadius: 5
|
||||
},
|
||||
storeInfoText: {
|
||||
color: '#000',
|
||||
fontWeight: '500',
|
||||
fontSize: 16,
|
||||
textDecorationLine: 'underline'
|
||||
},
|
||||
percentBox: {
|
||||
width: '48%',
|
||||
height: 100,
|
||||
minHeight: 100,
|
||||
backgroundColor: '#EAF1FF',
|
||||
borderRadius: 20,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
// Cross-platform shadow styles
|
||||
...Platform.select({
|
||||
ios: {
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 2 },
|
||||
shadowOpacity: 0.2,
|
||||
shadowRadius: 2,
|
||||
},
|
||||
android: {
|
||||
elevation: 2,
|
||||
},
|
||||
}),
|
||||
},
|
||||
boxText: {
|
||||
color: '#000',
|
||||
fontWeight: '400',
|
||||
fontSize: 16
|
||||
},
|
||||
yearLable: {
|
||||
color: '#000',
|
||||
fontSize: 14,
|
||||
fontWeight: '500'
|
||||
},
|
||||
yearText: {
|
||||
color: '#7F83AB',
|
||||
fontSize: 14,
|
||||
},
|
||||
yearView: {
|
||||
borderWidth: 2,
|
||||
borderColor: '#D8E3F1',
|
||||
borderRadius: 15,
|
||||
paddingHorizontal: 10,
|
||||
padding: 5,
|
||||
width: '28%',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between'
|
||||
},
|
||||
yearDropDown: {
|
||||
height: 40,
|
||||
borderWidth: 2,
|
||||
borderColor: '#D8E3F1',
|
||||
width: 100,
|
||||
borderRadius: 20
|
||||
},
|
||||
btnbg: {
|
||||
// marginLeft: 10,
|
||||
backgroundColor: GlobalTheme.colors.secondary,
|
||||
borderRadius: GlobalTheme.borderRadius.lgg,
|
||||
padding: 18,
|
||||
paddingVertical: 8
|
||||
},
|
||||
btntext: {
|
||||
color: GlobalTheme.colors.white,
|
||||
fontSize: GlobalTheme.typography.fontSize.xsmall,
|
||||
fontWeight: GlobalTheme.typography.fontWeight.medium
|
||||
},
|
||||
seperator: {
|
||||
marginTop: 10,
|
||||
borderBottomWidth: 2,
|
||||
borderColor: '#E4E4E4'
|
||||
},
|
||||
dropdownIcon: {
|
||||
height: 12,
|
||||
width: 12,
|
||||
resizeMode: 'contain',
|
||||
tintColor: 'gray'
|
||||
},
|
||||
mtdTab: {
|
||||
borderBottomWidth: 2,
|
||||
borderColor: '#113F8C',
|
||||
width: '50%',
|
||||
padding: 10,
|
||||
alignItems: 'center',
|
||||
// borderWidth:0.5,
|
||||
},
|
||||
mtdTabText: {
|
||||
fontSize: 15,
|
||||
color: '#000',
|
||||
fontWeight: '600'
|
||||
},
|
||||
subTabView: {
|
||||
backgroundColor: '#EAEAEA',
|
||||
paddingVertical: 10,
|
||||
paddingHorizontal: 5,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center'
|
||||
},
|
||||
subTab: {
|
||||
backgroundColor: '#113F8C',
|
||||
padding: 5,
|
||||
paddingHorizontal: 10,
|
||||
borderRadius: 10,
|
||||
marginRight: 10
|
||||
},
|
||||
tabText: {
|
||||
color: '#fff',
|
||||
fontSize: 14,
|
||||
fontWeight: '400',
|
||||
},
|
||||
floatingBtn: {
|
||||
alignSelf: 'center',
|
||||
position: 'absolute',
|
||||
bottom: 10,
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.4)',
|
||||
// backgroundColor:'#fff',
|
||||
padding: 10,
|
||||
paddingHorizontal: 20,
|
||||
borderRadius: 30,
|
||||
// elevation: 2,
|
||||
zIndex: 999,
|
||||
borderWidth: 1,
|
||||
borderColor: '#DFDFDF'
|
||||
},
|
||||
modalOverlay: {
|
||||
flex: 1,
|
||||
// backgroundColor: 'transparent',
|
||||
backgroundColor: 'rgba(87, 79, 79, 0.2)'
|
||||
},
|
||||
modalContainer: {
|
||||
position: 'absolute',
|
||||
top: Platform.OS === 'ios' ? 100 : 50,
|
||||
right: 10,
|
||||
width: '50%',
|
||||
backgroundColor: 'white',
|
||||
borderRadius: 8,
|
||||
elevation: 8,
|
||||
shadowColor: '#000',
|
||||
shadowOpacity: 0.2,
|
||||
shadowRadius: 5,
|
||||
shadowOffset: { width: 0, height: 2 },
|
||||
},
|
||||
searchByID: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
height: 40,
|
||||
width: '100%',
|
||||
borderColor: '#ccc',
|
||||
borderWidth: 1,
|
||||
borderRadius: 10,
|
||||
paddingHorizontal: 10,
|
||||
marginTop: 10,
|
||||
marginBottom: 10,
|
||||
|
||||
},
|
||||
barGraphView: {
|
||||
width: '100%',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
padding: 10,
|
||||
borderWidth: 0.5,
|
||||
borderRadius: 25,
|
||||
},
|
||||
trendTitle: {
|
||||
color: '#000',
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
marginBottom: 10
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,659 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { View, Text, ScrollView, TouchableOpacity, Platform, Keyboard } from 'react-native';
|
||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome';
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
import mockDataFlat1 from '../data.json';
|
||||
import * as RNFS from 'react-native-fs';
|
||||
import moment from 'moment';
|
||||
import CustomHeader from '../../../../components/CustomHeader';
|
||||
import IMAGES from '../../../../constants/Images';
|
||||
import CustomButton from '../../../../components/CustomButton';
|
||||
import { styles } from './style';
|
||||
import { GlobalTheme } from '../../../../theme';
|
||||
import db, { getAllFromTable } from '../../../../constants/database';
|
||||
import { UploadData2, UploadImagesWithoutWait } from '../../../../constants/uploadData';
|
||||
import { getAllFileForAFolder, getDownloadJson } from '../../../../constants/function';
|
||||
import { common_ImagePath, FeedbackImagesFolderPath } from '../../../../constants/constant';
|
||||
import { toastError } from '../../../../constants/Toast';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import Loader from '../../../../constants/Loader';
|
||||
import { ConfirmSaveAlert } from '../../../../components/Alert';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
// image upload url
|
||||
const imageUploadURL = "https://di1.parinaam.in/webservice/Imageupload.asmx/Uploadimages";
|
||||
|
||||
const FeedbackCategories = ({ navigation, route }) => {
|
||||
|
||||
let user_exist_data = useSelector(state => state?.user);
|
||||
|
||||
const userId = user_exist_data.UserId || '';
|
||||
|
||||
const storeData = route?.params?.storeData;
|
||||
|
||||
console.log("user_exist_data===", (user_exist_data.UserId, storeData?.StoreId));
|
||||
|
||||
const [completedCategories, setCompletedCategories] = useState([]);
|
||||
const [uniqueCategories, setUniqueCategories] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [loadingdownload, setLoadingDownload] = useState(false);
|
||||
const [loadingupload, setLoadingUpload] = useState(false);
|
||||
const [showAlert, setShowAlert] = useState(false);
|
||||
|
||||
|
||||
// get data
|
||||
|
||||
// Insert fallback mock data if empty
|
||||
const insertMasterSurveyQuestion = (data_arr = []) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!Array.isArray(data_arr) || data_arr.length === 0) {
|
||||
resolve(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const escape = str => (str || '').toString().replace(/'/g, "''");
|
||||
|
||||
const values = data_arr.map(item => {
|
||||
const {
|
||||
MenuId, SurveyId, SurveyName, CategoryId, Category, CategorySequence,
|
||||
QuestionId, Question, QuestionType, QuestionImageAllow, QEnable,
|
||||
LengthValidation, MinLength, MaxLength, OTP, DateRange, QuestionSequence,
|
||||
AnswerId, Answer, ImageAllow1, ImageAllow2, Image1Mandatory, Image2Mandatory,
|
||||
QuestionImageMandatory, EnableQuestion, DisableQuestion, AnswerSequence,
|
||||
ShowCat, SubCategoryId, SubCategory, SubCategorySequence,
|
||||
QuestionTypeNew, CalFormula, RefImage, QuestionRefImage
|
||||
} = item;
|
||||
|
||||
return `(
|
||||
'${MenuId}', '${SurveyId}', '${escape(SurveyName)}', '${CategoryId}', '${escape(Category)}',
|
||||
'${CategorySequence}', '${QuestionId}', '${escape(Question)}', '${escape(QuestionType)}',
|
||||
'${QuestionImageAllow ? 1 : 0}', '${QEnable ? 1 : 0}', '${LengthValidation ? 1 : 0}',
|
||||
'${MinLength}', '${MaxLength}', '${OTP ? 1 : 0}', '${escape(DateRange)}',
|
||||
'${QuestionSequence}', '${AnswerId}', '${escape(Answer)}',
|
||||
'${ImageAllow1 ? 1 : 0}', '${ImageAllow2 ? 1 : 0}', '${Image1Mandatory ? 1 : 0}',
|
||||
'${Image2Mandatory ? 1 : 0}', '${QuestionImageMandatory ? 1 : 0}',
|
||||
'${escape(EnableQuestion)}', '${escape(DisableQuestion)}', '${AnswerSequence}',
|
||||
'${ShowCat ? 1 : 0}', '${SubCategoryId}', '${escape(SubCategory)}',
|
||||
'${SubCategorySequence}', '${escape(QuestionTypeNew)}', '${escape(CalFormula)}',
|
||||
'${escape(RefImage)}', '${escape(QuestionRefImage)}'
|
||||
)`;
|
||||
});
|
||||
|
||||
const sql = `
|
||||
INSERT INTO FeedbackCategory (
|
||||
MenuId, SurveyId, SurveyName, CategoryId, Category, CategorySequence,
|
||||
QuestionId, Question, QuestionType, QuestionImageAllow, QEnable,
|
||||
LengthValidation, MinLength, MaxLength, OTP, DateRange, QuestionSequence,
|
||||
AnswerId, Answer, ImageAllow1, ImageAllow2, Image1Mandatory, Image2Mandatory,
|
||||
QuestionImageMandatory, EnableQuestion, DisableQuestion, AnswerSequence,
|
||||
ShowCat, SubCategoryId, SubCategory, SubCategorySequence,
|
||||
QuestionTypeNew, CalFormula, RefImage,QuestionRefImage
|
||||
) VALUES ${values.join(',')}
|
||||
`;
|
||||
|
||||
db.transaction(tx => {
|
||||
tx.executeSql(`DELETE FROM FeedbackCategory`, [], () => {
|
||||
tx.executeSql(sql, [], () => {
|
||||
console.log('FeedbackCategory inserted successfully');
|
||||
resolve(true);
|
||||
}, (err) => {
|
||||
console.log('Insert error in FeedbackCategory:', err);
|
||||
reject(err);
|
||||
});
|
||||
}, (err) => {
|
||||
console.log('Delete error before insert FeedbackCategory:', err);
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
async function getData() {
|
||||
setLoadingDownload(true);
|
||||
try {
|
||||
const data1 = {
|
||||
Downloadtype: "Master_SurveyQuestion_storeDNA",
|
||||
Param1: storeData?.StoreId || '',
|
||||
Param2: "",
|
||||
username: user_exist_data?.UserId || '',
|
||||
};
|
||||
|
||||
const url = "https://di1.parinaam.in/Webservice/GenericService.svc/DownloadJson";
|
||||
console.log("Downloading from:", url, data1);
|
||||
|
||||
const res = await getDownloadJson(url, data1);
|
||||
console.log('Response:', res);
|
||||
|
||||
if (res?.Master_SurveyQuestion_storeDNA?.length) {
|
||||
const data = res.Master_SurveyQuestion_storeDNA || [];
|
||||
console.log("Inserting downloaded data into FeedbackCategory...");
|
||||
const all = await getAllFromTable('FeedbackCategory');
|
||||
// if (all?.length === 0) {
|
||||
console.log("Table empty. Inserting fallback mock data...");
|
||||
await insertMasterSurveyQuestion(data);
|
||||
setLoadingDownload(false);
|
||||
// } else {
|
||||
// console.log("FeedbackCategory table already has data.");
|
||||
// setLoadingDownload(false);
|
||||
// }
|
||||
} else {
|
||||
console.log("No Master_SurveyQuestion_storeDNA data found in response");
|
||||
setLoadingDownload(false);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("Dashboard feedback survey download error:", err);
|
||||
setLoadingDownload(false);
|
||||
}
|
||||
}
|
||||
|
||||
// download data
|
||||
|
||||
// 1. Initial load → download and populate local DB and categories
|
||||
useEffect(() => {
|
||||
const init = async () => {
|
||||
await getData(); // Download and insert
|
||||
await loadCompleted(); // Load completion info
|
||||
const data = await getUniqueCategoriesFromDB(); // Load categories
|
||||
setUniqueCategories(data); // Update UI
|
||||
};
|
||||
init();
|
||||
}, []);
|
||||
|
||||
// 2. Every time screen is focused → recheck completed categories and ticks
|
||||
useEffect(() => {
|
||||
const loadOnFocus = async () => {
|
||||
await loadCompleted();
|
||||
const data = await getUniqueCategoriesFromDB();
|
||||
setUniqueCategories(data);
|
||||
};
|
||||
|
||||
const unsubscribe = navigation.addListener('focus', loadOnFocus);
|
||||
return unsubscribe;
|
||||
}, [navigation]);
|
||||
|
||||
|
||||
|
||||
// useEffect(() => {
|
||||
// const init = async () => {
|
||||
// await getData(); // fetch and insert data
|
||||
// await loadCompleted(); // ← added
|
||||
// const data = await getUniqueCategoriesFromDB(); // ← added
|
||||
// setUniqueCategories(data); // ← added
|
||||
// };
|
||||
// init();
|
||||
// // const unsubscribe = navigation.addListener('focus', loadOnFocus);
|
||||
// // return unsubscribe;
|
||||
|
||||
// }, [navigation]);
|
||||
|
||||
// end download data.
|
||||
|
||||
const isCompleted = (cat) => {
|
||||
return completedCategories.find(
|
||||
c => c?.CategoryId === cat?.CategoryId && c?.SurveyId === cat?.SurveyId
|
||||
);
|
||||
};
|
||||
|
||||
const loadCompleted = async () => {
|
||||
const d2 = moment().format('MM/DD/YYYY');
|
||||
console.log("loaddddd", `SELECT DISTINCT CATEGORY_ID, SURVEY_ID , IFNULL(STATUS , '') AS STATUS FROM FeedBackLocalTable WHERE STORE_ID='${storeData?.StoreId}' AND VISIT_DATE='${d2}'`)
|
||||
return new Promise((resolve, reject) => {
|
||||
db.transaction(tx => {
|
||||
tx.executeSql(
|
||||
`SELECT DISTINCT CATEGORY_ID, SURVEY_ID , IFNULL(STATUS , '') AS STATUS FROM FeedBackLocalTable WHERE STORE_ID='${storeData?.StoreId}' AND VISIT_DATE='${d2}'`,
|
||||
[],
|
||||
(tx, results) => {
|
||||
const completed = [];
|
||||
for (let i = 0; i < results.rows.length; i++) {
|
||||
const row = results.rows.item(i);
|
||||
completed.push({
|
||||
CategoryId: row.CATEGORY_ID,
|
||||
SurveyId: row.SURVEY_ID,
|
||||
Status: row.STATUS
|
||||
});
|
||||
}
|
||||
setCompletedCategories(completed);
|
||||
// console.log('Completed categories from table:', completed);
|
||||
resolve();
|
||||
},
|
||||
(tx, error) => {
|
||||
console.log('DB error loading completed:', error);
|
||||
reject(error);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const getUniqueCategoriesFromDB = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.transaction(tx => {
|
||||
tx.executeSql(
|
||||
`SELECT CategoryId, Category, SurveyId, MIN(QuestionSequence) AS minSeq
|
||||
FROM FeedbackCategory
|
||||
GROUP BY CategoryId, Category, SurveyId
|
||||
ORDER BY minSeq ASC`,
|
||||
[],
|
||||
(tx, results) => {
|
||||
const unique = [];
|
||||
for (let i = 0; i < results.rows.length; i++) {
|
||||
const row = results.rows.item(i);
|
||||
unique.push({
|
||||
CategoryId: row.CategoryId,
|
||||
Category: row.Category,
|
||||
SurveyId: row.SurveyId
|
||||
});
|
||||
}
|
||||
resolve(unique);
|
||||
},
|
||||
(tx, error) => {
|
||||
console.log('Error fetching distinct categories:', error);
|
||||
reject(error);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// upload data
|
||||
|
||||
async function Upload_Data() {
|
||||
// await saveData("P");
|
||||
setLoadingUpload(true);
|
||||
const UserId = userId;
|
||||
const UploadKeyName = 'Sales_DNA_FeedBack';
|
||||
const MID = 0;
|
||||
let postData = {};
|
||||
let allChilds = [];
|
||||
|
||||
const d2 = moment().format('MM/DD/YYYY');
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
db.transaction(async function (txn) {
|
||||
let query = `SELECT * FROM FeedBackLocalTable WHERE STORE_ID='${storeData?.StoreId}' AND VISIT_DATE='${d2}'`;
|
||||
|
||||
console.log("query=====", query)
|
||||
await txn.executeSql(
|
||||
query,
|
||||
[],
|
||||
async (txn2, txnres2) => {
|
||||
// console.log("Records found:", txnres2.rows.length);
|
||||
|
||||
if (txnres2.rows.length > 0) {
|
||||
for (let i = 0; i < txnres2.rows.length; i++) {
|
||||
let data = txnres2.rows.item(i);
|
||||
|
||||
let {
|
||||
SURVEY_ID, CATEGORY_ID, MaxLength, MinLength, QuestionImageAllow, QUESTION,
|
||||
QUESTION_ID, QUESTION_TYPE, OTP, ANSWER, ANSWER_ID, IMAGE_ALLOW1, IMAGE1,
|
||||
IMAGE_ALLOW2, IMAGE2, MULTI_OPTIONS_IDS, IS_DISABLED, IS_ENABLED
|
||||
} = data;
|
||||
|
||||
let renamedObj = {
|
||||
SurveyId: SURVEY_ID,
|
||||
CategoryId: CATEGORY_ID,
|
||||
QuestionId: QUESTION_ID,
|
||||
QuestionType: QUESTION_TYPE,
|
||||
Answer: ANSWER,
|
||||
AnswerId: ANSWER_ID,
|
||||
MultiOptionsIds: MULTI_OPTIONS_IDS,
|
||||
Image1: IMAGE1,
|
||||
Image2: IMAGE2,
|
||||
ImageAllow1: IMAGE_ALLOW1,
|
||||
ImageAllow2: IMAGE_ALLOW2
|
||||
};
|
||||
|
||||
// Fix: IS_DISABLED is expected to be 0 or 1
|
||||
let isQtnEnabled = JSON.parse(IS_DISABLED)[QUESTION_ID]
|
||||
let obj = {};
|
||||
if (isQtnEnabled) {
|
||||
obj['MID'] = 0;
|
||||
obj['UserId'] = userId;
|
||||
// obj['Store_Id'] = '';
|
||||
// obj['MenuId'] = '';
|
||||
obj['SurveyId'] = renamedObj?.SurveyId;
|
||||
obj['CategoryId'] = renamedObj?.CategoryId;
|
||||
obj['QuestionId'] = renamedObj?.QuestionId;
|
||||
obj['QuestionType'] = renamedObj?.QuestionType;
|
||||
obj['Answer'] = renamedObj?.Answer;
|
||||
obj['AnswerId'] = renamedObj?.AnswerId;
|
||||
obj['MultiAnswerId'] = (renamedObj?.MultiOptionsIds != null && renamedObj?.MultiOptionsIds != 'undefined') ? renamedObj?.MultiOptionsIds : '';
|
||||
obj['AnswerImage1'] = renamedObj?.Image1;
|
||||
obj['AnswerImage2'] = renamedObj?.Image2;
|
||||
|
||||
allChilds.push(obj);
|
||||
}
|
||||
}
|
||||
|
||||
postData['MID'] = MID;
|
||||
postData['Keys'] = UploadKeyName || 'Sales_DNA_FeedBack';
|
||||
postData['JsonData'] = JSON.stringify(allChilds);
|
||||
postData['UserId'] = UserId;
|
||||
|
||||
resolve({ PostData: postData });
|
||||
} else {
|
||||
resolve({ PostData: postData });
|
||||
}
|
||||
},
|
||||
(txnE, txnerr) => {
|
||||
// console.log('Query error:', txnerr);
|
||||
resolve({ PostData: postData });
|
||||
}
|
||||
);
|
||||
});
|
||||
}).catch((err) => {
|
||||
console.log("Transaction error:", err);
|
||||
});
|
||||
|
||||
// console.log("Preparing to upload data...");
|
||||
const url = 'https://di1.parinaam.in/Webservice/GenericService.svc/UploadJson';
|
||||
console.log("URL:", url);
|
||||
console.log("PostData:", postData);
|
||||
|
||||
let allFilesToUpload = await getAllFileForAFolder(FeedbackImagesFolderPath, "Store_DNA");
|
||||
console.log('All files to upload:', allFilesToUpload);
|
||||
|
||||
await uploadImagesFormFiles12(allFilesToUpload);
|
||||
|
||||
await UploadData2(url, postData)
|
||||
.then(async (res) => {
|
||||
// console.log('Upload Response:', res);
|
||||
if (res?.UploadJsonResult === "Success") {
|
||||
// console.log("Upload successful.");
|
||||
try {
|
||||
await updateAllUploadStatuses(d2);
|
||||
await loadCompleted(); // Refresh the UI with updated STATUS
|
||||
} catch (err) {
|
||||
console.log("Failed to update status after upload:", err);
|
||||
}
|
||||
setLoadingUpload(false);
|
||||
setShowAlert(false);
|
||||
} else {
|
||||
console.log("Upload failed.");
|
||||
setLoadingUpload(false);
|
||||
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log("Upload error:", err);
|
||||
setLoadingUpload(false);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
async function uploadImagesFormFiles12(allfiles = []) {
|
||||
|
||||
// console.log("allfiles===========", allfiles);
|
||||
let d1 = new Date();
|
||||
let d2 = moment(d1).format('MM/DD/YYYY');
|
||||
let uploadCount = 0;
|
||||
const url = imageUploadURL;
|
||||
|
||||
var isAllUploaded = false;
|
||||
return await Promise.all(
|
||||
allfiles.map(async (file, i) => {
|
||||
let index = i;
|
||||
let actualfilepath = 'file://' + file.uri;
|
||||
// console.log("actualfilepath==", actualfilepath);
|
||||
let isExists = await RNFS.exists(actualfilepath).then((res) => { return res; });
|
||||
console.log('isExists file', isExists, file.uri, file);
|
||||
let isImageUploaded = false;
|
||||
// isExists==false
|
||||
if (isExists) {
|
||||
let postData = new FormData();
|
||||
postData.append('file', {
|
||||
uri: actualfilepath,
|
||||
type: file.type,
|
||||
name: file.name,
|
||||
});
|
||||
|
||||
postData.append('Foldername', "AddNewStoreImages");
|
||||
postData.append('Path', d2);
|
||||
|
||||
isImageUploaded = await UploadImagesWithoutWait(postData, url);
|
||||
if (isImageUploaded == true) {
|
||||
// console.log('isExists file uploaded', isExists, uploadCount, index, allfiles.length - 1);
|
||||
await RNFS.unlink(actualfilepath);
|
||||
uploadCount++;
|
||||
// UpdateUploadCountLocal(uploadCount+1)
|
||||
if (uploadCount == allfiles.length) {
|
||||
isAllUploaded = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
console.log('file not uploaded:', isExists, actualfilepath);
|
||||
}
|
||||
|
||||
}
|
||||
else {//file does not exists
|
||||
uploadCount++;
|
||||
// UpdateUploadCountLocal(uploadCount+1)
|
||||
if (uploadCount == allfiles.length) {
|
||||
isAllUploaded = true;
|
||||
}
|
||||
}
|
||||
return isImageUploaded;
|
||||
})
|
||||
).then((val) => {
|
||||
console.log(val);
|
||||
return isAllUploaded;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
return false;
|
||||
})
|
||||
}
|
||||
// end upload image
|
||||
const areAllCategoriesCompleted = () => {
|
||||
return uniqueCategories?.every(cat => isCompleted(cat));
|
||||
};
|
||||
|
||||
const areAllCategoriesUploaded = () => {
|
||||
return uniqueCategories?.every(cat => {
|
||||
const completed = isCompleted(cat);
|
||||
return completed?.Status === 'U';
|
||||
});
|
||||
};
|
||||
|
||||
async function onSubmitData() {
|
||||
// let isvalid = await validate();
|
||||
if (areAllCategoriesCompleted()) {
|
||||
Keyboard.dismiss();
|
||||
setShowAlert(true);
|
||||
} else {
|
||||
toastError("Alert", "Please fill all categories.");
|
||||
}
|
||||
}
|
||||
|
||||
function onSaveCancel() {
|
||||
setShowAlert(false);
|
||||
}
|
||||
|
||||
// update status of uploading data
|
||||
const updateFeedbackStatusToUploaded = async (visitDate) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.transaction(tx => {
|
||||
tx.executeSql(
|
||||
`UPDATE FeedBackLocalTable SET STATUS = 'U' WHERE STORE_ID=? and VISIT_DATE = ?`,
|
||||
[storeData?.StoreId, visitDate],
|
||||
(_, result) => {
|
||||
// console.log("Local STATUS updated to 'U' after upload.");
|
||||
resolve(result);
|
||||
},
|
||||
(tx, error) => {
|
||||
console.log("Error updating STATUS locally:", error);
|
||||
reject(error);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
const updateUploadStatusForStores = (visitDate) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.transaction(tx => {
|
||||
// First: Set uploaded stores to 'U' for the given visit date
|
||||
tx.executeSql(
|
||||
`
|
||||
UPDATE StoreInfoDNALocal
|
||||
SET UPLOAD_STATUS = 'U'
|
||||
WHERE EXISTS (
|
||||
SELECT 1
|
||||
FROM FeedBackLocalTable
|
||||
WHERE FeedBackLocalTable.STORE_ID = StoreInfoDNALocal.StoreId
|
||||
AND FeedBackLocalTable.STATUS = 'U'
|
||||
AND FeedBackLocalTable.VISIT_DATE = ?
|
||||
)
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM FeedBackLocalTable
|
||||
WHERE FeedBackLocalTable.STORE_ID = StoreInfoDNALocal.StoreId
|
||||
AND FeedBackLocalTable.VISIT_DATE = ?
|
||||
)
|
||||
`,
|
||||
[visitDate, visitDate],
|
||||
() => {
|
||||
console.log('Uploaded stores marked as U');
|
||||
|
||||
|
||||
// Second: Set non-uploaded stores to 'P' for the given visit date
|
||||
tx.executeSql(
|
||||
`
|
||||
UPDATE StoreInfoDNALocal
|
||||
SET UPLOAD_STATUS = 'P'
|
||||
WHERE EXISTS (
|
||||
SELECT 1
|
||||
FROM FeedBackLocalTable
|
||||
WHERE FeedBackLocalTable.STORE_ID = StoreInfoDNALocal.StoreId
|
||||
AND FeedBackLocalTable.VISIT_DATE = ?
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM FeedBackLocalTable
|
||||
WHERE FeedBackLocalTable.STORE_ID = StoreInfoDNALocal.StoreId
|
||||
AND FeedBackLocalTable.STATUS = 'U'
|
||||
AND FeedBackLocalTable.VISIT_DATE = ?
|
||||
)
|
||||
`,
|
||||
[visitDate, visitDate],
|
||||
() => {
|
||||
console.log('Pending stores marked as P');
|
||||
resolve(true);
|
||||
},
|
||||
(tx, error) => {
|
||||
console.log('Error updating pending stores:', error);
|
||||
reject(error);
|
||||
}
|
||||
);
|
||||
},
|
||||
(tx, error) => {
|
||||
console.log('Error updating uploaded stores:', error);
|
||||
reject(error);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
const updateAllUploadStatuses = async (visitDate) => {
|
||||
try {
|
||||
await updateFeedbackStatusToUploaded(visitDate);
|
||||
await updateUploadStatusForStores(visitDate);
|
||||
console.log('All upload statuses updated successfully');
|
||||
} catch (error) {
|
||||
console.log('Error in updating upload statuses:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<KeyboardAwareScrollView style={{ flex: 1 }} contentContainerStyle={{ justifyContent: 'center', flex: 1 }}>
|
||||
<SafeAreaView style={{ flex: 1, backgroundColor: GlobalTheme.colors.primary }}>
|
||||
<View style={{ flex: 1, backgroundColor: GlobalTheme.colors.white }}>
|
||||
<CustomHeader
|
||||
title="Feedback Categories"
|
||||
// rightIcon={IMAGES.menuIcon}
|
||||
// onRightPress={() => navigation.navigate('Dashboard')}
|
||||
onLeftPress={() => navigation.goBack()}
|
||||
leftIcon={IMAGES.backIcon}
|
||||
/>
|
||||
<Loader visible={loading} loadingtext={'Loading ...'} />
|
||||
<Loader visible={loadingdownload} loadingtext={'data downloading ...'} />
|
||||
<Loader visible={loadingupload} loadingtext={'Uploading Data...'} />
|
||||
<ScrollView style={{ flex: 1 }} contentContainerStyle={{ paddingBottom: 10 }}>
|
||||
<View style={styles.container}>
|
||||
{uniqueCategories?.map((cat, index) => {
|
||||
const completedEntry = isCompleted(cat);
|
||||
{/* console.log("completedEntry", completedEntry); */ }
|
||||
const isUploaded = completedEntry?.Status === 'U';
|
||||
|
||||
{/* console.log("isUploaded", isUploaded); */ }
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
key={index}
|
||||
disabled={isUploaded} // 👈 disable if already uploaded
|
||||
style={[styles.cardview, styles.categoryItem]} // 👈 visually indicate disabled
|
||||
onPress={() => {
|
||||
if (!isUploaded) {
|
||||
navigation.navigate('Feedback', {
|
||||
CategoryId: cat?.CategoryId,
|
||||
SurveyId: cat?.SurveyId,
|
||||
CategoryName: cat?.Category,
|
||||
storeData: storeData
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
<View style={styles.circleIcon}>
|
||||
<Text style={styles.circleText}>{cat.Category?.charAt(0)}</Text>
|
||||
</View>
|
||||
<View style={{ flex: 1 }}>
|
||||
<Text style={styles.categoryName}>{cat.Category}</Text>
|
||||
</View>
|
||||
{isUploaded ? (
|
||||
<Ionicons name="checkmark-done" size={22} color="green" />
|
||||
) : completedEntry ? (
|
||||
<Icon name="check-circle" size={22} color="green" />
|
||||
) : null}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
})}
|
||||
|
||||
{!loading && uniqueCategories.length === 0 && (
|
||||
<Text style={{ textAlign: 'center', marginTop: 20 }}>No categories available.</Text>
|
||||
)}
|
||||
</View>
|
||||
</ScrollView>
|
||||
<CustomButton
|
||||
onPress={() => {
|
||||
if (areAllCategoriesUploaded()) return;
|
||||
onSubmitData();
|
||||
}}
|
||||
title={areAllCategoriesUploaded() ? 'Data Uploaded' : 'Upload & Save'}
|
||||
style={areAllCategoriesUploaded() ? styles.btnbg1 : styles.btnbg}
|
||||
textstyle={areAllCategoriesUploaded() ? styles.btntext1 : styles.btntext}
|
||||
disabled={areAllCategoriesUploaded()}
|
||||
/>
|
||||
|
||||
<ConfirmSaveAlert
|
||||
showAlert={showAlert}
|
||||
onCancelCallBack={onSaveCancel}
|
||||
onYesCallBack={Upload_Data}
|
||||
msg="Do you really want to upload data?"
|
||||
/>
|
||||
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
</KeyboardAwareScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
export default FeedbackCategories;
|
||||
@@ -0,0 +1,66 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { GlobalTheme } from '../../../../theme';
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: GlobalTheme.colors.white,
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 10
|
||||
},
|
||||
btnbg: {
|
||||
backgroundColor: GlobalTheme.colors.secondary, borderRadius: GlobalTheme.borderRadius.md, marginVertical: 10, marginHorizontal: 10, bottom:0
|
||||
},
|
||||
btntext: {
|
||||
color: GlobalTheme.colors.white,
|
||||
fontSize: GlobalTheme.typography.fontSize.medium
|
||||
},
|
||||
btnbg1: {
|
||||
backgroundColor: GlobalTheme.colors.gray, borderRadius: GlobalTheme.borderRadius.md, marginVertical: 10, marginHorizontal: 10, bottom:0 , opacity : 0.5
|
||||
},
|
||||
btntext1: {
|
||||
color: GlobalTheme.colors.white,
|
||||
fontSize: GlobalTheme.typography.fontSize.medium
|
||||
},
|
||||
cardview: {
|
||||
borderColor: GlobalTheme.colors.lightblue, borderWidth: 1, borderRadius: GlobalTheme.borderRadius.sm, padding: 8, backgroundColor: GlobalTheme.colors.lightblue, marginVertical: 10
|
||||
},
|
||||
categoryName: {
|
||||
fontSize: GlobalTheme.typography.fontSize.small, fontWeight: GlobalTheme.typography.fontWeight.medium, color: GlobalTheme.colors.black, marginVertical: 10
|
||||
},
|
||||
|
||||
//
|
||||
categoryItem: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingVertical: 12,
|
||||
paddingHorizontal: 10,
|
||||
backgroundColor: '#f6f8fd',
|
||||
borderRadius: 10,
|
||||
marginVertical: 6,
|
||||
elevation: 1,
|
||||
},
|
||||
|
||||
circleIcon: {
|
||||
width: 36,
|
||||
height: 36,
|
||||
borderRadius: 18,
|
||||
backgroundColor: '#dce6f9',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginRight: 12,
|
||||
},
|
||||
|
||||
circleText: {
|
||||
fontSize: 16,
|
||||
fontWeight: 'bold',
|
||||
color: '#4c6ef5',
|
||||
},
|
||||
|
||||
categoryName: {
|
||||
fontSize: 15,
|
||||
fontWeight: '600',
|
||||
color: '#333',
|
||||
},
|
||||
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,333 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
TextInput,
|
||||
ScrollView,
|
||||
TouchableOpacity,
|
||||
Platform,
|
||||
Image,
|
||||
Modal,
|
||||
} from 'react-native';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import ModalSelector from 'react-native-modal-selector';
|
||||
import MultiSelect from 'react-native-multiple-select';
|
||||
import CustomHeader from '../../../components/CustomHeader';
|
||||
import IMAGES from '../../../constants/Images';
|
||||
import { GlobalTheme } from '../../../theme';
|
||||
import CustomButton from '../../../components/CustomButton';
|
||||
import { styles } from './style';
|
||||
import { toastError, toastSuccess } from '../../../constants/Toast';
|
||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome';
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import mockDataFlat1 from './data.json';
|
||||
import CustomCamera from '../../../components/CustomCamera';
|
||||
import CustomModal from '../../../components/CustomModal';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
|
||||
const transformSurveyData = (flatData) => {
|
||||
const grouped = {};
|
||||
flatData?.forEach(item => {
|
||||
if (!grouped[item.QuestionId]) {
|
||||
grouped[item.QuestionId] = {
|
||||
QuestionId: item.QuestionId,
|
||||
Question: item.Question,
|
||||
QuestionType: item.QuestionTypeNew,
|
||||
QEnable: item.QEnable,
|
||||
EnableQuestion: item.EnableQuestion,
|
||||
DisableQuestion: item.DisableQuestion,
|
||||
QuestionSequence: item.QuestionSequence,
|
||||
CategorySequence: item.CategorySequence,
|
||||
Answers: []
|
||||
};
|
||||
}
|
||||
if (!['Number', 'Text', 'OnlyText'].includes(item.QuestionTypeNew)) {
|
||||
if (item.AnswerId || item.Answer) {
|
||||
grouped[item.QuestionId].Answers.push({
|
||||
AnswerId: item.AnswerId,
|
||||
Answer: item.Answer
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
return Object.values(grouped).sort((a, b) => a.QuestionSequence - b.QuestionSequence);
|
||||
};
|
||||
|
||||
const FeedbackFormScreen = ({ route, navigation }) => {
|
||||
const { CategoryId, SurveyId, CategoryName } = route.params || {};
|
||||
const [questions, setQuestions] = useState([]);
|
||||
const [answers, setAnswers] = useState({});
|
||||
const [enabledQuestions, setEnabledQuestions] = useState({});
|
||||
const [showCamera, setShowCamera] = useState(false);
|
||||
const [activeCameraQId, setActiveCameraQId] = useState(null);
|
||||
|
||||
// For modal
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [selectedImg, setSelectedImg] = useState(null);
|
||||
const [reCapImgModalObj, setReCapImgModalObj] = useState({});
|
||||
|
||||
useEffect(() => {
|
||||
const filtered = mockDataFlat1?.mockDataFlat?.filter(
|
||||
item => item.CategoryId === CategoryId && item.SurveyId === SurveyId
|
||||
);
|
||||
const transformed = transformSurveyData(filtered);
|
||||
setQuestions(transformed);
|
||||
|
||||
const enableMap = {};
|
||||
transformed.forEach(q => {
|
||||
enableMap[q.QuestionId] = q.QEnable;
|
||||
});
|
||||
setEnabledQuestions(enableMap);
|
||||
loadSavedAnswers();
|
||||
}, []);
|
||||
|
||||
const loadSavedAnswers = async () => {
|
||||
try {
|
||||
const saved = await AsyncStorage.getItem('feedback_answers');
|
||||
if (saved) setAnswers(JSON.parse(saved));
|
||||
} catch (e) {
|
||||
console.warn('Failed to load saved answers');
|
||||
}
|
||||
};
|
||||
|
||||
const saveAnswers = async () => {
|
||||
try {
|
||||
await AsyncStorage.setItem('feedback_answers', JSON.stringify(answers));
|
||||
const completedRaw = await AsyncStorage.getItem('completed_categories');
|
||||
let completed = completedRaw ? JSON.parse(completedRaw) : [];
|
||||
if (!completed.includes(CategoryId)) {
|
||||
completed.push(CategoryId);
|
||||
await AsyncStorage.setItem('completed_categories', JSON.stringify(completed));
|
||||
}
|
||||
toastSuccess('Success', 'Answers Saved Successfully');
|
||||
navigation.goBack();
|
||||
} catch (e) {
|
||||
toastError('Error', 'Failed to save answers');
|
||||
}
|
||||
};
|
||||
|
||||
const handleAnswerChange = (questionId, value, enableList = '', disableList = '') => {
|
||||
setAnswers(prev => ({ ...prev, [questionId]: value }));
|
||||
const updated = { ...enabledQuestions };
|
||||
if (disableList) {
|
||||
disableList.split(',').forEach(id => {
|
||||
updated[parseInt(id)] = false;
|
||||
});
|
||||
}
|
||||
if (enableList) {
|
||||
enableList.split(',').forEach(id => {
|
||||
updated[parseInt(id)] = true;
|
||||
});
|
||||
}
|
||||
setEnabledQuestions(updated);
|
||||
};
|
||||
|
||||
const handleImageCaptured = (photo) => {
|
||||
if (activeCameraQId) {
|
||||
setAnswers(prev => ({ ...prev, [activeCameraQId]: photo.uri }));
|
||||
setSelectedImg(photo.uri);
|
||||
setShowModal(true);
|
||||
}
|
||||
setShowCamera(false);
|
||||
setActiveCameraQId(null);
|
||||
};
|
||||
|
||||
const openCamera = (questionId) => {
|
||||
setActiveCameraQId(questionId);
|
||||
setShowCamera(true);
|
||||
};
|
||||
|
||||
const _OpenCaptureImage_Modal = (imgUri) => {
|
||||
const isImageCap = imgUri !== '' && imgUri != null;
|
||||
let { cameraType } = reCapImgModalObj;
|
||||
|
||||
return (
|
||||
<CustomModal
|
||||
showModal={showModal}
|
||||
title={'Captured Image'}
|
||||
message={''}
|
||||
style={{ alignItems: 'center' }}
|
||||
hideDefaultClose={true}
|
||||
>
|
||||
{isImageCap && (
|
||||
<View style={{ alignItems: 'center' }}>
|
||||
<Image
|
||||
source={{ uri: selectedImg }}
|
||||
style={{
|
||||
width: 250,
|
||||
height: 250,
|
||||
marginBottom: 10,
|
||||
borderRadius: 10,
|
||||
}}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
style={{ marginBottom: 10 }}
|
||||
onPress={() => {
|
||||
setShowModal(false);
|
||||
openCamera(activeCameraQId);
|
||||
}}
|
||||
>
|
||||
<MaterialCommunityIcons name="camera-retake" size={50} color={GlobalTheme.colors.primary} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onPress={() => setShowModal(false)}
|
||||
style={{ paddingVertical: 10, paddingHorizontal: 30, backgroundColor: GlobalTheme.colors.primary, borderRadius: 6 }}
|
||||
>
|
||||
<Text style={{ color: '#fff' }}>Close</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
</CustomModal>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<KeyboardAwareScrollView style={{ flex: 1 }} contentContainerStyle={{ flexGrow: 1 }}>
|
||||
<SafeAreaView style={{ flex: 1, backgroundColor: GlobalTheme.colors.white }}>
|
||||
<CustomHeader
|
||||
title="Feedback and Rating"
|
||||
rightIcon={IMAGES.menuIcon}
|
||||
leftIcon={IMAGES.leftArrowIcon}
|
||||
onLeftPress={() => navigation.goBack()}
|
||||
onRightPress={() => navigation.navigate('Dashboard')}
|
||||
/>
|
||||
<ScrollView>
|
||||
<View style={styles.container}>
|
||||
<View style={styles.cardview}>
|
||||
<Text style={styles.categoryName}>{CategoryName}</Text>
|
||||
{questions.map((qtn) => {
|
||||
if (!enabledQuestions[qtn.QuestionId]) return null;
|
||||
return (
|
||||
<View key={qtn.QuestionId} style={styles.questionBlock}>
|
||||
<Text style={styles.questionText}>{qtn.Question}</Text>
|
||||
|
||||
{qtn.QuestionType === 'Single choice list' && (
|
||||
<ModalSelector
|
||||
animationType='fade'
|
||||
optionContainerStyle={{ backgroundColor: '#fff' }}
|
||||
cancelContainerStyle={{backgroundColor: '#fff' }}
|
||||
key={qtn.QuestionId}
|
||||
data={qtn.Answers.map(ans => ({ key: ans.AnswerId, label: ans.Answer }))}
|
||||
initValue="Select one"
|
||||
onChange={option => {
|
||||
const selectedAnswer = option.label;
|
||||
// Look up the matching full answer entry from mockDataFlat1
|
||||
const matchedRow = mockDataFlat1.mockDataFlat.find(item =>
|
||||
item.QuestionId === qtn.QuestionId && item.Answer === selectedAnswer
|
||||
);
|
||||
const enableQ = matchedRow?.EnableQuestion || '';
|
||||
const disableQ = matchedRow?.DisableQuestion || '';
|
||||
handleAnswerChange(
|
||||
qtn.QuestionId,
|
||||
selectedAnswer,
|
||||
enableQ,
|
||||
disableQ
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Text style={styles.selectorBox}>
|
||||
{answers[qtn.QuestionId] || '---Select option---'}
|
||||
</Text>
|
||||
</ModalSelector>
|
||||
)}
|
||||
|
||||
{qtn.QuestionType === 'Multi choice list' && (
|
||||
<MultiSelect
|
||||
items={qtn.Answers}
|
||||
uniqueKey="AnswerId"
|
||||
displayKey="Answer"
|
||||
onSelectedItemsChange={(selected) =>
|
||||
handleAnswerChange(
|
||||
qtn.QuestionId,
|
||||
selected,
|
||||
qtn.EnableQuestion,
|
||||
qtn.DisableQuestion
|
||||
)
|
||||
}
|
||||
selectedItems={answers[qtn.QuestionId] || []}
|
||||
selectText="Pick Items"
|
||||
searchInputPlaceholderText="Search Items..."
|
||||
searchIcon={<Icon name="search" size={18} color="#888" />}
|
||||
tagRemoveIconColor="#ccc"
|
||||
tagBorderColor="#ccc"
|
||||
tagTextColor="#000"
|
||||
selectedItemTextColor={GlobalTheme.colors.primary}
|
||||
selectedItemIconColor="#000"
|
||||
itemTextColor="#000"
|
||||
styleMainWrapper={styles.multiSelect}
|
||||
submitButtonText={'Submit'}
|
||||
textColor={GlobalTheme.colors.black}
|
||||
submitButtonColor={GlobalTheme.colors.secondary}
|
||||
styleItemsContainer={styles.styleItemsContainer}
|
||||
styleListContainer={styles.styleListContainer}
|
||||
styleInputGroup={styles.styleInputGroup}
|
||||
styleDropdownMenuSubsection={styles.styleDropdownMenuSubsection}
|
||||
styleDropdownMenu={styles.styleDropdownMenu}
|
||||
/>
|
||||
)}
|
||||
|
||||
{(qtn.QuestionType === 'Text' || qtn.QuestionType === 'OnlyText' || qtn.QuestionType === 'Number') && (
|
||||
<TextInput
|
||||
style={styles.textInput}
|
||||
placeholder="Enter here..."
|
||||
keyboardType={(qtn.QuestionType == 'Decimal' ? 'decimal-pad' : (qtn.QuestionType == 'Text' || qtn.QuestionType == 'OnlyText' ? 'default' : 'number-pad'))}
|
||||
value={answers[qtn.QuestionId] || ''}
|
||||
onChangeText={(text) => handleAnswerChange(qtn.QuestionId, text)}
|
||||
returnKeyType={(Platform.OS === 'ios') ? 'done' : 'next'}
|
||||
/>
|
||||
)}
|
||||
|
||||
{qtn.QuestionType === 'Image' && (
|
||||
<>
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
if (answers[qtn.QuestionId]) {
|
||||
setSelectedImg(answers[qtn.QuestionId]);
|
||||
setReCapImgModalObj({ cameraType: '1' });
|
||||
setActiveCameraQId(qtn.QuestionId);
|
||||
setShowModal(true);
|
||||
} else {
|
||||
openCamera(qtn.QuestionId); // if no image yet, open camera directly
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
source={answers[qtn.QuestionId] ? IMAGES.greenCameraIcon : IMAGES.redCameraIcon}
|
||||
style={{ width: 40, height: 40 }}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
|
||||
<CustomButton
|
||||
onPress={saveAnswers}
|
||||
title={'Save'}
|
||||
style={styles.btnbg}
|
||||
textstyle={styles.btntext}
|
||||
/>
|
||||
|
||||
{showCamera && (
|
||||
<Modal visible={showCamera} animationType="slide" presentationStyle="fullScreen">
|
||||
<CustomCamera
|
||||
onImageCaptured={handleImageCaptured}
|
||||
onClose={() => setShowCamera(false)}
|
||||
/>
|
||||
</Modal>
|
||||
)}
|
||||
|
||||
{/* Modal Preview with Retake */}
|
||||
{_OpenCaptureImage_Modal(selectedImg)}
|
||||
</SafeAreaView>
|
||||
</KeyboardAwareScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
export default FeedbackFormScreen;
|
||||
@@ -0,0 +1,816 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { View, Text, TextInput, ScrollView, TouchableOpacity, Platform, Image, Modal, BackHandler, Keyboard } from 'react-native';
|
||||
import ModalSelector from 'react-native-modal-selector';
|
||||
import MultiSelect from 'react-native-multiple-select';
|
||||
import CustomHeader from '../../../components/CustomHeader';
|
||||
import IMAGES from '../../../constants/Images';
|
||||
import { GlobalTheme, Screen } from '../../../theme';
|
||||
import CustomButton from '../../../components/CustomButton';
|
||||
import { styles } from './style';
|
||||
import { toastError, toastSuccess } from '../../../constants/Toast';
|
||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome';
|
||||
import CustomCamera from '../../../components/CustomCamera';
|
||||
import db from '../../../constants/database';
|
||||
import { getImage } from '../../../constants/function';
|
||||
import CustomIcon from '../../../constants/IconGenerator';
|
||||
import { ImageZoom } from '@likashefqet/react-native-image-zoom';
|
||||
import { useFocusEffect } from '@react-navigation/native';
|
||||
import { validateNumber } from '../../../constants/validations';
|
||||
import { ConfirmSaveAlert } from '../../../components/Alert';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import moment from 'moment';
|
||||
import Loader from '../../../constants/Loader';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
const FeedbackFormScreen = ({ route, navigation }) => {
|
||||
const { CategoryId, SurveyId, CategoryName , storeData} = route.params || {};
|
||||
let user_exist_data = useSelector(state => state?.user);
|
||||
const userId = user_exist_data.UserId || '' ;
|
||||
const [questions, setQuestions] = useState([]);
|
||||
const [answers, setAnswers] = useState({});
|
||||
const [enabledQuestions, setEnabledQuestions] = useState({});
|
||||
const [showCamera, setShowCamera] = useState(false);
|
||||
const [activeCameraQId, setActiveCameraQId] = useState(null);
|
||||
const [selectedImg, setSelectedImg] = useState(null);
|
||||
const [questionsFlat, setQuestionsFlat] = useState([]);
|
||||
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [zoomImageUrl, setZoomImageUrl] = useState(null);
|
||||
const [showZoomImage, setShowZoomImage] = useState(false);
|
||||
|
||||
const [showAlert, setShowAlert] = useState(false);
|
||||
const [loadingsave, setLoadingSave] = useState(false);
|
||||
const d2 = moment().format('MM/DD/YYYY');
|
||||
|
||||
// handle disable and enable functions
|
||||
|
||||
console.log("storeDatastoreDatastoreData",storeData)
|
||||
|
||||
const disableQtn = () => {
|
||||
let disableQ = questions?.map(q => {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
// end handle disable and enable functions
|
||||
|
||||
const loadSavedAnswers = async () => {
|
||||
const query = `SELECT * FROM FeedBackLocalTable WHERE CATEGORY_ID='${CategoryId}' AND SURVEY_ID='${SurveyId}' AND STORE_ID='${storeData?.StoreId}' AND VISIT_DATE='${d2}'`;
|
||||
// console.log("local saved answers query ===>", query)
|
||||
db.transaction(tx => {
|
||||
tx.executeSql(
|
||||
query,
|
||||
[],
|
||||
(tx, results) => {
|
||||
const localAnswers = {};
|
||||
let enb = {}
|
||||
for (let i = 0; i < results.rows.length; i++) {
|
||||
const item = results.rows.item(i);
|
||||
let answer = null;
|
||||
if (item.IMAGE1 && item.IMAGE1 !== '') {
|
||||
answer = item.IMAGE1.trim();
|
||||
} else if (item.ANSWER && item.ANSWER !== '') {
|
||||
if (typeof item.ANSWER === 'string' && item.ANSWER.includes(',')) {
|
||||
answer = item.ANSWER.split(',').map(val => parseInt(val.trim(), 10));
|
||||
} else {
|
||||
answer = item.ANSWER;
|
||||
}
|
||||
}
|
||||
|
||||
if (item.QUESTION_TYPE == 'Single choice list') {
|
||||
answer = `${item?.ANSWER_ID},${item.ANSWER}`
|
||||
} else if (item.QUESTION_TYPE == 'Multi choice list') {
|
||||
answer = item?.MULTI_OPTIONS_IDS && JSON.parse(item?.MULTI_OPTIONS_IDS)
|
||||
// console.log("answer------multi", answer, item)
|
||||
}
|
||||
|
||||
|
||||
|
||||
enb = item?.IS_DISABLED && JSON.parse(item?.IS_DISABLED)
|
||||
localAnswers[item.QUESTION_ID] = answer;
|
||||
// console.log("item?.IMAGE1", item?.IMAGE1)
|
||||
localAnswers[item.QUESTION_ID + "Img1"] = item?.IMAGE1 ? ('file:///data/user/0/com.performicsstoredna/files/PerformicsAllImages/Store_DNA/' + item.IMAGE1) : "";
|
||||
localAnswers[item.QUESTION_ID + "Img2"] = item?.IMAGE1 ? ('file:///data/user/0/com.performicsstoredna/files/PerformicsAllImages/Store_DNA/' + item.IMAGE2) : "";
|
||||
|
||||
// enabledMap[item.QUESTION_ID] = item.IS_DISABLED === 1 ? false : true; // isDisabled
|
||||
}
|
||||
|
||||
setAnswers(prev => ({
|
||||
...prev,
|
||||
...localAnswers
|
||||
}));
|
||||
// console.log("enb----",enb)
|
||||
if (Object.keys(enb).length > 0) {
|
||||
setEnabledQuestions(enb); // ✅ restore isDisabled state
|
||||
}
|
||||
},
|
||||
(tx, error) => {
|
||||
console.log('Error fetching saved answers:', error);
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const saveData = async () => {
|
||||
setLoadingSave(true);
|
||||
try {
|
||||
let valuesArray = [];
|
||||
|
||||
questions?.map(q => {
|
||||
let answer = answers[q.QuestionId] || '';
|
||||
let img1 = answers[q.QuestionId + "Img1"] || '';
|
||||
let img2 = answers[q.QuestionId + "Img2"] || '';
|
||||
let selanswer = "", selansid = "", multi = "";
|
||||
|
||||
// console.log("questionlist======", q, "questionlist====");
|
||||
|
||||
if (q.QuestionType == 'Single choice list') {
|
||||
let slValue = answer?.split(",")
|
||||
selanswer = slValue?.[1] || ''
|
||||
selansid = slValue?.[0] || "0"
|
||||
// console.log("selanswer==", selanswer, "selansid", selansid, "answ", answer, q)
|
||||
|
||||
} else if (q.QuestionType == 'Multi choice list') {
|
||||
// console.log("multi------", answer)
|
||||
multi = JSON.stringify(answer)
|
||||
selansid = "0"
|
||||
} else {
|
||||
selanswer = answer
|
||||
selansid = "0"
|
||||
}
|
||||
|
||||
// console.log("selanswer==",selanswer ,"selansid" , selansid , "answ",answer)
|
||||
|
||||
let imgName1 = img1.split("/").pop();
|
||||
let imgName2 = img2.split("/").pop();
|
||||
|
||||
// console.log("multi------multi",multi)
|
||||
let enb = JSON.stringify(enabledQuestions)
|
||||
valuesArray.push(` ('${d2}','${SurveyId}', '${CategoryId}','${q.Question}','${q.QuestionId}','${q.QuestionType}','${selanswer || ''}','${selansid}','${q.QuestionImageAllow}','${imgName1 || ''}','${imgName2 || ''}','${q.ImageAllow1}','${q.ImageAllow2}','${multi}','${q.QuestionRefImage}', '${enb}', '${q.EnableQuestion}' , '${storeData.StoreId || ''}') `);
|
||||
});
|
||||
|
||||
const queryStr = valuesArray.join(', ');
|
||||
let insertQuery = `INSERT INTO FeedBackLocalTable (VISIT_DATE, SURVEY_ID, CATEGORY_ID, QUESTION, QUESTION_ID, QUESTION_TYPE ,ANSWER,ANSWER_ID,QuestionImageAllow,IMAGE1,IMAGE2,IMAGE_ALLOW1,IMAGE_ALLOW2,MULTI_OPTIONS_IDS, QUESTION_REF_IMAGE, IS_DISABLED , IS_ENABLED, STORE_ID) VALUES ${queryStr}`
|
||||
|
||||
db.transaction(tx => {
|
||||
let deleteQuery = `DELETE FROM FeedBackLocalTable WHERE CATEGORY_ID='${CategoryId}' AND SURVEY_ID='${SurveyId}' AND STORE_ID='${storeData?.StoreId}' AND VISIT_DATE='${d2}'`;
|
||||
console.log('Executing DELETE query:', deleteQuery);
|
||||
tx.executeSql(deleteQuery, [], () => {
|
||||
|
||||
// console.log("insertQuery------",insertQuery)
|
||||
tx.executeSql(insertQuery, [], async function (txn2, txnres) {
|
||||
toastSuccess('Success', 'Data saved successfully.');
|
||||
setLoadingSave(false);
|
||||
navigation.goBack();
|
||||
}, function (txnE, txnerr) {
|
||||
console.log('Delete error:', txnerr); toastError('Error', txnerr);
|
||||
setLoadingSave(false);
|
||||
},);
|
||||
|
||||
}, err => console.log('Delete error:', err));
|
||||
});
|
||||
} catch (e) {
|
||||
toastError('Error', e);
|
||||
setLoadingSave(false);
|
||||
console.log('Transaction error:', e);
|
||||
}
|
||||
};
|
||||
|
||||
// const handleAnswerChange = (questionId, value, enableList = '', disableList = '', qtn) => {
|
||||
|
||||
// setAnswers(prev => ({ ...prev, [questionId]: value }));
|
||||
// const updated = { ...enabledQuestions };
|
||||
// if (disableList) {
|
||||
// disableList.split(',').forEach(id => {
|
||||
// updated[parseInt(id)] = false;
|
||||
// });
|
||||
// }
|
||||
// if (enableList) {
|
||||
// enableList.split(',').forEach(id => {
|
||||
// updated[parseInt(id)] = true;
|
||||
// });
|
||||
// }
|
||||
// setEnabledQuestions(updated);
|
||||
// };
|
||||
|
||||
function cleanSelector(disableList,qtn,showImageTag,showImageTag2) {
|
||||
let objTemp={...answers}
|
||||
disableList?.split(",").map((itm,index)=>{
|
||||
objTemp[itm]=""
|
||||
delete objTemp[itm+"Img1"]
|
||||
delete objTemp[itm+"Img2"]
|
||||
})
|
||||
if(showImageTag){
|
||||
delete objTemp[qtn?.QuestionId+"Img1"]
|
||||
}
|
||||
if(showImageTag2){
|
||||
delete objTemp[qtn?.QuestionId+"Img2"]
|
||||
}
|
||||
// console.log("objTemp-----3",showImageTag,showImageTag2,objTemp)s
|
||||
setAnswers(objTemp);
|
||||
|
||||
}
|
||||
|
||||
|
||||
const handleAnswerChange = (questionId, value, enableList = '', disableList = '', qtn,showImageTag=false,showImageTag2=false) => {
|
||||
const prevValue = answers[questionId];
|
||||
|
||||
// Clean selector logic: only for Single choice list
|
||||
if (
|
||||
qtn.QuestionType === 'Single choice list' &&
|
||||
prevValue &&
|
||||
prevValue !== value
|
||||
) {
|
||||
cleanSelector(disableList,qtn,showImageTag,showImageTag2);
|
||||
console.log('qtn------',qtn)
|
||||
}
|
||||
|
||||
// Update the answer
|
||||
setAnswers(prev => ({ ...prev, [questionId]: value }));
|
||||
|
||||
// Enable/disable dependent questions
|
||||
const updated = { ...enabledQuestions };
|
||||
|
||||
if (disableList) {
|
||||
disableList.split(',').forEach(id => {
|
||||
updated[parseInt(id)] = false;
|
||||
});
|
||||
}
|
||||
|
||||
if (enableList) {
|
||||
enableList.split(',').forEach(id => {
|
||||
updated[parseInt(id)] = true;
|
||||
});
|
||||
}
|
||||
|
||||
setEnabledQuestions(updated);
|
||||
};
|
||||
|
||||
const handleImageCaptured = async (photo) => {
|
||||
console.log("activeCameraQId-----", activeCameraQId)
|
||||
if (activeCameraQId && photo?.uri) {
|
||||
try {
|
||||
const imgdata = {
|
||||
uri: photo.uri,
|
||||
width: photo.width,
|
||||
ExtendedHeight: photo.height,
|
||||
storeData: {}
|
||||
};
|
||||
|
||||
const res = await getImage(imgdata ,userId , storeData);
|
||||
const imagePath = 'file://' + (res?.finalPath || photo.uri);
|
||||
setAnswers(prev => ({
|
||||
...prev,
|
||||
[activeCameraQId]: imagePath
|
||||
}));
|
||||
setSelectedImg(imagePath);
|
||||
setShowModal(true);
|
||||
} catch (e) {
|
||||
console.warn("Watermarking failed:", e);
|
||||
}
|
||||
}
|
||||
setShowCamera(false);
|
||||
};
|
||||
|
||||
const openCamera = (questionId, type = 0) => {
|
||||
setActiveCameraQId(questionId);
|
||||
setShowCamera(true);
|
||||
};
|
||||
|
||||
// Fixed function to handle image tap - properly set activeCameraQId
|
||||
const handleImageTap = (questionId, type = 0) => {
|
||||
const currentImage = answers[questionId];
|
||||
// Set the active camera question ID
|
||||
setActiveCameraQId(questionId);
|
||||
|
||||
if (currentImage) {
|
||||
setSelectedImg(currentImage);
|
||||
setShowModal(true);
|
||||
// setActiveCameraQId(questionId+"Img"+type);
|
||||
} else {
|
||||
openCamera(questionId, type);
|
||||
}
|
||||
};
|
||||
|
||||
const transformSurveyData = (flatData) => {
|
||||
const grouped = {};
|
||||
flatData?.forEach(item => {
|
||||
if (!grouped[item.QuestionId]) {
|
||||
grouped[item.QuestionId] = {
|
||||
QuestionId: item.QuestionId,
|
||||
Question: item.Question,
|
||||
QuestionType: item.QuestionTypeNew,
|
||||
QEnable: item.QEnable,
|
||||
EnableQuestion: item.EnableQuestion,
|
||||
DisableQuestion: item.DisableQuestion,
|
||||
QuestionSequence: item.QuestionSequence,
|
||||
CategorySequence: item.CategorySequence,
|
||||
QuestionRefImage: item.QuestionRefImage,
|
||||
MinLength: item.MinLength,
|
||||
MaxLength: item.MaxLength,
|
||||
LengthValidation: item.LengthValidation,
|
||||
QuestionImageMandatory: item.QuestionImageMandatory, // images
|
||||
QuestionImageAllow: item.QuestionImageAllow,
|
||||
ImageAllow1: item.ImageAllow1,
|
||||
ImageAllow2: item.ImageAllow2,
|
||||
Image1Mandatory: item.Image1Mandatory,
|
||||
Image2Mandatory: item.Image2Mandatory,
|
||||
Answers: []
|
||||
};
|
||||
}
|
||||
if (!['Number', 'Text', 'OnlyText'].includes(item.QuestionTypeNew)) {
|
||||
if (item.AnswerId || item.Answer) {
|
||||
grouped[item.QuestionId].Answers.push({
|
||||
AnswerId: item.AnswerId,
|
||||
Answer: item.Answer,
|
||||
isDisabled: item.DisableQuestion,
|
||||
isEnabled: item.EnableQuestion,
|
||||
ImageAllow2: item.ImageAllow2,
|
||||
ImageAllow1: item.ImageAllow1
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
return Object.values(grouped).sort((a, b) => a.QuestionSequence - b.QuestionSequence);
|
||||
};
|
||||
|
||||
const loadQuestions = () => {
|
||||
const query = `SELECT * FROM FeedbackCategory WHERE CategoryId = '${CategoryId}' AND SurveyId = '${SurveyId}' ORDER BY QuestionSequence ASC`;
|
||||
console.log('Executing SELECT query:', query);
|
||||
|
||||
db.transaction(tx => {
|
||||
tx.executeSql(
|
||||
`SELECT * FROM FeedbackCategory WHERE CategoryId = ? AND SurveyId = ? ORDER BY QuestionSequence ASC`,
|
||||
[CategoryId, SurveyId],
|
||||
(tx, results) => {
|
||||
const rows = [];
|
||||
for (let i = 0; i < results.rows.length; i++) {
|
||||
rows.push(results.rows.item(i));
|
||||
}
|
||||
// console.log('Fetched Questions:', rows);
|
||||
|
||||
setQuestionsFlat(rows);
|
||||
const transformed = transformSurveyData(rows);
|
||||
setQuestions(transformed);
|
||||
|
||||
const enableMap = {};
|
||||
transformed.forEach(q => {
|
||||
enableMap[q.QuestionId] = q.QEnable === true || q.QEnable === 1;
|
||||
});
|
||||
setEnabledQuestions(enableMap);
|
||||
loadSavedAnswers();
|
||||
},
|
||||
(tx, err) => {
|
||||
console.log('Error loading questions:', err);
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const openRefImageView = (imgUrl) => {
|
||||
setZoomImageUrl(imgUrl);
|
||||
setShowZoomImage(true);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
loadQuestions();
|
||||
}, []);
|
||||
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
const onBackPress = () => {
|
||||
if (showZoomImage) {
|
||||
setShowZoomImage(false);
|
||||
return true; // block default back action
|
||||
}
|
||||
return false; // allow default back behavior
|
||||
};
|
||||
|
||||
const subscription = BackHandler.addEventListener('hardwareBackPress', onBackPress);
|
||||
|
||||
return () => subscription.remove(); // ✅ modern cleanup
|
||||
}, [showZoomImage])
|
||||
);
|
||||
|
||||
async function validate() {
|
||||
let isValid = true;
|
||||
|
||||
for (let qtn of questions) {
|
||||
// Skip disabled questions
|
||||
// console.log("enabledQuestions[qtn.QuestionId]", typeof enabledQuestions[qtn.QuestionId] , qtn)
|
||||
if (!enabledQuestions[qtn.QuestionId]) continue;
|
||||
|
||||
let selansid = '', selanswer = '', selimg = '', showImageTag = false, showImageTag2 = false, isImageMandateforAns = false;
|
||||
|
||||
// console.log("answers===", JSON.stringify(answers))
|
||||
const answer = answers[qtn.QuestionId];
|
||||
const qType = qtn.QuestionType;
|
||||
const qText = qtn.Question;
|
||||
|
||||
let image1 = answers[qtn?.QuestionId + "Img1"] || '';
|
||||
let image2 = answers[qtn.QuestionId + "Img2"] || '';
|
||||
// console.log(answers, "answer==========", image1, answer)
|
||||
// images
|
||||
|
||||
const isTruthy = (val) => val === true || val === 'true' || val === 1 || val === '1';
|
||||
|
||||
let isImg1mandatory = isTruthy(qtn.Image1Mandatory) || isTruthy(qtn.QuestionImageMandatory);
|
||||
let isImg2mandatory = isTruthy(qtn.Image2Mandatory);
|
||||
|
||||
let isImgAllowed = ((qtn.QuestionImageAllow == true || qtn.QuestionImageAllow == 'true' || qtn.QuestionImageAllow == 1) || (qtn.QuestionType == "Image"));
|
||||
// let isImg1mandatory = (qtn.Image1Mandatory == "true") || (qtn.Image1Mandatory == true) || (qtn.QuestionImageMandatory == "true") || (qtn.QuestionImageMandatory == true)
|
||||
|
||||
// let isImg2mandatory = (qtn?.Image2Mandatory == "true" || qtn?.Image2Mandatory == 'true');
|
||||
let isQuestionImageMandatory = qtn.QuestionType == "Image" ? (qtn?.QuestionImageMandatory == "true" || qtn?.QuestionImageMandatory == true) : true;
|
||||
|
||||
// console.log("isImg1mandatory qutn", qtn.Image1Mandatory, "questionss", qtn)
|
||||
// TEXT / NUMBER / ONLYTEXT fields
|
||||
if (['Text', 'Number', 'OnlyText'].includes(qType)) {
|
||||
if (!answer || answer === '') {
|
||||
toastError('Please fill details for: ', `${qText}`);
|
||||
isValid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
const minL = qtn.MinLength || 0;
|
||||
const maxL = qtn.MaxLength || 10;
|
||||
const needsLengthValidation = qtn.LengthValidation === 'true' || qtn.LengthValidation === true || qtn.LengthValidation === 1; // works file recheck
|
||||
|
||||
// console.log("needsLengthValidation",needsLengthValidation)
|
||||
|
||||
if (needsLengthValidation) {
|
||||
if (answer?.length < minL) {
|
||||
toastError('', `Minimum ${minL} characters required in: ${qText}`);
|
||||
isValid = false;
|
||||
break;
|
||||
}
|
||||
if (answer?.length > maxL) {
|
||||
toastError('', `Maximum ${maxL} characters allowed in: ${qText}`);
|
||||
isValid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SINGLE CHOICE
|
||||
else if (qType === 'Single choice list') {
|
||||
console.log("Single choice questions", qType, answer)
|
||||
const selectedValue = answer?.split(',')[1]; // get the actual ANSWER value
|
||||
|
||||
if (!selectedValue || selectedValue.trim() === '') {
|
||||
toastError('Please select an option for:', `${qText}`);
|
||||
isValid = false;
|
||||
break;
|
||||
}
|
||||
// if (!answer || answer === '') {
|
||||
// toastError('Please select an option for:', `${qText}`);
|
||||
// isValid = false;
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
|
||||
// MULTI CHOICE
|
||||
else if (qType === 'Multi choice list') {
|
||||
if (!Array.isArray(answer) || answer.length === 0) {
|
||||
toastError('Please select at least one option for:', `${qText}`);
|
||||
isValid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// IMAGE
|
||||
else if (qType === 'Image') {
|
||||
if (!image1 || image1 === '') {
|
||||
toastError('', `Please capture image for: ${qText}`);
|
||||
isValid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((qtn.QuestionType == 'Single choice list' || qtn.QuestionType == 'Multi choice list')) {
|
||||
// console.log("answers[qtn?.QuestionId]----", answers[qtn?.QuestionId], qtn?.QuestionId)
|
||||
if (qtn.QuestionType != 'Multi choice list') {
|
||||
let slValue = answers[qtn?.QuestionId]?.split(",")
|
||||
selanswer = slValue?.[1] || ''
|
||||
selansid = slValue?.[0] || '0'
|
||||
}
|
||||
|
||||
if (qtn.Answers && qtn.Answers.length > 0) {
|
||||
for (var i = 0; i < qtn.Answers.length; i++) {
|
||||
let ansss = qtn.Answers[i];
|
||||
|
||||
let isandImgAl = (ansss.ImageAllow1 == true || ansss.ImageAllow1 == 'true' || ansss.ImageAllow1 == 1);
|
||||
let isandImgAl2 = (ansss.ImageAllow2 == true || ansss.ImageAllow2 == 'true' || ansss.ImageAllow2 == 1);
|
||||
|
||||
let an = answers[qtn.QuestionId]
|
||||
// console.log("showImageTag2------", isandImgAl, ansss, qtn.AnswerId, qtn, an, answers)
|
||||
if (qtn.QuestionType == 'Single choice list' && (isandImgAl && ansss.AnswerId == selansid)) {
|
||||
showImageTag = true;
|
||||
}
|
||||
else if (qtn.QuestionType == 'Multi choice list' && (isandImgAl && qtn?.AnswerId?.indexOf(ansss?.AnswerId) >= 0)) {
|
||||
showImageTag = true;
|
||||
}
|
||||
|
||||
if (qtn.QuestionType == 'Single choice list' && (isandImgAl2 && ansss.AnswerId == selansid)) {
|
||||
showImageTag2 = true;
|
||||
}
|
||||
else if (qtn.QuestionType == 'Multi choice list' && (isandImgAl2 && qtn?.AnswerId?.indexOf(ansss?.AnswerId) >= 0)) {
|
||||
showImageTag2 = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// console.log("isImg1mandatory answerrrrrrrr", isImg1mandatory, image1, image2)
|
||||
|
||||
if (showImageTag && isImg1mandatory && (!image1 || image1 === '')) {
|
||||
isValid = false;
|
||||
toastError('', `Please capture image for: ${qText}`);
|
||||
break;
|
||||
}
|
||||
if (showImageTag2 && isImg2mandatory && (!image2 || image2 === '')) {
|
||||
isValid = false;
|
||||
toastError('', `Please capture image for 2: ${qText}`);
|
||||
break;
|
||||
}
|
||||
|
||||
// Other types like Audio, Rating, Date can be added similarly here
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
function setTextValue(value, qtn, type = '') {
|
||||
if (value !== '') {
|
||||
const isValid = validateNumber(value, type);
|
||||
if (!isValid) return;
|
||||
}
|
||||
|
||||
let valToSave = value;
|
||||
|
||||
// If it's decimal type and requires rounding
|
||||
if (qtn.QuestionType === 'Decimal' && qtn.LengthValidation === 'true') {
|
||||
const valSplit = value.split('.')[1]?.length;
|
||||
if (valSplit === undefined || valSplit < 2) {
|
||||
valToSave = value;
|
||||
} else if (/^\d+\.\d{2}$/.test(value)) {
|
||||
valToSave = Number(value).toFixed(2);
|
||||
}
|
||||
}
|
||||
|
||||
setAnswers(prev => ({
|
||||
...prev,
|
||||
[qtn.QuestionId]: valToSave
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
async function onSubmitData() {
|
||||
let isvalid = await validate();
|
||||
if (isvalid) {
|
||||
Keyboard.dismiss();
|
||||
setShowAlert(true);
|
||||
}
|
||||
}
|
||||
|
||||
function onSaveCancel() {
|
||||
setShowAlert(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView style={{ flex: 1, backgroundColor: GlobalTheme.colors.primary }}>
|
||||
<CustomHeader title="Feedback and Rating" rightIcon={IMAGES.menuIcon} leftIcon={IMAGES.leftArrowIcon} onLeftPress={() => navigation.goBack()} onRightPress={() => navigation.navigate('Dashboard')} />
|
||||
<KeyboardAwareScrollView extraScrollHeight={Platform.OS === 'android' ? 200 : 0} keyboardShouldPersistTaps="handled" enableOnAndroid contentContainerStyle={{ flexGrow: 1 }} style={{ flex: 1, backgroundColor: GlobalTheme.colors.white }}>
|
||||
<View style={{ flex: 1, backgroundColor: GlobalTheme.colors.white }}>
|
||||
<View style={styles.container}>
|
||||
<View style={styles.cardview}>
|
||||
<Text style={styles.categoryName}>{CategoryName}</Text>
|
||||
{questions.map((qtn) => {
|
||||
let selansid = '', selanswer = '';
|
||||
let imgQS = qtn.QuestionId + "Img"
|
||||
|
||||
if (!enabledQuestions[qtn.QuestionId]) return null;
|
||||
|
||||
let maxlen = (qtn.LengthValidation == true || qtn.LengthValidation == 'true') && qtn.MaxLength != null && qtn.MaxLength != '' ? qtn.MaxLength : 10;
|
||||
let minlen = (qtn.LengthValidation == true || qtn.LengthValidation == 'true') && qtn.MinLength != null && qtn.MinLength != '' ? qtn.MinLength : 0;
|
||||
// question image
|
||||
let isImgAllowed = ((qtn.QuestionImageAllow == true || qtn.QuestionImageAllow == 'true' || qtn.QuestionImageAllow == 1) || (qtn.QuestionType == "Image"));
|
||||
let isQuestionImageMandatory = qtn.QuestionType == "Image" ? (qtn?.QuestionImageMandatory == "true" || qtn?.QuestionImageMandatory == true) : true;
|
||||
|
||||
// Answer Images
|
||||
let Image1Mandatory = (qtn.Image1Mandatory == "true") || (qtn.Image1Mandatory == true) || (qtn.QuestionImageMandatory == "true") || (qtn.QuestionImageMandatory == true)
|
||||
let Image2Mandatory = (qtn.Image2Mandatory == "true") || (qtn.Image2Mandatory == true)
|
||||
|
||||
{/* console.log(Image1Mandatory, "Image1Mandatory", qtn.QuestionImageMandatory, "qtn.QuestionImageMandatory") */ }
|
||||
|
||||
{/* console.log("maxlen", maxlen, "===========", "minlen", minlen); */ }
|
||||
let showImageTag = false, showImageTag2 = false
|
||||
if (qtn.QuestionType == 'Image' && isImgAllowed) {
|
||||
showImageTag = true;
|
||||
}
|
||||
if ((qtn.QuestionType == 'Single choice list' || qtn.QuestionType == 'Multi choice list')) {
|
||||
{/* console.log("answers[qtn?.QuestionId]----", answers[qtn?.QuestionId], qtn?.QuestionId) */ }
|
||||
if (qtn.QuestionType != 'Multi choice list') {
|
||||
let slValue = answers[qtn?.QuestionId]?.split(",")
|
||||
selanswer = slValue?.[1] || ''
|
||||
selansid = slValue?.[0] || '0'
|
||||
}
|
||||
|
||||
if (qtn.Answers && qtn.Answers.length > 0) {
|
||||
for (var i = 0; i < qtn.Answers.length; i++) {
|
||||
let ansss = qtn.Answers[i];
|
||||
|
||||
let isandImgAl = (ansss.ImageAllow1 == true || ansss.ImageAllow1 == 'true' || ansss.ImageAllow1 == 1);
|
||||
let isandImgAl2 = (ansss.ImageAllow2 == true || ansss.ImageAllow2 == 'true' || ansss.ImageAllow2 == 1);
|
||||
|
||||
let an = answers[qtn.QuestionId]
|
||||
{/* console.log("showImageTag2------", isandImgAl, ansss, qtn.AnswerId, qtn, an, answers) */ }
|
||||
if (qtn.QuestionType == 'Single choice list' && (isandImgAl && ansss.AnswerId == selansid)) {
|
||||
showImageTag = true;
|
||||
}
|
||||
else if (qtn.QuestionType == 'Multi choice list' && (isandImgAl && qtn?.AnswerId?.indexOf(ansss?.AnswerId) >= 0)) {
|
||||
showImageTag = true;
|
||||
}
|
||||
|
||||
if (qtn.QuestionType == 'Single choice list' && (isandImgAl2 && ansss.AnswerId == selansid)) {
|
||||
showImageTag2 = true;
|
||||
}
|
||||
else if (qtn.QuestionType == 'Multi choice list' && (isandImgAl2 && qtn?.AnswerId?.indexOf(ansss?.AnswerId) >= 0)) {
|
||||
showImageTag2 = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<View key={qtn.QuestionId} style={styles.questionBlock}>
|
||||
<Text style={styles.questionText}>{qtn.Question}</Text>
|
||||
{/* {console.log("qtn.QuestionRefImage", qtn.QuestionRefImage, Image2Mandatory)} */}
|
||||
{qtn.QuestionRefImage != null && qtn.QuestionRefImage != '' && (
|
||||
<TouchableOpacity style={styles.WItem_RefImgBtn} onPress={() => openRefImageView(qtn.QuestionRefImage)}>
|
||||
<CustomIcon iconLibrary={'Entypo'} icon='image-inverted' size={30} color="black" />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
|
||||
{qtn.QuestionType === 'Single choice list' && (
|
||||
<ModalSelector animationType='fade' optionContainerStyle={{ backgroundColor: '#fff' }} cancelContainerStyle={{ backgroundColor: '#fff' }}
|
||||
key={qtn.QuestionId}
|
||||
data={qtn.Answers.map(ans => ({ key: ans.AnswerId, label: ans.Answer }))}
|
||||
initValue="Select one"
|
||||
onChange={option => {
|
||||
// console.log("option---", option)
|
||||
const selectedAnswer = option.label;
|
||||
const matchedRow = questionsFlat?.find(item =>
|
||||
item.QuestionId === qtn.QuestionId && item.Answer === selectedAnswer
|
||||
);
|
||||
const enableQ = matchedRow?.EnableQuestion || '';
|
||||
const disableQ = matchedRow?.DisableQuestion || '';
|
||||
console.log("showImageTag------",showImageTag,showImageTag2)
|
||||
handleAnswerChange(
|
||||
qtn.QuestionId,
|
||||
`${option?.key},${selectedAnswer}`,
|
||||
enableQ,
|
||||
disableQ,
|
||||
qtn,
|
||||
showImageTag,
|
||||
showImageTag2
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Text style={styles.selectorBox}>
|
||||
{selanswer || '---Select option---'}
|
||||
</Text>
|
||||
</ModalSelector>
|
||||
)}
|
||||
|
||||
{qtn.QuestionType === 'Multi choice list' && (
|
||||
<MultiSelect
|
||||
// items={list_mcdata}
|
||||
// uniqueKey="AnswerId"
|
||||
// onSelectedItemsChange={(selectedItems) => { console.log('onSelectedItemsChange'); setMultiSelectValue(selectedItems, qtn) }}
|
||||
// selectedItems={selansid}
|
||||
items={qtn.Answers}
|
||||
uniqueKey="AnswerId"
|
||||
displayKey="Answer"
|
||||
onSelectedItemsChange={(selected) =>
|
||||
handleAnswerChange(qtn.QuestionId, selected, qtn.EnableQuestion, qtn.DisableQuestion, qtn , "", "")
|
||||
}
|
||||
selectedItems={
|
||||
Array.isArray(answers[qtn.QuestionId])
|
||||
? answers[qtn.QuestionId].map(a => parseInt(a))
|
||||
: []
|
||||
}
|
||||
selectText="Pick Items"
|
||||
searchInputPlaceholderText="Search Items..."
|
||||
searchIcon={<Icon name="search" size={18} color="#888" />}
|
||||
tagRemoveIconColor="#ccc"
|
||||
tagBorderColor="#ccc"
|
||||
tagTextColor="#000"
|
||||
selectedItemTextColor={GlobalTheme.colors.primary}
|
||||
selectedItemIconColor="#000"
|
||||
itemTextColor="#000"
|
||||
styleMainWrapper={styles.multiSelect}
|
||||
submitButtonText={'Submit'}
|
||||
textColor={GlobalTheme.colors.black}
|
||||
submitButtonColor={GlobalTheme.colors.secondary}
|
||||
styleItemsContainer={styles.styleItemsContainer}
|
||||
styleListContainer={styles.styleListContainer}
|
||||
styleInputGroup={styles.styleInputGroup}
|
||||
styleDropdownMenuSubsection={styles.styleDropdownMenuSubsection}
|
||||
styleDropdownMenu={styles.styleDropdownMenu}
|
||||
/>
|
||||
)}
|
||||
|
||||
{(qtn.QuestionType === 'Text' || qtn.QuestionType === 'OnlyText' || qtn.QuestionType === 'Number') && (
|
||||
<TextInput
|
||||
style={styles.textInput}
|
||||
placeholder="Enter here..."
|
||||
placeholderTextColor={'gray'}
|
||||
keyboardType={qtn.QuestionType === 'Number' ? 'number-pad' : 'default'}
|
||||
value={answers[qtn.QuestionId] || ''}
|
||||
minLength={minlen}
|
||||
maxLength={maxlen}
|
||||
onChangeText={(val) => { setTextValue(val, qtn, qtn.QuestionType == 'Decimal' ? 'decimal' : qtn.QuestionType == 'Text' ? 'text' : qtn.QuestionType == 'OnlyText' ? 'onlytext' : 'numeric') }}
|
||||
// onChangeText={(text) => handleAnswerChange(qtn.QuestionId, text)}
|
||||
returnKeyType={(Platform.OS === 'ios') ? 'done' : 'next'}
|
||||
/>
|
||||
)}
|
||||
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center', flex: 1 }}>
|
||||
{showImageTag &&
|
||||
<View style={[]}>
|
||||
<TouchableOpacity onPress={() => { handleImageTap(imgQS + 1) }}>
|
||||
<Image source={answers[imgQS + 1] ? IMAGES.greenCameraIcon : Image1Mandatory ? IMAGES.redCameraIcon : IMAGES.normalCameraIcon} style={styles.iconStyle} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
}
|
||||
|
||||
{showImageTag2 &&
|
||||
<View style={[]}>
|
||||
<TouchableOpacity onPress={() => { handleImageTap(imgQS + 2) }}>
|
||||
<Image source={answers[imgQS + 2] ? IMAGES.greenCameraIcon : Image2Mandatory ? IMAGES.redCameraIcon : IMAGES.normalCameraIcon} style={styles.iconStyle} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</View>
|
||||
{showZoomImage && zoomImageUrl && (
|
||||
<View style={styles.album_ZOOM_wrap}>
|
||||
<TouchableOpacity style={styles.closeIcon} onPress={() => setShowZoomImage(false)} >
|
||||
<Icon name="times-circle" size={35} color="#fff" />
|
||||
</TouchableOpacity>
|
||||
<ImageZoom cropWidth={Screen.screenWidth} cropHeight={Screen.screenHeight} imageWidth={Screen.screenWidth} imageHeight={Screen.screenHeight} style={styles.album_ZOOM} uri={zoomImageUrl} minScale={1} maxScale={5} doubleTapScale={3} isSingleTapEnabled isDoubleTapEnabled resizeMode="contain" />
|
||||
</View>
|
||||
)}
|
||||
|
||||
{showModal && selectedImg && (
|
||||
<Modal visible={showModal} transparent={true} animationType="fade" onRequestClose={() => setShowModal(false)}>
|
||||
<View style={{ flex: 1, backgroundColor: '#00000088', justifyContent: 'center', alignItems: 'center' }}>
|
||||
<View style={styles.modal_view}>
|
||||
<Image source={{ uri: selectedImg }} style={{ width: 250, height: 250, borderRadius: 10, marginBottom: 15 }} resizeMode="contain" />
|
||||
<TouchableOpacity
|
||||
style={styles.modal_view2}
|
||||
onPress={() => {
|
||||
setShowModal(false);
|
||||
if (activeCameraQId) {
|
||||
openCamera(activeCameraQId);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: '#fff' }}>Retake</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity style={styles.modal_view2} onPress={() => setShowModal(false)}>
|
||||
<Text style={{ color: '#fff' }}>Close</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
)}
|
||||
|
||||
<ConfirmSaveAlert showAlert={showAlert} onCancelCallBack={onSaveCancel} onYesCallBack={saveData} msg="Do you really want to save data?" />
|
||||
{showCamera && (
|
||||
<Modal visible={showCamera} animationType="slide" presentationStyle="fullScreen">
|
||||
<CustomCamera
|
||||
onImageCaptured={handleImageCaptured}
|
||||
onClose={() => setShowCamera(false)}
|
||||
/>
|
||||
</Modal>
|
||||
)}
|
||||
<Loader visible={loadingsave} loadingtext={'Saving Data...'} />
|
||||
</View>
|
||||
</KeyboardAwareScrollView>
|
||||
<View style={{ backgroundColor: GlobalTheme.colors.white }}>
|
||||
<CustomButton onPress={onSubmitData} title={'Save'} style={styles.btnbg} textstyle={styles.btntext} />
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
|
||||
export default FeedbackFormScreen;
|
||||
@@ -0,0 +1,232 @@
|
||||
{
|
||||
"mappingsurvey":[
|
||||
{
|
||||
"StoreId": 403,
|
||||
"SurveyId": 1
|
||||
},
|
||||
{
|
||||
"StoreId": 484,
|
||||
"SurveyId": 1
|
||||
},
|
||||
{
|
||||
"StoreId": 510,
|
||||
"SurveyId": 1
|
||||
},
|
||||
{
|
||||
"StoreId": 583,
|
||||
"SurveyId": 1
|
||||
},
|
||||
{
|
||||
"StoreId": 2928,
|
||||
"SurveyId": 1
|
||||
},
|
||||
{
|
||||
"StoreId": 2949,
|
||||
"SurveyId": 1
|
||||
},
|
||||
{
|
||||
"StoreId": 1,
|
||||
"SurveyId": 1
|
||||
},
|
||||
{
|
||||
"StoreId": 2,
|
||||
"SurveyId": 1
|
||||
},
|
||||
{
|
||||
"StoreId": 3,
|
||||
"SurveyId": 1
|
||||
},
|
||||
{
|
||||
"StoreId": 4,
|
||||
"SurveyId": 1
|
||||
},
|
||||
{
|
||||
"StoreId": 5,
|
||||
"SurveyId": 1
|
||||
},
|
||||
{
|
||||
"StoreId": 1,
|
||||
"SurveyId": 9
|
||||
},
|
||||
{
|
||||
"StoreId": 2,
|
||||
"SurveyId": 9
|
||||
},
|
||||
{
|
||||
"StoreId": 3,
|
||||
"SurveyId": 9
|
||||
},
|
||||
{
|
||||
"StoreId": 4,
|
||||
"SurveyId": 9
|
||||
},
|
||||
{
|
||||
"StoreId": 5,
|
||||
"SurveyId": 9
|
||||
},
|
||||
{
|
||||
"StoreId": 585,
|
||||
"SurveyId": 9
|
||||
},
|
||||
{
|
||||
"StoreId": 2532,
|
||||
"SurveyId": 9
|
||||
},
|
||||
{
|
||||
"StoreId": 1,
|
||||
"SurveyId": 10
|
||||
},
|
||||
{
|
||||
"StoreId": 2,
|
||||
"SurveyId": 10
|
||||
},
|
||||
{
|
||||
"StoreId": 3,
|
||||
"SurveyId": 10
|
||||
},
|
||||
{
|
||||
"StoreId": 4,
|
||||
"SurveyId": 10
|
||||
},
|
||||
{
|
||||
"StoreId": 1171,
|
||||
"SurveyId": 11
|
||||
},
|
||||
{
|
||||
"StoreId": 1,
|
||||
"SurveyId": 12
|
||||
},
|
||||
{
|
||||
"StoreId": 2,
|
||||
"SurveyId": 12
|
||||
},
|
||||
{
|
||||
"StoreId": 3,
|
||||
"SurveyId": 12
|
||||
},
|
||||
{
|
||||
"StoreId": 4,
|
||||
"SurveyId": 12
|
||||
},
|
||||
{
|
||||
"StoreId": 5,
|
||||
"SurveyId": 12
|
||||
},
|
||||
{
|
||||
"StoreId": 691,
|
||||
"SurveyId": 10
|
||||
},
|
||||
{
|
||||
"StoreId": 2949,
|
||||
"SurveyId": 10
|
||||
},
|
||||
{
|
||||
"StoreId": 402,
|
||||
"SurveyId": 10
|
||||
},
|
||||
{
|
||||
"StoreId": 484,
|
||||
"SurveyId": 10
|
||||
},
|
||||
{
|
||||
"StoreId": 2928,
|
||||
"SurveyId": 10
|
||||
},
|
||||
{
|
||||
"StoreId": 403,
|
||||
"SurveyId": 10
|
||||
},
|
||||
{
|
||||
"StoreId": 583,
|
||||
"SurveyId": 10
|
||||
},
|
||||
{
|
||||
"StoreId": 3739,
|
||||
"SurveyId": 10
|
||||
},
|
||||
{
|
||||
"StoreId": 510,
|
||||
"SurveyId": 10
|
||||
},
|
||||
{
|
||||
"StoreId": 2958,
|
||||
"SurveyId": 10
|
||||
},
|
||||
{
|
||||
"StoreId": 4041,
|
||||
"SurveyId": 10
|
||||
},
|
||||
{
|
||||
"StoreId": 2920,
|
||||
"SurveyId": 10
|
||||
},
|
||||
{
|
||||
"StoreId": 45,
|
||||
"SurveyId": 11
|
||||
},
|
||||
{
|
||||
"StoreId": 402,
|
||||
"SurveyId": 11
|
||||
},
|
||||
{
|
||||
"StoreId": 484,
|
||||
"SurveyId": 11
|
||||
},
|
||||
{
|
||||
"StoreId": 510,
|
||||
"SurveyId": 11
|
||||
},
|
||||
{
|
||||
"StoreId": 653,
|
||||
"SurveyId": 11
|
||||
},
|
||||
{
|
||||
"StoreId": 1122,
|
||||
"SurveyId": 11
|
||||
},
|
||||
{
|
||||
"StoreId": 1483,
|
||||
"SurveyId": 11
|
||||
},
|
||||
{
|
||||
"StoreId": 1532,
|
||||
"SurveyId": 11
|
||||
},
|
||||
{
|
||||
"StoreId": 1605,
|
||||
"SurveyId": 11
|
||||
},
|
||||
{
|
||||
"StoreId": 1711,
|
||||
"SurveyId": 11
|
||||
},
|
||||
{
|
||||
"StoreId": 2091,
|
||||
"SurveyId": 11
|
||||
},
|
||||
{
|
||||
"StoreId": 2308,
|
||||
"SurveyId": 11
|
||||
},
|
||||
{
|
||||
"StoreId": 2532,
|
||||
"SurveyId": 11
|
||||
},
|
||||
{
|
||||
"StoreId": 2928,
|
||||
"SurveyId": 11
|
||||
},
|
||||
{
|
||||
"StoreId": 2949,
|
||||
"SurveyId": 11
|
||||
},
|
||||
{
|
||||
"StoreId": 2958,
|
||||
"SurveyId": 11
|
||||
},
|
||||
{
|
||||
"StoreId": 3198,
|
||||
"SurveyId": 11
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { GlobalTheme, Screen } from '../../../theme';
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: GlobalTheme.colors.white,
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 10
|
||||
},
|
||||
btnbg: {
|
||||
backgroundColor: GlobalTheme.colors.secondary, borderRadius: GlobalTheme.borderRadius.md , marginVertical:10 , marginHorizontal:10 , bottom:0
|
||||
},
|
||||
btntext: {
|
||||
color: GlobalTheme.colors.white,
|
||||
fontSize: GlobalTheme.typography.fontSize.medium
|
||||
},
|
||||
cardview: {
|
||||
borderColor: GlobalTheme.colors.lightblue, borderWidth: 1, borderRadius: GlobalTheme.borderRadius.lg, padding: 10
|
||||
},
|
||||
questionBlock: {
|
||||
marginBottom: 16,
|
||||
},
|
||||
questionText: {
|
||||
color:'#000',
|
||||
fontSize: GlobalTheme.typography.fontSize.xsmall,
|
||||
marginVertical: 5
|
||||
},
|
||||
categoryName: {
|
||||
fontSize: GlobalTheme.typography.fontSize.medium , fontWeight : GlobalTheme.typography.fontWeight.medium , color : GlobalTheme.colors.black , marginVertical:0
|
||||
},
|
||||
|
||||
textInput: {
|
||||
borderWidth: 1.5,
|
||||
borderColor: GlobalTheme.colors.lightblue,
|
||||
borderRadius: 6,
|
||||
padding: 10,
|
||||
color : GlobalTheme.colors.black,
|
||||
marginVertical: 5
|
||||
},
|
||||
multiSelect: {
|
||||
// marginTop: 8,
|
||||
// backgroundColor:'red'
|
||||
},
|
||||
selectorBox: {
|
||||
color:'gray',
|
||||
padding: 15,
|
||||
backgroundColor: GlobalTheme.colors.bluebgcolor,
|
||||
borderRadius: GlobalTheme.borderRadius.sm,
|
||||
marginVertical: 5
|
||||
},
|
||||
//multi select
|
||||
styleItemsContainer:{
|
||||
backgroundColor: GlobalTheme.colors.bluebgcolor , borderRadius :GlobalTheme.borderRadius.md , overflow:'hidden', paddingHorizontal:10, marginHorizontal:0,marginVertical:0 , marginBottom:20
|
||||
},
|
||||
styleListContainer:{
|
||||
backgroundColor: GlobalTheme.colors.bluebgcolor , borderRadius :GlobalTheme.borderRadius.md , padding:0 , overflow:'hidden', paddingHorizontal:0, marginHorizontal:0,marginVertical:10
|
||||
},
|
||||
styleInputGroup:{
|
||||
backgroundColor: GlobalTheme.colors.bluebgcolor , borderRadius :GlobalTheme.borderRadius.md , padding:0 , overflow:'hidden',paddingHorizontal:10, marginVertical:10,height:50
|
||||
},
|
||||
styleDropdownMenuSubsection:{
|
||||
backgroundColor: GlobalTheme.colors.bluebgcolor , borderRadius :GlobalTheme.borderRadius.md , padding:0 , overflow:'hidden',paddingHorizontal:10, marginHorizontal:10
|
||||
},
|
||||
styleDropdownMenu:{
|
||||
backgroundColor: GlobalTheme.colors.bluebgcolor , borderRadius :GlobalTheme.borderRadius.md , overflow:'hidden', marginVertical:10, height:50
|
||||
},
|
||||
|
||||
// camera
|
||||
openStk_prdCameras:{marginTop:10,flexDirection:'row',flexWrap:'wrap'},
|
||||
openStkCameraCon:{marginRight:10,},
|
||||
openStkCameraCon2:{marginRight:10,alignItems: 'center'},
|
||||
iconStyle : {
|
||||
height :70 , width : 70 , resizeMode : "contain"
|
||||
},
|
||||
// refImage
|
||||
WItem_RefImgBtn:{position:'absolute',right:0,top:-5,width:40,height:40,borderRadius:20,alignItems:'center',justifyContent:'center'},
|
||||
album_ZOOM_wrap:{backgroundColor:'#000',position:'absolute',top:0,left:0,width:Screen.screenWidth,height:Screen.screenHeight,zIndex:1},
|
||||
album_ZOOM:{backgroundColor:'#000',width:Screen.screenWidth,height:Screen.screenHeight},
|
||||
|
||||
closeIcon : {
|
||||
resizeMode : 'contain',
|
||||
alignSelf:'flex-end',
|
||||
right:20,
|
||||
marginTop:20
|
||||
},
|
||||
store_audit_img_con:{width:'100%',marginTop:10,height:150,marginHorizontal:5,alignSelf:'center',alignItems:'center',justifyContent:'center',position:'relative',backgroundColor:'#f5f5f5'},
|
||||
modal_view : {
|
||||
backgroundColor: 'white',
|
||||
borderRadius: 12,
|
||||
padding: 20,
|
||||
width: 300,
|
||||
alignItems: 'center',
|
||||
elevation: 10
|
||||
},
|
||||
modal_view2: {
|
||||
marginBottom: 15,
|
||||
paddingHorizontal: 25,
|
||||
paddingVertical: 10,
|
||||
backgroundColor: GlobalTheme.colors.secondary,
|
||||
borderRadius: 6
|
||||
}
|
||||
});
|
||||
@@ -1,3 +1,4 @@
|
||||
<<<<<<< HEAD
|
||||
import React, { useState } from 'react';
|
||||
import {View,Text,TouchableOpacity,ScrollView,FlatList} from 'react-native';
|
||||
import { styles } from './style';
|
||||
@@ -202,3 +203,442 @@ const StoreInfo = () => {
|
||||
};
|
||||
|
||||
export default StoreInfo;
|
||||
=======
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import { View, Text, TouchableOpacity, ScrollView, FlatList } from 'react-native';
|
||||
import { styles } from './style';
|
||||
import { horizonalLine, Screen } from '../../../theme/theme';
|
||||
import CustomHeader from '../../../components/CustomHeader';
|
||||
import IMAGES from '../../../constants/Images';
|
||||
import axios from 'axios';
|
||||
import Loader from '../../../constants/Loader';
|
||||
|
||||
const storeinfodata = [
|
||||
{
|
||||
tabId: 0,
|
||||
section: 'Store details',
|
||||
items: [
|
||||
{ brand: 'Store Name', name: 'Reliance Smart' },
|
||||
{ brand: 'Store ID', name: '#98440' },
|
||||
{ brand: 'Address', name: 'Rabindra Nagar, Delhi 110003' },
|
||||
{ brand: 'City', name: 'Okhla' },
|
||||
{ brand: 'Store Size', name: '1500–2000 sq ft' },
|
||||
{ brand: 'Average Footfall', name: '10000' },
|
||||
{ brand: 'Store age', name: '8' },
|
||||
{ brand: 'Store Ranking', name: '24' },
|
||||
],
|
||||
},
|
||||
{
|
||||
tabId: 0,
|
||||
section: 'Dabur Employees',
|
||||
items: [
|
||||
{ brand: 'RKAM', name: 'Rajesh Paal Singh' },
|
||||
{ brand: 'SO', name: 'Soniya Singhal' },
|
||||
],
|
||||
},
|
||||
{
|
||||
tabId: 0,
|
||||
section: '3P employees',
|
||||
items: [
|
||||
{ brand: 'Promoter Name', name: 'Payal Singh' },
|
||||
{ brand: 'AM Name', name: 'Soniya Singhal' },
|
||||
{ brand: 'Supervisor Name', name: 'Soniya Dhankar' },
|
||||
{ brand: 'City', name: 'Okhla' },
|
||||
{ brand: 'Promoter duration', name: '2 Year 7 months' },
|
||||
{ brand: 'Average incentive', name: '5000' },
|
||||
],
|
||||
},
|
||||
|
||||
// Last Visit Details (tabId: 1)
|
||||
{
|
||||
tabId: 1,
|
||||
section: 'Dabur employee',
|
||||
items: [
|
||||
{ brand: 'SO', name: 'Rajesh Paal Singh', date: '23/05/2025', test: 'gxsjhxbas' },
|
||||
{ brand: 'AH', name: 'Umesh Singh', date: '18/04/2025' },
|
||||
{ brand: 'KAM', name: 'Rahul Tawde', date: '15/05/2025' },
|
||||
{ brand: 'Others', name: 'Singhal Singh', date: '06/05/2025' },
|
||||
],
|
||||
},
|
||||
{
|
||||
tabId: 1,
|
||||
section: '3P team',
|
||||
items: [
|
||||
{ brand: 'Supervisor', name: 'Ashish Talwar', date: '27/05/2025' },
|
||||
{ brand: 'AM', name: 'Soniya Singhal', date: '23/05/2025' },
|
||||
],
|
||||
},
|
||||
|
||||
// Competition (tabId: 2)
|
||||
{
|
||||
tabId: 2,
|
||||
section: 'Competition assets',
|
||||
items: [
|
||||
{ brand: 'Marico', value: 5 },
|
||||
{ brand: 'Colgate', value: 1 },
|
||||
{ brand: 'Godrej', value: 2 },
|
||||
{ brand: 'HUL', value: 1 },
|
||||
{ brand: 'XX', value: 2 },
|
||||
],
|
||||
},
|
||||
{
|
||||
tabId: 2,
|
||||
section: 'Promoter details',
|
||||
items: [
|
||||
{ brand: 'Marico', value: 1 },
|
||||
{ brand: 'Colgate', value: 1 },
|
||||
{ brand: 'Godrej', value: 1 },
|
||||
{ brand: 'HUL', value: 1 },
|
||||
{ brand: 'XX', value: 0 },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
|
||||
const tabs = [
|
||||
{ id: 0, title: 'Store Info' },
|
||||
{ id: 1, title: 'Last visit details' },
|
||||
{ id: 2, title: 'Competition' },
|
||||
];
|
||||
|
||||
|
||||
const RenderHeader = ({ columns }) => {
|
||||
const colWidth = Screen.screenWidth * 0.95 / columns?.length;
|
||||
|
||||
return (
|
||||
null
|
||||
// <View style={{ flexDirection: 'row', paddingVertical: 6 }}>
|
||||
// {columns.map((col, index) => (
|
||||
// <View key={index} style={{ width: colWidth }}>
|
||||
// <Text style={styles.subheaderText}>{col.toUpperCase()}</Text>
|
||||
// </View>
|
||||
// ))}
|
||||
// </View>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const RenderItem = ({ item, columns }) => {
|
||||
const colWidth = Screen.screenWidth * 0.95 / columns?.length;
|
||||
|
||||
console.log('item------>',item);
|
||||
let col=item?.brand == 'Designation' ? [...columns[0]]:columns
|
||||
|
||||
return (
|
||||
<View>
|
||||
<View style={styles.row}>
|
||||
|
||||
{col.map((key, index) => (
|
||||
<View key={index} style={{ width: colWidth }}>
|
||||
{console.log("columns---",columns,"Designation",item)}
|
||||
<Text style={styles.name}>{item?.brand == 'Designation'? item?.name :String(item[key] ?? '')}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
<View style={[horizonalLine, { marginVertical: 4 }]} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const SectionListView = ({ listData }) => {
|
||||
const scrollRef = useRef(null); // shared horizontal scroll ref
|
||||
console.log("/-",listData)
|
||||
return (
|
||||
<FlatList
|
||||
data={listData}
|
||||
keyExtractor={(item, index) => item.section + index}
|
||||
contentContainerStyle={{ paddingBottom: 20 }}
|
||||
ItemSeparatorComponent={() => <View style={{ paddingVertical: 5 }} />}
|
||||
renderItem={({ item }) => {
|
||||
const columns = Object.keys(item.items[0] || {}).filter(
|
||||
key => item.items.some(obj => obj[key] !== undefined && obj[key] !== null)
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionTitle}>{item.section}</Text>
|
||||
<View style={[horizonalLine, { marginVertical: 10 }]} />
|
||||
|
||||
{/* Shared horizontal scroll view for header + rows */}
|
||||
<ScrollView
|
||||
horizontal
|
||||
ref={scrollRef}
|
||||
showsHorizontalScrollIndicator={false}
|
||||
scrollEventThrottle={16}
|
||||
>
|
||||
<View>
|
||||
<RenderHeader columns={columns} />
|
||||
{item.items.map((subItem, index) => (
|
||||
<RenderItem key={index} item={subItem} columns={columns} />
|
||||
))}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const StoreInfo = ({ navigation, route }) => {
|
||||
|
||||
const { storeData } = route.params || {};
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [selectedTab, setSelectedTab] = useState(0);
|
||||
const [storeInfoData, setStoreInfoData] = useState([])
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
getStoreInfo()
|
||||
}, [])
|
||||
|
||||
// const getStoreInfo = async () => {
|
||||
// setLoading(true)
|
||||
// try {
|
||||
// const params = { StoreId: storeData?.StoreId || "723" };
|
||||
// const config = {
|
||||
// method: 'post',
|
||||
// url: 'https://api1.parinaam.in/api/dabur/StoreDNAstoreInfo',
|
||||
// headers: {
|
||||
// 'api_key': '9a1f056fecb84eaf8eb4152dda22ab0501955c4f9bbe7daa8780740459fdde7a',
|
||||
// 'Content-Type': 'application/json'
|
||||
// },
|
||||
// data: params
|
||||
// };
|
||||
|
||||
// const response = await axios.request(config);
|
||||
// const res = response.data?.StoreDNAstoreInfo || {};
|
||||
|
||||
// // Flatten & transform API response into format usable by SectionListView
|
||||
// const tempData = [];
|
||||
|
||||
// Object.entries(res).forEach(([sectionTitle, dataArray]) => {
|
||||
// if (dataArray?.length > 0) {
|
||||
// const tabId = dataArray[0]?.TabId ?? 0;
|
||||
|
||||
// // Convert single object to list of { key: value } pairs
|
||||
// dataArray.forEach(item => {
|
||||
// const cleanItem = { ...item };
|
||||
// delete cleanItem.TabId;
|
||||
// delete cleanItem.TabName;
|
||||
|
||||
// const formattedItems = Object.entries(cleanItem).map(([key, value]) => ({
|
||||
// brand: key,
|
||||
// name: String(value)
|
||||
// }));
|
||||
|
||||
// tempData.push({
|
||||
// tabId,
|
||||
// section: sectionTitle.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase()),
|
||||
// items: formattedItems
|
||||
// });
|
||||
|
||||
|
||||
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// setStoreInfoData(tempData);
|
||||
// setLoading(false)
|
||||
// } catch (error) {
|
||||
// console.log("❌ store info api error:", error);
|
||||
// setLoading(false)
|
||||
// }
|
||||
// };
|
||||
|
||||
const getStoreInfo = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const params = { StoreId: storeData?.StoreId || "723" };
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: 'https://api1.parinaam.in/api/dabur/StoreDNAstoreInfo',
|
||||
headers: {
|
||||
'api_key': '9a1f056fecb84eaf8eb4152dda22ab0501955c4f9bbe7daa8780740459fdde7a',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: params
|
||||
};
|
||||
|
||||
const response = await axios.request(config);
|
||||
const res = response.data?.StoreDNAstoreInfo || {};
|
||||
|
||||
// Step 1: Flatten API data
|
||||
const tempData = [];
|
||||
|
||||
Object.entries(res).forEach(([sectionTitle, dataArray]) => {
|
||||
if (dataArray?.length > 0) {
|
||||
const tabId = dataArray[0]?.TabId ?? 0;
|
||||
let sec =sectionTitle.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase())
|
||||
dataArray.forEach(item => {
|
||||
const cleanItem = { ...item };
|
||||
delete cleanItem.TabId;
|
||||
delete cleanItem.TabName;
|
||||
|
||||
let formattedItems=[]
|
||||
if("Dabur Employee"==sec){
|
||||
console.log("tempData---14",item,sec)
|
||||
formattedItems = Object.entries(cleanItem).map(([key, value]) => ({
|
||||
brand: key,
|
||||
name: String(value)
|
||||
}));
|
||||
}else{
|
||||
formattedItems = Object.entries(cleanItem).map(([key, value]) => ({
|
||||
brand: key,
|
||||
name: String(value)
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
|
||||
tempData.push({
|
||||
tabId,
|
||||
section: sec,
|
||||
items: formattedItems
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Step 2: Group items by tabId and section
|
||||
const groupedData = {};
|
||||
|
||||
tempData.forEach(entry => {
|
||||
const key = `${entry.tabId}-${entry.section}`;
|
||||
if (!groupedData[key]) {
|
||||
groupedData[key] = {
|
||||
tabId: entry.tabId,
|
||||
section: entry.section,
|
||||
items: []
|
||||
};
|
||||
}
|
||||
groupedData[key].items.push(...entry.items);
|
||||
});
|
||||
|
||||
// let objTemp={}
|
||||
// groupedData['0-Dabur Employee']?.items
|
||||
console.log("tempData-----gD",groupedData)
|
||||
|
||||
// Step 3: Set to state
|
||||
setStoreInfoData(Object.values(groupedData));
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
console.log("❌ store info api error:", error);
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
const filteredData = Array.isArray(storeInfoData)
|
||||
? storeInfoData.filter(item => item.tabId === selectedTab)
|
||||
: [];
|
||||
const selectedTabTitle = tabs?.find(tab => tab.id === selectedTab)?.title ?? 'NA';
|
||||
|
||||
const dynamicTabs = Array.isArray(storeInfoData)
|
||||
? Array.from(new Set(storeInfoData.map(item => item.tabId))).map(id => ({
|
||||
id,
|
||||
title: tabs.find(tab => tab.id === id)?.title || `Tab ${id}`
|
||||
}))
|
||||
: [];
|
||||
|
||||
console.log("listData-----12",storeInfoData,filteredData)
|
||||
|
||||
// const getStoreInfo = async () => {
|
||||
// try {
|
||||
// const params = {
|
||||
// "StoreId": "723"
|
||||
// };
|
||||
|
||||
// const config = {
|
||||
// method: 'post',
|
||||
// url: 'https://api1.parinaam.in/api/dabur/StoreDNAstoreInfo',
|
||||
// headers: {
|
||||
// 'api_key': '9a1f056fecb84eaf8eb4152dda22ab0501955c4f9bbe7daa8780740459fdde7a',
|
||||
// 'Content-Type': 'application/json'
|
||||
// },
|
||||
// data: params
|
||||
// };
|
||||
|
||||
// const response = await axios.request(config);
|
||||
// const res = response.data?.StoreDNAstoreInfo || {};
|
||||
// console.log('GET STORE INFO ==> ', JSON.stringify(res));
|
||||
|
||||
// const allItems = res && Object.values(res).flat(); // Flattened array
|
||||
// setStoreInfoData(allItems);
|
||||
|
||||
// // Now extract TabId and TabName from array
|
||||
// const tabData = allItems.map(item => ({
|
||||
// TabId: item.TabId,
|
||||
// TabName: item.TabName
|
||||
// })).filter(item => item.TabId !== undefined && item.TabName);
|
||||
|
||||
// // Remove duplicates
|
||||
// const uniqueTabs = Array.from(
|
||||
// new Map(tabData.map(item => [`${item.TabId}-${item.TabName}`, item])).values()
|
||||
// );
|
||||
|
||||
// console.log("tabData----", tabData, uniqueTabs)
|
||||
// let NewObj = {}
|
||||
// let ourVlue = uniqueTabs.map((item, i) => {
|
||||
// NewObj[item?.TabName] = allItems?.filter((val) => val?.TabName == item?.TabName)
|
||||
// })
|
||||
|
||||
// console.log("Unique Tabs:", uniqueTabs, JSON.stringify(NewObj));
|
||||
// console.log("All Items:", JSON.stringify(allItems));
|
||||
|
||||
// } catch (error) {
|
||||
// console.log("❌ store info api error:", error);
|
||||
// }
|
||||
// };
|
||||
|
||||
const renderTabContent = () => {
|
||||
switch (selectedTab) {
|
||||
case 0:
|
||||
return <SectionListView listData={filteredData} />
|
||||
case 1:
|
||||
return <SectionListView listData={filteredData} />
|
||||
case 2:
|
||||
return <SectionListView listData={filteredData} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={[styles.container, { paddingHorizontal: 0 }]}>
|
||||
<CustomHeader
|
||||
title={'Store Info'}
|
||||
leftIcon={IMAGES.leftArrowIcon}
|
||||
onLeftPress={() => navigation.goBack()} />
|
||||
<View style={styles.container}>
|
||||
<View style={styles.tabstyle}>
|
||||
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
|
||||
<View style={{ flexDirection: 'row' }}>
|
||||
{/* {tabs?.map((tab) => ( */}
|
||||
{dynamicTabs?.map((tab) => (
|
||||
<TouchableOpacity key={tab.id} style={styles.tabview} activeOpacity={1} onPress={() => setSelectedTab(tab.id)}>
|
||||
<View style={selectedTab === tab.id ? styles.selecttabView : styles.unselecttabView}>
|
||||
<Text style={[styles.tabtext, selectedTab === tab.id ? styles.selecttabText : styles.unselecttabText]}>
|
||||
{tab.title}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
<ScrollView horizontal={false} style={{ flex: 1 }}>
|
||||
<Text style={styles.headerText}>{selectedTabTitle} </Text>
|
||||
<View style={{ width: '100%' }}>{renderTabContent()}</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
<Loader visible={loading} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
export default StoreInfo;
|
||||
>>>>>>> dabur-store-dna
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<<<<<<< HEAD
|
||||
import React, { useState , useRef} from 'react';
|
||||
import {View,Text,TouchableOpacity,ScrollView,FlatList} from 'react-native';
|
||||
import { styles } from './style';
|
||||
@@ -208,3 +209,359 @@ const StoreInfo = () => {
|
||||
};
|
||||
|
||||
export default StoreInfo;
|
||||
=======
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import { View, Text, TouchableOpacity, ScrollView, FlatList } from 'react-native';
|
||||
import { styles } from './style';
|
||||
import GlobalTheme, { horizonalLine, Screen } from '../../../theme/theme';
|
||||
import CustomHeader from '../../../components/CustomHeader';
|
||||
import IMAGES from '../../../constants/Images';
|
||||
import axios from 'axios';
|
||||
import Loader from '../../../constants/Loader';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { ApiURL } from '../../../api/ApiConstant';
|
||||
|
||||
const storeinfodata = [
|
||||
{
|
||||
tabId: 0,
|
||||
section: 'Store details',
|
||||
items: [
|
||||
{ brand: 'Store Name', name: 'Reliance Smart' },
|
||||
{ brand: 'Store ID', name: '#98440' },
|
||||
{ brand: 'Address', name: 'Rabindra Nagar, Delhi 110003' },
|
||||
{ brand: 'City', name: 'Okhla' },
|
||||
{ brand: 'Store Size', name: '1500–2000 sq ft' },
|
||||
{ brand: 'Average Footfall', name: '10000' },
|
||||
{ brand: 'Store age', name: '8' },
|
||||
{ brand: 'Store Ranking', name: '24' },
|
||||
],
|
||||
},
|
||||
{
|
||||
tabId: 0,
|
||||
section: 'Dabur Employees',
|
||||
items: [
|
||||
{ brand: 'RKAM', name: 'Rajesh Paal Singh' },
|
||||
{ brand: 'SO', name: 'Soniya Singhal' },
|
||||
],
|
||||
},
|
||||
{
|
||||
tabId: 0,
|
||||
section: '3P employees',
|
||||
items: [
|
||||
{ brand: 'Promoter Name', name: 'Payal Singh' },
|
||||
{ brand: 'AM Name', name: 'Soniya Singhal' },
|
||||
{ brand: 'Supervisor Name', name: 'Soniya Dhankar' },
|
||||
{ brand: 'City', name: 'Okhla' },
|
||||
{ brand: 'Promoter duration', name: '2 Year 7 months' },
|
||||
{ brand: 'Average incentive', name: '5000' },
|
||||
],
|
||||
},
|
||||
|
||||
// Last Visit Details (tabId: 1)
|
||||
{
|
||||
tabId: 1,
|
||||
section: 'Dabur employee',
|
||||
items: [
|
||||
{ brand: 'SO', name: 'Rajesh Paal Singh', date: '23/05/2025', test: 'gxsjhxbas' },
|
||||
{ brand: 'AH', name: 'Umesh Singh', date: '18/04/2025' },
|
||||
{ brand: 'KAM', name: 'Rahul Tawde', date: '15/05/2025' },
|
||||
{ brand: 'Others', name: 'Singhal Singh', date: '06/05/2025' },
|
||||
],
|
||||
},
|
||||
{
|
||||
tabId: 1,
|
||||
section: '3P team',
|
||||
items: [
|
||||
{ brand: 'Supervisor', name: 'Ashish Talwar', date: '27/05/2025' },
|
||||
{ brand: 'AM', name: 'Soniya Singhal', date: '23/05/2025' },
|
||||
],
|
||||
},
|
||||
|
||||
// Competition (tabId: 2)
|
||||
{
|
||||
tabId: 2,
|
||||
section: 'Competition assets',
|
||||
items: [
|
||||
{ brand: 'Marico', value: 5 },
|
||||
{ brand: 'Colgate', value: 1 },
|
||||
{ brand: 'Godrej', value: 2 },
|
||||
{ brand: 'HUL', value: 1 },
|
||||
{ brand: 'XX', value: 2 },
|
||||
],
|
||||
},
|
||||
{
|
||||
tabId: 2,
|
||||
section: 'Promoter details',
|
||||
items: [
|
||||
{ brand: 'Marico', value: 1 },
|
||||
{ brand: 'Colgate', value: 1 },
|
||||
{ brand: 'Godrej', value: 1 },
|
||||
{ brand: 'HUL', value: 1 },
|
||||
{ brand: 'XX', value: 0 },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
|
||||
const tabs = [
|
||||
{ id: 0, title: 'Store Info' },
|
||||
{ id: 1, title: 'Last visit details' },
|
||||
{ id: 2, title: 'Competition' },
|
||||
];
|
||||
|
||||
|
||||
const RenderHeader = ({ columns }) => {
|
||||
const colWidth = Screen.screenWidth * 0.95 / columns?.length;
|
||||
|
||||
return (
|
||||
null
|
||||
// <View style={{ flexDirection: 'row', paddingVertical: 6 }}>
|
||||
// {columns.map((col, index) => (
|
||||
// <View key={index} style={{ width: colWidth }}>
|
||||
// <Text style={styles.subheaderText}>{col.toUpperCase()}</Text>
|
||||
// </View>
|
||||
// ))}
|
||||
// </View>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const RenderItem = ({ item, columns }) => {
|
||||
const colWidth = Screen.screenWidth * 0.95 / columns?.length;
|
||||
|
||||
return (
|
||||
<View>
|
||||
<View style={styles.row}>
|
||||
{columns.map((key, index) => (
|
||||
<View key={index} style={{ width: colWidth }}>
|
||||
<Text style={styles.name}>{String(item[key] ?? '')}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
<View style={[horizonalLine, { marginVertical: 4 }]} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const SectionListView = ({ listData }) => {
|
||||
const scrollRef = useRef(null); // shared horizontal scroll ref
|
||||
console.log("/-", listData)
|
||||
return (
|
||||
<FlatList
|
||||
data={listData}
|
||||
keyExtractor={(item, index) => item.section + index}
|
||||
contentContainerStyle={{ paddingBottom: 20 }}
|
||||
ItemSeparatorComponent={() => <View style={{ paddingVertical: 5 }} />}
|
||||
renderItem={({ item }) => {
|
||||
const columns = Object.keys(item.items[0] || {}).filter(
|
||||
key => item.items.some(obj => obj[key] !== undefined && obj[key] !== null)
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{!item.hideSectionTitle && (
|
||||
<>
|
||||
<Text style={styles.sectionTitle}>{item.section}</Text>
|
||||
{/* <View style={[horizonalLine, { marginVertical: 10 }]} /> */}
|
||||
</>
|
||||
)}
|
||||
<View style={styles.section}>
|
||||
<ScrollView
|
||||
horizontal
|
||||
ref={scrollRef}
|
||||
showsHorizontalScrollIndicator={false}
|
||||
scrollEventThrottle={16}
|
||||
>
|
||||
<View>
|
||||
<RenderHeader columns={columns} />
|
||||
{item.items.map((subItem, index) => (
|
||||
<RenderItem key={index} item={subItem} columns={columns} />
|
||||
))}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const StoreInfo = ({ navigation, route }) => {
|
||||
|
||||
const { storeData } = route.params || {};
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [selectedTab, setSelectedTab] = useState(0);
|
||||
const [storeInfoData, setStoreInfoData] = useState([])
|
||||
|
||||
useEffect(() => {
|
||||
getStoreInfo()
|
||||
}, [])
|
||||
|
||||
const getStoreInfo = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const params = { StoreId: storeData?.StoreId || "723" };
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: ApiURL.storeInfo,
|
||||
headers: {
|
||||
'api_key': '9a1f056fecb84eaf8eb4152dda22ab0501955c4f9bbe7daa8780740459fdde7a',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: params
|
||||
};
|
||||
|
||||
const response = await axios.request(config);
|
||||
const res = response.data?.StoreDNAstoreInfo || {};
|
||||
|
||||
// Step 1: Flatten API data
|
||||
const tempData = [];
|
||||
|
||||
Object.entries(res).forEach(([sectionTitle, dataArray]) => {
|
||||
if (dataArray?.length > 0) {
|
||||
const tabId = dataArray[0]?.TabId ?? 0;
|
||||
|
||||
dataArray.forEach(item => {
|
||||
const cleanItem = { ...item };
|
||||
delete cleanItem.TabId;
|
||||
delete cleanItem.TabName;
|
||||
console.log("tempData---", item)
|
||||
const formattedItems = Object.entries(cleanItem).map(([key, value]) => ({
|
||||
brand: key,
|
||||
name: String(value)
|
||||
}));
|
||||
|
||||
|
||||
tempData.push({
|
||||
tabId,
|
||||
section: sectionTitle.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase()),
|
||||
items: formattedItems
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Step 2: Group items by tabId and section
|
||||
// const groupedData = {};
|
||||
// tempData.forEach(entry => {
|
||||
// const key = `${entry.tabId}-${entry.section}`;
|
||||
// if (!groupedData[key]) {
|
||||
// groupedData[key] = {
|
||||
// tabId: entry.tabId,
|
||||
// section: entry.section,
|
||||
// items: []
|
||||
// };
|
||||
// }
|
||||
// groupedData[key].items.push(...entry.items);
|
||||
// });
|
||||
|
||||
// 👇 Replace Step 2 with this
|
||||
const groupedData = {};
|
||||
let threePEmployeeCount = 0;
|
||||
|
||||
tempData.forEach(entry => {
|
||||
if (entry.section === "3P Employee") {
|
||||
// increment counter
|
||||
threePEmployeeCount += 1;
|
||||
const uniqueKey = `${entry.tabId}-${entry.section}-${Math.random()}`;
|
||||
groupedData[uniqueKey] = {
|
||||
tabId: entry.tabId,
|
||||
section: entry.section,
|
||||
items: entry.items,
|
||||
hideSectionTitle: threePEmployeeCount > 1 // 👈 hide title after first card
|
||||
};
|
||||
} else {
|
||||
const key = `${entry.tabId}-${entry.section}`;
|
||||
if (!groupedData[key]) {
|
||||
groupedData[key] = {
|
||||
tabId: entry.tabId,
|
||||
section: entry.section,
|
||||
items: []
|
||||
};
|
||||
}
|
||||
groupedData[key].items.push(...entry.items);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
// let objTemp={}
|
||||
// groupedData['0-Dabur Employee']?.items
|
||||
|
||||
|
||||
// Step 3: Set to state
|
||||
setStoreInfoData(Object.values(groupedData));
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
console.log("❌ store info api error:", error);
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const filteredData = Array.isArray(storeInfoData)
|
||||
? storeInfoData.filter(item => item.tabId === selectedTab)
|
||||
: [];
|
||||
const selectedTabTitle = tabs?.find(tab => tab.id === selectedTab)?.title ?? 'NA';
|
||||
|
||||
const dynamicTabs = Array.isArray(storeInfoData)
|
||||
? Array.from(new Set(storeInfoData.map(item => item.tabId))).map(id => ({
|
||||
id,
|
||||
title: tabs.find(tab => tab.id === id)?.title || `Tab ${id}`
|
||||
}))
|
||||
: [];
|
||||
|
||||
const renderTabContent = () => {
|
||||
switch (selectedTab) {
|
||||
case 0:
|
||||
return <SectionListView listData={filteredData} />
|
||||
case 1:
|
||||
return <SectionListView listData={filteredData} />
|
||||
case 2:
|
||||
return <SectionListView listData={filteredData} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
<SafeAreaView style={{ flex: 1, backgroundColor: GlobalTheme.colors.primary }}>
|
||||
<View style={[styles.container, { paddingHorizontal: 0 }]}>
|
||||
<CustomHeader
|
||||
title={'Store Info'}
|
||||
leftIcon={IMAGES.leftArrowIcon}
|
||||
onLeftPress={() => navigation.goBack()} />
|
||||
<View style={styles.container}>
|
||||
<View style={styles.tabstyle}>
|
||||
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
|
||||
<View style={{ flexDirection: 'row' }}>
|
||||
{/* {tabs?.map((tab) => ( */}
|
||||
{dynamicTabs?.map((tab) => (
|
||||
<TouchableOpacity key={tab.id} style={styles.tabview} activeOpacity={1} onPress={() => setSelectedTab(tab.id)}>
|
||||
<View style={selectedTab === tab.id ? styles.selecttabView : styles.unselecttabView}>
|
||||
<Text style={[styles.tabtext, selectedTab === tab.id ? styles.selecttabText : styles.unselecttabText]}>
|
||||
{tab.title}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
<ScrollView horizontal={false} style={{ flex: 1 }}>
|
||||
{/* <Text style={styles.headerText}>{selectedTabTitle} </Text> */}
|
||||
<View style={{ width: '100%', marginTop: 20, }}>{renderTabContent()}</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
<Loader visible={loading} />
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
export default StoreInfo;
|
||||
>>>>>>> dabur-store-dna
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<<<<<<< HEAD
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import { GlobalTheme, Screen, shadow } from '../../../theme';
|
||||
@@ -109,3 +110,123 @@ export const styles = StyleSheet.create({
|
||||
}
|
||||
|
||||
});
|
||||
=======
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import { GlobalTheme, Screen, shadow } from '../../../theme';
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: GlobalTheme.colors.white,
|
||||
paddingHorizontal: 10
|
||||
},
|
||||
// tabs
|
||||
tabview: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
marginVertical: 10,
|
||||
flexDirection: 'row',
|
||||
},
|
||||
tabstyle: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
borderColor: GlobalTheme.colors.lightblue,
|
||||
borderWidth: 1.5,
|
||||
borderRadius: GlobalTheme.borderRadius.xxlg,
|
||||
marginTop: 10,
|
||||
paddingHorizontal: 10,
|
||||
},
|
||||
tabtext: {
|
||||
overflow: 'hidden',
|
||||
color:'#000'
|
||||
},
|
||||
selecttabView: {
|
||||
backgroundColor: GlobalTheme.colors.primary,
|
||||
paddingVertical: 8,
|
||||
paddingHorizontal: 15,
|
||||
borderRadius: GlobalTheme.borderRadius.lgg
|
||||
},
|
||||
selecttabText: {
|
||||
color: GlobalTheme.colors.white,
|
||||
fontSize: GlobalTheme.typography.fontSize.small,
|
||||
fontWeight: GlobalTheme.typography.fontWeight.regular,
|
||||
textAlign: 'center'
|
||||
},
|
||||
unselecttabView: {
|
||||
paddingVertical: 8,
|
||||
paddingHorizontal: 15,
|
||||
borderRadius: GlobalTheme.borderRadius.md
|
||||
},
|
||||
unselecttabText: {
|
||||
color: GlobalTheme.colors.lightbluetext,
|
||||
fontSize: GlobalTheme.typography.fontSize.xsmall,
|
||||
fontWeight: GlobalTheme.typography.fontWeight.regular,
|
||||
textAlign: 'center'
|
||||
},
|
||||
// comp
|
||||
section: {
|
||||
backgroundColor: GlobalTheme.colors.white,
|
||||
padding: 12,
|
||||
marginHorizontal: 5,
|
||||
borderRadius: 8,
|
||||
elevation: 2,
|
||||
width: Screen.screenWidth * 0.92,
|
||||
marginVertical: 5,
|
||||
borderWidth: 0.5,
|
||||
borderColor: 'gray',
|
||||
marginBottom:15,
|
||||
marginTop:10,
|
||||
// ...shadow,
|
||||
|
||||
},
|
||||
sectionTitle: {
|
||||
color:'#000',
|
||||
fontWeight: GlobalTheme.typography.fontWeight.bold,
|
||||
fontSize: GlobalTheme.typography.fontSize.small,
|
||||
marginHorizontal:10
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
paddingVertical: 4
|
||||
},
|
||||
brand: {
|
||||
fontSize: GlobalTheme.typography.fontSize.xsmall,
|
||||
color: GlobalTheme.colors.black,
|
||||
fontWeight: GlobalTheme.typography.fontWeight.medium,
|
||||
},
|
||||
value: {
|
||||
fontSize: GlobalTheme.typography.fontSize.xsmall,
|
||||
fontWeight: GlobalTheme.typography.fontWeight.medium,
|
||||
},
|
||||
name: {
|
||||
fontSize: GlobalTheme.typography.fontSize.xsmall,
|
||||
fontWeight: GlobalTheme.typography.fontWeight.regular,
|
||||
flexWrap:'wrap',
|
||||
color:'#000'
|
||||
|
||||
},
|
||||
date: {
|
||||
fontSize: GlobalTheme.typography.fontSize.xsmall,
|
||||
fontWeight: GlobalTheme.typography.fontWeight.regular,
|
||||
flexWrap:'wrap'
|
||||
},
|
||||
subheaderText:{
|
||||
fontSize: GlobalTheme.typography.fontSize.xsmall,
|
||||
fontWeight: GlobalTheme.typography.fontWeight.regular,
|
||||
flexWrap:'wrap',
|
||||
color : GlobalTheme.colors.gray,
|
||||
textTransform: 'capitalize',
|
||||
},
|
||||
headerText:{
|
||||
fontSize: GlobalTheme.typography.fontSize.medium,
|
||||
fontWeight: GlobalTheme.typography.fontWeight.medium,
|
||||
flexWrap:'wrap',
|
||||
color : GlobalTheme.colors.black,
|
||||
paddingVertical:10,
|
||||
paddingHorizontal:10
|
||||
}
|
||||
|
||||
});
|
||||
>>>>>>> dabur-store-dna
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import { View, Text, ImageBackground, Image, TouchableOpacity } from 'react-native';
|
||||
import IMAGES from '../../../constants/Images';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { styles } from './style';
|
||||
|
||||
const Welcome = ({ navigation }) => {
|
||||
|
||||
const goToDashboard=()=>{
|
||||
navigation.reset({ index: 0, routes: [{ name: 'Dashboard' }] })
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ImageBackground source={IMAGES.WelcomeBackground} style={styles.background} resizeMode='contain'>
|
||||
<View style={styles.content}>
|
||||
<Image source={IMAGES.Welcomelogo} style={styles.illustration} />
|
||||
<Text style={styles.title}>Welcome to {"\n"} Performics Store DNA</Text>
|
||||
<Text style={styles.subtitle}>Get quick access to store feedback and performance reports.</Text>
|
||||
<TouchableOpacity style={styles.button} onPress={() => goToDashboard()} >
|
||||
<Text style={styles.buttonText}>Continue</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</ImageBackground>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
export default Welcome;
|
||||
@@ -0,0 +1,61 @@
|
||||
import { Dimensions, StyleSheet } from 'react-native';
|
||||
|
||||
import { GlobalTheme, Screen, shadow } from '../../../theme';
|
||||
|
||||
|
||||
const { width, height } = Dimensions.get('window');
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
containermain: {
|
||||
flex: 1,
|
||||
// backgroundColor: 'red',
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
|
||||
},
|
||||
background: {
|
||||
flex: 1,
|
||||
},
|
||||
content: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: 20,
|
||||
|
||||
},
|
||||
illustration: {
|
||||
width: 200,
|
||||
height: 200,
|
||||
marginBottom: 30,
|
||||
resizeMode:"contain"
|
||||
},
|
||||
title: {
|
||||
fontSize: GlobalTheme.typography.fontSize.large,
|
||||
fontWeight: 'bold',
|
||||
color: GlobalTheme.colors.primary,
|
||||
marginBottom: 10,
|
||||
textAlign: 'center',
|
||||
},
|
||||
subtitle: {
|
||||
fontSize: 14,
|
||||
color: GlobalTheme.colors.primary,
|
||||
textAlign: 'center',
|
||||
marginBottom: 30,
|
||||
paddingHorizontal: 10,
|
||||
},
|
||||
button: {
|
||||
backgroundColor: GlobalTheme.colors.white,
|
||||
paddingVertical: 12,
|
||||
paddingHorizontal: 30,
|
||||
borderRadius: 30,
|
||||
borderColor:'#91A2CB',
|
||||
borderWidth:1
|
||||
},
|
||||
buttonText: {
|
||||
color: GlobalTheme.colors.primary,
|
||||
fontSize: GlobalTheme.typography.fontSize.xsmall,
|
||||
// fontWeight: '600',
|
||||
},
|
||||
|
||||
})
|
||||
Reference in New Issue
Block a user