OSA and promotion details page updated
This commit is contained in:
@@ -263,7 +263,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 5;
|
CURRENT_PROJECT_VERSION = 6;
|
||||||
DEVELOPMENT_TEAM = JGDHGNH9XY;
|
DEVELOPMENT_TEAM = JGDHGNH9XY;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = PerformicsStoreDNA/Info.plist;
|
INFOPLIST_FILE = PerformicsStoreDNA/Info.plist;
|
||||||
@@ -272,7 +272,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.5;
|
MARKETING_VERSION = 1.6;
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"-ObjC",
|
"-ObjC",
|
||||||
@@ -292,7 +292,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 5;
|
CURRENT_PROJECT_VERSION = 6;
|
||||||
DEVELOPMENT_TEAM = JGDHGNH9XY;
|
DEVELOPMENT_TEAM = JGDHGNH9XY;
|
||||||
INFOPLIST_FILE = PerformicsStoreDNA/Info.plist;
|
INFOPLIST_FILE = PerformicsStoreDNA/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
||||||
@@ -300,7 +300,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.5;
|
MARKETING_VERSION = 1.6;
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"-ObjC",
|
"-ObjC",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import Dashboard from '../screens/MainScreen/Dashboard';
|
|||||||
import FeedbackCategories from '../screens/MainScreen/Feedback/FeedbackCategories';
|
import FeedbackCategories from '../screens/MainScreen/Feedback/FeedbackCategories';
|
||||||
import { Platform, StatusBar, View } from 'react-native';
|
import { Platform, StatusBar, View } from 'react-native';
|
||||||
import Welcome from '../screens/MainScreen/WelcomePage';
|
import Welcome from '../screens/MainScreen/WelcomePage';
|
||||||
|
import Details from '../screens/MainScreen/Dashboard/Details';
|
||||||
|
|
||||||
const Stack = createNativeStackNavigator();
|
const Stack = createNativeStackNavigator();
|
||||||
|
|
||||||
@@ -38,6 +39,8 @@ const Routes = () => {
|
|||||||
<Stack.Screen name="Dashboard" component={Dashboard} />
|
<Stack.Screen name="Dashboard" component={Dashboard} />
|
||||||
<Stack.Screen name="Feedback" component={Feedback} />
|
<Stack.Screen name="Feedback" component={Feedback} />
|
||||||
<Stack.Screen name="FeedbackCategories" component={FeedbackCategories} />
|
<Stack.Screen name="FeedbackCategories" component={FeedbackCategories} />
|
||||||
|
<Stack.Screen name="Details" component={Details} />
|
||||||
|
|
||||||
</Stack.Navigator>
|
</Stack.Navigator>
|
||||||
<ToastComponent />
|
<ToastComponent />
|
||||||
</NavigationContainer>
|
</NavigationContainer>
|
||||||
|
|||||||
@@ -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,405 @@
|
|||||||
|
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;
|
||||||
@@ -303,7 +303,7 @@ const Dashboard = (props) => {
|
|||||||
[d2],
|
[d2],
|
||||||
(tx, results) => {
|
(tx, results) => {
|
||||||
|
|
||||||
console.log("results===", results);
|
// console.log("results===", results);
|
||||||
const rows = [];
|
const rows = [];
|
||||||
for (let i = 0; i < results.rows.length; i++) {
|
for (let i = 0; i < results.rows.length; i++) {
|
||||||
rows.push(results.rows.item(i));
|
rows.push(results.rows.item(i));
|
||||||
@@ -429,7 +429,7 @@ const Dashboard = (props) => {
|
|||||||
|
|
||||||
const openBottomSheet = () => {
|
const openBottomSheet = () => {
|
||||||
refRBSheet.current.open()
|
refRBSheet.current.open()
|
||||||
}
|
};
|
||||||
|
|
||||||
const onSelectStore = async (item) => {
|
const onSelectStore = async (item) => {
|
||||||
await insertStoreInfoDNALocal([item]);
|
await insertStoreInfoDNALocal([item]);
|
||||||
@@ -442,11 +442,11 @@ const Dashboard = (props) => {
|
|||||||
|
|
||||||
getTabData(currentTab?.MainTabData);
|
getTabData(currentTab?.MainTabData);
|
||||||
refRBSheet.current.close()
|
refRBSheet.current.close()
|
||||||
}
|
};
|
||||||
|
|
||||||
const onSelectSubTab = (item) => {
|
const onSelectSubTab = (item) => {
|
||||||
setActiveTab(item?.TabId)
|
setActiveTab(item?.TabId)
|
||||||
}
|
};
|
||||||
|
|
||||||
const getFilterStateCity = async () => {
|
const getFilterStateCity = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -516,7 +516,7 @@ const Dashboard = (props) => {
|
|||||||
setStoreList(resData)
|
setStoreList(resData)
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
|
|
||||||
console.log('storeSearchApi====>', JSON.stringify(resData));
|
// console.log('storeSearchApi====>', JSON.stringify(resData));
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
@@ -707,6 +707,9 @@ const Dashboard = (props) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// console.log('mainTabIndex----->',mainTabIndex);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={{ flex: 1, backgroundColor: GlobalTheme.colors.primary }}>
|
<SafeAreaView style={{ flex: 1, backgroundColor: GlobalTheme.colors.primary }}>
|
||||||
<View style={{ flex: 1, backgroundColor: '#fff' }}>
|
<View style={{ flex: 1, backgroundColor: '#fff' }}>
|
||||||
@@ -914,11 +917,23 @@ const Dashboard = (props) => {
|
|||||||
{firstItem && (
|
{firstItem && (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
activeOpacity={0.8}
|
activeOpacity={0.8}
|
||||||
|
// onPress={() => {
|
||||||
|
// if (firstItem.clickable === 1 && firstItem.DetailsPage?.length > 0) {
|
||||||
|
// setSelectedDetails(firstItem.DetailsPage);
|
||||||
|
// setShowDetailsModal(true);
|
||||||
|
// fetchDetailGraphs(firstItem.DetailsPage);
|
||||||
|
// }
|
||||||
|
// }}
|
||||||
|
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
if (firstItem.clickable === 1 && firstItem.DetailsPage?.length > 0) {
|
if (firstItem.clickable === 1 && firstItem.DetailsPage?.length > 0) {
|
||||||
setSelectedDetails(firstItem.DetailsPage);
|
navigation.navigate('Details', {
|
||||||
setShowDetailsModal(true);
|
selectedDetails: firstItem.DetailsPage,
|
||||||
fetchDetailGraphs(firstItem.DetailsPage);
|
storeData,
|
||||||
|
year,
|
||||||
|
month,
|
||||||
|
mainTabIndex
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -17,12 +17,6 @@
|
|||||||
"TabRow": 1,
|
"TabRow": 1,
|
||||||
"TabCol": 2
|
"TabCol": 2
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// "TabId": 3,
|
|
||||||
// "TabName": "SOS Compliance",
|
|
||||||
// "TabRow": 1,
|
|
||||||
// "TabCol": 3
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
"TabId": 4,
|
"TabId": 4,
|
||||||
"TabName": "OSA",
|
"TabName": "OSA",
|
||||||
@@ -42,6 +36,9 @@
|
|||||||
"TabCol": 6
|
"TabCol": 6
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"graphDetails": [
|
"graphDetails": [
|
||||||
{
|
{
|
||||||
"TabId": 1,
|
"TabId": 1,
|
||||||
@@ -61,15 +58,6 @@
|
|||||||
"GraphBackground": "#E2C8FE",
|
"GraphBackground": "#E2C8FE",
|
||||||
"GraphOptions": {}
|
"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,
|
"TabId": 1,
|
||||||
"GraphId": 4,
|
"GraphId": 4,
|
||||||
@@ -262,16 +250,26 @@
|
|||||||
"TabId": 6,
|
"TabId": 6,
|
||||||
"GraphId": 9,
|
"GraphId": 9,
|
||||||
"GraphType": "Table",
|
"GraphType": "Table",
|
||||||
"GraphTitle": "Promotion Availability",
|
"GraphTitle": "Promotion Not Executed",
|
||||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/promotion_availability_mtd",
|
"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",
|
"GraphBackground": "#ECFFFA",
|
||||||
"GraphOptions": {}
|
"GraphOptions": {}
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"TabId": 6,
|
"TabId": 6,
|
||||||
"GraphId": 10,
|
"GraphId": 11,
|
||||||
"GraphType": "BarGraph",
|
"GraphType": "BarGraph",
|
||||||
"GraphTitle": "Promotion",
|
"GraphTitle": "Promotion",
|
||||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/promotion_trend_perc_mtd",
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/promotion_trend_perc_mtd",
|
||||||
@@ -298,12 +296,6 @@
|
|||||||
"TabRow": 1,
|
"TabRow": 1,
|
||||||
"TabCol": 2
|
"TabCol": 2
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// "TabId": 3,
|
|
||||||
// "TabName": "SOS Compliance",
|
|
||||||
// "TabRow": 1,
|
|
||||||
// "TabCol": 3
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
"TabId": 4,
|
"TabId": 4,
|
||||||
"TabName": "OSA",
|
"TabName": "OSA",
|
||||||
@@ -342,15 +334,6 @@
|
|||||||
"GraphBackground": "#E2C8FE",
|
"GraphBackground": "#E2C8FE",
|
||||||
"GraphOptions": {}
|
"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,
|
"TabId": 1,
|
||||||
"GraphId": 4,
|
"GraphId": 4,
|
||||||
@@ -474,7 +457,7 @@
|
|||||||
"TabId": 5,
|
"TabId": 5,
|
||||||
"GraphId": 5,
|
"GraphId": 5,
|
||||||
"GraphType": "Table",
|
"GraphType": "Table",
|
||||||
"GraphTitle": "Asset Availability",
|
"GraphTitle": "Visibility",
|
||||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/asset_availability_lsv",
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/asset_availability_lsv",
|
||||||
"GraphBackground": "#ECFFFA",
|
"GraphBackground": "#ECFFFA",
|
||||||
"GraphOptions": {}
|
"GraphOptions": {}
|
||||||
@@ -483,7 +466,7 @@
|
|||||||
"TabId": 5,
|
"TabId": 5,
|
||||||
"GraphId": 5,
|
"GraphId": 5,
|
||||||
"GraphType": "Table",
|
"GraphType": "Table",
|
||||||
"GraphTitle": "Asset",
|
"GraphTitle": "Additional Visibility",
|
||||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/additional_visibility_lsv",
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/additional_visibility_lsv",
|
||||||
"GraphBackground": "#ECFFFA",
|
"GraphBackground": "#ECFFFA",
|
||||||
"GraphOptions": {}
|
"GraphOptions": {}
|
||||||
@@ -524,7 +507,7 @@
|
|||||||
"TabId": 4,
|
"TabId": 4,
|
||||||
"GraphId": 7,
|
"GraphId": 7,
|
||||||
"GraphType": "Table",
|
"GraphType": "Table",
|
||||||
"GraphTitle": "SOS Actual - Category",
|
"GraphTitle": "OSA - Category",
|
||||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detlsv/osa_lsv_perc_on_category",
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detlsv/osa_lsv_perc_on_category",
|
||||||
"GraphBackground": "#ECFFFA",
|
"GraphBackground": "#ECFFFA",
|
||||||
"GraphOptions": {}
|
"GraphOptions": {}
|
||||||
@@ -554,8 +537,17 @@
|
|||||||
"TabId": 6,
|
"TabId": 6,
|
||||||
"GraphId": 9,
|
"GraphId": 9,
|
||||||
"GraphType": "Table",
|
"GraphType": "Table",
|
||||||
"GraphTitle": "Promotion Availability",
|
"GraphTitle": "Promotion Not Executed",
|
||||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/promotion_availability_lsv",
|
"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",
|
"GraphBackground": "#ECFFFA",
|
||||||
"GraphOptions": {}
|
"GraphOptions": {}
|
||||||
}
|
}
|
||||||
@@ -563,7 +555,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"TabId": 6,
|
"TabId": 6,
|
||||||
"GraphId": 10,
|
"GraphId": 11,
|
||||||
"GraphType": "BarGraph",
|
"GraphType": "BarGraph",
|
||||||
"GraphTitle": "Promotion",
|
"GraphTitle": "Promotion",
|
||||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/promotion_trend_lsv_perc",
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/promotion_trend_lsv_perc",
|
||||||
|
|||||||
Reference in New Issue
Block a user