Store Info Updated

This commit is contained in:
CPM
2025-08-07 13:38:34 +05:30
parent 5a910f62e2
commit 2280bd6d19
16 changed files with 1642 additions and 1689 deletions
+79 -75
View File
@@ -6,90 +6,94 @@ import { useDispatch } from 'react-redux';
import { setUser } from '../../../redux/slices/userSlice';
const SplashScreen = ({ navigation }) => {
const dispatch = useDispatch();
const dispatch = useDispatch();
useEffect(() => {
checkLoginStatus();
}, []);
useEffect(() => {
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));
navigation.reset({
index: 0,
routes: [{ name: 'Welcome' }],
});
} else {
navigation.reset({
index: 0,
routes: [{ name: 'Login' }],
});
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);
}
} catch (error) {
console.error('Error checking login status:', error);
}
};
checkLoginStatus();
}, []);
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>
);
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
},
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
},
});
+45 -153
View File
@@ -231,12 +231,6 @@ const Dashboard = (props) => {
setTabCache({}); // reset cache when filters change
}, [month, year]);
// useEffect(() => {
// if (mainDisplayJson && storeData?.StoreId) {
// getTabData(mainDisplayJson);
// }
// }, [mainTabIndex, storeData]);
useEffect(() => {
if (mainDisplayJson && storeData?.StoreId) {
setTimeout(() => getTabData(mainDisplayJson), 0);
@@ -257,14 +251,9 @@ const Dashboard = (props) => {
return;
}
const escape = str => (str || '').toString().replace(/'/g, "''");
db.transaction(tx => {
data_arr.forEach(item => {
const { StoreId, StoreName, ChainName, Address, Pincode, StateName, StoreType, CityName } = item;
// First, check if the StoreId exists
tx.executeSql(
`SELECT * FROM StoreInfoDNALocal WHERE StoreId = ?`,
[StoreId],
@@ -275,8 +264,6 @@ const Dashboard = (props) => {
INSERT INTO StoreInfoDNALocal
(VISIT_DATE, StoreId, StoreName, ChainName, Address, Pincode, CityName, StateName, StoreType, UPLOAD_STATUS)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
tx.executeSql(sql, [
d2,
StoreId,
@@ -335,47 +322,6 @@ const Dashboard = (props) => {
});
};
// const getTabData = async (tabData) => {
// setLoading(true)
// try {
// const params = {
// parameters: {
// projectid: 41654,
// year: year,
// monthno: month,
// storeid: storeData?.StoreId
// }
// };
// const graphDetails = tabData?.graphDetails || [];
// const uniqueUrls = [...new Set(graphDetails.map(graph => graph.GraphUrl))];
// const apiCalls = uniqueUrls.map(url => {
// const config = {
// method: 'post',
// url: url, // each URL from the list
// headers: {
// 'X-API-Key': 'f7fa9b09-ced8-4862-8cb7-5e7599d90fa2',
// 'Content-Type': 'application/json'
// },
// data: params
// };
// return axios.request(config);
// });
// const results = await Promise.all(apiCalls);
// const dataMap = {};
// uniqueUrls.forEach((url, idx) => {
// dataMap[url] = results[idx].data; // collect raw API response
// });
// setGraphApiData(dataMap);
// setLoading(false)
// } catch (err) {
// console.log("❌ Error fetching tab data:", err);
// }
// };
// 🔧 Optimized getTabData with caching logic added
const getTabData = async (tabData) => {
if (!storeData?.StoreId) return;
@@ -400,23 +346,8 @@ const Dashboard = (props) => {
console.log("🔁 API Params:", params);
const graphDetails = tabData?.graphDetails || [];
const uniqueUrls = [...new Set(graphDetails.map(graph => graph.GraphUrl))];
// const apiCalls = uniqueUrls.map(url => {
// const config = {
// method: 'post',
// url: url,
// headers: {
// 'X-API-Key': 'f7fa9b09-ced8-4862-8cb7-5e7599d90fa2',
// 'Content-Type': 'application/json'
// },
// data: params
// };
// return axios.request(config);
// });
const apiCalls = uniqueUrls.map(async url => {
const config = {
method: 'post',
@@ -430,15 +361,10 @@ const Dashboard = (props) => {
return await fetchWithRetry(config);
});
const results = await Promise.all(apiCalls);
console.log("📊 API Results:", results.map(r => r?.data));
const dataMap = {};
// uniqueUrls.forEach((url, idx) => {
// dataMap[url] = results[idx].data;
// });
uniqueUrls.forEach((url, idx) => {
const responseData = results[idx]?.data;
if (!responseData || !responseData.data || responseData.data.length === 0) {
@@ -447,8 +373,6 @@ const Dashboard = (props) => {
}
dataMap[url] = responseData;
});
console.log('uniqueUrls-dataMap---------->', dataMap);
setGraphApiData(dataMap);
setTabCache(prev => ({ ...prev, [tabKey]: dataMap }));
@@ -459,7 +383,6 @@ const Dashboard = (props) => {
}
};
const fetchWithRetry = async (config, retries = 2, delay = 1000) => {
for (let i = 0; i <= retries; i++) {
try {
@@ -477,8 +400,6 @@ const Dashboard = (props) => {
return null; // all attempts failed
};
const fetchDetailGraphs = async (detailPages) => {
try {
const resultMap = {};
@@ -501,7 +422,6 @@ const Dashboard = (props) => {
}
};
const handleScroll = (event) => {
const offsetY = event.nativeEvent.contentOffset.y;
setShowButton(offsetY > 0); // Show button only if not at the top
@@ -567,7 +487,7 @@ const Dashboard = (props) => {
console.log('state--', state, city);
console.log('searchText--', searchText);
setSearchResult(!searchResult)
// setSearchResult(!searchResult)
setLoading(true)
try {
const params = JSON.stringify({
@@ -577,6 +497,9 @@ const Dashboard = (props) => {
"StoreSearchText": searchText ? searchText : "",
"UserId": userId || 0,
});
console.log('params---->', params);
const config = {
method: 'post',
@@ -604,18 +527,11 @@ const Dashboard = (props) => {
const renderItem = ({ item }) => {
const apiData = graphApiData[item.GraphUrl];
// const values = apiData?.data || [];
const values = apiData?.data?.length ? apiData.data : [];
const scoreValue = values.length > 0 ? Object.values(values[0])[0] : null;
// <Text>{scoreValue !== undefined ? `${scoreValue.toFixed(1)}%` : "No Data"}</Text>
console.log('apiData --->', apiData);
if (apiData?.status === 'error') {
return (
<View style={styles.percentBox}>
@@ -625,15 +541,6 @@ const Dashboard = (props) => {
);
}
// if (!apiData) {
// return (
// <View style={[styles.percentBox, { justifyContent: 'center', alignItems: 'center' }]}>
// <ActivityIndicator size="small" color="#113F8C" />
// </View>
// );
// }
switch (item.GraphType) {
case "ScoreCard":
const firstDataObj = values[0] || {};
@@ -650,7 +557,7 @@ const Dashboard = (props) => {
//GIFTED CHART LIBRARY -----
case "BarGraph":
const chartWidth = screenWidth * 0.75;
const chartWidth = screenWidth * 0.80;
const barWidth = 40;
const barColors = ['#1BF2E0', '#1B7BF2', '#1BC0F2'];
@@ -675,7 +582,7 @@ const Dashboard = (props) => {
}
return (
<View style={{ alignItems: 'center', justifyContent: 'center', padding: 10, borderWidth: 0.5, borderRadius: 10, }}>
<View style={{ width: '100%', alignItems: 'center', justifyContent: 'center', padding: 10, borderWidth: 0.5, borderRadius: 25, }}>
{/* <View style={{ alignSelf: 'center', borderWidth: 0.5,borderRadius:20, paddingBottom: 10 }}> */}
<Text style={{ fontSize: 16, fontWeight: '600', marginBottom: 10 }}>
@@ -800,7 +707,6 @@ const Dashboard = (props) => {
}, 300), []);
const feedbackCount = visitedStoreData1?.filter(item => item?.UPLOAD_STATUS == 'U')?.length;
const filteredStores = storeList.filter((store) => {
const query = searchQuery.toLowerCase();
return (
@@ -904,14 +810,13 @@ const Dashboard = (props) => {
onRightPress={() => setFeedBackModal(true)}
/>
{/* Store Name Card */}
<View style={styles.row}>
<View style={styles.selectedStoreText}>
{/* <Text style={[styles.storeNameText, { width: '90%' }]}> {`${storeData?.StoreName} \n(Store Id :${storeData?.StoreId})`}</Text> */}
<View style={{ width: '90%' }}>
<View style={{ width: '88%' }}>
<Text style={[styles.storeNameText, {}]}>{storeData?.StoreName}</Text>
<Text style={{ color: GlobalTheme.colors.gray, fontSize: 13 }}>Store Id : {storeData?.StoreId}</Text>
</View>
<Text style={{}}></Text>
<TouchableOpacity onPress={() => openBottomSheet()} style={styles.filterIcon}>
<Image source={IMAGES.filterIcon} style={{ height: 18, width: 18 }} />
</TouchableOpacity>
@@ -960,7 +865,6 @@ const Dashboard = (props) => {
<View style={styles.seperator} />
{/* Main Tab */}
<View style={{ flexDirection: 'row' }}>
{mainTabs.map((tab, index) => {
const isSelected = index === mainTabIndex;
@@ -1014,8 +918,7 @@ const Dashboard = (props) => {
{/* Score Card */}
<View style={{ margin: 5 }}>
<View style={{ marginHorizontal: 5 }}>
<View style={{ marginHorizontal: 5, marginTop: 5 }}>
{firstItem && (
<TouchableOpacity
activeOpacity={0.8}
@@ -1027,16 +930,7 @@ const Dashboard = (props) => {
}
}}
>
<View
style={[
styles.percentBox,
{
backgroundColor: "#C3D7FF",
width: '100%',
elevation: 0,
},
]}
>
<View style={{ width: '48%', height: 100, minHeight: 100, borderRadius: 20, justifyContent: 'center', alignItems: 'center', backgroundColor: "#C3D7FF", width: '100%', elevation: 0, }} >
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<View style={{ width: '80%', alignItems: 'center' }}>
<Text style={styles.boxText}>{firstItem.GraphTitle}</Text>
@@ -1286,7 +1180,7 @@ const Dashboard = (props) => {
<View style={[styles.row, {}]}>
<Text style={styles.dropHeaderText}>State</Text>
<Text style={styles.dropHeaderText}> City</Text>
<Text style={styles.dropHeaderText}> ASM Area</Text>
{/* <Text style={styles.dropHeaderText}> ASM Area</Text> */}
</View>
{/* Dropdown */}
@@ -1340,9 +1234,9 @@ const Dashboard = (props) => {
const uniqueAsms = Array.from(new Map(asms.map(a => [a.value, a])).values());
setCityOptions(uniqueCities);
setAsmOptions(uniqueAsms);
// setAsmOptions(uniqueAsms);
setCity(null); // reset
setAsmArea(null); // reset
// setAsmArea(null); // reset
}}
containerStyle={{ flex: 1 }}
/>
@@ -1356,12 +1250,12 @@ const Dashboard = (props) => {
/>
{/* ASM Area Dropdown */}
<CustomDropdown
{/* <CustomDropdown
data={asmOptions}
value={asmArea}
onChange={(item) => setAsmArea(item.value)}
containerStyle={{ flex: 1 }}
/>
/> */}
</View>
@@ -1382,38 +1276,38 @@ const Dashboard = (props) => {
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 }}>{storeList ? storeList.length : 0} Store</Text> */}
<Text style={{ color: '#000', fontSize: 14 }}>{filteredStores.length} Store{filteredStores.length !== 1 ? 's' : ''}</Text>
</View>
<View style={styles.searchByID}>
<Image source={IMAGES.searchIcon} style={{ height: 15, width: 15 }} />
<TextInput
placeholder="Search by Store Name or Store ID"
placeholderTextColor={'gray'}
value={searchQuery}
onChangeText={setSearchQuery}
style={{ color: '#000', marginLeft: 5, height: 38, width: '95%' }}
/>
</View>
{filteredStores && filteredStores.length > 0 ? filteredStores.map((store) => (
<TouchableOpacity onPress={() => onSelectStore(store)}
key={store.StoreId} style={styles.storeCard}>
<Text style={styles.cardTextBold}>{store.StoreName}</Text>
<Text style={styles.cardText}>{store.Address}</Text>
<Text style={styles.cardText}>{'Store Id:'} {store.StoreId}</Text>
</TouchableOpacity>
)) : null
}
<View style={{ marginBottom: 70 }}>
<View style={{ marginTop: 20 }}>
{/* <Text style={{ color: '#000', fontSize: 14 }}>{storeList ? storeList.length : 0} Store</Text> */}
<Text style={{ color: '#000', fontSize: 14 }}>{filteredStores.length} Store{filteredStores.length !== 1 ? 's' : ''}</Text>
</View>
: null
}
<View style={styles.searchByID}>
<Image source={IMAGES.searchIcon} style={{ height: 15, width: 15 }} />
<TextInput
placeholder="Search by Store Name or Store ID"
placeholderTextColor={'gray'}
value={searchQuery}
onChangeText={setSearchQuery}
style={{ color: '#000', marginLeft: 5, height: 38, width: '95%' }}
/>
</View>
{filteredStores && filteredStores.length > 0 ? filteredStores.map((store) => (
<TouchableOpacity onPress={() => onSelectStore(store)}
key={store.StoreId} style={styles.storeCard}>
<Text style={styles.cardTextBold}>{store.StoreName}</Text>
<Text style={styles.cardText}>{store.Address}</Text>
<Text style={styles.cardText}>{'Store Id:'} {store.StoreId}</Text>
</TouchableOpacity>
))
: null
}
</View>
</View>
@@ -1436,5 +1330,3 @@ const Dashboard = (props) => {
}
export default Dashboard
@@ -17,12 +17,12 @@
"TabRow": 1,
"TabCol": 2
},
{
"TabId": 3,
"TabName": "SOS Compliance",
"TabRow": 1,
"TabCol": 3
},
// {
// "TabId": 3,
// "TabName": "SOS Compliance",
// "TabRow": 1,
// "TabCol": 3
// },
{
"TabId": 4,
"TabName": "OSA",
@@ -61,15 +61,15 @@
"GraphBackground": "#E2C8FE",
"GraphOptions": {}
},
{
"TabId": 1,
"GraphId": 3,
"GraphType": "ScoreCard",
"GraphTitle": "SOS Compliance",
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/SOS_Compliance_Perc",
"GraphBackground": "#FFD7C3",
"GraphOptions": {}
},
// {
// "TabId": 1,
// "GraphId": 3,
// "GraphType": "ScoreCard",
// "GraphTitle": "SOS Compliance",
// "GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/SOS_Compliance_Perc",
// "GraphBackground": "#FFD7C3",
// "GraphOptions": {}
// },
{
"TabId": 1,
"GraphId": 4,
@@ -193,7 +193,7 @@
"TabId": 5,
"GraphId": 5,
"GraphType": "Table",
"GraphTitle": "Asset Availability",
"GraphTitle": "Visibility",
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/asset_availability_mtd",
"GraphBackground": "#ECFFFA",
"GraphOptions": {}
@@ -202,7 +202,7 @@
"TabId": 5,
"GraphId": 5,
"GraphType": "Table",
"GraphTitle": "Asset",
"GraphTitle": "Additional Visibility",
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/additional_visibility_mtd",
"GraphBackground": "#ECFFFA",
"GraphOptions": {}
@@ -232,7 +232,7 @@
"TabId": 3,
"GraphId": 3,
"GraphType": "Table",
"GraphTitle": "SOS Compliance - Category",
"GraphTitle": "OSA - Category",
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/osa_perc_on_category",
"GraphBackground": "#ECFFFA",
"GraphOptions": {}
@@ -298,12 +298,12 @@
"TabRow": 1,
"TabCol": 2
},
{
"TabId": 3,
"TabName": "SOS Compliance",
"TabRow": 1,
"TabCol": 3
},
// {
// "TabId": 3,
// "TabName": "SOS Compliance",
// "TabRow": 1,
// "TabCol": 3
// },
{
"TabId": 4,
"TabName": "OSA",
@@ -342,15 +342,15 @@
"GraphBackground": "#E2C8FE",
"GraphOptions": {}
},
{
"TabId": 1,
"GraphId": 3,
"GraphType": "ScoreCard",
"GraphTitle": "SOS Compliance",
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/sos_compliance_lsv_perc",
"GraphBackground": "#FFD7C3",
"GraphOptions": {}
},
// {
// "TabId": 1,
// "GraphId": 3,
// "GraphType": "ScoreCard",
// "GraphTitle": "SOS Compliance",
// "GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/sos_compliance_lsv_perc",
// "GraphBackground": "#FFD7C3",
// "GraphOptions": {}
// },
{
"TabId": 1,
"GraphId": 4,
+14 -3
View File
@@ -146,7 +146,7 @@ export const styles = StyleSheet.create({
fontWeight: '400'
},
dropHeaderText: {
width: '33%',
width: '50%',
color: '#000',
fontWeight: '400',
fontSize: 14
@@ -202,7 +202,7 @@ export const styles = StyleSheet.create({
},
filterIcon: {
backgroundColor: '#D8E3F1',
padding: 3,
padding: 5,
borderRadius: 5
},
storeInfoText: {
@@ -217,9 +217,20 @@ export const styles = StyleSheet.create({
minHeight: 100,
backgroundColor: '#EAF1FF',
borderRadius: 20,
elevation: 2,
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',
+300 -259
View File
@@ -9,311 +9,352 @@ import Loader from '../../../constants/Loader';
import { SafeAreaView } from 'react-native-safe-area-context';
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: '15002000 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' },
],
},
{
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: '15002000 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' },
],
},
// 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 },
],
},
// 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' },
{ 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;
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>
);
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;
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>
))}
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>
<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)
);
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 }]} />
return (
<>
{!item.hideSectionTitle && (
<>
<Text style={styles.sectionTitle}>{item.section}</Text>
{/* <View style={[horizonalLine, { marginVertical: 10 }]} /> */}
</>
)}
<View style={styles.section}>
{/* ✅ Only show title if not hidden */}
{/* 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>
);
}}
/>
);
{/* <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([])
const { storeData } = route.params || {};
const [loading, setLoading] = useState(false)
const [selectedTab, setSelectedTab] = useState(0);
const [storeInfoData, setStoreInfoData] = useState([])
useEffect(() => {
getStoreInfo()
}, [])
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 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 || {};
const response = await axios.request(config);
const res = response.data?.StoreDNAstoreInfo || {};
// Step 1: Flatten API data
const tempData = [];
// Step 1: Flatten API data
const tempData = [];
Object.entries(res).forEach(([sectionTitle, dataArray]) => {
if (dataArray?.length > 0) {
const tabId = dataArray[0]?.TabId ?? 0;
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)
}));
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
});
});
}
});
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 = {};
// 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);
// });
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;
// let objTemp={}
// groupedData['0-Dabur Employee']?.items
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);
}
});
// 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}`
}))
: [];
// let objTemp={}
// groupedData['0-Dabur Employee']?.items
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 (
// Step 3: Set to state
setStoreInfoData(Object.values(groupedData));
setLoading(false);
} catch (error) {
console.log("❌ store info api error:", error);
setLoading(false);
}
};
<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%' }}>{renderTabContent()}</View>
</ScrollView>
</View>
<Loader visible={loading} />
</View>
</SafeAreaView>
);
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;
+4 -1
View File
@@ -61,7 +61,9 @@ export const styles = StyleSheet.create({
width: Screen.screenWidth * 0.92,
marginVertical: 5,
borderWidth: 1,
borderColor: GlobalTheme.colors.lightblueborder,
borderColor: '#113F8C',
marginBottom:15,
marginTop:10,
// ...shadow,
},
@@ -69,6 +71,7 @@ export const styles = StyleSheet.create({
color:'#000',
fontWeight: GlobalTheme.typography.fontWeight.bold,
fontSize: GlobalTheme.typography.fontSize.small,
marginHorizontal:10
},
row: {
flexDirection: 'row',
+1 -1
View File
@@ -12,7 +12,7 @@ const Welcome = ({ navigation }) => {
return (
<View style={styles.container}>
<ImageBackground source={IMAGES.WelcomeBackground} style={styles.background} resizeMode='cover'>
<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>