diff --git a/ios/PerformicsStoreDNA.xcodeproj/project.pbxproj b/ios/PerformicsStoreDNA.xcodeproj/project.pbxproj index 4f83986..ee6c6b7 100644 --- a/ios/PerformicsStoreDNA.xcodeproj/project.pbxproj +++ b/ios/PerformicsStoreDNA.xcodeproj/project.pbxproj @@ -263,7 +263,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = JGDHGNH9XY; ENABLE_BITCODE = NO; INFOPLIST_FILE = PerformicsStoreDNA/Info.plist; @@ -272,7 +272,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.3; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -292,7 +292,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = JGDHGNH9XY; INFOPLIST_FILE = PerformicsStoreDNA/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.1; @@ -300,7 +300,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.3; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -382,10 +382,7 @@ "-DFOLLY_CFG_NO_COROUTINES=1", "-DFOLLY_HAVE_CLOCK_GETTIME=1", ); - OTHER_LDFLAGS = ( - "$(inherited)", - " ", - ); + OTHER_LDFLAGS = "$(inherited) "; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; @@ -454,10 +451,7 @@ "-DFOLLY_CFG_NO_COROUTINES=1", "-DFOLLY_HAVE_CLOCK_GETTIME=1", ); - OTHER_LDFLAGS = ( - "$(inherited)", - " ", - ); + OTHER_LDFLAGS = "$(inherited) "; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; USE_HERMES = true; diff --git a/src.zip b/src.zip new file mode 100644 index 0000000..007f22b Binary files /dev/null and b/src.zip differ diff --git a/src/screens/AuthScreen/Login/index.js b/src/screens/AuthScreen/Login/index.js index 64c0d01..9c4c09d 100644 --- a/src/screens/AuthScreen/Login/index.js +++ b/src/screens/AuthScreen/Login/index.js @@ -67,7 +67,6 @@ const Login = ({ navigation }) => { setLoading(false); } }; - return ( diff --git a/src/screens/MainScreen/Dashboard/index.js b/src/screens/MainScreen/Dashboard/index.js index 7258784..54b9418 100644 --- a/src/screens/MainScreen/Dashboard/index.js +++ b/src/screens/MainScreen/Dashboard/index.js @@ -226,11 +226,22 @@ const Dashboard = (props) => { getFilterStateCity() }, []); + useEffect(() => { + setTabCache({}); // reset cache when filters change + }, [month, year]); + + // useEffect(() => { + // if (mainDisplayJson && storeData?.StoreId) { + // getTabData(mainDisplayJson); + // } + // }, [mainTabIndex, storeData]); + useEffect(() => { if (mainDisplayJson && storeData?.StoreId) { - getTabData(mainDisplayJson); + setTimeout(() => getTabData(mainDisplayJson), 0); } - }, [mainTabIndex, storeData]); + }, [mainDisplayJson, storeData]); + useEffect(() => { getDataFromLocal(); @@ -367,16 +378,15 @@ const Dashboard = (props) => { const getTabData = async (tabData) => { 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]) { console.log("Using cached data for tab:", tabKey); setGraphApiData(tabCache[tabKey]); return; } - + console.log("📦 TabKey:", tabKey); setLoading(true); - try { const params = { parameters: { @@ -386,11 +396,27 @@ const Dashboard = (props) => { storeid: storeData?.StoreId } }; + console.log("🔁 API Params:", params); const graphDetails = tabData?.graphDetails || []; + + 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 = { method: 'post', url: url, @@ -400,15 +426,27 @@ const Dashboard = (props) => { }, data: params }; - return axios.request(config); + 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) => { - 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); 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 offsetY = event.nativeEvent.contentOffset.y; setShowButton(offsetY > 0); // Show button only if not at the top @@ -521,23 +602,42 @@ const Dashboard = (props) => { const renderItem = ({ item }) => { 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; + // {scoreValue !== undefined ? `${scoreValue.toFixed(1)}%` : "No Data"} + console.log('apiData --->', apiData); - if (!apiData) { + + if (apiData?.status === 'error') { return ( - - + + {item.GraphTitle} + ); } + + // if (!apiData) { + // return ( + // + // + // + // ); + // } + switch (item.GraphType) { case "ScoreCard": const firstDataObj = values[0] || {}; const scoreValue = Object.values(firstDataObj)[0]; // dynamically get first value + // const scoreValue = values.length > 0 ? Object.values(values[0])[0] : null; return ( {item.GraphTitle} @@ -547,63 +647,11 @@ const Dashboard = (props) => { ); - // 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 ( - // - // {item.GraphTitle} - - // `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 - // /> - // - // ); - //GIFTED CHART LIBRARY ----- case "BarGraph": - const chartWidth = screenWidth * 0.8; - const barWidth = 36; - const barColors = ['#0088FE', '#FF8042', '#00C49F']; + const chartWidth = screenWidth * 0.75; + const barWidth = 40; + const barColors = ['#1BF2E0', '#1B7BF2', '#1BC0F2']; const barData = values.map((v, idx) => { const value = parseFloat(Object.values(v).find(val => typeof val === 'number').toFixed(1)); @@ -612,7 +660,7 @@ const Dashboard = (props) => { label: v.CalendarYear_Month, frontColor: barColors[idx % barColors.length], topLabelComponent: () => ( - {value}% + {value}% ) }; }); @@ -626,7 +674,9 @@ const Dashboard = (props) => { } return ( - + + {/* */} + {item.GraphTitle} @@ -636,20 +686,37 @@ const Dashboard = (props) => { barWidth={barWidth} spacing={spacing} noOfSections={5} - maxValue={100} + maxValue={105} roundedTop={false} disableScroll={true} yAxisLabelTexts={['0%', '20%', '40%', '60%', '80%', '100%']} // yAxisLabelTexts={['0%', '👉', '👉', '👉', '👉', '100%']} // 👈 only 0% and 100% - yAxisTextStyle={{ color: '#000', fontSize: 10 }} - xAxisLabelTextStyle={{ fontSize: 10, marginTop: 4 }} + yAxisTextStyle={{ color: '#000', fontSize: 12 }} + xAxisLabelTextStyle={{ color: '#000', fontSize: 12, fontWeight: '500', marginTop: 5 }} isAnimated 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 }} /> + {/* */} + ); + + case "Table": return ( @@ -721,36 +788,10 @@ const Dashboard = (props) => { default: return ( null - // - // - // Unsupported Graph Type: {item.GraphType} - // - // ); } }; - 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) const debouncedSearch = useCallback(_.debounce((text) => { @@ -896,7 +937,10 @@ const Dashboard = (props) => { textstyle={styles.btntext} onPress={() => { if (storeData) { - getTabData(mainDisplayJson); + console.log("🔽 Triggered getTabData with filters:", { year, month }); + setTimeout(() => { + getTabData(mainDisplayJson); + }, 50); } else { Alert.alert('Please select a store first.'); } @@ -960,55 +1004,57 @@ const Dashboard = (props) => { {/* Score Card */} - + - {firstItem && ( - { - if (firstItem.clickable === 1 && firstItem.DetailsPage?.length > 0) { - setSelectedDetails(firstItem.DetailsPage); - setShowDetailsModal(true); - fetchDetailGraphs(firstItem.DetailsPage); - } - }} - > - + {firstItem && ( + { + if (firstItem.clickable === 1 && firstItem.DetailsPage?.length > 0) { + setSelectedDetails(firstItem.DetailsPage); + setShowDetailsModal(true); + fetchDetailGraphs(firstItem.DetailsPage); + } + }} > - - - {firstItem.GraphTitle} - - {(() => { - const values = graphApiData[firstItem.GraphUrl]?.data || []; - const score = Object.values(values[0] || {})[0]; - return score !== undefined ? `${score.toFixed(1)}%` : '0.0%'; - })()} - - - - {firstItem.clickable === 1 && ( - - )} + + + + {firstItem.GraphTitle} + + {(() => { + const values = graphApiData[firstItem.GraphUrl]?.data || []; + const score = Object.values(values[0] || {})[0]; + return score !== undefined ? `${score.toFixed(1)}%` : '0.0%'; + })()} + + + + {firstItem.clickable === 1 && ( + + )} + - - - )} - + + )} + + `${item.GraphId}-${index}`} @@ -1018,6 +1064,7 @@ const Dashboard = (props) => { contentContainerStyle={{ paddingHorizontal: 2, paddingVertical: 2 }} showsVerticalScrollIndicator={false} /> + @@ -1115,8 +1162,8 @@ const Dashboard = (props) => { borderTopLeftRadius: 8, borderTopRightRadius: 8, }}> - {displayKey ? displayKey.replace(/_/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2') : 'Display'} - {presentKey ? presentKey.replace(/_/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2') : 'Present'} + {displayKey ? displayKey.replace(/_/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2') : ''} + {presentKey ? presentKey.replace(/_/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2') : ''}