Graph design 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 = 1;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
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.0;
|
MARKETING_VERSION = 1.3;
|
||||||
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 = 1;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
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.0;
|
MARKETING_VERSION = 1.3;
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"-ObjC",
|
"-ObjC",
|
||||||
@@ -382,10 +382,7 @@
|
|||||||
"-DFOLLY_CFG_NO_COROUTINES=1",
|
"-DFOLLY_CFG_NO_COROUTINES=1",
|
||||||
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
|
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
|
||||||
);
|
);
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = "$(inherited) ";
|
||||||
"$(inherited)",
|
|
||||||
" ",
|
|
||||||
);
|
|
||||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
|
||||||
@@ -454,10 +451,7 @@
|
|||||||
"-DFOLLY_CFG_NO_COROUTINES=1",
|
"-DFOLLY_CFG_NO_COROUTINES=1",
|
||||||
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
|
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
|
||||||
);
|
);
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = "$(inherited) ";
|
||||||
"$(inherited)",
|
|
||||||
" ",
|
|
||||||
);
|
|
||||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
USE_HERMES = true;
|
USE_HERMES = true;
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ const Login = ({ navigation }) => {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.container}>
|
<SafeAreaView style={styles.container}>
|
||||||
<KeyboardAwareScrollView keyboardShouldPersistTaps="handled" enableOnAndroid={true} contentContainerStyle={{ justifyContent: 'center', flexGrow: 1, marginTop: 0 }} style={styles.container}>
|
<KeyboardAwareScrollView keyboardShouldPersistTaps="handled" enableOnAndroid={true} contentContainerStyle={{ justifyContent: 'center', flexGrow: 1, marginTop: 0 }} style={styles.container}>
|
||||||
|
|||||||
@@ -226,11 +226,22 @@ const Dashboard = (props) => {
|
|||||||
getFilterStateCity()
|
getFilterStateCity()
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTabCache({}); // reset cache when filters change
|
||||||
|
}, [month, year]);
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (mainDisplayJson && storeData?.StoreId) {
|
||||||
|
// getTabData(mainDisplayJson);
|
||||||
|
// }
|
||||||
|
// }, [mainTabIndex, storeData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (mainDisplayJson && storeData?.StoreId) {
|
if (mainDisplayJson && storeData?.StoreId) {
|
||||||
getTabData(mainDisplayJson);
|
setTimeout(() => getTabData(mainDisplayJson), 0);
|
||||||
}
|
}
|
||||||
}, [mainTabIndex, storeData]);
|
}, [mainDisplayJson, storeData]);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getDataFromLocal();
|
getDataFromLocal();
|
||||||
@@ -367,16 +378,15 @@ const Dashboard = (props) => {
|
|||||||
const getTabData = async (tabData) => {
|
const getTabData = async (tabData) => {
|
||||||
if (!storeData?.StoreId) return;
|
if (!storeData?.StoreId) return;
|
||||||
|
|
||||||
const tabKey = `${mainTabIndex}_${storeData?.StoreId}_${year}_${month}`;
|
// const tabKey = `${mainTabIndex}_${storeData?.StoreId}_${year}_${month}`;
|
||||||
|
const tabKey = `${mainTabIndex}_${storeData?.StoreId}_${year}_${month}_${Date.now()}`;
|
||||||
if (tabCache[tabKey]) {
|
if (tabCache[tabKey]) {
|
||||||
console.log("Using cached data for tab:", tabKey);
|
console.log("Using cached data for tab:", tabKey);
|
||||||
setGraphApiData(tabCache[tabKey]);
|
setGraphApiData(tabCache[tabKey]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
console.log("📦 TabKey:", tabKey);
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const params = {
|
const params = {
|
||||||
parameters: {
|
parameters: {
|
||||||
@@ -386,11 +396,27 @@ const Dashboard = (props) => {
|
|||||||
storeid: storeData?.StoreId
|
storeid: storeData?.StoreId
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
console.log("🔁 API Params:", params);
|
||||||
|
|
||||||
const graphDetails = tabData?.graphDetails || [];
|
const graphDetails = tabData?.graphDetails || [];
|
||||||
|
|
||||||
|
|
||||||
const uniqueUrls = [...new Set(graphDetails.map(graph => graph.GraphUrl))];
|
const uniqueUrls = [...new Set(graphDetails.map(graph => graph.GraphUrl))];
|
||||||
|
|
||||||
const apiCalls = uniqueUrls.map(url => {
|
// 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 = {
|
const config = {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: url,
|
url: url,
|
||||||
@@ -400,15 +426,27 @@ const Dashboard = (props) => {
|
|||||||
},
|
},
|
||||||
data: params
|
data: params
|
||||||
};
|
};
|
||||||
return axios.request(config);
|
return await fetchWithRetry(config);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const results = await Promise.all(apiCalls);
|
const results = await Promise.all(apiCalls);
|
||||||
|
console.log("📊 API Results:", results.map(r => r?.data));
|
||||||
|
|
||||||
const dataMap = {};
|
const dataMap = {};
|
||||||
|
// uniqueUrls.forEach((url, idx) => {
|
||||||
|
// dataMap[url] = results[idx].data;
|
||||||
|
// });
|
||||||
|
|
||||||
uniqueUrls.forEach((url, idx) => {
|
uniqueUrls.forEach((url, idx) => {
|
||||||
dataMap[url] = results[idx].data;
|
const responseData = results[idx]?.data;
|
||||||
|
if (!responseData || !responseData.data || responseData.data.length === 0) {
|
||||||
|
console.warn(`⚠️ API ${url} returned empty or invalid data`);
|
||||||
|
// Optional: Retry or show error
|
||||||
|
}
|
||||||
|
dataMap[url] = responseData;
|
||||||
});
|
});
|
||||||
|
console.log('uniqueUrls-dataMap---------->', dataMap);
|
||||||
|
|
||||||
setGraphApiData(dataMap);
|
setGraphApiData(dataMap);
|
||||||
setTabCache(prev => ({ ...prev, [tabKey]: dataMap }));
|
setTabCache(prev => ({ ...prev, [tabKey]: dataMap }));
|
||||||
@@ -420,6 +458,49 @@ const Dashboard = (props) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const fetchWithRetry = async (config, retries = 2, delay = 1000) => {
|
||||||
|
for (let i = 0; i <= retries; i++) {
|
||||||
|
try {
|
||||||
|
const res = await axios.request(config);
|
||||||
|
if (res?.data?.status === 'success' && res?.data?.data) {
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
|
console.warn(`Attempt ${i + 1} failed:`, res?.data?.error || 'No data');
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn(`Attempt ${i + 1} failed with error:`, err.message);
|
||||||
|
}
|
||||||
|
if (i < retries) await new Promise(res => setTimeout(res, delay));
|
||||||
|
}
|
||||||
|
return null; // all attempts failed
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log(`Data for ${item.GraphTitle}:`, response?.data); // Add this
|
||||||
|
resultMap[item.GraphUrl] = response?.data || [];
|
||||||
|
}
|
||||||
|
setModalGraphData(resultMap);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("❌ Error fetching detail graphs:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const handleScroll = (event) => {
|
const handleScroll = (event) => {
|
||||||
const offsetY = event.nativeEvent.contentOffset.y;
|
const offsetY = event.nativeEvent.contentOffset.y;
|
||||||
setShowButton(offsetY > 0); // Show button only if not at the top
|
setShowButton(offsetY > 0); // Show button only if not at the top
|
||||||
@@ -521,23 +602,42 @@ const Dashboard = (props) => {
|
|||||||
|
|
||||||
const renderItem = ({ item }) => {
|
const renderItem = ({ item }) => {
|
||||||
const apiData = graphApiData[item.GraphUrl];
|
const apiData = graphApiData[item.GraphUrl];
|
||||||
const values = apiData?.data || [];
|
// 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);
|
console.log('apiData --->', apiData);
|
||||||
|
|
||||||
|
|
||||||
if (!apiData) {
|
|
||||||
|
if (apiData?.status === 'error') {
|
||||||
return (
|
return (
|
||||||
<View style={[styles.percentBox, { justifyContent: 'center', alignItems: 'center' }]}>
|
<View style={styles.percentBox}>
|
||||||
<ActivityIndicator size="small" color="#113F8C" />
|
<Text style={styles.boxText}>{item.GraphTitle}</Text>
|
||||||
|
<Text style={styles.boxText}>❌</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// if (!apiData) {
|
||||||
|
// return (
|
||||||
|
// <View style={[styles.percentBox, { justifyContent: 'center', alignItems: 'center' }]}>
|
||||||
|
// <ActivityIndicator size="small" color="#113F8C" />
|
||||||
|
// </View>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
switch (item.GraphType) {
|
switch (item.GraphType) {
|
||||||
case "ScoreCard":
|
case "ScoreCard":
|
||||||
const firstDataObj = values[0] || {};
|
const firstDataObj = values[0] || {};
|
||||||
const scoreValue = Object.values(firstDataObj)[0]; // dynamically get first value
|
const scoreValue = Object.values(firstDataObj)[0]; // dynamically get first value
|
||||||
|
// const scoreValue = values.length > 0 ? Object.values(values[0])[0] : null;
|
||||||
return (
|
return (
|
||||||
<View style={[styles.percentBox, { backgroundColor: item.GraphBackground }]}>
|
<View style={[styles.percentBox, { backgroundColor: item.GraphBackground }]}>
|
||||||
<Text style={styles.boxText}>{item.GraphTitle}</Text>
|
<Text style={styles.boxText}>{item.GraphTitle}</Text>
|
||||||
@@ -547,63 +647,11 @@ const Dashboard = (props) => {
|
|||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
// CHART KIT
|
|
||||||
// case "BarGraph":
|
|
||||||
// const barLabels = values.map(v => v.CalendarYear_Month);
|
|
||||||
// const barValues = values.map(v => {
|
|
||||||
// const num = Object.values(v).find(val => typeof val === 'number');
|
|
||||||
// return num ? parseFloat(num.toFixed(1)) : 0;
|
|
||||||
// });
|
|
||||||
|
|
||||||
// const barData = {
|
|
||||||
// labels: barLabels,
|
|
||||||
// datasets: [
|
|
||||||
// {
|
|
||||||
// data: barValues,
|
|
||||||
// }
|
|
||||||
// ]
|
|
||||||
// };
|
|
||||||
|
|
||||||
// return (
|
|
||||||
// <View style={{ padding: 10, borderWidth: 0.5, borderColor: 'gray' }}>
|
|
||||||
// <Text style={{ fontSize: 16, fontWeight: '600', marginBottom: 10 }}>{item.GraphTitle}</Text>
|
|
||||||
|
|
||||||
// <BarChart
|
|
||||||
// data={barData}
|
|
||||||
// width={screenWidth - 40}
|
|
||||||
// height={240}
|
|
||||||
// yAxisSuffix="%"
|
|
||||||
// fromZero={true}
|
|
||||||
// showValuesOnTopOfBars={true}
|
|
||||||
// segments={5} // Will give 0%, 20%, ..., 100%
|
|
||||||
// chartConfig={{
|
|
||||||
// backgroundColor: '#ffffff',
|
|
||||||
// backgroundGradientFrom: '#ffffff',
|
|
||||||
// backgroundGradientTo: '#ffffff',
|
|
||||||
// fillShadowGradientFrom: '#BFC2FF',
|
|
||||||
// fillShadowGradientTo: '#BFC2FF',
|
|
||||||
// fillShadowGradientFromOpacity: 1,
|
|
||||||
// fillShadowGradientToOpacity: 1,
|
|
||||||
// decimalPlaces: 0,
|
|
||||||
// color: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
|
|
||||||
// labelColor: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
|
|
||||||
// barPercentage: 1,
|
|
||||||
// propsForVerticalLabels: { fontSize: 10 },
|
|
||||||
// }}
|
|
||||||
// withInnerLines={true}
|
|
||||||
// withHorizontalLabels={true}
|
|
||||||
// withVerticalLabels={true}
|
|
||||||
// style={{ marginLeft: -10 }}
|
|
||||||
// yAxisInterval={20} // Trick to help scale till 100% cleanly
|
|
||||||
// />
|
|
||||||
// </View>
|
|
||||||
// );
|
|
||||||
|
|
||||||
//GIFTED CHART LIBRARY -----
|
//GIFTED CHART LIBRARY -----
|
||||||
case "BarGraph":
|
case "BarGraph":
|
||||||
const chartWidth = screenWidth * 0.8;
|
const chartWidth = screenWidth * 0.75;
|
||||||
const barWidth = 36;
|
const barWidth = 40;
|
||||||
const barColors = ['#0088FE', '#FF8042', '#00C49F'];
|
const barColors = ['#1BF2E0', '#1B7BF2', '#1BC0F2'];
|
||||||
|
|
||||||
const barData = values.map((v, idx) => {
|
const barData = values.map((v, idx) => {
|
||||||
const value = parseFloat(Object.values(v).find(val => typeof val === 'number').toFixed(1));
|
const value = parseFloat(Object.values(v).find(val => typeof val === 'number').toFixed(1));
|
||||||
@@ -612,7 +660,7 @@ const Dashboard = (props) => {
|
|||||||
label: v.CalendarYear_Month,
|
label: v.CalendarYear_Month,
|
||||||
frontColor: barColors[idx % barColors.length],
|
frontColor: barColors[idx % barColors.length],
|
||||||
topLabelComponent: () => (
|
topLabelComponent: () => (
|
||||||
<Text style={{ color: '#000', fontSize: 10, marginBottom: 4 }}>{value}%</Text>
|
<Text style={{ color: '#000', fontSize: 12, fontWeight: '500', marginBottom: 5 }}>{value}%</Text>
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -626,7 +674,9 @@ const Dashboard = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{ alignItems: 'center', padding: 10, }}>
|
<View style={{ alignItems: 'center', justifyContent: 'center', padding: 10, borderWidth: 0.5, borderRadius: 10, }}>
|
||||||
|
{/* <View style={{ alignSelf: 'center', borderWidth: 0.5,borderRadius:20, paddingBottom: 10 }}> */}
|
||||||
|
|
||||||
<Text style={{ fontSize: 16, fontWeight: '600', marginBottom: 10 }}>
|
<Text style={{ fontSize: 16, fontWeight: '600', marginBottom: 10 }}>
|
||||||
{item.GraphTitle}
|
{item.GraphTitle}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -636,20 +686,37 @@ const Dashboard = (props) => {
|
|||||||
barWidth={barWidth}
|
barWidth={barWidth}
|
||||||
spacing={spacing}
|
spacing={spacing}
|
||||||
noOfSections={5}
|
noOfSections={5}
|
||||||
maxValue={100}
|
maxValue={105}
|
||||||
roundedTop={false}
|
roundedTop={false}
|
||||||
disableScroll={true}
|
disableScroll={true}
|
||||||
yAxisLabelTexts={['0%', '20%', '40%', '60%', '80%', '100%']}
|
yAxisLabelTexts={['0%', '20%', '40%', '60%', '80%', '100%']}
|
||||||
// yAxisLabelTexts={['0%', '👉', '👉', '👉', '👉', '100%']} // 👈 only 0% and 100%
|
// yAxisLabelTexts={['0%', '👉', '👉', '👉', '👉', '100%']} // 👈 only 0% and 100%
|
||||||
yAxisTextStyle={{ color: '#000', fontSize: 10 }}
|
yAxisTextStyle={{ color: '#000', fontSize: 12 }}
|
||||||
xAxisLabelTextStyle={{ fontSize: 10, marginTop: 4 }}
|
xAxisLabelTextStyle={{ color: '#000', fontSize: 12, fontWeight: '500', marginTop: 5 }}
|
||||||
isAnimated
|
isAnimated
|
||||||
width={chartWidth}
|
width={chartWidth}
|
||||||
hideYAxisText={false}
|
|
||||||
|
hideYAxisText={true} //to hide y axis text
|
||||||
|
// hideRules={true}
|
||||||
|
hideYAxisLine={true}
|
||||||
|
yAxisThickness={0}
|
||||||
|
xAxisThickness={1}
|
||||||
|
rulesLength={chartWidth}
|
||||||
|
// xAxisLength={chartWidth}
|
||||||
|
hideAxesAndRules={true}
|
||||||
|
// backgroundColor={'red'}
|
||||||
|
|
||||||
|
backgroundColor={'yellow'}
|
||||||
|
|
||||||
|
// xAxisLabelTextStyle={{ color: '#000', fontSize: 10, marginTop: 4 }}
|
||||||
/>
|
/>
|
||||||
|
{/* </View> */}
|
||||||
|
<View style={{height:10}} />
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "Table":
|
case "Table":
|
||||||
return (
|
return (
|
||||||
<View style={{ flex: 1 }}>
|
<View style={{ flex: 1 }}>
|
||||||
@@ -721,36 +788,10 @@ const Dashboard = (props) => {
|
|||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
null
|
null
|
||||||
// <View style={[styles.percentBox, { backgroundColor: "#f8d7da", padding: 10, marginVertical: 5 }]}>
|
|
||||||
// <Text style={[styles.boxText, { color: "#721c24" }]}>
|
|
||||||
// Unsupported Graph Type: {item.GraphType}
|
|
||||||
// </Text>
|
|
||||||
// </View>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchDetailGraphs = async (detailPages) => {
|
|
||||||
try {
|
|
||||||
const resultMap = {};
|
|
||||||
|
|
||||||
for (let item of detailPages) {
|
|
||||||
const response = await post(item.GraphUrl, {
|
|
||||||
parameters: {
|
|
||||||
projectid: 41654,
|
|
||||||
year: 2025,
|
|
||||||
monthno: 6,
|
|
||||||
storeid: 2702,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
console.log(`Data for ${item.GraphTitle}:`, response?.data); // Add this
|
|
||||||
resultMap[item.GraphUrl] = response?.data || [];
|
|
||||||
}
|
|
||||||
setModalGraphData(resultMap);
|
|
||||||
} catch (error) {
|
|
||||||
console.log("❌ Error fetching detail graphs:", error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 🔧 Debounced search text handler (use lodash.debounce or implement custom debounce)
|
// 🔧 Debounced search text handler (use lodash.debounce or implement custom debounce)
|
||||||
const debouncedSearch = useCallback(_.debounce((text) => {
|
const debouncedSearch = useCallback(_.debounce((text) => {
|
||||||
@@ -896,7 +937,10 @@ const Dashboard = (props) => {
|
|||||||
textstyle={styles.btntext}
|
textstyle={styles.btntext}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
if (storeData) {
|
if (storeData) {
|
||||||
getTabData(mainDisplayJson);
|
console.log("🔽 Triggered getTabData with filters:", { year, month });
|
||||||
|
setTimeout(() => {
|
||||||
|
getTabData(mainDisplayJson);
|
||||||
|
}, 50);
|
||||||
} else {
|
} else {
|
||||||
Alert.alert('Please select a store first.');
|
Alert.alert('Please select a store first.');
|
||||||
}
|
}
|
||||||
@@ -960,55 +1004,57 @@ const Dashboard = (props) => {
|
|||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Score Card */}
|
{/* Score Card */}
|
||||||
<View style={{ margin: 10 }}>
|
<View style={{ margin:5 }}>
|
||||||
|
|
||||||
{firstItem && (
|
<View style={{ marginHorizontal: 5 }}>
|
||||||
<TouchableOpacity
|
{firstItem && (
|
||||||
activeOpacity={0.8}
|
<TouchableOpacity
|
||||||
onPress={() => {
|
activeOpacity={0.8}
|
||||||
if (firstItem.clickable === 1 && firstItem.DetailsPage?.length > 0) {
|
onPress={() => {
|
||||||
setSelectedDetails(firstItem.DetailsPage);
|
if (firstItem.clickable === 1 && firstItem.DetailsPage?.length > 0) {
|
||||||
setShowDetailsModal(true);
|
setSelectedDetails(firstItem.DetailsPage);
|
||||||
fetchDetailGraphs(firstItem.DetailsPage);
|
setShowDetailsModal(true);
|
||||||
}
|
fetchDetailGraphs(firstItem.DetailsPage);
|
||||||
}}
|
}
|
||||||
>
|
}}
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
styles.percentBox,
|
|
||||||
{
|
|
||||||
backgroundColor: firstItem.GraphBackground,
|
|
||||||
width: '100%',
|
|
||||||
elevation: 0,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
>
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
<View
|
||||||
<View style={{ width: '80%', alignItems: 'center' }}>
|
style={[
|
||||||
<Text style={styles.boxText}>{firstItem.GraphTitle}</Text>
|
styles.percentBox,
|
||||||
<Text
|
{
|
||||||
style={[
|
backgroundColor: "#C3D7FF",
|
||||||
styles.boxText,
|
width: '100%',
|
||||||
{ fontWeight: '500', fontSize: 24, marginTop: 10 },
|
elevation: 0,
|
||||||
]}
|
},
|
||||||
>
|
]}
|
||||||
{(() => {
|
>
|
||||||
const values = graphApiData[firstItem.GraphUrl]?.data || [];
|
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||||
const score = Object.values(values[0] || {})[0];
|
<View style={{ width: '80%', alignItems: 'center' }}>
|
||||||
return score !== undefined ? `${score.toFixed(1)}%` : '0.0%';
|
<Text style={styles.boxText}>{firstItem.GraphTitle}</Text>
|
||||||
})()}
|
<Text
|
||||||
</Text>
|
style={[
|
||||||
</View>
|
styles.boxText,
|
||||||
<View>
|
{ fontWeight: '500', fontSize: 24, marginTop: 10 },
|
||||||
{firstItem.clickable === 1 && (
|
]}
|
||||||
<Image source={IMAGES.rightArrowIcon} style={{ tintColor: '#000', height: 20, width: 20, resizeMode: 'contain' }} />
|
>
|
||||||
)}
|
{(() => {
|
||||||
|
const values = graphApiData[firstItem.GraphUrl]?.data || [];
|
||||||
|
const score = Object.values(values[0] || {})[0];
|
||||||
|
return score !== undefined ? `${score.toFixed(1)}%` : '0.0%';
|
||||||
|
})()}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View>
|
||||||
|
{firstItem.clickable === 1 && (
|
||||||
|
<Image source={IMAGES.rightArrowIcon} style={{ tintColor: '#000', height: 20, width: 20, resizeMode: 'contain' }} />
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</TouchableOpacity>
|
||||||
</TouchableOpacity>
|
)}
|
||||||
)}
|
</View>
|
||||||
|
<View style={{ marginHorizontal: 10 }}>
|
||||||
<FlatList
|
<FlatList
|
||||||
data={restItems}
|
data={restItems}
|
||||||
keyExtractor={(item, index) => `${item.GraphId}-${index}`}
|
keyExtractor={(item, index) => `${item.GraphId}-${index}`}
|
||||||
@@ -1018,6 +1064,7 @@ const Dashboard = (props) => {
|
|||||||
contentContainerStyle={{ paddingHorizontal: 2, paddingVertical: 2 }}
|
contentContainerStyle={{ paddingHorizontal: 2, paddingVertical: 2 }}
|
||||||
showsVerticalScrollIndicator={false}
|
showsVerticalScrollIndicator={false}
|
||||||
/>
|
/>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<Loader visible={loading} />
|
<Loader visible={loading} />
|
||||||
|
|
||||||
@@ -1115,8 +1162,8 @@ const Dashboard = (props) => {
|
|||||||
borderTopLeftRadius: 8,
|
borderTopLeftRadius: 8,
|
||||||
borderTopRightRadius: 8,
|
borderTopRightRadius: 8,
|
||||||
}}>
|
}}>
|
||||||
<Text style={{ color: '#000', fontWeight: 'bold', width: '80%' }}>{displayKey ? displayKey.replace(/_/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2') : 'Display'}</Text>
|
<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') : 'Present'}</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>
|
||||||
|
|
||||||
<View style={{
|
<View style={{
|
||||||
|
|||||||
@@ -105,7 +105,7 @@
|
|||||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/SOS_Actual_Perc",
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/SOS_Actual_Perc",
|
||||||
"GraphBackground": "#ECFFFA",
|
"GraphBackground": "#ECFFFA",
|
||||||
"GraphOptions": {},
|
"GraphOptions": {},
|
||||||
"clickable": 1,
|
"clickable": 1,
|
||||||
"DetailsPage": [
|
"DetailsPage": [
|
||||||
{
|
{
|
||||||
"TabId": 2,
|
"TabId": 2,
|
||||||
@@ -158,7 +158,6 @@
|
|||||||
"GraphOptions": {}
|
"GraphOptions": {}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"TabId": 3,
|
"TabId": 3,
|
||||||
@@ -331,7 +330,7 @@
|
|||||||
"GraphType": "ScoreCard",
|
"GraphType": "ScoreCard",
|
||||||
"GraphTitle": "PSS Score",
|
"GraphTitle": "PSS Score",
|
||||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/PSS_Score_LSV_Perc",
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/PSS_Score_LSV_Perc",
|
||||||
"GraphBackground": "#F4EAFF",
|
"GraphBackground": "#E2C8FE",
|
||||||
"GraphOptions": {}
|
"GraphOptions": {}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -340,7 +339,7 @@
|
|||||||
"GraphType": "ScoreCard",
|
"GraphType": "ScoreCard",
|
||||||
"GraphTitle": "SOS Actual",
|
"GraphTitle": "SOS Actual",
|
||||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/sos_actual_lsv_perc",
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/sos_actual_lsv_perc",
|
||||||
"GraphBackground": "#FFF3ED",
|
"GraphBackground": "#E2C8FE",
|
||||||
"GraphOptions": {}
|
"GraphOptions": {}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -349,7 +348,7 @@
|
|||||||
"GraphType": "ScoreCard",
|
"GraphType": "ScoreCard",
|
||||||
"GraphTitle": "SOS Compliance",
|
"GraphTitle": "SOS Compliance",
|
||||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/sos_compliance_lsv_perc",
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/sos_compliance_lsv_perc",
|
||||||
"GraphBackground": "#FFFEF0",
|
"GraphBackground": "#FFD7C3",
|
||||||
"GraphOptions": {}
|
"GraphOptions": {}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -358,7 +357,7 @@
|
|||||||
"GraphType": "ScoreCard",
|
"GraphType": "ScoreCard",
|
||||||
"GraphTitle": "OSA",
|
"GraphTitle": "OSA",
|
||||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/osa_lsv_perc",
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/osa_lsv_perc",
|
||||||
"GraphBackground": "#ECFFFA",
|
"GraphBackground": "#FFF9A1",
|
||||||
"GraphOptions": {}
|
"GraphOptions": {}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -367,7 +366,7 @@
|
|||||||
"GraphType": "ScoreCard",
|
"GraphType": "ScoreCard",
|
||||||
"GraphTitle": "Asset",
|
"GraphTitle": "Asset",
|
||||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/asset_lsv_perc",
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/asset_lsv_perc",
|
||||||
"GraphBackground": "#EBECFF",
|
"GraphBackground": "#A2F3DE",
|
||||||
"GraphOptions": {}
|
"GraphOptions": {}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -376,7 +375,7 @@
|
|||||||
"GraphType": "ScoreCard",
|
"GraphType": "ScoreCard",
|
||||||
"GraphTitle": "Promotion",
|
"GraphTitle": "Promotion",
|
||||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/promotion_lsv_perc",
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/promotion_lsv_perc",
|
||||||
"GraphBackground": "#FFFEF0",
|
"GraphBackground": "#BFC2FF",
|
||||||
"GraphOptions": {}
|
"GraphOptions": {}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -387,7 +386,7 @@
|
|||||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/sos_actual_lsv_perc",
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/sos_actual_lsv_perc",
|
||||||
"GraphBackground": "#ECFFFA",
|
"GraphBackground": "#ECFFFA",
|
||||||
"GraphOptions": {},
|
"GraphOptions": {},
|
||||||
"clickable": 1,
|
"clickable": 1,
|
||||||
"DetailsPage": [
|
"DetailsPage": [
|
||||||
{
|
{
|
||||||
"TabId": 2,
|
"TabId": 2,
|
||||||
@@ -494,11 +493,22 @@
|
|||||||
{
|
{
|
||||||
"TabId": 5,
|
"TabId": 5,
|
||||||
"GraphId": 6,
|
"GraphId": 6,
|
||||||
"GraphType": "Table",
|
"GraphType": "BarGraph",
|
||||||
"GraphTitle": "Asset Details",
|
"GraphTitle": "Asset Details",
|
||||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/asset_trend_lsv_perc",
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/asset_trend_lsv_perc",
|
||||||
"GraphBackground": "#ECFFFA",
|
"GraphBackground": "#fff",
|
||||||
"GraphOptions": {}
|
"GraphOptions": {
|
||||||
|
"axisX": "month",
|
||||||
|
"axisY": "score",
|
||||||
|
"labelShow": 1,
|
||||||
|
"barColors": [
|
||||||
|
"#11a4ff",
|
||||||
|
"#0ea3e3",
|
||||||
|
"#0b9ddb"
|
||||||
|
],
|
||||||
|
"gridLinesH": 1,
|
||||||
|
"gridLinesV": 1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"TabId": 4,
|
"TabId": 4,
|
||||||
@@ -524,7 +534,7 @@
|
|||||||
{
|
{
|
||||||
"TabId": 4,
|
"TabId": 4,
|
||||||
"GraphId": 8,
|
"GraphId": 8,
|
||||||
"GraphType": "PieChart",
|
"GraphType": "BarGraph",
|
||||||
"GraphTitle": "OSA",
|
"GraphTitle": "OSA",
|
||||||
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/osa_trend_lsv_perc",
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/osa_trend_lsv_perc",
|
||||||
"GraphBackground": "#ECFFFA",
|
"GraphBackground": "#ECFFFA",
|
||||||
|
|||||||
Reference in New Issue
Block a user