first commit
|
After Width: | Height: | Size: 168 KiB |
@@ -110,6 +110,11 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
// The version of react-native is set by the React Native Gradle Plugin
|
// The version of react-native is set by the React Native Gradle Plugin
|
||||||
implementation("com.facebook.react:react-android")
|
implementation("com.facebook.react:react-android")
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
implementation project(':react-native-vector-icons')
|
||||||
|
implementation project(':react-native-fs')
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|
||||||
if (hermesEnabled.toBoolean()) {
|
if (hermesEnabled.toBoolean()) {
|
||||||
implementation("com.facebook.react:hermes-android")
|
implementation("com.facebook.react:hermes-android")
|
||||||
@@ -117,3 +122,9 @@ dependencies {
|
|||||||
implementation jscFlavor
|
implementation jscFlavor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
|
||||||
|
apply from: file("../../node_modules/react-native-vector-icons/fonts.gradle")
|
||||||
|
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".MainApplication"
|
android:name=".MainApplication"
|
||||||
|
|||||||
|
After Width: | Height: | Size: 3.5 KiB |
@@ -1,3 +1,7 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
<<<<<<< HEAD
|
||||||
<string name="app_name">PerformicsStoreDNA</string>
|
<string name="app_name">PerformicsStoreDNA</string>
|
||||||
|
=======
|
||||||
|
<string name="app_name">Performics Store DNA</string>
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -32,7 +32,12 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
|
|||||||
# your application. You should enable this flag either if you want
|
# your application. You should enable this flag either if you want
|
||||||
# to write custom TurboModules/Fabric components OR use libraries that
|
# to write custom TurboModules/Fabric components OR use libraries that
|
||||||
# are providing them.
|
# are providing them.
|
||||||
|
<<<<<<< HEAD
|
||||||
newArchEnabled=true
|
newArchEnabled=true
|
||||||
|
=======
|
||||||
|
newArchEnabled=false
|
||||||
|
org.gradle.java.home=/opt/homebrew/opt/openjdk@17
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|
||||||
# Use this property to enable or disable the Hermes JS engine.
|
# Use this property to enable or disable the Hermes JS engine.
|
||||||
# If set to false, you will be using JSC instead.
|
# If set to false, you will be using JSC instead.
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
@REM Copyright (c) Meta Platforms, Inc. and affiliates.
|
@REM Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
@REM
|
@REM
|
||||||
@REM This source code is licensed under the MIT license found in the
|
@REM This source code is licensed under the MIT license found in the
|
||||||
@@ -97,3 +98,104 @@ exit /b %EXIT_CODE%
|
|||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
:omega
|
:omega
|
||||||
|
=======
|
||||||
|
@REM Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
@REM
|
||||||
|
@REM This source code is licensed under the MIT license found in the
|
||||||
|
@REM LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%"=="" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
|
@rem This is normally unused
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
|
echo. 1>&2
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
|
echo. 1>&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
|
echo. 1>&2
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
|
echo. 1>&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=
|
||||||
|
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|||||||
@@ -4,3 +4,9 @@ extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autoli
|
|||||||
rootProject.name = 'PerformicsStoreDNA'
|
rootProject.name = 'PerformicsStoreDNA'
|
||||||
include ':app'
|
include ':app'
|
||||||
includeBuild('../node_modules/@react-native/gradle-plugin')
|
includeBuild('../node_modules/@react-native/gradle-plugin')
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
include ':react-native-fs'
|
||||||
|
project(':react-native-fs').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fs/android')
|
||||||
|
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|||||||
@@ -1,3 +1,10 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
presets: ['module:@react-native/babel-preset'],
|
presets: ['module:@react-native/babel-preset'],
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
plugins: [
|
||||||
|
// other plugins here...
|
||||||
|
'react-native-reanimated/plugin', // 👈 must be last
|
||||||
|
],
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,275 @@
|
|||||||
|
|
||||||
|
// const getTabData = async (tabData) => {
|
||||||
|
// try {
|
||||||
|
// const params = {
|
||||||
|
// parameters: {
|
||||||
|
// projectid: 41654,
|
||||||
|
// year: 2025,
|
||||||
|
// monthno: 6,
|
||||||
|
// storeid: storeData?.StoreId
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const graphDetails = tabData?.graphDetails || [];
|
||||||
|
|
||||||
|
// const uniqueUrls = [...new Set(graphDetails.map(graph => graph.GraphUrl))];
|
||||||
|
// // console.log('🔄 Unique URLs:', uniqueUrls);
|
||||||
|
|
||||||
|
// const apiCalls = uniqueUrls.map(url => post(url, params));
|
||||||
|
// const results = await Promise.all(apiCalls);
|
||||||
|
|
||||||
|
// const dataMap = {};
|
||||||
|
// uniqueUrls.forEach((url, idx) => {
|
||||||
|
// dataMap[url] = results[idx];
|
||||||
|
// });
|
||||||
|
|
||||||
|
// setGraphApiData(dataMap);
|
||||||
|
// } catch (err) {
|
||||||
|
// console.log("❌ Error fetching tab data:", err);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// Handle scroll event to show/hide button
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// const getTabData = async () => {
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// const params = {
|
||||||
|
// parameters: {
|
||||||
|
// projectid: 41654,
|
||||||
|
// year: 2025,
|
||||||
|
// monthno: 6,
|
||||||
|
// storeid: 2702
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // Extract all unique GraphUrls
|
||||||
|
// const uniqueUrls = [...new Set(graphDetails.map(graph => graph.GraphUrl))];
|
||||||
|
|
||||||
|
// console.log('uniqueUrls---->', uniqueUrls);
|
||||||
|
|
||||||
|
// // Call all APIs in parallel
|
||||||
|
// const apiCalls = uniqueUrls.map(url => post(url, params));
|
||||||
|
|
||||||
|
// const results = await Promise.all(apiCalls);
|
||||||
|
|
||||||
|
// // Optional: Map result to url if needed
|
||||||
|
// const dataMap = {};
|
||||||
|
// uniqueUrls.forEach((url, idx) => {
|
||||||
|
// dataMap[url] = results[idx];
|
||||||
|
// });
|
||||||
|
// setGraphApiData(dataMap);
|
||||||
|
|
||||||
|
// console.log("✅ All API responses:", JSON.stringify(dataMap));
|
||||||
|
|
||||||
|
// // You can now store `dataMap` into a state if needed
|
||||||
|
// // setGraphApiData(dataMap);
|
||||||
|
|
||||||
|
// } catch (err) {
|
||||||
|
// console.log("❌ Error fetching tab data:", err);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// };
|
||||||
|
|
||||||
|
|
||||||
|
// const getTabData = () => {
|
||||||
|
// let params = {
|
||||||
|
// "parameters": {
|
||||||
|
// "projectid": 41654,
|
||||||
|
// "year": 2025,
|
||||||
|
// "monthno": 6,
|
||||||
|
// "storeid": 2702
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// post(ApiURL.pssscoreApi, params)
|
||||||
|
// .then(res => {
|
||||||
|
// console.log('psscoreApi res==>', res);
|
||||||
|
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const renderItem = ({ item }) => {
|
||||||
|
|
||||||
|
// switch (item.GraphType) {
|
||||||
|
// case "ScoreCard":
|
||||||
|
// return (
|
||||||
|
// <View style={[styles.percentBox, { backgroundColor: item.GraphBackground }]}>
|
||||||
|
// <Text style={styles.boxText}>{item.GraphTitle}</Text>
|
||||||
|
// <Text style={[styles.boxText, { fontWeight: '500', fontSize: 24, marginTop: 10 }]}>{"45%"}</Text>
|
||||||
|
// </View>
|
||||||
|
// );
|
||||||
|
|
||||||
|
// case "BarGraph":
|
||||||
|
// const barData = {
|
||||||
|
// labels: ["Jan", "Feb", "Mar", "Apr"],
|
||||||
|
// datasets: [{ data: [35, 45, 20, 55] }]
|
||||||
|
// };
|
||||||
|
// return (
|
||||||
|
// <View style={{ padding: 10, backgroundColor: '', borderRadius: 8 }}>
|
||||||
|
// <Text style={{ fontSize: 16, fontWeight: '600', marginBottom: 10 }}>
|
||||||
|
// SOS Compliance Trend
|
||||||
|
// </Text>
|
||||||
|
// <BarChart
|
||||||
|
// data={barData}
|
||||||
|
// width={screenWidth - 40}
|
||||||
|
// height={220}
|
||||||
|
// yAxisSuffix="%"
|
||||||
|
// chartConfig={chartConfig}
|
||||||
|
// fromZero
|
||||||
|
// showValuesOnTopOfBars
|
||||||
|
// withInnerLines
|
||||||
|
// />
|
||||||
|
// </View>
|
||||||
|
// );
|
||||||
|
|
||||||
|
// case "Table":
|
||||||
|
// return (
|
||||||
|
// <View style={{ flex: 1, }}>
|
||||||
|
// <ScrollView>
|
||||||
|
// <View style={{ flexDirection: 'row', borderWidth: 1, borderColor: '#EAEAEA', alignItems: 'center', alignSelf: 'flex-start', padding: 5, borderRadius: 15 }}>
|
||||||
|
// <TouchableOpacity
|
||||||
|
// style={[styles.subTab, { backgroundColor: '#113F8C' }]}>
|
||||||
|
// <Text style={[styles.tabText, { color: "#fff" }]}>{'Asset'}</Text>
|
||||||
|
// </TouchableOpacity>
|
||||||
|
|
||||||
|
// <TouchableOpacity
|
||||||
|
// style={[styles.subTab, { backgroundColor: '#113F8C' }]}>
|
||||||
|
// <Text style={[styles.tabText, { color: "#fff" }]}>{'Asset Details'}</Text>
|
||||||
|
// </TouchableOpacity>
|
||||||
|
|
||||||
|
// </View>
|
||||||
|
|
||||||
|
// {assetData && assetData.map((table, index) => (
|
||||||
|
// <View key={index} style={{ marginTop: 10 }}>
|
||||||
|
// <Text style={{ fontSize: 16, color: '#000', fontWeight: '500' }}>{table.section}</Text>
|
||||||
|
|
||||||
|
// <View style={{ marginTop: 5, backgroundColor: '#fff', elevation: 5, padding: 10, borderRadius: 10 }}>
|
||||||
|
// <View style={{ flexDirection: 'row', borderBottomWidth: 1, borderColor: '#E0E0E0', paddingBottom: 7, }}>
|
||||||
|
// <Text style={{ width: '50%', color: '#676767', fontSize: 14 }}>Display</Text>
|
||||||
|
// <Text style={{ width: '50%', color: '#676767', fontSize: 14 }}>Present</Text>
|
||||||
|
// </View>
|
||||||
|
// {
|
||||||
|
// table && table.data.map((item) => (
|
||||||
|
// <View style={{ marginTop: 3, flexDirection: 'row', paddingBottom: 7, borderBottomWidth: 1, borderColor: '#E0E0E0', }}>
|
||||||
|
// <Text style={{ width: '50%', color: '#000', fontSize: 14, }}>{item.display}</Text>
|
||||||
|
// <Text style={{ width: '50%', color: '#000', fontSize: 14, }}>{item?.present}</Text>
|
||||||
|
// </View>
|
||||||
|
// ))}
|
||||||
|
// </View>
|
||||||
|
// </View>
|
||||||
|
|
||||||
|
// ))}
|
||||||
|
// <View style={{ marginBottom: 500 }} />
|
||||||
|
// </ScrollView>
|
||||||
|
// </View>
|
||||||
|
// )
|
||||||
|
|
||||||
|
// case "LineChart":
|
||||||
|
// return (
|
||||||
|
// <View style={{ flex: 1, }}>
|
||||||
|
// <Text>Bezier Line Chart</Text>
|
||||||
|
// <LineChart
|
||||||
|
// data={{
|
||||||
|
// labels: ["January", "February", "March", "April", "May", "June"],
|
||||||
|
// datasets: [
|
||||||
|
// {
|
||||||
|
// data: [
|
||||||
|
// Math.random() * 100,
|
||||||
|
// Math.random() * 100,
|
||||||
|
// Math.random() * 100,
|
||||||
|
// Math.random() * 100,
|
||||||
|
// Math.random() * 100,
|
||||||
|
// Math.random() * 100
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// }}
|
||||||
|
// width={Dimensions.get("window").width} // from react-native
|
||||||
|
// height={220}
|
||||||
|
// yAxisLabel="$"
|
||||||
|
// yAxisSuffix="k"
|
||||||
|
// yAxisInterval={1} // optional, defaults to 1
|
||||||
|
// chartConfig={{
|
||||||
|
// backgroundColor: "#e26a00",
|
||||||
|
// backgroundGradientFrom: "lgray",
|
||||||
|
// backgroundGradientTo: "lightblue",
|
||||||
|
// decimalPlaces: 2, // optional, defaults to 2dp
|
||||||
|
// color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
|
||||||
|
// labelColor: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
|
||||||
|
// style: {
|
||||||
|
// borderRadius: 16
|
||||||
|
// },
|
||||||
|
// propsForDots: {
|
||||||
|
// r: "6",
|
||||||
|
// strokeWidth: "2",
|
||||||
|
// stroke: "#ffa726"
|
||||||
|
// }
|
||||||
|
// }}
|
||||||
|
// bezier
|
||||||
|
// style={{
|
||||||
|
// marginVertical: 8,
|
||||||
|
// borderRadius: 16
|
||||||
|
// }}
|
||||||
|
// />
|
||||||
|
// </View>
|
||||||
|
// )
|
||||||
|
// case "PieChart":
|
||||||
|
// return (
|
||||||
|
// <View style={{ flex: 1, }}>
|
||||||
|
// <PieChart
|
||||||
|
// data={PieData}
|
||||||
|
// width={screenWidth}
|
||||||
|
// height={220}
|
||||||
|
// chartConfig={chartConfig}
|
||||||
|
// accessor={"population"}
|
||||||
|
// backgroundColor={"transparent"}
|
||||||
|
// paddingLeft={"15"}
|
||||||
|
// center={[10, 50]}
|
||||||
|
// absolute
|
||||||
|
// />
|
||||||
|
// </View>
|
||||||
|
// )
|
||||||
|
|
||||||
|
// default:
|
||||||
|
// return (
|
||||||
|
// <View style={[styles.percentBox, { backgroundColor: "#f8d7da", padding: 10, marginVertical: 5 }]}>
|
||||||
|
// <Text style={[styles.boxText, { color: "#721c24" }]}>
|
||||||
|
// Unsupported Graph Type: {item.GraphType}
|
||||||
|
// </Text>
|
||||||
|
// </View>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const getFilterStateCity = () => {
|
||||||
|
|
||||||
|
// let data = JSON.stringify({
|
||||||
|
// "UserId": "RH5"
|
||||||
|
// });
|
||||||
|
|
||||||
|
// let config = {
|
||||||
|
// method: 'post',
|
||||||
|
// maxBodyLength: Infinity,
|
||||||
|
// url: 'https://api1.parinaam.in/api/dabur/StoreDNAfilter',
|
||||||
|
// headers: {
|
||||||
|
// 'api_key': '9a1f056fecb84eaf8eb4152dda22ab0501955c4f9bbe7daa8780740459fdde7a',
|
||||||
|
// 'Content-Type': 'application/json'
|
||||||
|
// },
|
||||||
|
// data: data
|
||||||
|
// };
|
||||||
|
|
||||||
|
// axios.request(config)
|
||||||
|
// .then((response) => {
|
||||||
|
// console.log("filter", JSON.stringify(response.data));
|
||||||
|
|
||||||
|
|
||||||
|
// })
|
||||||
|
// .catch((error) => {
|
||||||
|
// console.log(error);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// }
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||||
761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; };
|
761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; };
|
||||||
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
|
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
|
||||||
|
<<<<<<< HEAD
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@@ -25,6 +26,13 @@
|
|||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
=======
|
||||||
|
D36C74772E212F7200955E13 /* white.png in Resources */ = {isa = PBXBuildFile; fileRef = D36C74762E212F7200955E13 /* white.png */; };
|
||||||
|
DB45BE4A6E0F03A0CC859A6F /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXFileReference section */
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
13B07F961A680F5B00A75B9A /* PerformicsStoreDNA.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PerformicsStoreDNA.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
13B07F961A680F5B00A75B9A /* PerformicsStoreDNA.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PerformicsStoreDNA.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = PerformicsStoreDNA/Images.xcassets; sourceTree = "<group>"; };
|
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = PerformicsStoreDNA/Images.xcassets; sourceTree = "<group>"; };
|
||||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = PerformicsStoreDNA/Info.plist; sourceTree = "<group>"; };
|
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = PerformicsStoreDNA/Info.plist; sourceTree = "<group>"; };
|
||||||
@@ -34,6 +42,10 @@
|
|||||||
5DCACB8F33CDC322A6C60F78 /* libPods-PerformicsStoreDNA.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PerformicsStoreDNA.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
5DCACB8F33CDC322A6C60F78 /* libPods-PerformicsStoreDNA.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PerformicsStoreDNA.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = PerformicsStoreDNA/AppDelegate.swift; sourceTree = "<group>"; };
|
761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = PerformicsStoreDNA/AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = PerformicsStoreDNA/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = PerformicsStoreDNA/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
D36C74762E212F7200955E13 /* white.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = white.png; sourceTree = "<group>"; };
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
@@ -49,6 +61,7 @@
|
|||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
<<<<<<< HEAD
|
||||||
00E356F01AD99517003FC87E /* Supporting Files */ = {
|
00E356F01AD99517003FC87E /* Supporting Files */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -57,6 +70,8 @@
|
|||||||
name = "Supporting Files";
|
name = "Supporting Files";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
=======
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
13B07FAE1A68108700A75B9A /* PerformicsStoreDNA */ = {
|
13B07FAE1A68108700A75B9A /* PerformicsStoreDNA */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -88,6 +103,10 @@
|
|||||||
83CBB9F61A601CBA00E9B192 = {
|
83CBB9F61A601CBA00E9B192 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
D36C74762E212F7200955E13 /* white.png */,
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
13B07FAE1A68108700A75B9A /* PerformicsStoreDNA */,
|
13B07FAE1A68108700A75B9A /* PerformicsStoreDNA */,
|
||||||
832341AE1AAA6A7D00B99B32 /* Libraries */,
|
832341AE1AAA6A7D00B99B32 /* Libraries */,
|
||||||
83CBBA001A601CBA00E9B192 /* Products */,
|
83CBBA001A601CBA00E9B192 /* Products */,
|
||||||
@@ -172,6 +191,7 @@
|
|||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
<<<<<<< HEAD
|
||||||
00E356EC1AD99517003FC87E /* Resources */ = {
|
00E356EC1AD99517003FC87E /* Resources */ = {
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -179,12 +199,20 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
=======
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
13B07F8E1A680F5B00A75B9A /* Resources */ = {
|
13B07F8E1A680F5B00A75B9A /* Resources */ = {
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
|
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
|
||||||
|
<<<<<<< HEAD
|
||||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||||
|
=======
|
||||||
|
D36C74772E212F7200955E13 /* white.png in Resources */,
|
||||||
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||||
|
DB45BE4A6E0F03A0CC859A6F /* PrivacyInfo.xcprivacy in Resources */,
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -215,10 +243,20 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-PerformicsStoreDNA/Pods-PerformicsStoreDNA-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-PerformicsStoreDNA/Pods-PerformicsStoreDNA-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
);
|
);
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
name = "[CP] Embed Pods Frameworks";
|
name = "[CP] Embed Pods Frameworks";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-PerformicsStoreDNA/Pods-PerformicsStoreDNA-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-PerformicsStoreDNA/Pods-PerformicsStoreDNA-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
);
|
);
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PerformicsStoreDNA/Pods-PerformicsStoreDNA-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PerformicsStoreDNA/Pods-PerformicsStoreDNA-frameworks.sh\"\n";
|
||||||
@@ -254,10 +292,20 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-PerformicsStoreDNA/Pods-PerformicsStoreDNA-resources-${CONFIGURATION}-input-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-PerformicsStoreDNA/Pods-PerformicsStoreDNA-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
);
|
);
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
name = "[CP] Copy Pods Resources";
|
name = "[CP] Copy Pods Resources";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-PerformicsStoreDNA/Pods-PerformicsStoreDNA-resources-${CONFIGURATION}-output-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-PerformicsStoreDNA/Pods-PerformicsStoreDNA-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
);
|
);
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PerformicsStoreDNA/Pods-PerformicsStoreDNA-resources.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PerformicsStoreDNA/Pods-PerformicsStoreDNA-resources.sh\"\n";
|
||||||
@@ -276,6 +324,7 @@
|
|||||||
};
|
};
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
/* Begin PBXTargetDependency section */
|
/* Begin PBXTargetDependency section */
|
||||||
00E356F51AD99517003FC87E /* PBXTargetDependency */ = {
|
00E356F51AD99517003FC87E /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
@@ -284,6 +333,8 @@
|
|||||||
};
|
};
|
||||||
/* End PBXTargetDependency section */
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
@@ -291,7 +342,12 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
<<<<<<< HEAD
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
=======
|
||||||
|
CURRENT_PROJECT_VERSION = 9;
|
||||||
|
DEVELOPMENT_TEAM = JGDHGNH9XY;
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = PerformicsStoreDNA/Info.plist;
|
INFOPLIST_FILE = PerformicsStoreDNA/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
||||||
@@ -299,13 +355,21 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
|
<<<<<<< HEAD
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
|
=======
|
||||||
|
MARKETING_VERSION = 1.9;
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"-ObjC",
|
"-ObjC",
|
||||||
"-lc++",
|
"-lc++",
|
||||||
);
|
);
|
||||||
|
<<<<<<< HEAD
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
||||||
|
=======
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.performicsstoredna;
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
PRODUCT_NAME = PerformicsStoreDNA;
|
PRODUCT_NAME = PerformicsStoreDNA;
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
@@ -319,20 +383,33 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
<<<<<<< HEAD
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
=======
|
||||||
|
CURRENT_PROJECT_VERSION = 9;
|
||||||
|
DEVELOPMENT_TEAM = JGDHGNH9XY;
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
INFOPLIST_FILE = PerformicsStoreDNA/Info.plist;
|
INFOPLIST_FILE = PerformicsStoreDNA/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
|
<<<<<<< HEAD
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
|
=======
|
||||||
|
MARKETING_VERSION = 1.9;
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"-ObjC",
|
"-ObjC",
|
||||||
"-lc++",
|
"-lc++",
|
||||||
);
|
);
|
||||||
|
<<<<<<< HEAD
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
||||||
|
=======
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.performicsstoredna;
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
PRODUCT_NAME = PerformicsStoreDNA;
|
PRODUCT_NAME = PerformicsStoreDNA;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
@@ -408,7 +485,15 @@
|
|||||||
"-DFOLLY_CFG_NO_COROUTINES=1",
|
"-DFOLLY_CFG_NO_COROUTINES=1",
|
||||||
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
|
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
|
||||||
);
|
);
|
||||||
|
<<<<<<< HEAD
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
=======
|
||||||
|
OTHER_LDFLAGS = "$(inherited) ";
|
||||||
|
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
|
||||||
|
USE_HERMES = true;
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
@@ -473,7 +558,14 @@
|
|||||||
"-DFOLLY_CFG_NO_COROUTINES=1",
|
"-DFOLLY_CFG_NO_COROUTINES=1",
|
||||||
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
|
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
|
||||||
);
|
);
|
||||||
|
<<<<<<< HEAD
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
=======
|
||||||
|
OTHER_LDFLAGS = "$(inherited) ";
|
||||||
|
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
USE_HERMES = true;
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
VALIDATE_PRODUCT = YES;
|
VALIDATE_PRODUCT = YES;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "group:PerformicsStoreDNA.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
<FileRef
|
||||||
|
location = "group:Pods/Pods.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict/>
|
||||||
|
</plist>
|
||||||
|
After Width: | Height: | Size: 393 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
@@ -1,46 +1,82 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
"filename" : "40.png",
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "20x20"
|
"size" : "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
"filename" : "60.png",
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "3x",
|
"scale" : "3x",
|
||||||
"size" : "20x20"
|
"size" : "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
"filename" : "58.png",
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "29x29"
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
"filename" : "87.png",
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "3x",
|
"scale" : "3x",
|
||||||
"size" : "29x29"
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
"filename" : "80.png",
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "40x40"
|
"size" : "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
"filename" : "120.png",
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "3x",
|
"scale" : "3x",
|
||||||
"size" : "40x40"
|
"size" : "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
"filename" : "120 1.png",
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "60x60"
|
"size" : "60x60"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
"filename" : "180.png",
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "3x",
|
"scale" : "3x",
|
||||||
"size" : "60x60"
|
"size" : "60x60"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
"filename" : "1024.png",
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
"idiom" : "ios-marketing",
|
"idiom" : "ios-marketing",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "1024x1024"
|
"size" : "1024x1024"
|
||||||
|
|||||||
|
After Width: | Height: | Size: 3.5 KiB |
@@ -26,16 +26,52 @@
|
|||||||
<true/>
|
<true/>
|
||||||
<key>NSAppTransportSecurity</key>
|
<key>NSAppTransportSecurity</key>
|
||||||
<dict>
|
<dict>
|
||||||
|
<<<<<<< HEAD
|
||||||
<!-- Do not change NSAllowsArbitraryLoads to true, or you will risk app rejection! -->
|
<!-- Do not change NSAllowsArbitraryLoads to true, or you will risk app rejection! -->
|
||||||
|
=======
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
<key>NSAllowsArbitraryLoads</key>
|
<key>NSAllowsArbitraryLoads</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>NSAllowsLocalNetworking</key>
|
<key>NSAllowsLocalNetworking</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>NSLocationWhenInUseUsageDescription</key>
|
<key>NSLocationWhenInUseUsageDescription</key>
|
||||||
|
<<<<<<< HEAD
|
||||||
<string></string>
|
<string></string>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
|
=======
|
||||||
|
<string>This app uses your location to enhance reporting and store-related services.</string>
|
||||||
|
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||||
|
<string>We need access to your location for [your reason, e.g., providing location-based services].</string>
|
||||||
|
<key>RCTNewArchEnabled</key>
|
||||||
|
<true/>
|
||||||
|
<key>UILaunchStoryboardName</key>
|
||||||
|
<string>LaunchScreen</string>
|
||||||
|
<key>NSCameraUsageDescription</key>
|
||||||
|
<string>We need access to your camera to take photos.</string>
|
||||||
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
|
<string>We need access to your microphone for video recording.</string>
|
||||||
|
<key>UIAppFonts</key>
|
||||||
|
<array>
|
||||||
|
<string>AntDesign.ttf</string>
|
||||||
|
<string>Entypo.ttf</string>
|
||||||
|
<string>EvilIcons.ttf</string>
|
||||||
|
<string>Feather.ttf</string>
|
||||||
|
<string>FontAwesome.ttf</string>
|
||||||
|
<string>FontAwesome5_Brands.ttf</string>
|
||||||
|
<string>FontAwesome5_Regular.ttf</string>
|
||||||
|
<string>FontAwesome5_Solid.ttf</string>
|
||||||
|
<string>Fontisto.ttf</string>
|
||||||
|
<string>Foundation.ttf</string>
|
||||||
|
<string>Ionicons.ttf</string>
|
||||||
|
<string>MaterialIcons.ttf</string>
|
||||||
|
<string>MaterialCommunityIcons.ttf</string>
|
||||||
|
<string>SimpleLineIcons.ttf</string>
|
||||||
|
<string>Octicons.ttf</string>
|
||||||
|
<string>Zocial.ttf</string>
|
||||||
|
</array>
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
<key>UIRequiredDeviceCapabilities</key>
|
<key>UIRequiredDeviceCapabilities</key>
|
||||||
<array>
|
<array>
|
||||||
<string>arm64</string>
|
<string>arm64</string>
|
||||||
|
|||||||
|
After Width: | Height: | Size: 3.5 KiB |
@@ -0,0 +1,16 @@
|
|||||||
|
-----BEGIN CERTIFICATE REQUEST-----
|
||||||
|
MIICiDCCAXACAQAwQzEmMCQGCSqGSIb3DQEJARYXY3BtaW5kaWFpdEBjcG1pbmRp
|
||||||
|
YS5jb20xDDAKBgNVBAMMA0NQTTELMAkGA1UEBhMCSU4wggEiMA0GCSqGSIb3DQEB
|
||||||
|
AQUAA4IBDwAwggEKAoIBAQD5H7EcZgD+77Vb5lruKpetnuU7vSZvZgnmL/4bkLuk
|
||||||
|
R2iSNmu/kGGp/oY87kHeTEoNV6YJ7vveDAs5r1OInU6s/YKve6w94cK6IG0NFUnH
|
||||||
|
6gR3TJbLduoKRvlPPne0Yrgap5YfYfnQ7GkMHohpa2zyCUlo1+u8KqjPos5f07S/
|
||||||
|
6vSEAV4FMAgrYqSgRxRPPhw8UUJ9MFiSH3NtYYYXcbql1j/fFHiL/gJmClKRilNd
|
||||||
|
TScorE4h95YeylJtBmiqRQSN76gophmjiWDVLnP7s3AyGKhw0FmwYJMc2b89/TwL
|
||||||
|
uDGVFSxM9IGRb7UoKYWU9N8ThGoOghmiAwCiNd+VDKbnAgMBAAGgADANBgkqhkiG
|
||||||
|
9w0BAQsFAAOCAQEAxXc475lytyZVl/Iahdgj9xHS2shwgL6k9Eu5OqIGkGovrx0F
|
||||||
|
63Eu4pyqgjh0ZfTC2somOYvA39NHEDiNXfjNYLRUo6PVNMxuVRVjjSR0UvfBcC88
|
||||||
|
Fjo8I8m/2ovTjNSTgIgDCexfNYFdlJP7mqGJ9nybmPdvzWLVuB9N77zElnusLsTl
|
||||||
|
pr3q1RBnetkYf9xNGRdeQIRHtJJrnVTDgXHwCcd9W91z1O2vnxHubhwqHf8gsr8h
|
||||||
|
GRL2bFZGJBc8JJ91lo2NNrXAzeFEUALOdfBPtzoB98+Npo1pjlUoFJNZvirrOyq3
|
||||||
|
DZzLyLlz3PH9Qvw9GGVQ63NHsbTcX84YFpfRZg==
|
||||||
|
-----END CERTIFICATE REQUEST-----
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
{
|
{
|
||||||
"name": "PerformicsStoreDNA",
|
"name": "PerformicsStoreDNA",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
@@ -56,3 +57,85 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
=======
|
||||||
|
{
|
||||||
|
"name": "PerformicsStoreDNA",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"android": "react-native run-android",
|
||||||
|
"ios": "react-native run-ios",
|
||||||
|
"lint": "eslint .",
|
||||||
|
"start": "react-native start",
|
||||||
|
"test": "jest",
|
||||||
|
"postinstall": "patch-package"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@bam.tech/react-native-image-resizer": "^3.0.11",
|
||||||
|
"@gluestack-ui/nativewind-utils": "^1.0.26",
|
||||||
|
"@gluestack-ui/overlay": "^0.1.22",
|
||||||
|
"@gluestack-ui/toast": "^1.0.9",
|
||||||
|
"@likashefqet/react-native-image-zoom": "^4.3.0",
|
||||||
|
"@react-native-async-storage/async-storage": "^2.2.0",
|
||||||
|
"@react-native-community/geolocation": "^3.4.0",
|
||||||
|
"@react-native/new-app-screen": "0.80.0",
|
||||||
|
"@react-navigation/elements": "^2.5.2",
|
||||||
|
"@react-navigation/native": "^7.1.14",
|
||||||
|
"@react-navigation/native-stack": "^7.3.21",
|
||||||
|
"@reduxjs/toolkit": "^2.8.2",
|
||||||
|
"axios": "^1.10.0",
|
||||||
|
"deprecated-react-native-prop-types": "^5.0.0",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
"moment": "^2.30.1",
|
||||||
|
"patch-package": "^8.0.0",
|
||||||
|
"react": "19.1.0",
|
||||||
|
"react-native": "0.80.0",
|
||||||
|
"react-native-chart-kit": "^6.12.0",
|
||||||
|
"react-native-element-dropdown": "^2.12.4",
|
||||||
|
"react-native-fs": "^2.20.0",
|
||||||
|
"react-native-gesture-handler": "^2.27.1",
|
||||||
|
"react-native-gifted-charts": "^1.4.63",
|
||||||
|
"react-native-keyboard-aware-scroll-view": "^0.9.5",
|
||||||
|
"react-native-linear-gradient": "^2.8.3",
|
||||||
|
"react-native-loader-kit": "^3.0.0",
|
||||||
|
"react-native-modal-selector": "^2.1.2",
|
||||||
|
"react-native-multiple-select": "^0.5.12",
|
||||||
|
"react-native-otp-entry": "^1.8.5",
|
||||||
|
"react-native-permissions": "^5.4.1",
|
||||||
|
"react-native-photo-manipulator": "^1.9.2",
|
||||||
|
"react-native-raw-bottom-sheet": "^3.0.0",
|
||||||
|
"react-native-reanimated": "^3.18.0",
|
||||||
|
"react-native-safe-area-context": "^5.5.0",
|
||||||
|
"react-native-screens": "^4.11.1",
|
||||||
|
"react-native-sqlite-storage": "^6.0.1",
|
||||||
|
"react-native-svg": "^15.12.0",
|
||||||
|
"react-native-toast-message": "^2.3.1",
|
||||||
|
"react-native-vector-icons": "^10.2.0",
|
||||||
|
"react-native-vision-camera": "^4.7.1",
|
||||||
|
"react-redux": "^9.2.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.25.2",
|
||||||
|
"@babel/preset-env": "^7.25.3",
|
||||||
|
"@babel/runtime": "^7.25.0",
|
||||||
|
"@react-native-community/cli": "19.0.0",
|
||||||
|
"@react-native-community/cli-platform-android": "19.0.0",
|
||||||
|
"@react-native-community/cli-platform-ios": "19.0.0",
|
||||||
|
"@react-native/babel-preset": "0.80.0",
|
||||||
|
"@react-native/eslint-config": "0.80.0",
|
||||||
|
"@react-native/metro-config": "0.80.0",
|
||||||
|
"@react-native/typescript-config": "0.80.0",
|
||||||
|
"@types/jest": "^29.5.13",
|
||||||
|
"@types/react": "^19.1.0",
|
||||||
|
"@types/react-test-renderer": "^19.1.0",
|
||||||
|
"eslint": "^8.19.0",
|
||||||
|
"jest": "^29.6.3",
|
||||||
|
"prettier": "2.8.8",
|
||||||
|
"react-test-renderer": "19.1.0",
|
||||||
|
"typescript": "5.0.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
// In App.js in a new project
|
// In App.js in a new project
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {Provider} from 'react-redux';
|
import {Provider} from 'react-redux';
|
||||||
@@ -13,3 +14,30 @@ function App() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
=======
|
||||||
|
import * as React from 'react';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
import Routes from './navigation/Routes';
|
||||||
|
import { store } from './redux/store';
|
||||||
|
import { initTables } from './constants/database';
|
||||||
|
import { CreateImageFolders } from './constants/function';
|
||||||
|
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
useEffect(() => {
|
||||||
|
initTables(); // Ensure DB tables are created
|
||||||
|
CreateImageFolders();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GestureHandlerRootView style={{ flex: 1 }}>
|
||||||
|
<Provider store={store}>
|
||||||
|
<Routes />
|
||||||
|
</Provider>
|
||||||
|
</GestureHandlerRootView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export const BASE_URL = 'https://dax.parinaam.in/execute/dabur';
|
||||||
|
|
||||||
|
export const ApiURL = {
|
||||||
|
|
||||||
|
pssscoreApi: `${BASE_URL}/mtd/pssscore`,
|
||||||
|
getotpApi: `https://api1.parinaam.in/api/dabur/SendOTP`,
|
||||||
|
verifyotpApi: `https://api1.parinaam.in/api/dabur/AuthenticateOTP`,
|
||||||
|
storeDNAfilter:`https://api1.parinaam.in/api/dabur/StoreDNAfilter`,
|
||||||
|
storeSearch :`https://api1.parinaam.in/api/dabur/StoreDNAstoreSearch`,
|
||||||
|
storeInfo :`https://api1.parinaam.in/api/dabur/StoreDNAstoreInfo`,
|
||||||
|
};
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { Alert } from 'react-native';
|
||||||
|
import { toastError } from '../components/Toast';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Call this api function without token only for login
|
||||||
|
export const request = async (url, formData) => {
|
||||||
|
const header = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
};
|
||||||
|
|
||||||
|
return axios.post(url, formData, { headers: header })
|
||||||
|
.then(response => {
|
||||||
|
return response.data;
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
return error;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Call this api function with token (POST type)
|
||||||
|
// export const post = async (url: string, formData: any) => {
|
||||||
|
// const header = {
|
||||||
|
// Authorization: 'Bearer ',
|
||||||
|
// Accept: 'application/json',
|
||||||
|
// };
|
||||||
|
// return AsyncStorage.getItem('token').then(async value => {
|
||||||
|
|
||||||
|
// const loginToken = JSON.parse(value as any);
|
||||||
|
|
||||||
|
// console.log('loginToken----->',loginToken);
|
||||||
|
|
||||||
|
// header.Authorization = `Bearer ${loginToken}`;
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// const response = await axios
|
||||||
|
// .post(url, formData, { headers: header });
|
||||||
|
// return response.data;
|
||||||
|
// } catch (error) {
|
||||||
|
// // console.log(url);
|
||||||
|
// // console.log(formData);
|
||||||
|
// console.log('AXIOS ERROR status: ', error);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
|
||||||
|
export const post = async (url, formData) => {
|
||||||
|
try {
|
||||||
|
// const tokenValue = await AsyncStorage.getItem('token');
|
||||||
|
// if (!tokenValue) {
|
||||||
|
// console.error('No token found in AsyncStorage');
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const loginToken = JSON.parse(tokenValue);
|
||||||
|
// console.log('loginToken----->', loginToken);
|
||||||
|
|
||||||
|
const headers = {
|
||||||
|
Authorization: ``,
|
||||||
|
Accept: 'application/json',
|
||||||
|
"X-API-Key":"f7fa9b09-ced8-4862-8cb7-5e7599d90fa2"
|
||||||
|
};
|
||||||
|
|
||||||
|
// console.log('URL => ',url);
|
||||||
|
// console.log('PARAMS => ',formData);
|
||||||
|
|
||||||
|
|
||||||
|
const response = await axios.post(url, formData, { headers });
|
||||||
|
return response.data;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('API Error:', error.response?.data || error.message);
|
||||||
|
Alert.alert(`Alert`,`${error.response?.data?.message ?error.response?.data?.message:'Server Error'}`)
|
||||||
|
// toastError('Alert',`${error.response?.data?.message}`)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// CALL THIS API FUNCTION FOR GET TYPE API
|
||||||
|
export const get = async (url) => {
|
||||||
|
const header = {
|
||||||
|
Authorization: 'Bearer ',
|
||||||
|
Accept: 'application/json',
|
||||||
|
};
|
||||||
|
return AsyncStorage.getItem('token').then(async value => {
|
||||||
|
const loginToken = JSON.parse(value);
|
||||||
|
|
||||||
|
// console.log('URL---->',url);
|
||||||
|
// console.log('loginToken---->',loginToken);
|
||||||
|
|
||||||
|
header.Authorization = `Bearer ${loginToken}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await axios
|
||||||
|
.get(url, { headers: header });
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
if (error) {
|
||||||
|
console.log('AXIOS ERROR status: ', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const uploadImage = async (url, formData) => {
|
||||||
|
const header = {
|
||||||
|
Authorization: 'Bearer ',
|
||||||
|
Accept: 'application/json',
|
||||||
|
'Content-Type': `multipart/form-data`,
|
||||||
|
};
|
||||||
|
|
||||||
|
return AsyncStorage.getItem('userToken').then(value => {
|
||||||
|
const token = JSON.parse(value);
|
||||||
|
header.Authorization = `Bearer ${token}`;
|
||||||
|
|
||||||
|
let dataf = {
|
||||||
|
uri: formData.path,
|
||||||
|
type: formData.mime,
|
||||||
|
name: formData.path,
|
||||||
|
};
|
||||||
|
var data = new FormData();
|
||||||
|
data.append('image', dataf);
|
||||||
|
console.log('header', header);
|
||||||
|
return fetch(url, {
|
||||||
|
headers: header,
|
||||||
|
method: 'POST',
|
||||||
|
body: data,
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(json => {
|
||||||
|
console.log('API', url);
|
||||||
|
console.log('formData', formData);
|
||||||
|
console.log('json data', json);
|
||||||
|
return json;
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log('API', url);
|
||||||
|
console.log('formData', formData);
|
||||||
|
console.log('error ', error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const cityData = async () => {
|
||||||
|
return AsyncStorage.getItem('cityshortname').then(e => {
|
||||||
|
const user = JSON.parse(e);
|
||||||
|
console.log('user,user', user);
|
||||||
|
return user;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
After Width: | Height: | Size: 546 B |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 601 B |
|
After Width: | Height: | Size: 458 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 408 B |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 221 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
@@ -0,0 +1,102 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
Alert,
|
||||||
|
View,
|
||||||
|
TouchableOpacity,
|
||||||
|
Text,
|
||||||
|
} from 'react-native';
|
||||||
|
import CustomModal from './CustomModal';
|
||||||
|
import { useRoute } from '@react-navigation/native';
|
||||||
|
import { GlobalTheme } from '../theme';
|
||||||
|
|
||||||
|
export const CustomAlert = (
|
||||||
|
title = '',
|
||||||
|
msg = '',
|
||||||
|
onCancel = () => { },
|
||||||
|
onDone = () => { }
|
||||||
|
) => {
|
||||||
|
Alert.alert(title, msg, [
|
||||||
|
{
|
||||||
|
text: 'Cancel',
|
||||||
|
onPress: onCancel,
|
||||||
|
style: 'cancel',
|
||||||
|
},
|
||||||
|
{ text: 'OK', onPress: onDone },
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
export function ConfirmSaveAlert({
|
||||||
|
showAlert = false,
|
||||||
|
onCancelCallBack = () => { },
|
||||||
|
onYesCallBack = () => { },
|
||||||
|
msg = 'Do you really want to save data?',
|
||||||
|
yesText = 'Yes',
|
||||||
|
cancelText = 'No',
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<CustomModal
|
||||||
|
title={msg}
|
||||||
|
showModal={showAlert}
|
||||||
|
onClose={onCancelCallBack} // 👈 ensures modal closes when tapping close icon
|
||||||
|
>
|
||||||
|
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginTop: 20, width: '60%' }}>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={{
|
||||||
|
paddingHorizontal: 25,
|
||||||
|
paddingVertical: 10,
|
||||||
|
backgroundColor: GlobalTheme.colors.primary,
|
||||||
|
borderRadius: 5,
|
||||||
|
}}
|
||||||
|
onPress={onYesCallBack}
|
||||||
|
>
|
||||||
|
<Text style={{
|
||||||
|
color: '#FFF',
|
||||||
|
fontSize: GlobalTheme.typography.fontSize.small,
|
||||||
|
fontWeight: GlobalTheme.typography.fontWeight.medium
|
||||||
|
}}>
|
||||||
|
{yesText}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={{
|
||||||
|
paddingHorizontal: 25,
|
||||||
|
paddingVertical: 10,
|
||||||
|
backgroundColor: '#ccc',
|
||||||
|
borderRadius: 5,
|
||||||
|
}}
|
||||||
|
onPress={onCancelCallBack}
|
||||||
|
>
|
||||||
|
<Text style={{
|
||||||
|
color: '#000',
|
||||||
|
fontSize: GlobalTheme.typography.fontSize.small,
|
||||||
|
fontWeight: GlobalTheme.typography.fontWeight.medium
|
||||||
|
}}>
|
||||||
|
{cancelText}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</CustomModal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function ExitScreenAlert(props, callback) {
|
||||||
|
Alert.alert(
|
||||||
|
'',
|
||||||
|
'Do you really want to exit the screen?',
|
||||||
|
[
|
||||||
|
{
|
||||||
|
text: 'Cancel',
|
||||||
|
onPress: () => { },
|
||||||
|
style: 'cancel',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'OK',
|
||||||
|
onPress: () => {
|
||||||
|
if (typeof callback === 'function') callback();
|
||||||
|
props.navigation.goBack();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
// src/components/Background.js
|
// src/components/Background.js
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
@@ -28,3 +29,38 @@ const styles = StyleSheet.create({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export default Background;
|
export default Background;
|
||||||
|
=======
|
||||||
|
// src/components/Background.js
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { StyleSheet, StatusBar, useColorScheme } from 'react-native';
|
||||||
|
import LinearGradient from 'react-native-linear-gradient';
|
||||||
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||||
|
import { GlobalTheme } from '../theme';
|
||||||
|
|
||||||
|
const Background = ({ children, barcolor = 'light-content'}) => {
|
||||||
|
const isDarkMode = useColorScheme() === 'dark';
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container}>
|
||||||
|
<StatusBar barStyle={'light-content'} />
|
||||||
|
<LinearGradient colors={['#E3EBF8', '#ffffff']} start={{ x: 0.5, y: 0 }} end={{ x: 0.5, y: 1 }} style={styles.gradient}>
|
||||||
|
{children}
|
||||||
|
</LinearGradient>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: GlobalTheme.colors.primary,
|
||||||
|
|
||||||
|
},
|
||||||
|
gradient: {
|
||||||
|
flex: 1,
|
||||||
|
// paddingHorizontal: 20,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Background;
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { View, TouchableOpacity, Image, StyleSheet, Modal } from 'react-native';
|
||||||
|
|
||||||
|
import IMAGES from '../constants/Images';
|
||||||
|
import CustomCamera from './CustomCamera';
|
||||||
|
|
||||||
|
const CameraScreen = () => {
|
||||||
|
const [showCamera, setShowCamera] = useState(false);
|
||||||
|
const [imageUri, setImageUri] = useState(null);
|
||||||
|
|
||||||
|
const handleImageCaptured = (photo) => {
|
||||||
|
setImageUri(photo.uri);
|
||||||
|
setShowCamera(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<TouchableOpacity onPress={() => setShowCamera(true)}>
|
||||||
|
<Image
|
||||||
|
source={imageUri ? { uri: imageUri } : IMAGES.cameraIcon}
|
||||||
|
style={styles.imagePreview}
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
{/* Fullscreen Modal Camera */}
|
||||||
|
<Modal visible={showCamera} animationType="slide" presentationStyle="fullScreen">
|
||||||
|
<CustomCamera
|
||||||
|
onImageCaptured={handleImageCaptured}
|
||||||
|
onClose={() => setShowCamera(false)}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CameraScreen;
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
imagePreview: {
|
||||||
|
width: 150,
|
||||||
|
height: 150,
|
||||||
|
borderRadius: 10,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: '#ccc',
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
TouchableOpacity,
|
||||||
|
Modal,
|
||||||
|
StyleSheet,
|
||||||
|
} from "react-native";
|
||||||
|
import { GlobalTheme } from "../theme";
|
||||||
|
|
||||||
|
const CustomAlertModal = ({
|
||||||
|
showModal,
|
||||||
|
title,
|
||||||
|
message,
|
||||||
|
buttons = [],
|
||||||
|
style = {},
|
||||||
|
titleStyle = {},
|
||||||
|
messageStyle = {},
|
||||||
|
children,
|
||||||
|
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
visible={showModal}
|
||||||
|
transparent
|
||||||
|
animationType="fade"
|
||||||
|
>
|
||||||
|
<View style={styles.backdrop}>
|
||||||
|
<View style={[styles.modalContainer, style]}>
|
||||||
|
<TouchableOpacity onPress={onClose} style={styles.closeIcon}>
|
||||||
|
<Text style={{ fontSize: 18 }}>✕</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
{title ? (
|
||||||
|
<Text style={[styles.title, titleStyle]}>{title}</Text>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{message ? (
|
||||||
|
<Text style={[styles.message, messageStyle]}>{message}</Text>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{children}
|
||||||
|
|
||||||
|
<View style={styles.buttonRow}>
|
||||||
|
{buttons.map((btn, index) => (
|
||||||
|
<TouchableOpacity
|
||||||
|
key={index}
|
||||||
|
style={[styles.button, { backgroundColor: btn.backgroundColor || GlobalTheme.colors.primary }]}
|
||||||
|
onPress={btn.onPress}
|
||||||
|
>
|
||||||
|
<Text style={[styles.buttonText, { color: btn.color || "#FFF" }]}>
|
||||||
|
{btn.label}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomAlertModal;
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
backdrop: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: "rgba(0,0,0,0.5)",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
modalContainer: {
|
||||||
|
width: "80%",
|
||||||
|
backgroundColor: "#fff",
|
||||||
|
borderRadius: 10,
|
||||||
|
padding: 20,
|
||||||
|
elevation: 5,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: "bold",
|
||||||
|
marginBottom: 10,
|
||||||
|
textAlign: "center",
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
fontSize: 16,
|
||||||
|
marginBottom: 20,
|
||||||
|
textAlign: "center",
|
||||||
|
},
|
||||||
|
buttonRow: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
marginTop: 10,
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
paddingHorizontal: 15,
|
||||||
|
paddingVertical: 8,
|
||||||
|
borderRadius: 5,
|
||||||
|
marginLeft: 10,
|
||||||
|
},
|
||||||
|
buttonText: {
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
import { View, Text, TouchableOpacity } from 'react-native';
|
import { View, Text, TouchableOpacity } from 'react-native';
|
||||||
|
|
||||||
const CustomButton = ({ title, style, textstyle, onPress }) => {
|
const CustomButton = ({ title, style, textstyle, onPress }) => {
|
||||||
@@ -11,3 +12,18 @@ const CustomButton = ({ title, style, textstyle, onPress }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default CustomButton;
|
export default CustomButton;
|
||||||
|
=======
|
||||||
|
import { View, Text, TouchableOpacity } from 'react-native';
|
||||||
|
|
||||||
|
const CustomButton = ({ title, style, textstyle, onPress , disabled}) => {
|
||||||
|
return (
|
||||||
|
<TouchableOpacity disabled={disabled} onPress={onPress}>
|
||||||
|
<View style={{ marginHorizontal: 0, paddingVertical: 10, ...style }}>
|
||||||
|
<Text style={{ textAlign: 'center', ...textstyle }}>{title}</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomButton;
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|||||||
@@ -0,0 +1,173 @@
|
|||||||
|
import React, { useState, useRef, useEffect } from 'react';
|
||||||
|
import { View, Text, TouchableOpacity, Image, StyleSheet, PermissionsAndroid, Platform } from 'react-native';
|
||||||
|
import { Camera, useCameraDevice } from 'react-native-vision-camera';
|
||||||
|
import { useIsFocused } from '@react-navigation/native';
|
||||||
|
|
||||||
|
const CustomCamera = ({ onImageCaptured, onClose }) => {
|
||||||
|
const cameraRef = useRef(null);
|
||||||
|
const [hasPermission, setHasPermission] = useState(false);
|
||||||
|
const [cameraPosition, setCameraPosition] = useState('back');
|
||||||
|
const [capturedPhoto, setCapturedPhoto] = useState(null);
|
||||||
|
const isFocused = useIsFocused();
|
||||||
|
const device = useCameraDevice(cameraPosition);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
const status = await Camera.requestCameraPermission();
|
||||||
|
console.log(status, "Camera permission status");
|
||||||
|
setHasPermission(status === 'granted');
|
||||||
|
})();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const takePhoto = async () => {
|
||||||
|
if (cameraRef.current) {
|
||||||
|
try {
|
||||||
|
const photo = await cameraRef.current.takePhoto({
|
||||||
|
flash: 'off',
|
||||||
|
});
|
||||||
|
const photoUri = Platform.OS === 'android' ? `file://${photo.path}` : photo.path;
|
||||||
|
setCapturedPhoto(photoUri);
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Error taking photo:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const flipCamera = () => {
|
||||||
|
setCameraPosition(prev => (prev === 'back' ? 'front' : 'back'));
|
||||||
|
};
|
||||||
|
|
||||||
|
const confirmPhoto = async () => {
|
||||||
|
if (onImageCaptured && capturedPhoto) {
|
||||||
|
try {
|
||||||
|
const imageInfo = await new Promise((resolve, reject) => {
|
||||||
|
Image.getSize(
|
||||||
|
capturedPhoto,
|
||||||
|
(width, height) => resolve({ width, height }),
|
||||||
|
(error) => reject(error)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const normalizedUri = Platform.OS === 'android' ? capturedPhoto : `file://${capturedPhoto}`;
|
||||||
|
|
||||||
|
onImageCaptured({
|
||||||
|
uri: normalizedUri,
|
||||||
|
width: imageInfo.width,
|
||||||
|
height: imageInfo.height,
|
||||||
|
storeData: {},
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Failed to get image size:', e);
|
||||||
|
onImageCaptured({
|
||||||
|
uri: capturedPhoto,
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
storeData: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const retakePhoto = () => {
|
||||||
|
setCapturedPhoto(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!device || !hasPermission) {
|
||||||
|
return (
|
||||||
|
<View style={styles.centered}>
|
||||||
|
<Text>Loading Camera...</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
{capturedPhoto ? (
|
||||||
|
<View style={styles.previewContainer}>
|
||||||
|
<Image source={{ uri: capturedPhoto }} style={styles.preview} resizeMode="contain" />
|
||||||
|
<View style={styles.buttonRow}>
|
||||||
|
<TouchableOpacity onPress={retakePhoto} style={styles.button}>
|
||||||
|
<Text>Retake</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity onPress={confirmPhoto} style={styles.button}>
|
||||||
|
<Text>Use Photo</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{isFocused && !capturedPhoto && (
|
||||||
|
<Camera
|
||||||
|
style={StyleSheet.absoluteFill}
|
||||||
|
device={device}
|
||||||
|
isActive={true}
|
||||||
|
photo={true}
|
||||||
|
ref={cameraRef}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<View style={styles.controls}>
|
||||||
|
<TouchableOpacity onPress={flipCamera} style={styles.button}>
|
||||||
|
<Text>Flip</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity onPress={takePhoto} style={styles.captureButton} />
|
||||||
|
<TouchableOpacity onPress={onClose} style={styles.button}>
|
||||||
|
<Text>Close</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomCamera;
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: 'black',
|
||||||
|
height: '100%',
|
||||||
|
},
|
||||||
|
previewContainer: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
height: '100%',
|
||||||
|
},
|
||||||
|
preview: {
|
||||||
|
width: '100%',
|
||||||
|
height: '80%',
|
||||||
|
},
|
||||||
|
controls: {
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: 30,
|
||||||
|
width: '100%',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-around',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
captureButton: {
|
||||||
|
width: 70,
|
||||||
|
height: 70,
|
||||||
|
borderRadius: 35,
|
||||||
|
backgroundColor: 'white',
|
||||||
|
borderWidth: 5,
|
||||||
|
borderColor: 'gray',
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
backgroundColor: 'white',
|
||||||
|
padding: 10,
|
||||||
|
borderRadius: 8,
|
||||||
|
},
|
||||||
|
buttonRow: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-around',
|
||||||
|
marginTop: 20,
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
centered: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
// src/components/CustomDropdown.js
|
||||||
|
import React from 'react';
|
||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
import { Dropdown } from 'react-native-element-dropdown';
|
||||||
|
|
||||||
|
const CustomDropdown = ({
|
||||||
|
data = [],
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
placeholder = '--Select--',
|
||||||
|
containerStyle = {},
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<Dropdown
|
||||||
|
style={[styles.dropdown, containerStyle]}
|
||||||
|
data={data}
|
||||||
|
labelField="label"
|
||||||
|
valueField="value"
|
||||||
|
placeholder={placeholder}
|
||||||
|
placeholderStyle={{ fontSize: 13, fontWeight: '500', color: 'gray' }}
|
||||||
|
value={value}
|
||||||
|
selectedTextStyle={{fontSize: 13, fontWeight: '500', color: '#000'}}
|
||||||
|
itemTextStyle={{fontSize:13,color:'#000'}}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
dropdown: {
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: '#ccc',
|
||||||
|
borderRadius: 8,
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
height: 45,
|
||||||
|
marginBottom: 0, // ✅ no margin
|
||||||
|
paddingBottom: 0, // ✅ no padding
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default CustomDropdown;
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import { StyleSheet, Text, View, Image, TouchableOpacity } from 'react-native'
|
||||||
|
import React from 'react'
|
||||||
|
import { GlobalTheme } from '../theme'
|
||||||
|
|
||||||
|
const CustomHeader = ({ title, leftIcon, rightIcon, onLeftPress, onRightPress }) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.headerStyle}>
|
||||||
|
{leftIcon &&
|
||||||
|
<TouchableOpacity onPress={onLeftPress} style={styles.leftSection}>
|
||||||
|
{leftIcon && <Image source={leftIcon} style={styles.leftIconStyle} />}
|
||||||
|
</TouchableOpacity>
|
||||||
|
}
|
||||||
|
|
||||||
|
<View style={styles.titleContainer}>
|
||||||
|
<Text style={styles.headerText}>{title}</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<TouchableOpacity onPress={onRightPress} style={styles.rightSection}>
|
||||||
|
{rightIcon && <Image source={rightIcon} style={styles.rightIconStyle} />}
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CustomHeader
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
headerStyle: {
|
||||||
|
height: '8%',
|
||||||
|
backgroundColor: '#113F8C',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
paddingHorizontal: 15,
|
||||||
|
},
|
||||||
|
leftSection: {
|
||||||
|
backgroundColor: '#295398',
|
||||||
|
flexDirection: 'row',
|
||||||
|
padding: 8,
|
||||||
|
alignItems: 'center',
|
||||||
|
borderRadius: 20
|
||||||
|
// width: 70,
|
||||||
|
},
|
||||||
|
rightSection: {
|
||||||
|
alignItems: 'flex-end',
|
||||||
|
width: 40,
|
||||||
|
},
|
||||||
|
titleContainer: {
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
headerText: {
|
||||||
|
color: GlobalTheme.colors.white,
|
||||||
|
fontSize: GlobalTheme.typography.fontSize.medium,
|
||||||
|
fontWeight: '600',
|
||||||
|
},
|
||||||
|
backText: {
|
||||||
|
marginLeft: 6,
|
||||||
|
color: GlobalTheme.colors.white,
|
||||||
|
fontSize: GlobalTheme.typography.fontSize.small,
|
||||||
|
},
|
||||||
|
leftIconStyle: {
|
||||||
|
height: 20,
|
||||||
|
width: 20,
|
||||||
|
resizeMode: 'contain',
|
||||||
|
},
|
||||||
|
rightIconStyle: {
|
||||||
|
height: 35,
|
||||||
|
width: 35,
|
||||||
|
resizeMode: 'contain',
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { View, Text, Modal, StyleSheet, TouchableOpacity, Image } from 'react-native';
|
||||||
|
import IMAGES from '../constants/Images';
|
||||||
|
|
||||||
|
const CustomModal = ({
|
||||||
|
showModal,
|
||||||
|
title,
|
||||||
|
message,
|
||||||
|
children,
|
||||||
|
// onClose,
|
||||||
|
style = {},
|
||||||
|
titleStyle = {},
|
||||||
|
messageStyle = {},
|
||||||
|
hideDefaultClose = false, // 🔥 new prop
|
||||||
|
onClose = null
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<Modal visible={showModal} transparent animationType="fade">
|
||||||
|
<View style={styles.overlay}>
|
||||||
|
<View style={[styles.modalContainer, style]}>
|
||||||
|
{/* {onClose && (
|
||||||
|
<TouchableOpacity onPress={onClose} style={styles.closeButton}>
|
||||||
|
<Image source={IMAGES.crossIcon} style={styles.iconStyle} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
)} */}
|
||||||
|
|
||||||
|
{/* <TouchableOpacity onPress={onClose} style={styles.closeButton}>
|
||||||
|
<Image source={IMAGES.alert} style={styles.iconStyle} />
|
||||||
|
</TouchableOpacity> */}
|
||||||
|
<View style={{ marginTop: 10 }}>
|
||||||
|
{title && <Text style={[styles.title, titleStyle]}>{title}</Text>}
|
||||||
|
{message && <Text style={[styles.message, messageStyle]}>{message}</Text>}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={{ marginVertical: 10 }}>{children}</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomModal;
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
overlay: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#00000088',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
modalContainer: {
|
||||||
|
width: '90%',
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
borderRadius: 12,
|
||||||
|
padding: 15,
|
||||||
|
alignItems: 'center',
|
||||||
|
minHeight: 180,
|
||||||
|
justifyContent: 'center'
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
marginBottom: 6,
|
||||||
|
color: "#000"
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: '#555',
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
closeButton: {
|
||||||
|
alignSelf: 'center',
|
||||||
|
marginBottom: 15
|
||||||
|
},
|
||||||
|
closeText: {
|
||||||
|
color: '#fff',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
|
iconStyle: {
|
||||||
|
height: 50,
|
||||||
|
width: 50,
|
||||||
|
resizeMode: 'contain',
|
||||||
|
// tintColor:'red'
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
import { View, Text, TextInput, StyleSheet, } from 'react-native';
|
import { View, Text, TextInput, StyleSheet, } from 'react-native';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { GlobalTheme, Screen } from '../theme';
|
import { GlobalTheme, Screen } from '../theme';
|
||||||
@@ -83,3 +84,90 @@ const styles = StyleSheet.create({
|
|||||||
marginBottom: 16,
|
marginBottom: 16,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
=======
|
||||||
|
import { View, Text, TextInput, StyleSheet, } from 'react-native';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { GlobalTheme, Screen } from '../theme';
|
||||||
|
|
||||||
|
const CustomTextInput = ({
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
onChangeText,
|
||||||
|
keyboardType,
|
||||||
|
secureTextEntry,
|
||||||
|
right,
|
||||||
|
textstyle,
|
||||||
|
viewstyle,
|
||||||
|
maxLength
|
||||||
|
}) => {
|
||||||
|
const [isFocused, setFocused] = useState(false);
|
||||||
|
const [hidepassword, setHidePassword] = useState(false);
|
||||||
|
|
||||||
|
const handleFocus = () => {
|
||||||
|
setFocused(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBlur = () => {
|
||||||
|
setFocused(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const inputStyle = {
|
||||||
|
borderColor: isFocused ? '#2680EB' : '#DFDFDF',
|
||||||
|
borderWidth: isFocused ? 2 : 1,
|
||||||
|
backgroundColor: isFocused ? '#FFF' : '#Fff',
|
||||||
|
borderRadius: GlobalTheme.borderRadius.md,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.inputContainer}>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
color: GlobalTheme.colors.black,
|
||||||
|
fontSize: GlobalTheme.typography.fontSize.small,
|
||||||
|
fontWeight: GlobalTheme.typography.fontWeight.regular,
|
||||||
|
marginTop: 10,
|
||||||
|
marginHorizontal: 0,
|
||||||
|
...textstyle,
|
||||||
|
}}>
|
||||||
|
{label}
|
||||||
|
</Text>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
borderRadius: GlobalTheme.borderRadius.lgg,
|
||||||
|
// borderWidth: 6,
|
||||||
|
borderColor: isFocused ? '#DFECFF' : 'transparent',
|
||||||
|
marginTop: 8,
|
||||||
|
...viewstyle,
|
||||||
|
}}>
|
||||||
|
<TextInput
|
||||||
|
maxLength={maxLength}
|
||||||
|
style={[styles.input, inputStyle]}
|
||||||
|
value={value}
|
||||||
|
onChangeText={onChangeText}
|
||||||
|
keyboardType={keyboardType}
|
||||||
|
autoCapitalize="none"
|
||||||
|
onFocus={handleFocus}
|
||||||
|
onBlur={handleBlur}
|
||||||
|
placeholder={`Enter your ${label.toLowerCase()}`}
|
||||||
|
placeholderTextColor={'#555555'}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomTextInput;
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
input: {
|
||||||
|
height: 50,
|
||||||
|
borderWidth: 1,
|
||||||
|
padding: 10,
|
||||||
|
color: GlobalTheme.colors.black,
|
||||||
|
},
|
||||||
|
inputContainer: {
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
// colors.js
|
// colors.js
|
||||||
export const colors = [
|
export const colors = [
|
||||||
{ bgColor: '#eddeb8', textColor: '#0c8fa5' },
|
{ bgColor: '#eddeb8', textColor: '#0c8fa5' },
|
||||||
@@ -6,3 +7,13 @@ export const colors = [
|
|||||||
{ bgColor: '#d1c4e9', textColor: '#6A1B9A' },
|
{ bgColor: '#d1c4e9', textColor: '#6A1B9A' },
|
||||||
{ bgColor: '#ffe0b2', textColor: '#EF6C00' },
|
{ bgColor: '#ffe0b2', textColor: '#EF6C00' },
|
||||||
];
|
];
|
||||||
|
=======
|
||||||
|
// colors.js
|
||||||
|
export const colors = [
|
||||||
|
{ bgColor: '#eddeb8', textColor: '#0c8fa5' },
|
||||||
|
{ bgColor: '#dcf2ee', textColor: '#f39a19' },
|
||||||
|
{ bgColor: '#eebdc3', textColor: '#ff5f5f' },
|
||||||
|
{ bgColor: '#d1c4e9', textColor: '#6A1B9A' },
|
||||||
|
{ bgColor: '#ffe0b2', textColor: '#EF6C00' },
|
||||||
|
];
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import AntDesign from 'react-native-vector-icons/AntDesign';
|
import AntDesign from 'react-native-vector-icons/AntDesign';
|
||||||
import Entypo from 'react-native-vector-icons/Entypo';
|
import Entypo from 'react-native-vector-icons/Entypo';
|
||||||
@@ -72,3 +73,80 @@ function CustomIcon({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default CustomIcon;
|
export default CustomIcon;
|
||||||
|
=======
|
||||||
|
import React from 'react';
|
||||||
|
import AntDesign from 'react-native-vector-icons/AntDesign';
|
||||||
|
import Entypo from 'react-native-vector-icons/Entypo';
|
||||||
|
import EvilIcons from 'react-native-vector-icons/EvilIcons';
|
||||||
|
import Feather from 'react-native-vector-icons/Feather';
|
||||||
|
import FontAwesome from 'react-native-vector-icons/FontAwesome';
|
||||||
|
import Fontisto from 'react-native-vector-icons/Fontisto';
|
||||||
|
import Foundation from 'react-native-vector-icons/Foundation';
|
||||||
|
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||||
|
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
|
||||||
|
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
|
import Octicons from 'react-native-vector-icons/Octicons';
|
||||||
|
import Zocial from 'react-native-vector-icons/Zocial';
|
||||||
|
import SimpleLineIcons from 'react-native-vector-icons/SimpleLineIcons';
|
||||||
|
import { GlobalTheme } from '../theme';
|
||||||
|
|
||||||
|
|
||||||
|
function CustomIcon({
|
||||||
|
iconLibrary,
|
||||||
|
icon,
|
||||||
|
size = 22,
|
||||||
|
color = GlobalTheme.colors.primary,
|
||||||
|
style = {},
|
||||||
|
...rest
|
||||||
|
}) {
|
||||||
|
let Icon = AntDesign;
|
||||||
|
|
||||||
|
switch (iconLibrary) {
|
||||||
|
case 'AntDesign':
|
||||||
|
Icon = AntDesign;
|
||||||
|
break;
|
||||||
|
case 'Entypo':
|
||||||
|
Icon = Entypo;
|
||||||
|
break;
|
||||||
|
case 'EvilIcons':
|
||||||
|
Icon = EvilIcons;
|
||||||
|
break;
|
||||||
|
case 'Feather':
|
||||||
|
Icon = Feather;
|
||||||
|
break;
|
||||||
|
case 'FontAwesome':
|
||||||
|
Icon = FontAwesome;
|
||||||
|
break;
|
||||||
|
case 'Fontisto':
|
||||||
|
Icon = Fontisto;
|
||||||
|
break;
|
||||||
|
case 'Foundation':
|
||||||
|
Icon = Foundation;
|
||||||
|
break;
|
||||||
|
case 'Ionicons':
|
||||||
|
Icon = Ionicons;
|
||||||
|
break;
|
||||||
|
case 'MaterialIcons':
|
||||||
|
Icon = MaterialIcons;
|
||||||
|
break;
|
||||||
|
case 'MaterialCommunityIcons':
|
||||||
|
Icon = MaterialCommunityIcons;
|
||||||
|
break;
|
||||||
|
case 'Octicons':
|
||||||
|
Icon = Octicons;
|
||||||
|
break;
|
||||||
|
case 'Zocial':
|
||||||
|
Icon = Zocial;
|
||||||
|
break;
|
||||||
|
case 'SimpleLineIcons':
|
||||||
|
Icon = SimpleLineIcons;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Icon = AntDesign;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Icon name={icon} size={size} style={style} color={color} {...rest} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CustomIcon;
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
const IMAGES = {
|
const IMAGES = {
|
||||||
// AppLogo: require('../assets/Images/logo.png'),
|
// AppLogo: require('../assets/Images/logo.png'),
|
||||||
AppLogo: require('../assets/Images/logo.png'),
|
AppLogo: require('../assets/Images/logo.png'),
|
||||||
@@ -10,3 +11,41 @@ const IMAGES = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default IMAGES;
|
export default IMAGES;
|
||||||
|
=======
|
||||||
|
const IMAGES = {
|
||||||
|
// AppLogo: require('../assets/Images/logo.png'),
|
||||||
|
AppLogo: require('../assets/Images/logo.png'),
|
||||||
|
filterIcon: require('../assets/Icons/filter.png'),
|
||||||
|
menuIcon: require('../assets/Icons/menu.png'),
|
||||||
|
pluscircleIcon: require('../assets/Icons/pluscircle.png'),
|
||||||
|
rightArrowIcon: require('../assets/Icons/rightarrow.png'),
|
||||||
|
leftArrowIcon: require('../assets/Icons/leftarrow.png'),
|
||||||
|
crossIcon: require('../assets/Icons/cross.png'),
|
||||||
|
searchIcon: require('../assets/Icons/search.png'),
|
||||||
|
greenCameraIcon: require('../assets/Icons/green_camera.png'),
|
||||||
|
redCameraIcon: require('../assets/Icons/red_camera.png'),
|
||||||
|
normalCameraIcon: require('../assets/Icons/camera.png'),
|
||||||
|
WhiteBGIMG: require('../assets/Images/white.png'),
|
||||||
|
backIcon:require('../assets/Icons/backIcon.png'),
|
||||||
|
greenTick:require('../assets/Icons/greenTick.png'),
|
||||||
|
storeIcon:require('../assets/Icons/store.png'),
|
||||||
|
reportIcon:require('../assets/Icons/report.png'),
|
||||||
|
downIcon:require('../assets/Icons/down.png'),
|
||||||
|
upArrow:require('../assets/Icons/uparrow.png'),
|
||||||
|
footerImage : require('../assets/Images/footerImage.png'),
|
||||||
|
Logo: require('../assets/Images/applogo.png'),
|
||||||
|
WelcomeBackground: require('../assets/Images/welcomebackground.png'),
|
||||||
|
Welcomelogo: require('../assets/Images/welcomelogo.png'),
|
||||||
|
AuthTopBG: require('../assets/Images/logintopBG.png'),
|
||||||
|
AuthTopBGNew: require('../assets/Images/appLogoNew.png'),
|
||||||
|
AuthBottomBG: require('../assets/Images/loginbottomBG.png'),
|
||||||
|
projectIdImg: require('../assets/Images/projectId.png'),
|
||||||
|
PerformicsLogo: require('../assets/Images/PerformicsLogo.png'),
|
||||||
|
dotsIcon: require('../assets/Icons/dots.png'),
|
||||||
|
pending: require('../assets/Icons/wall-clock.png'),
|
||||||
|
alert: require('../assets/Icons/question-mark.png'),
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export default IMAGES;
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { useWindowDimensions, Dimensions, View, Text, ActivityIndicator, StyleSheet, Image, StatusBar } from 'react-native';
|
||||||
|
import LoaderKit from 'react-native-loader-kit'
|
||||||
|
|
||||||
|
|
||||||
|
const Loader = ({ visible = false , loadingtext = 'Loading...'}) => {
|
||||||
|
const { width, height } = useWindowDimensions();
|
||||||
|
const height2 = height + 100
|
||||||
|
|
||||||
|
return (
|
||||||
|
visible && (
|
||||||
|
<View style={[style.container, { width }]}>
|
||||||
|
<View style={{ marginTop: 20,alignItems:'center' }}>
|
||||||
|
<LoaderKit
|
||||||
|
style={{ width: 70, height: 70 }}
|
||||||
|
name={'BallSpinFadeLoader'} // Optional: see list of animations below
|
||||||
|
color={'#fff'} // Optional: color can be: 'red', 'green',... or '#ddd', '#ffffff',...
|
||||||
|
/>
|
||||||
|
<Text style={{ color: '#fff', fontSize: 14, textAlign: 'center', marginTop: 10, fontWeight: '500' }}>{loadingtext}</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const style = StyleSheet.create({
|
||||||
|
label: {
|
||||||
|
marginLeft: 10,
|
||||||
|
fontSize: 16,
|
||||||
|
color: 'white',
|
||||||
|
fontFamily: "FuturaPT-Book",
|
||||||
|
},
|
||||||
|
loader: {
|
||||||
|
height: 100,
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
marginHorizontal: 50,
|
||||||
|
borderRadius: 5,
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'center',
|
||||||
|
paddingHorizontal: 0,
|
||||||
|
},
|
||||||
|
container: {
|
||||||
|
top: 0,
|
||||||
|
bottom: 0,
|
||||||
|
position: 'absolute',
|
||||||
|
zIndex: 1050,
|
||||||
|
backgroundColor: 'rgba(0,0,0,0.5)',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Loader;
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
// Toast.js
|
// Toast.js
|
||||||
import Toast from 'react-native-toast-message';
|
import Toast from 'react-native-toast-message';
|
||||||
const showToast = (type, text1, text2) => {
|
const showToast = (type, text1, text2) => {
|
||||||
@@ -33,4 +34,41 @@ const toastError = (text1, text2) => {
|
|||||||
showToast('error', text1, text2);
|
showToast('error', text1, text2);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
=======
|
||||||
|
// Toast.js
|
||||||
|
import Toast from 'react-native-toast-message';
|
||||||
|
const showToast = (type, text1, text2) => {
|
||||||
|
Toast.show({
|
||||||
|
type: type,
|
||||||
|
text1: text1,
|
||||||
|
text2: text2,
|
||||||
|
position: 'top',
|
||||||
|
visibilityTime: 3000,
|
||||||
|
autoHide: true,
|
||||||
|
topOffset: 30,
|
||||||
|
bottomOffset: 40,
|
||||||
|
text1Style: {
|
||||||
|
fontSize: 15, // Custom font size for the main text
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
|
text2Style: {
|
||||||
|
fontSize: 14, // Custom font size for the secondary text
|
||||||
|
color:'gray'
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const ToastComponent = () => {
|
||||||
|
return <Toast innerRef={(ref) => Toast.setRef(ref)} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
const toastSuccess = (text1, text2) => {
|
||||||
|
showToast('success', text1, text2);
|
||||||
|
};
|
||||||
|
|
||||||
|
const toastError = (text1, text2) => {
|
||||||
|
showToast('error', text1, text2);
|
||||||
|
};
|
||||||
|
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
export { ToastComponent, toastSuccess, toastError };
|
export { ToastComponent, toastSuccess, toastError };
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import * as RNFS from 'react-native-fs';
|
||||||
|
|
||||||
|
const common_ImagePath=`${RNFS.DocumentDirectoryPath}/`;
|
||||||
|
const ImageFolderPath=`${common_ImagePath}PerformicsAllImages/`;
|
||||||
|
const FeedbackImagesFolderPath=ImageFolderPath+`Store_DNA/`;
|
||||||
|
const defUploadFolder='BulkImages';
|
||||||
|
|
||||||
|
export {common_ImagePath ,FeedbackImagesFolderPath , ImageFolderPath ,defUploadFolder};
|
||||||
|
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
import SQLite from 'react-native-sqlite-storage';
|
||||||
|
|
||||||
|
const db = SQLite.openDatabase({ name: 'feedback.db', location: 'default' });
|
||||||
|
|
||||||
|
// Initialize FeedbackCategory table (full structure from mockDataFlat)
|
||||||
|
export const initTables = () => {
|
||||||
|
db.transaction(tx => {
|
||||||
|
// Table for API-fetched question/answer data
|
||||||
|
tx.executeSql(`
|
||||||
|
CREATE TABLE IF NOT EXISTS FeedbackCategory (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
MenuId INTEGER,
|
||||||
|
SurveyId INTEGER,
|
||||||
|
SurveyName TEXT,
|
||||||
|
CategoryId INTEGER,
|
||||||
|
Category TEXT,
|
||||||
|
CategorySequence INTEGER,
|
||||||
|
QuestionId INTEGER,
|
||||||
|
Question TEXT,
|
||||||
|
QuestionType TEXT,
|
||||||
|
QuestionTypeNew TEXT,
|
||||||
|
QEnable BOOLEAN,
|
||||||
|
QuestionImageAllow BOOLEAN,
|
||||||
|
QuestionImageMandatory BOOLEAN,
|
||||||
|
LengthValidation BOOLEAN,
|
||||||
|
MinLength INTEGER,
|
||||||
|
MaxLength INTEGER,
|
||||||
|
OTP BOOLEAN,
|
||||||
|
DateRange TEXT,
|
||||||
|
QuestionSequence INTEGER,
|
||||||
|
AnswerId INTEGER,
|
||||||
|
Answer TEXT,
|
||||||
|
AnswerSequence INTEGER,
|
||||||
|
ImageAllow1 BOOLEAN,
|
||||||
|
ImageAllow2 BOOLEAN,
|
||||||
|
Image1Mandatory BOOLEAN,
|
||||||
|
Image2Mandatory BOOLEAN,
|
||||||
|
EnableQuestion TEXT,
|
||||||
|
DisableQuestion TEXT,
|
||||||
|
ShowCat INTEGER,
|
||||||
|
SubCategoryId INTEGER,
|
||||||
|
SubCategory TEXT,
|
||||||
|
SubCategorySequence INTEGER,
|
||||||
|
CalFormula TEXT,
|
||||||
|
RefImage TEXT,
|
||||||
|
QuestionRefImage TEXT
|
||||||
|
);
|
||||||
|
`);
|
||||||
|
|
||||||
|
// Table for locally saved user responses
|
||||||
|
tx.executeSql(`
|
||||||
|
CREATE TABLE IF NOT EXISTS FeedBackLocalTable (
|
||||||
|
KEY_ID INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
STORE_ID INTEGER,
|
||||||
|
VISIT_DATE NVARCHAR,
|
||||||
|
SURVEY_ID INTEGER,
|
||||||
|
CATEGORY_ID INTEGER,
|
||||||
|
SUB_CATEGORY_ID INTEGER,
|
||||||
|
QUESTION NVARCHAR,
|
||||||
|
QUESTION_ID INTEGER,
|
||||||
|
QUESTION_TYPE NVARCHAR,
|
||||||
|
ANSWER NVARCHAR,
|
||||||
|
ANSWER_ID INTEGER,
|
||||||
|
QuestionImageAllow INTEGER,
|
||||||
|
IMAGE_ALLOW1 INTEGER,
|
||||||
|
IMAGE1 NVARCHAR,
|
||||||
|
IMAGE_ALLOW2 INTEGER,
|
||||||
|
IMAGE2 NVARCHAR,
|
||||||
|
MULTI_OPTIONS_IDS NVARCHAR,
|
||||||
|
IS_DISABLED NVARCHAR,
|
||||||
|
IS_ENABLED NVARCHAR,
|
||||||
|
MENU_ID INTEGER,
|
||||||
|
ADDED_DATE TEXT,
|
||||||
|
VerifyOTP INTEGER,
|
||||||
|
QUESTION_REF_IMAGE TEXT,
|
||||||
|
STATUS NVARCHAR
|
||||||
|
);
|
||||||
|
`);
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
tx.executeSql(`
|
||||||
|
CREATE TABLE IF NOT EXISTS StoreInfoDNALocal (
|
||||||
|
KEY_ID INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
VISIT_DATE NVARCHAR ,
|
||||||
|
StoreId INTEGER,
|
||||||
|
StoreName NVARCHAR,
|
||||||
|
ChainName NVARCHAR,
|
||||||
|
Address NVARCHAR,
|
||||||
|
Pincode NVARCHAR,
|
||||||
|
CityName NVARCHAR,
|
||||||
|
StateName NVARCHAR,
|
||||||
|
StoreType NVARCHAR,
|
||||||
|
UPLOAD_STATUS NVARCHAR
|
||||||
|
);
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Bulk insert for FeedbackCategory (full schema)
|
||||||
|
export const bulkInsertData = (tableName, dataArray) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!Array.isArray(dataArray) || dataArray.length === 0) {
|
||||||
|
resolve(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tableName !== 'FeedbackCategory') {
|
||||||
|
reject(`Unsupported table: ${tableName}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const escape = str => (str || '').toString().replace(/'/g, "''");
|
||||||
|
|
||||||
|
const values = dataArray.map(item => `(
|
||||||
|
'${item.MenuId}', '${item.SurveyId}', '${escape(item.SurveyName)}',
|
||||||
|
'${item.CategoryId}', '${escape(item.Category)}', '${item.CategorySequence}',
|
||||||
|
'${item.QuestionId}', '${escape(item.Question)}', '${escape(item.QuestionType)}',
|
||||||
|
'${escape(item.QuestionTypeNew)}', '${item.QEnable ? 1 : 0}', '${item.QuestionImageAllow ? 1 : 0}',
|
||||||
|
'${item.QuestionImageMandatory ? 1 : 0}', '${item.LengthValidation ? 1 : 0}', '${item.MinLength}',
|
||||||
|
'${item.MaxLength}', '${item.OTP ? 1 : 0}', '${escape(item.DateRange)}', '${item.QuestionSequence}',
|
||||||
|
'${item.AnswerId}', '${escape(item.Answer)}', '${item.AnswerSequence}',
|
||||||
|
'${item.ImageAllow1 ? 1 : 0}', '${item.ImageAllow2 ? 1 : 0}', '${item.Image1Mandatory ? 1 : 0}',
|
||||||
|
'${item.Image2Mandatory ? 1 : 0}', '${escape(item.EnableQuestion)}', '${escape(item.DisableQuestion)}',
|
||||||
|
'${item.ShowCat}', '${item.SubCategoryId}', '${escape(item.SubCategory)}', '${item.SubCategorySequence}',
|
||||||
|
'${escape(item.CalFormula)}', '${escape(item.RefImage)}', '${escape(item.QuestionRefImage)}'
|
||||||
|
)`);
|
||||||
|
|
||||||
|
const sql = `
|
||||||
|
INSERT INTO FeedbackCategory (
|
||||||
|
MenuId, SurveyId, SurveyName, CategoryId, Category, CategorySequence,
|
||||||
|
QuestionId, Question, QuestionType, QuestionTypeNew, QEnable, QuestionImageAllow,
|
||||||
|
QuestionImageMandatory, LengthValidation, MinLength, MaxLength, OTP, DateRange,
|
||||||
|
QuestionSequence, AnswerId, Answer, AnswerSequence, ImageAllow1, ImageAllow2,
|
||||||
|
Image1Mandatory, Image2Mandatory, EnableQuestion, DisableQuestion,
|
||||||
|
ShowCat, SubCategoryId, SubCategory, SubCategorySequence,
|
||||||
|
CalFormula, RefImage, QuestionRefImage
|
||||||
|
)
|
||||||
|
VALUES ${values.join(',')}
|
||||||
|
`;
|
||||||
|
|
||||||
|
db.transaction(tx => {
|
||||||
|
tx.executeSql(`DELETE FROM FeedbackCategory`, [], () => {
|
||||||
|
tx.executeSql(sql, [], () => {
|
||||||
|
console.log(`${tableName} inserted successfully`);
|
||||||
|
resolve(true);
|
||||||
|
}, (e1, err) => {
|
||||||
|
console.log('Insert error:', err);
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
}, (err) => {
|
||||||
|
console.log('Delete error:', err);
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generic SELECT
|
||||||
|
export const getAllFromTable = (tableName) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
db.transaction(tx => {
|
||||||
|
tx.executeSql(`SELECT * FROM ${tableName}`, [], (tx, results) => {
|
||||||
|
const rows = [];
|
||||||
|
for (let i = 0; i < results.rows.length; i++) {
|
||||||
|
rows.push(results.rows.item(i));
|
||||||
|
}
|
||||||
|
resolve(rows);
|
||||||
|
}, (err) => {
|
||||||
|
console.log(`Select error on ${tableName}:`, err);
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default db;
|
||||||
@@ -0,0 +1,455 @@
|
|||||||
|
import { defUploadFolder, FeedbackImagesFolderPath, ImageFolderPath } from "./constant";
|
||||||
|
import moment from 'moment';
|
||||||
|
import { Image } from "react-native";
|
||||||
|
import * as RNFS from 'react-native-fs';
|
||||||
|
import PhotoManipulator from 'react-native-photo-manipulator';
|
||||||
|
import ImageResizer from '@bam.tech/react-native-image-resizer';
|
||||||
|
import { toastError } from "./Toast";
|
||||||
|
import IMAGES from "./Images";
|
||||||
|
|
||||||
|
export async function CreateImageFolders() {
|
||||||
|
console.log('CreateDirKPIimg:');
|
||||||
|
await RNFS.mkdir(ImageFolderPath);
|
||||||
|
await RNFS.mkdir(FeedbackImagesFolderPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getImage(imgdata , userId , item) {
|
||||||
|
console.log("item===", item);
|
||||||
|
if (typeof imgdata == 'object' && imgdata.errorCode === 'camera_unavailable') {
|
||||||
|
console.log("camera not available");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof imgdata == 'object' && imgdata.uri != null) {
|
||||||
|
try {
|
||||||
|
const imgurl = imgdata.uri.startsWith('file://') ? imgdata.uri : `file://${imgdata.uri}`;
|
||||||
|
|
||||||
|
// 🔹 Get dynamic image width and height
|
||||||
|
const { width: imgWidth, height: imgHeight } = await new Promise((resolve, reject) => {
|
||||||
|
Image.getSize(imgurl, (width, height) => resolve({ width, height }), reject);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Image size ===", imgWidth, imgHeight);
|
||||||
|
|
||||||
|
const picture_clickedd = new Date();
|
||||||
|
const picture_clicked_time = moment(picture_clickedd).format('MM-DD-YYYY HH:mm:ss');
|
||||||
|
const picture_clicked_time_for_pic_name = moment(picture_clickedd).format('MMDDYYYY_HHmmss');
|
||||||
|
|
||||||
|
const filename = userId + picture_clicked_time_for_pic_name + '.jpg';
|
||||||
|
const mark_text1 = picture_clicked_time;
|
||||||
|
const mark_text2 = `User Id: ${userId} | StoreName: ${item?.StoreName} | StoreId: ${item?.StoreId} | Date: ${picture_clicked_time}`;
|
||||||
|
const imagePath = `${FeedbackImagesFolderPath}${filename}`;
|
||||||
|
|
||||||
|
console.log("Copying image to:", imagePath);
|
||||||
|
await RNFS.copyFile(imgurl.replace('file://', ''), imagePath);
|
||||||
|
|
||||||
|
const restore_data = {
|
||||||
|
destFilePath: imagePath,
|
||||||
|
imgurl: imagePath,
|
||||||
|
imgWidth,
|
||||||
|
imgHeight,
|
||||||
|
mark_text1,
|
||||||
|
mark_text2,
|
||||||
|
};
|
||||||
|
|
||||||
|
const is_restored = await restore_ImageWithMetaData(restore_data, imgdata);
|
||||||
|
console.log("Image restored:", is_restored);
|
||||||
|
console.log("Image imagePath:", imagePath);
|
||||||
|
|
||||||
|
return { finalPath: imagePath };
|
||||||
|
} catch (err) {
|
||||||
|
console.log('❌ ERROR in getImage:', err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// const waterMarkText = async (text = '', imgurl = '', text2 = '', imgWidth = 0, imgHeight = 0) => {
|
||||||
|
|
||||||
|
// const wrapText = (text2, maxCharsPerLine) => {
|
||||||
|
// const words = text2.split(' ');
|
||||||
|
// const lines = [];
|
||||||
|
// let currentLine = '';
|
||||||
|
|
||||||
|
// for (let word of words) {
|
||||||
|
// if ((currentLine + word).length <= maxCharsPerLine) {
|
||||||
|
// currentLine += (currentLine ? ' ' : '') + word;
|
||||||
|
// } else {
|
||||||
|
// lines.push(currentLine);
|
||||||
|
// currentLine = word;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// console.log('currentLine====>', currentLine);
|
||||||
|
|
||||||
|
// if (currentLine) lines.push(currentLine);
|
||||||
|
// return lines;
|
||||||
|
// };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// if (!imgurl) throw new Error("Image URL is missing");
|
||||||
|
|
||||||
|
// const cleanPath = imgurl.startsWith('file://') ? imgurl : `file://${imgurl}`;
|
||||||
|
// const stripHeight = 250;
|
||||||
|
|
||||||
|
// // ✅ Copy from Android assets folder to filesystem
|
||||||
|
// const destPath = `${RNFS.CachesDirectoryPath}/white.png`;
|
||||||
|
// const exists = await RNFS.exists(destPath);
|
||||||
|
|
||||||
|
// if (!exists) {
|
||||||
|
// await RNFS.copyFileAssets('white.png', destPath); // white.png is in android/app/src/main/assets
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const stripFilePath = `file://${destPath}`;
|
||||||
|
|
||||||
|
// // ✅ Step 2: Overlay strip
|
||||||
|
// const imageWithStrip = await PhotoManipulator.overlayImage(
|
||||||
|
// cleanPath,
|
||||||
|
// stripFilePath,
|
||||||
|
// { x: 0, y: imgHeight - stripHeight },
|
||||||
|
// 'image/jpeg'
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // ✅ Step 3: Add text
|
||||||
|
// const lines = wrapText(text2, 80); // You can adjust 25 depending on font size / image width
|
||||||
|
|
||||||
|
// const texts = [
|
||||||
|
// {
|
||||||
|
// position: { x: 30, y: 50 },
|
||||||
|
// text: text,
|
||||||
|
// textSize: 80,
|
||||||
|
// color: '#FF0000',
|
||||||
|
// },
|
||||||
|
// ...lines.map((line, i) => ({
|
||||||
|
// position: { x: 30, y: imgHeight - 120 + i * 90 }, // 90 = line height
|
||||||
|
// text: line,
|
||||||
|
// textSize: 80,
|
||||||
|
// color: '#000000',
|
||||||
|
// })),
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// const finalImagePath = await PhotoManipulator.printText(imageWithStrip, texts, 'image/jpeg');
|
||||||
|
// const uri = finalImagePath.startsWith('file://') ? finalImagePath : `file://${finalImagePath}`;
|
||||||
|
|
||||||
|
// return { success: true, uri };
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error("❌ Error in waterMarkText:", error);
|
||||||
|
// return { success: false, error: error.message };
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
const waterMarkText = async (text = '', imgurl = '', text2 = '', imgWidth = 0, imgHeight = 0) => {
|
||||||
|
const wrapTextByImageWidth = (text, imgWidth, fontSize = 80, padding = 60) => {
|
||||||
|
const avgCharWidth = fontSize * 0.6; // Conservative estimate
|
||||||
|
const maxChars = Math.floor((imgWidth - padding) / avgCharWidth);
|
||||||
|
|
||||||
|
const words = text.split(' ');
|
||||||
|
const lines = [];
|
||||||
|
let currentLine = '';
|
||||||
|
|
||||||
|
for (let word of words) {
|
||||||
|
if ((currentLine + ' ' + word).trim().length <= maxChars) {
|
||||||
|
currentLine += (currentLine ? ' ' : '') + word;
|
||||||
|
} else {
|
||||||
|
lines.push(currentLine);
|
||||||
|
currentLine = word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentLine) lines.push(currentLine);
|
||||||
|
|
||||||
|
return lines;
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!imgurl) throw new Error("Image URL is missing");
|
||||||
|
|
||||||
|
const cleanPath = imgurl.startsWith('file://') ? imgurl : `file://${imgurl}`;
|
||||||
|
const stripHeight = 250;
|
||||||
|
|
||||||
|
// ✅ White strip setup
|
||||||
|
const destPath = `${RNFS.CachesDirectoryPath}/white.png`;
|
||||||
|
const exists = await RNFS.exists(destPath);
|
||||||
|
if (!exists) {
|
||||||
|
await RNFS.copyFileAssets('white.png', destPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
const stripFilePath = `file://${destPath}`;
|
||||||
|
|
||||||
|
// ✅ Overlay strip at bottom
|
||||||
|
const imageWithStrip = await PhotoManipulator.overlayImage(
|
||||||
|
cleanPath,
|
||||||
|
stripFilePath,
|
||||||
|
{ x: 0, y: imgHeight - stripHeight },
|
||||||
|
'image/jpeg'
|
||||||
|
);
|
||||||
|
|
||||||
|
// ✅ Wrap text2 according to image width
|
||||||
|
const fontSize = 80;
|
||||||
|
const lineHeight = 90;
|
||||||
|
const padding = 60;
|
||||||
|
const lines = wrapTextByImageWidth(text2, imgWidth, fontSize, padding);
|
||||||
|
|
||||||
|
const startY = imgHeight - stripHeight + 40; // Add top padding inside strip
|
||||||
|
|
||||||
|
// ✅ Build text objects
|
||||||
|
const texts = [
|
||||||
|
{
|
||||||
|
position: { x: 30, y: 50 },
|
||||||
|
text: text,
|
||||||
|
textSize: fontSize,
|
||||||
|
color: '#FF0000',
|
||||||
|
},
|
||||||
|
...lines.map((line, index) => ({
|
||||||
|
position: { x: 30, y: startY + index * lineHeight },
|
||||||
|
text: line,
|
||||||
|
textSize: fontSize,
|
||||||
|
color: '#000000',
|
||||||
|
})),
|
||||||
|
];
|
||||||
|
|
||||||
|
const finalImagePath = await PhotoManipulator.printText(imageWithStrip, texts, 'image/jpeg');
|
||||||
|
const uri = finalImagePath.startsWith('file://') ? finalImagePath : `file://${finalImagePath}`;
|
||||||
|
|
||||||
|
return { success: true, uri };
|
||||||
|
} catch (error) {
|
||||||
|
console.error("❌ Error in waterMarkText:", error);
|
||||||
|
return { success: false, error: error.message };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export async function restore_ImageWithMetaData(data, imgdata) {
|
||||||
|
let { destFilePath, imgurl, imgWidth, imgHeight, mark_text1, mark_text2 } = data;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const cleanImgUrl = imgurl.startsWith('file://') ? imgurl : `file://${imgurl}`;
|
||||||
|
const rawPath = cleanImgUrl.replace('file://', '');
|
||||||
|
|
||||||
|
// Fallback to imgdata values
|
||||||
|
if (!imgWidth && imgdata?.width) imgWidth = imgdata.width;
|
||||||
|
if (!imgHeight && imgdata?.height) imgHeight = imgdata.height;
|
||||||
|
|
||||||
|
if (!imgWidth || !imgHeight || !rawPath) {
|
||||||
|
console.log('❌ Invalid resize parameters', { imgWidth, imgHeight, imgurl });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileExists = await RNFS.exists(rawPath);
|
||||||
|
if (!fileExists) {
|
||||||
|
console.log('❌ Image file not found at:', rawPath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 1: Resize (only if dimensions are large)
|
||||||
|
const resized = await resizeImage(cleanImgUrl, imgWidth, imgHeight);
|
||||||
|
if (!resized.success) {
|
||||||
|
console.log("❌ Resize failed:", resized.error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const resizedUrl = resized.uri;
|
||||||
|
const resizedData = resized.imgData;
|
||||||
|
const resizedWidth = parseInt(resizedData.width);
|
||||||
|
const resizedHeight = parseInt(resizedData.height);
|
||||||
|
|
||||||
|
// Step 2: Watermark
|
||||||
|
const marked = await waterMarkText(mark_text1, resizedUrl, mark_text2, resizedWidth, resizedHeight);
|
||||||
|
if (!marked.success || !marked.uri) {
|
||||||
|
console.log("❌ Watermark failed:", marked.error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const markedUrl = marked.uri;
|
||||||
|
|
||||||
|
// Step 3: Reduce pixels (if needed)
|
||||||
|
const reduced = await reducePixels(markedUrl, resizedWidth, resizedHeight);
|
||||||
|
if (!reduced.success) {
|
||||||
|
console.error("❌ Pixel reduction failed:", reduced.error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const finalUri = reduced.uri;
|
||||||
|
|
||||||
|
// Step 4: Copy to destination
|
||||||
|
const exists = await RNFS.exists(destFilePath);
|
||||||
|
if (exists) await RNFS.unlink(destFilePath);
|
||||||
|
|
||||||
|
await RNFS.copyFile(finalUri, destFilePath);
|
||||||
|
console.log("✅ Image with metadata saved at:", destFilePath);
|
||||||
|
|
||||||
|
// Step 5: DO NOT delete destFilePath — it's the one used in UI!
|
||||||
|
// Optional: Clean up temp files
|
||||||
|
const filesToDelete = [rawPath, resizedUrl, markedUrl]
|
||||||
|
.map(f => f.replace('file://', ''))
|
||||||
|
.filter(f => f !== destFilePath); // protect final image
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
filesToDelete.map(f => RNFS.unlink(f).catch(() => {}))
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
console.log("❌ restore_ImageWithMetaData failed:", err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function bytesToSize(bytes) {
|
||||||
|
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
||||||
|
if (bytes === 0) return '0 Byte';
|
||||||
|
const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
|
||||||
|
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const resizeImage = async (imgurl = '', imgWidth, imgHeight) => {
|
||||||
|
if (!imgurl || !imgWidth || !imgHeight || isNaN(imgWidth) || isNaN(imgHeight)) {
|
||||||
|
console.log("❌ resizeImage: Invalid parameters", { imgurl, imgWidth, imgHeight });
|
||||||
|
return { success: false, error: 'Invalid resize parameters' };
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await ImageResizer.createResizedImage(
|
||||||
|
imgurl, imgWidth, imgHeight, 'JPEG', 100, 0, null, false, { onlyScaleDown: true }
|
||||||
|
);
|
||||||
|
let size = bytesToSize(response.size);
|
||||||
|
console.log('✅ resizeImage: reduced filesize:', size);
|
||||||
|
return { success: true, uri: response.uri, imgData: response };
|
||||||
|
} catch (err) {
|
||||||
|
console.log("❌ resizeImage error:", err);
|
||||||
|
return { success: false, error: err };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const reducePixels = async (imgurl = '', imgWidth, imgHeight) => {
|
||||||
|
if (!imgurl || !imgWidth || !imgHeight || isNaN(imgWidth) || isNaN(imgHeight)) {
|
||||||
|
console.log("❌ reducePixels: Invalid parameters", { imgurl, imgWidth, imgHeight });
|
||||||
|
return { success: false, error: 'Invalid pixel reduction parameters' };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resize only if image is large
|
||||||
|
if (imgWidth > 1100 || imgHeight > 1100) {
|
||||||
|
try {
|
||||||
|
const response = await ImageResizer.createResizedImage(
|
||||||
|
imgurl, 1100, 1100, 'JPEG', 40, 0, null, false,
|
||||||
|
{ onlyScaleDown: true, mode: 'contain' }
|
||||||
|
);
|
||||||
|
let size = bytesToSize(response.size);
|
||||||
|
console.log('✅ reducePixels: reduced size to', size, '→', response.width, 'x', response.height);
|
||||||
|
return { success: true, uri: response.uri };
|
||||||
|
} catch (err) {
|
||||||
|
console.log("❌ reducePixels error:", err);
|
||||||
|
return { success: false, error: err };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No resizing needed
|
||||||
|
return { success: true, uri: imgurl };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// end image resize and reduce pixel function
|
||||||
|
|
||||||
|
|
||||||
|
export async function getAllFileForAFolder(path, Up_Foldername, KPIName = '') {
|
||||||
|
|
||||||
|
let subFolPath = path;
|
||||||
|
const ImgFiles = await RNFS.readDir(subFolPath);
|
||||||
|
Up_Foldername = Up_Foldername != null && Up_Foldername != '' ? Up_Foldername : defUploadFolder;
|
||||||
|
|
||||||
|
console.log("ImgFiles in ", subFolPath, ' are:', ImgFiles.length);
|
||||||
|
let allKPIfiles = [];
|
||||||
|
return new Promise.all(
|
||||||
|
ImgFiles.map(async sfile => {
|
||||||
|
if (sfile.isFile() && (sfile.name.includes('jpg') || sfile.name.includes('jpeg') || sfile.name.includes('png'))) {
|
||||||
|
|
||||||
|
let file = {
|
||||||
|
uri: sfile.path,
|
||||||
|
type: 'image/jpeg',
|
||||||
|
name: sfile.name,
|
||||||
|
filetype: 'image',
|
||||||
|
folderName: Up_Foldername,
|
||||||
|
}
|
||||||
|
allKPIfiles.push(file);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
else if (sfile.isDirectory() && sfile.name == 'Recordings') {
|
||||||
|
let recordingsPath = sfile.path;
|
||||||
|
let recordingFiles = await RNFS.readDir(recordingsPath);
|
||||||
|
let VoiceUp_FolderPath = KPIName != null && KPIName != '' ? FolderForREC[KPIName] : defUploadFolder;
|
||||||
|
return new Promise.all(
|
||||||
|
recordingFiles.map(async rfile => {
|
||||||
|
|
||||||
|
if (rfile.isFile() && (rfile.name.includes('m4a') || rfile.name.includes('mp3'))) {
|
||||||
|
|
||||||
|
let file = {
|
||||||
|
uri: rfile.path,
|
||||||
|
type: (Platform.OS == 'ios' ? 'audio/m4a' : 'audio/mp3'),
|
||||||
|
name: rfile.name,
|
||||||
|
filetype: 'audio',
|
||||||
|
folderName: VoiceUp_FolderPath,
|
||||||
|
}
|
||||||
|
allKPIfiles.push(file);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
).then((val2) => {
|
||||||
|
return val2;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
).then((val1) => {
|
||||||
|
console.log('getAllFileForAFolder', val1);
|
||||||
|
return allKPIfiles;
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log('error in getAllFileForAFolder', err);
|
||||||
|
return allKPIfiles;
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// download
|
||||||
|
|
||||||
|
|
||||||
|
export async function getDownloadJson(url, indata) {
|
||||||
|
let postdata = {
|
||||||
|
Downloadtype: indata.Downloadtype,
|
||||||
|
Username: indata.username,
|
||||||
|
Param1: '',
|
||||||
|
Param2: '',
|
||||||
|
};
|
||||||
|
console.log(postdata);
|
||||||
|
return await fetch(url, {
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(postdata),
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
// console.log('res',res);
|
||||||
|
let resd = JSON.parse(res);
|
||||||
|
return resd;
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log('getdashboard error', err);
|
||||||
|
return { success: false };
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export async function UploadImagesWithoutWait(postData,url){
|
||||||
|
console.log(url,postData);
|
||||||
|
return await UploadFormData(url,postData)
|
||||||
|
.then((res)=>{
|
||||||
|
console.log('test:',res);
|
||||||
|
if(typeof res=='object' && res.error!=null){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if(res.includes('Success')){
|
||||||
|
console.log('image uploaded');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
.catch((err)=>{
|
||||||
|
console.log(err);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function UploadData2(url, indata) {
|
||||||
|
|
||||||
|
return await fetch(url, {
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(indata),
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
return res;
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log('UploadData error', err);
|
||||||
|
return { success: false, error: true, errorMsg: err };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function UploadFormData(url, formData) {
|
||||||
|
// console.log(url,formData._parts);
|
||||||
|
return await fetch(url, {
|
||||||
|
method: 'post',
|
||||||
|
headers: new Headers({ 'Content-Type': 'multipart/form-data', }),
|
||||||
|
body: formData,
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
console.log('UploadData error3', response);
|
||||||
|
return response.text();
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
console.log('UploadData error1', res);
|
||||||
|
return res;
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log('UploadData error2', err);
|
||||||
|
return { success: false, error: err };
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import { toastError } from "./Toast";
|
||||||
|
|
||||||
|
|
||||||
|
export function validateNumber(val, type = '', showMsg = true) {
|
||||||
|
console.log(val, "type=======", type);
|
||||||
|
let isValid = true;
|
||||||
|
if (type.toLowerCase() == 'numeric' && val != '') {
|
||||||
|
let regex = new RegExp(/^\d+$/);
|
||||||
|
let isNUmeric = regex.test(val);
|
||||||
|
if (!isNUmeric) {
|
||||||
|
isValid = false;
|
||||||
|
if (showMsg) toastError('Alert', 'Please enter whole numbers only');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type.toLowerCase() == 'decimal' && val != '') {
|
||||||
|
let regex = new RegExp(/^\d*\.?\d*$/);
|
||||||
|
let isNUmeric = regex.test(val);
|
||||||
|
if (!isNUmeric) {
|
||||||
|
isValid = false;
|
||||||
|
if (showMsg) toastError('Alert', 'Please enter decimal numbers only');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type.toLowerCase() == 'text' && val != '') {
|
||||||
|
let regex = new RegExp(/^[a-zA-Z0-9@\s_.-]*$/);
|
||||||
|
let isNUmeric = regex.test(val);
|
||||||
|
if (!isNUmeric) {
|
||||||
|
isValid = false;
|
||||||
|
if (showMsg) toastError('Alert', 'Please enter only characters and digits');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (type.toLowerCase() === 'onlytext' && val !== '') {
|
||||||
|
let regex = /^[a-zA-Z\s]*$/; // ✅ allows only alphabets and space
|
||||||
|
const isAlpha = regex.test(val);
|
||||||
|
if (!isAlpha) {
|
||||||
|
isValid = false;
|
||||||
|
if (showMsg) toastError('Alert', 'Please enter only letters and spaces');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (type.toLowerCase() == 'textspc' && val != '') {
|
||||||
|
let regex = new RegExp(/^[a-zA-Z0-9\/-]*$/);
|
||||||
|
let isNUmeric = regex.test(val);
|
||||||
|
if (!isNUmeric) {
|
||||||
|
isValid = false;
|
||||||
|
if (showMsg) toastError('Alert', 'Please enter only characters and digits');
|
||||||
|
}
|
||||||
|
} else if (type.toLowerCase() == 'alphanumeric' && val != '') {
|
||||||
|
let regex = new RegExp(/^[a-zA-Z0-9]+$/);
|
||||||
|
let isNUmeric = regex.test(val);
|
||||||
|
if (!isNUmeric) {
|
||||||
|
isValid = false;
|
||||||
|
if (showMsg) toastError('Alert', 'Please enter only characters and digits');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return isValid;
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { NavigationContainer } from '@react-navigation/native';
|
import { NavigationContainer } from '@react-navigation/native';
|
||||||
@@ -27,4 +28,57 @@ const Routes = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
=======
|
||||||
|
import React from 'react';
|
||||||
|
import { NavigationContainer } from '@react-navigation/native';
|
||||||
|
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
||||||
|
import Splash from '../screens/AuthScreen/Splash';
|
||||||
|
import Login from '../screens/AuthScreen/Login/Login';
|
||||||
|
import VerifyOTP from '../screens/AuthScreen/VerifyOTP';
|
||||||
|
import { ToastComponent } from '../constants/Toast';
|
||||||
|
import StoreInfo from '../screens/MainScreen/StoreInfo';
|
||||||
|
|
||||||
|
import Feedback from '../screens/MainScreen/Feedback';
|
||||||
|
import Dashboard from '../screens/MainScreen/Dashboard';
|
||||||
|
import FeedbackCategories from '../screens/MainScreen/Feedback/FeedbackCategories';
|
||||||
|
import { Platform, StatusBar, View } from 'react-native';
|
||||||
|
import Welcome from '../screens/MainScreen/WelcomePage';
|
||||||
|
import Details from '../screens/MainScreen/Dashboard/Details';
|
||||||
|
import Project from '../screens/AuthScreen/Project/Project';
|
||||||
|
|
||||||
|
const Stack = createNativeStackNavigator();
|
||||||
|
|
||||||
|
const Routes = () => {
|
||||||
|
const STATUSBAR_HEIGHT = Platform.OS === 'ios' ? 50 : StatusBar.currentHeight;
|
||||||
|
return (
|
||||||
|
<NavigationContainer>
|
||||||
|
{Platform.OS === 'ios' && (
|
||||||
|
<View style={{
|
||||||
|
height: STATUSBAR_HEIGHT,
|
||||||
|
bbarStyle:'light-content',
|
||||||
|
backgroundColor: '#113F8C',
|
||||||
|
}} />
|
||||||
|
)}
|
||||||
|
<StatusBar barStyle={'light-content'} backgroundColor={'#113F8C'} />
|
||||||
|
<Stack.Navigator
|
||||||
|
screenOptions={{ headerShown: false }}
|
||||||
|
initialRouteName="Splash">
|
||||||
|
<Stack.Screen name="Splash" component={Splash} />
|
||||||
|
<Stack.Screen name="Login" component={Login} />
|
||||||
|
<Stack.Screen name="VerifyOTP" component={VerifyOTP} />
|
||||||
|
<Stack.Screen name="Welcome" component={Welcome} />
|
||||||
|
<Stack.Screen name="StoreInfo" component={StoreInfo} />
|
||||||
|
<Stack.Screen name="Dashboard" component={Dashboard} />
|
||||||
|
<Stack.Screen name="Feedback" component={Feedback} />
|
||||||
|
<Stack.Screen name="FeedbackCategories" component={FeedbackCategories} />
|
||||||
|
<Stack.Screen name="Details" component={Details} />
|
||||||
|
<Stack.Screen name="Project" component={Project} />
|
||||||
|
|
||||||
|
</Stack.Navigator>
|
||||||
|
<ToastComponent />
|
||||||
|
</NavigationContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
export default Routes;
|
export default Routes;
|
||||||
@@ -1,5 +1,13 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
import userSlice from '../slices/userSlice';
|
import userSlice from '../slices/userSlice';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
user: userSlice,
|
user: userSlice,
|
||||||
};
|
};
|
||||||
|
=======
|
||||||
|
import userSlice from '../slices/userSlice';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
user: userSlice,
|
||||||
|
};
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
// // src/redux/slices/authSlice.js
|
// // src/redux/slices/authSlice.js
|
||||||
// import { createSlice } from '@reduxjs/toolkit';
|
// import { createSlice } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
@@ -30,4 +31,38 @@
|
|||||||
// });
|
// });
|
||||||
|
|
||||||
// export const { loginStart, loginSuccess, loginFailure, logout } = authSlice.actions;
|
// export const { loginStart, loginSuccess, loginFailure, logout } = authSlice.actions;
|
||||||
|
=======
|
||||||
|
// // src/redux/slices/authSlice.js
|
||||||
|
// import { createSlice } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
|
// const initialState = {
|
||||||
|
// token: null,
|
||||||
|
// loading: false,
|
||||||
|
// error: null,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const authSlice = createSlice({
|
||||||
|
// name: 'auth',
|
||||||
|
// initialState,
|
||||||
|
// reducers: {
|
||||||
|
// loginStart: (state) => {
|
||||||
|
// state.loading = true;
|
||||||
|
// state.error = null;
|
||||||
|
// },
|
||||||
|
// loginSuccess: (state, action) => {
|
||||||
|
// state.loading = false;
|
||||||
|
// state.token = action.payload;
|
||||||
|
// },
|
||||||
|
// loginFailure: (state, action) => {
|
||||||
|
// state.loading = false;
|
||||||
|
// state.error = action.payload;
|
||||||
|
// },
|
||||||
|
// logout: (state) => {
|
||||||
|
// state.token = null;
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
|
// export const { loginStart, loginSuccess, loginFailure, logout } = authSlice.actions;
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
// export default authSlice.reducer;
|
// export default authSlice.reducer;
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
import {createSlice} from '@reduxjs/toolkit';
|
import {createSlice} from '@reduxjs/toolkit';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
@@ -23,3 +24,30 @@ const userSlice = createSlice({
|
|||||||
|
|
||||||
export const {setUser, resetUserState} = userSlice.actions;
|
export const {setUser, resetUserState} = userSlice.actions;
|
||||||
export default userSlice.reducer;
|
export default userSlice.reducer;
|
||||||
|
=======
|
||||||
|
import {createSlice} from '@reduxjs/toolkit';
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
token: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const userSlice = createSlice({
|
||||||
|
name: 'user',
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
setUser(state, action) {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
...action.payload,
|
||||||
|
token: action?.payload?.usertoken,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
resetUserState() {
|
||||||
|
return initialState;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const {setUser, resetUserState} = userSlice.actions;
|
||||||
|
export default userSlice.reducer;
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
import { configureStore } from '@reduxjs/toolkit'
|
import { configureStore } from '@reduxjs/toolkit'
|
||||||
import reducer from './reducer'
|
import reducer from './reducer'
|
||||||
|
|
||||||
|
|
||||||
|
=======
|
||||||
|
import { configureStore } from '@reduxjs/toolkit'
|
||||||
|
import reducer from './reducer'
|
||||||
|
|
||||||
|
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
export const store = configureStore({ reducer: reducer })
|
export const store = configureStore({ reducer: reducer })
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { View, Text, Image, Platform, ImageBackground } from 'react-native';
|
||||||
|
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||||
|
import IMAGES from '../../../constants/Images';
|
||||||
|
import { styles } from './style';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import CustomTextInput from '../../../components/CustomTextInput';
|
||||||
|
import CustomButton from '../../../components/CustomButton';
|
||||||
|
import Loader from '../../../constants/Loader';
|
||||||
|
import { ApiURL } from '../../../api/ApiConstant';
|
||||||
|
import { toastError, toastSuccess } from '../../../constants/Toast';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||||
|
import { GlobalTheme } from '../../../theme';
|
||||||
|
import Geolocation from '@react-native-community/geolocation';
|
||||||
|
|
||||||
|
|
||||||
|
const Login = ({ navigation }) => {
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const [username, setUsername] = useState('');
|
||||||
|
|
||||||
|
|
||||||
|
// geo loc
|
||||||
|
useEffect(() => {
|
||||||
|
Geolocation.getCurrentPosition(info => console.log("Location infoooo====>", JSON.stringify(info)));
|
||||||
|
}, [])
|
||||||
|
// end geo loc
|
||||||
|
|
||||||
|
|
||||||
|
const onSubmit = () => {
|
||||||
|
setLoading(true);
|
||||||
|
getOTP();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getOTP = async () => {
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
"UserId": username
|
||||||
|
};
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
method: 'post',
|
||||||
|
url: ApiURL.getotpApi,
|
||||||
|
headers: {
|
||||||
|
'api_key': '9a1f056fecb84eaf8eb4152dda22ab0501955c4f9bbe7daa8780740459fdde7a',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
data: params
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await axios.request(config);
|
||||||
|
const res = response.data || [];
|
||||||
|
console.log('OTP is ===> ', res?.SendOTP);
|
||||||
|
if (res?.SendOTP[0].OTP === '0' || res?.SendOTP[0].OTP === 0) {
|
||||||
|
setLoading(false);
|
||||||
|
toastError("Alert", "Invalid User");
|
||||||
|
} else {
|
||||||
|
toastSuccess("Alert", res?.SendOTP[0]?.Messages);
|
||||||
|
navigation.navigate('VerifyOTP', { username: username });
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
// console.log('getotpApi res==>', JSON.stringify(res?.SendOTP[0]));
|
||||||
|
} catch (error) {
|
||||||
|
console.log("❌ OTP API error:", error);
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container}>
|
||||||
|
<KeyboardAwareScrollView keyboardShouldPersistTaps="handled" enableOnAndroid={true} contentContainerStyle={{ justifyContent: 'center', flexGrow: 1, marginTop: 0 }} style={styles.container}>
|
||||||
|
<View style={{ backgroundColor: GlobalTheme.colors.primary, height: 40 }} />
|
||||||
|
<Image style={styles.appLogo} source={IMAGES.AuthTopBGNew} resizeMode='contain' />
|
||||||
|
<View style={styles.card}>
|
||||||
|
<Text style={styles.loginTitle}>Login</Text>
|
||||||
|
<CustomTextInput
|
||||||
|
label="Username"
|
||||||
|
placeholder="Enter username"
|
||||||
|
value={username}
|
||||||
|
onChangeText={setUsername}
|
||||||
|
containerStyle={styles.inputWrapper}
|
||||||
|
/>
|
||||||
|
<CustomButton onPress={() => onSubmit()} title={'Continue'} style={styles.btnbg} textstyle={styles.btntext} />
|
||||||
|
<ImageBackground source={IMAGES.AuthBottomBG} style={styles.AuthBottomBG} >
|
||||||
|
<Text style={{ position: 'absolute', textAlign: 'center', alignContent: 'center', alignSelf: 'center', bottom: 0, color: GlobalTheme.colors.gray }}> Copyright CPM India - 2025</Text>
|
||||||
|
{/* <Image source={IMAGES.Logo} style={styles.footerImage} resizeMode="contain"/> */}
|
||||||
|
</ImageBackground>
|
||||||
|
</View>
|
||||||
|
</KeyboardAwareScrollView>
|
||||||
|
<Loader visible={loading} loadingtext={'Loading ...'} />
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Login;
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
import { StyleSheet } from 'react-native';
|
import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
import { GlobalTheme, Screen } from '../../../theme';
|
import { GlobalTheme, Screen } from '../../../theme';
|
||||||
@@ -33,3 +34,87 @@ export const styles = StyleSheet.create({
|
|||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
=======
|
||||||
|
import { StyleSheet, Dimensions } from 'react-native';
|
||||||
|
import { GlobalTheme } from '../../../theme';
|
||||||
|
import { normalize } from '../../../utilis/responsive';
|
||||||
|
const { width, height } = Dimensions.get('window');
|
||||||
|
|
||||||
|
export const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: GlobalTheme.colors.primary,
|
||||||
|
},
|
||||||
|
logoContainer: {
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
appLogo: {
|
||||||
|
height: normalize(170),
|
||||||
|
width: '100%',
|
||||||
|
resizeMode: 'contain',
|
||||||
|
},
|
||||||
|
titleContainer: {
|
||||||
|
alignSelf: 'center',
|
||||||
|
marginBottom: normalize(10),
|
||||||
|
},
|
||||||
|
titleText: {
|
||||||
|
fontSize: normalize(20),
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: GlobalTheme.colors.black,
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
backgroundColor: GlobalTheme.colors.white,
|
||||||
|
borderTopLeftRadius: GlobalTheme.borderRadius.xxlg || normalize(20),
|
||||||
|
borderTopRightRadius: GlobalTheme.borderRadius.xxlg || normalize(20),
|
||||||
|
padding: normalize(20),
|
||||||
|
width: width,
|
||||||
|
alignSelf: 'center',
|
||||||
|
// marginTop: normalize(30),
|
||||||
|
shadowColor: '#000',
|
||||||
|
shadowOpacity: 0.05,
|
||||||
|
shadowOffset: { width: 0, height: 4 },
|
||||||
|
shadowRadius: 8,
|
||||||
|
elevation: 4,
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
btnbg: {
|
||||||
|
backgroundColor: GlobalTheme.colors.secondary,
|
||||||
|
borderRadius: GlobalTheme.borderRadius.md,
|
||||||
|
marginTop: normalize(30),
|
||||||
|
paddingVertical: normalize(12),
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
btntext: {
|
||||||
|
color: GlobalTheme.colors.white,
|
||||||
|
fontSize: normalize(GlobalTheme.typography.fontSize.small),
|
||||||
|
fontWeight: GlobalTheme.typography.fontWeight.regular,
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
marginTop: normalize(60),
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
footerImage: {
|
||||||
|
width: '100%',
|
||||||
|
height: normalize(80),
|
||||||
|
resizeMode: 'contain',
|
||||||
|
marginTop : normalize(160),
|
||||||
|
},
|
||||||
|
AuthBottomBG: {
|
||||||
|
width: '100%',
|
||||||
|
resizeMode: 'contain',
|
||||||
|
height: normalize(300),
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
loginTitle: {
|
||||||
|
color: GlobalTheme.colors.black,
|
||||||
|
fontSize: normalize(GlobalTheme.typography.fontSize.large),
|
||||||
|
fontWeight: GlobalTheme.typography.fontWeight.medium,
|
||||||
|
textAlign: 'center',
|
||||||
|
marginBottom: normalize(20),
|
||||||
|
},
|
||||||
|
mainContainer: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#EAF0FF',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { View, Text, Image, Platform, ImageBackground, TextInput } from 'react-native';
|
||||||
|
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||||
|
import IMAGES from '../../../constants/Images';
|
||||||
|
import { styles } from './style';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import CustomButton from '../../../components/CustomButton';
|
||||||
|
import Loader from '../../../constants/Loader';
|
||||||
|
import { ApiURL } from '../../../api/ApiConstant';
|
||||||
|
import { toastError, toastSuccess } from '../../../constants/Toast';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||||
|
import { GlobalTheme } from '../../../theme';
|
||||||
|
import Geolocation from '@react-native-community/geolocation';
|
||||||
|
|
||||||
|
|
||||||
|
const Project = ({ navigation }) => {
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const [username, setUsername] = useState('');
|
||||||
|
|
||||||
|
|
||||||
|
// geo loc
|
||||||
|
useEffect(() => {
|
||||||
|
Geolocation.getCurrentPosition(info => console.log("Location infoooo====>", JSON.stringify(info)));
|
||||||
|
}, [])
|
||||||
|
// end geo loc
|
||||||
|
|
||||||
|
|
||||||
|
const onSubmit = () => {
|
||||||
|
// setLoading(true);
|
||||||
|
// getOTP();
|
||||||
|
navigation.navigate("Login")
|
||||||
|
};
|
||||||
|
|
||||||
|
const getOTP = async () => {
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
"UserId": username
|
||||||
|
};
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
method: 'post',
|
||||||
|
url: ApiURL.getotpApi,
|
||||||
|
headers: {
|
||||||
|
'api_key': '9a1f056fecb84eaf8eb4152dda22ab0501955c4f9bbe7daa8780740459fdde7a',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
data: params
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await axios.request(config);
|
||||||
|
const res = response.data || [];
|
||||||
|
console.log('OTP is ===> ', res?.SendOTP);
|
||||||
|
if (res?.SendOTP[0].OTP === '0' || res?.SendOTP[0].OTP === 0) {
|
||||||
|
setLoading(false);
|
||||||
|
toastError("Alert", "Invalid User");
|
||||||
|
} else {
|
||||||
|
toastSuccess("Alert", res?.SendOTP[0]?.Messages);
|
||||||
|
navigation.navigate('VerifyOTP', { username: username });
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
// console.log('getotpApi res==>', JSON.stringify(res?.SendOTP[0]));
|
||||||
|
} catch (error) {
|
||||||
|
console.log("❌ OTP API error:", error);
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container}>
|
||||||
|
<KeyboardAwareScrollView keyboardShouldPersistTaps="handled" enableOnAndroid={true} contentContainerStyle={{ justifyContent: 'center', flexGrow: 1, marginTop: 0 }} style={styles.container}>
|
||||||
|
{/* <View style={{ backgroundColor: GlobalTheme.colors.primary, height: 40 }} /> */}
|
||||||
|
<Image style={styles.performicsLogo} source={IMAGES.PerformicsLogo} resizeMode='contain' />
|
||||||
|
<Image style={styles.appLogo} source={IMAGES.projectIdImg} resizeMode='contain' />
|
||||||
|
<View style={styles.card}>
|
||||||
|
<View style={{marginTop:25}}>
|
||||||
|
<Text style={[styles.loginTitle, { fontSize: 15, color: '#555555', marginBottom: 10 }]}>Hey There</Text>
|
||||||
|
<Text style={styles.loginTitle}>Enter Your Project Id</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={{ marginTop: 20, height: 50, backgroundColor: '#eee', borderRadius: 10 }}>
|
||||||
|
<TextInput
|
||||||
|
style={{ height: 50, paddingHorizontal: 15 }}
|
||||||
|
placeholder='Enter Project Id'
|
||||||
|
placeholderTextColor={'gray'}
|
||||||
|
keyboardType='numeric'
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<CustomButton onPress={() => onSubmit()} title={'Next'} style={styles.btnbg} textstyle={styles.btntext} />
|
||||||
|
<ImageBackground source={IMAGES.AuthBottomBG} style={styles.AuthBottomBG} >
|
||||||
|
<Text style={{ position: 'absolute', textAlign: 'center', alignContent: 'center', alignSelf: 'center', bottom: 20, color: GlobalTheme.colors.gray }}> Copyright CPM India - 2025</Text>
|
||||||
|
</ImageBackground>
|
||||||
|
</View>
|
||||||
|
</KeyboardAwareScrollView>
|
||||||
|
<Loader visible={loading} loadingtext={'Loading ...'} />
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Project;
|
||||||
|
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
import { StyleSheet, Dimensions } from 'react-native';
|
||||||
|
import { GlobalTheme } from '../../../theme';
|
||||||
|
import { normalize } from '../../../utilis/responsive';
|
||||||
|
const { width, height } = Dimensions.get('window');
|
||||||
|
|
||||||
|
export const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: "#fff",
|
||||||
|
},
|
||||||
|
logoContainer: {
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
appLogo: {
|
||||||
|
height: normalize(180),
|
||||||
|
width: '100%',
|
||||||
|
resizeMode: 'contain',
|
||||||
|
marginTop: 30,
|
||||||
|
},
|
||||||
|
performicsLogo: {
|
||||||
|
height: normalize(50),
|
||||||
|
width: '55%',
|
||||||
|
resizeMode: 'contain',
|
||||||
|
alignSelf: 'center',
|
||||||
|
marginTop:10,
|
||||||
|
},
|
||||||
|
titleContainer: {
|
||||||
|
alignSelf: 'center',
|
||||||
|
marginBottom: normalize(10),
|
||||||
|
},
|
||||||
|
titleText: {
|
||||||
|
fontSize: normalize(20),
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: GlobalTheme.colors.black,
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
padding: normalize(25),
|
||||||
|
width: width,
|
||||||
|
alignSelf: 'center',
|
||||||
|
// marginTop: normalize(30),
|
||||||
|
shadowColor: '#000',
|
||||||
|
shadowOpacity: 0.05,
|
||||||
|
shadowOffset: { width: 0, height: 4 },
|
||||||
|
shadowRadius: 8,
|
||||||
|
// elevation: 4,
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
btnbg: {
|
||||||
|
backgroundColor: GlobalTheme.colors.secondary,
|
||||||
|
borderRadius: GlobalTheme.borderRadius.md,
|
||||||
|
marginTop: normalize(30),
|
||||||
|
paddingVertical: normalize(12),
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
btntext: {
|
||||||
|
color: GlobalTheme.colors.white,
|
||||||
|
fontSize: normalize(GlobalTheme.typography.fontSize.small),
|
||||||
|
fontWeight: GlobalTheme.typography.fontWeight.regular,
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
marginTop: normalize(60),
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
footerImage: {
|
||||||
|
width: '100%',
|
||||||
|
height: normalize(80),
|
||||||
|
resizeMode: 'contain',
|
||||||
|
marginTop: normalize(160),
|
||||||
|
},
|
||||||
|
AuthBottomBG: {
|
||||||
|
width: '100%',
|
||||||
|
resizeMode: 'contain',
|
||||||
|
height: normalize(210),
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
loginTitle: {
|
||||||
|
color: GlobalTheme.colors.black,
|
||||||
|
fontSize: normalize(GlobalTheme.typography.fontSize.small),
|
||||||
|
fontWeight: GlobalTheme.typography.fontWeight.medium,
|
||||||
|
textAlign: 'center',
|
||||||
|
marginBottom: normalize(20),
|
||||||
|
},
|
||||||
|
mainContainer: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#EAF0FF',
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
import {View, Text, Image, Dimensions, StyleSheet} from 'react-native';
|
import {View, Text, Image, Dimensions, StyleSheet} from 'react-native';
|
||||||
import React, {useEffect} from 'react';
|
import React, {useEffect} from 'react';
|
||||||
import IMAGES from '../../../constants/Images';
|
import IMAGES from '../../../constants/Images';
|
||||||
@@ -97,3 +98,104 @@ const styles = StyleSheet.create({
|
|||||||
//borderWidth:1
|
//borderWidth:1
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
=======
|
||||||
|
import { View, Text, Image, Dimensions, StyleSheet } from 'react-native';
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import IMAGES from '../../../constants/Images';
|
||||||
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { setUser } from '../../../redux/slices/userSlice';
|
||||||
|
|
||||||
|
const SplashScreen = ({ navigation }) => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
checkLoginStatus();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const checkLoginStatus = async () => {
|
||||||
|
try {
|
||||||
|
const isuserlogin = await AsyncStorage.getItem('@Dabur_DNA_User');
|
||||||
|
console.log("isuserlogin", isuserlogin)
|
||||||
|
const parsedUser = JSON.parse(isuserlogin);
|
||||||
|
if (isuserlogin) {
|
||||||
|
dispatch(setUser(parsedUser));
|
||||||
|
setTimeout(() => {
|
||||||
|
navigation.reset({
|
||||||
|
index: 0,
|
||||||
|
routes: [{ name: 'Welcome' }],
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
setTimeout(() => {
|
||||||
|
navigation.reset({
|
||||||
|
index: 0,
|
||||||
|
routes: [{ name: 'Login' }],
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error checking login status:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<View style={styles.backgroundContainer}>
|
||||||
|
<Image
|
||||||
|
source={IMAGES.splashFullImg}
|
||||||
|
resizeMode="stretch"
|
||||||
|
style={styles.backdrop}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<View style={styles.overlay}>
|
||||||
|
<Image style={styles.logo} source={IMAGES.AppLogo} />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SplashScreen;
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
backgroundContainer: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
},
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
overlay: {
|
||||||
|
opacity: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
logo: {
|
||||||
|
backgroundColor: 'rgba(0,0,0,0)',
|
||||||
|
height: 200,
|
||||||
|
width: 200,
|
||||||
|
overflow: 'hidden',
|
||||||
|
resizeMode: 'contain',
|
||||||
|
marginTop: 5,
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
backdrop: {
|
||||||
|
flex: 1,
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
},
|
||||||
|
headline: {
|
||||||
|
fontSize: 18,
|
||||||
|
textAlign: 'center',
|
||||||
|
backgroundColor: 'black',
|
||||||
|
color: 'white',
|
||||||
|
//borderWidth:1
|
||||||
|
},
|
||||||
|
});
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import { View, Text, Image, Alert, TouchableOpacity } from 'react-native';
|
import { View, Text, Image, Alert, TouchableOpacity } from 'react-native';
|
||||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||||
@@ -122,3 +123,224 @@ const VerifyOTP = ({ navigation }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default VerifyOTP;
|
export default VerifyOTP;
|
||||||
|
=======
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { View, Text, Image, TouchableOpacity, ImageBackground } from 'react-native';
|
||||||
|
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { OtpInput } from "react-native-otp-entry";
|
||||||
|
import CustomButton from '../../../components/CustomButton';
|
||||||
|
import Background from '../../../components/Background';
|
||||||
|
import IMAGES from '../../../constants/Images';
|
||||||
|
import { GlobalTheme } from '../../../theme';
|
||||||
|
import { styles } from './style';
|
||||||
|
import { toastError, toastSuccess } from '../../../constants/Toast';
|
||||||
|
import Loader from '../../../constants/Loader';
|
||||||
|
import { ApiURL } from '../../../api/ApiConstant';
|
||||||
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
|
import { setUser } from '../../../redux/slices/userSlice';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||||
|
|
||||||
|
const VerifyOTP = ({ navigation, route }) => {
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const [otp, setOTP] = useState('');
|
||||||
|
const [timer, setTimer] = useState(300); // 5 minutes = 300 seconds
|
||||||
|
const [showResend, setShowResend] = useState(false);
|
||||||
|
|
||||||
|
const username = route.params.username;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (timer === 0) {
|
||||||
|
setShowResend(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
setTimer(prev => prev - 1);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}, [timer]);
|
||||||
|
|
||||||
|
const formatTime = (secs) => {
|
||||||
|
const minutes = Math.floor(secs / 60);
|
||||||
|
const seconds = secs % 60;
|
||||||
|
return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handle_validate = () => {
|
||||||
|
if (otp.length < 6) {
|
||||||
|
toastError('Alert', "Please enter 6 digit PIN");
|
||||||
|
} else {
|
||||||
|
onSubmit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const resendOTP = async () => {
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
"UserId": username
|
||||||
|
}
|
||||||
|
const config = {
|
||||||
|
method: 'post',
|
||||||
|
url: ApiURL.getotpApi,
|
||||||
|
headers: {
|
||||||
|
'api_key': '9a1f056fecb84eaf8eb4152dda22ab0501955c4f9bbe7daa8780740459fdde7a',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
data: params
|
||||||
|
};
|
||||||
|
const response = await axios.request(config);
|
||||||
|
const res = response.data || [];
|
||||||
|
// console.log('storeSearchApi====>', res);
|
||||||
|
if (res?.SendOTP[0].OTP === '0' || res?.SendOTP[0].OTP === 0) {
|
||||||
|
toastError("Alert", res?.SendOTP[0]?.Messages)
|
||||||
|
} else {
|
||||||
|
toastSuccess("Alert", res?.SendOTP[0]?.Messages)
|
||||||
|
navigation.navigate('VerifyOTP', { username: username });
|
||||||
|
}
|
||||||
|
// console.log('getotpApi res==>', JSON.stringify(res?.SendOTP[0]));
|
||||||
|
// setLoading(false)
|
||||||
|
} catch (error) {
|
||||||
|
// setLoading(false)
|
||||||
|
console.log("❌ Filter API error:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const resend_OTP = () => {
|
||||||
|
setTimer(300);
|
||||||
|
setShowResend(false);
|
||||||
|
toastSuccess('Resend OTP Successfully.')
|
||||||
|
resendOTP();
|
||||||
|
}
|
||||||
|
|
||||||
|
const onSubmit = () => {
|
||||||
|
setLoading(true)
|
||||||
|
VerifyOTP();
|
||||||
|
setTimeout(() => {
|
||||||
|
setLoading(false)
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
const VerifyOTP = async () => {
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
"UserId": username,
|
||||||
|
"OTP": otp
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
method: 'post',
|
||||||
|
url: ApiURL.verifyotpApi,
|
||||||
|
headers: {
|
||||||
|
'api_key': '9a1f056fecb84eaf8eb4152dda22ab0501955c4f9bbe7daa8780740459fdde7a',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
data: params
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await axios.request(config);
|
||||||
|
const res = response.data || [];
|
||||||
|
|
||||||
|
if (res?.AuthenticateOTP[0].Message == 'OTP is matched') {
|
||||||
|
toastSuccess("Alert", res?.AuthenticateOTP[0]?.Message || "Alert", "Login Successfully.")
|
||||||
|
await AsyncStorage.setItem('@Dabur_DNA_User', JSON.stringify(res?.AuthenticateOTP[0]));
|
||||||
|
dispatch(setUser(res?.AuthenticateOTP[0]));
|
||||||
|
navigation.reset({ index: 0, routes: [{ name: 'Welcome' }] })
|
||||||
|
} else {
|
||||||
|
toastError("Alert", res?.AuthenticateOTP[0]?.Message);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// setLoading(false)
|
||||||
|
console.log("❌ Filter API error:", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container}>
|
||||||
|
<TouchableOpacity onPress={() => navigation.goBack()}>
|
||||||
|
<View style={styles.backTextView}>
|
||||||
|
<Image source={IMAGES.leftArrowIcon} style={styles.iconStyle} />
|
||||||
|
<Text style={styles.backIconText}>Back</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<KeyboardAwareScrollView keyboardShouldPersistTaps="handled" enableOnAndroid={true} style={styles.container} contentContainerStyle={{ justifyContent: 'center', flex: 1 }}>
|
||||||
|
<View style={{ backgroundColor: GlobalTheme.colors.primary, height: 40 }} />
|
||||||
|
<Image style={styles.appLogo} source={IMAGES.AuthTopBGNew} resizeMode='contain' />
|
||||||
|
<View style={styles.card}>
|
||||||
|
<View style={styles.titleContainer}>
|
||||||
|
<Text style={styles.titleText}>Enter the OTP sent to your {"\n"} registered contact</Text>
|
||||||
|
</View>
|
||||||
|
<View style={{ marginTop: 50 }}>
|
||||||
|
<OtpInput
|
||||||
|
numberOfDigits={6}
|
||||||
|
focusColor={GlobalTheme.colors.primary}
|
||||||
|
autoFocus={false}
|
||||||
|
hideStick={true}
|
||||||
|
placeholder=""
|
||||||
|
blurOnFilled={true}
|
||||||
|
disabled={false}
|
||||||
|
type="numeric"
|
||||||
|
secureTextEntry={false}
|
||||||
|
focusStickBlinkingDuration={500}
|
||||||
|
// onFocus={() => console.log("Focused")}
|
||||||
|
// onBlur={() => console.log("Blurred")}
|
||||||
|
onTextChange={(text) => setOTP(text)}
|
||||||
|
onFilled={(text) => {
|
||||||
|
setOTP(text);
|
||||||
|
console.log(`OTP is ${text}`);
|
||||||
|
}}
|
||||||
|
textInputProps={{
|
||||||
|
accessibilityLabel: "One-Time Password",
|
||||||
|
}}
|
||||||
|
textProps={{
|
||||||
|
accessibilityRole: "text",
|
||||||
|
accessibilityLabel: "OTP digit",
|
||||||
|
allowFontScaling: false,
|
||||||
|
}}
|
||||||
|
theme={{
|
||||||
|
containerStyle: styles.container,
|
||||||
|
pinCodeContainerStyle: styles.pinCodeContainer,
|
||||||
|
pinCodeTextStyle: styles.pinCodeText,
|
||||||
|
focusStickStyle: styles.focusStick,
|
||||||
|
focusedPinCodeContainerStyle: styles.activePinCodeContainer,
|
||||||
|
placeholderTextStyle: styles.placeholderText,
|
||||||
|
filledPinCodeContainerStyle: styles.filledPinCodeContainer,
|
||||||
|
disabledPinCodeContainerStyle: styles.disabledPinCodeContainer,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
<View style={{ marginTop: 100}}>
|
||||||
|
<CustomButton onPress={handle_validate} title={'Verify'} style={styles.btnbg} textstyle={styles.btntext} />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={{ alignItems: 'center', marginTop: 20 }}>
|
||||||
|
{!showResend ? (
|
||||||
|
<Text style={{ color: GlobalTheme.colors.darkGray }}>Resend OTP in {formatTime(timer)}</Text>
|
||||||
|
) : (
|
||||||
|
<TouchableOpacity onPress={resend_OTP}>
|
||||||
|
<Text style={styles.resendOTP} >
|
||||||
|
Resend OTP
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<ImageBackground source={IMAGES.AuthBottomBG} style={styles.AuthBottomBG} >
|
||||||
|
{/* <Image source={IMAGES.Logo} style={styles.footerImage} resizeMode="contain"/> */}
|
||||||
|
<Text style={{ position : 'absolute', textAlign:'center', alignContent:'center',alignSelf:'center', bottom:0 , color : GlobalTheme.colors.gray}}> Copyright CPM India - 2025</Text>
|
||||||
|
</ImageBackground>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
</KeyboardAwareScrollView>
|
||||||
|
<Loader visible={loading} />
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default VerifyOTP;
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
import { StyleSheet } from 'react-native';
|
import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
import { GlobalTheme, Screen } from '../../../theme';
|
import { GlobalTheme, Screen } from '../../../theme';
|
||||||
@@ -99,3 +100,154 @@ export const styles = StyleSheet.create({
|
|||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
=======
|
||||||
|
import { Dimensions, StyleSheet } from 'react-native';
|
||||||
|
import { GlobalTheme, Screen } from '../../../theme';
|
||||||
|
import { normalize } from '../../../utilis/responsive';
|
||||||
|
|
||||||
|
const { width, height } = Dimensions.get('window');
|
||||||
|
|
||||||
|
export const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
// flex: 1,
|
||||||
|
// paddingHorizontal: 5
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: GlobalTheme.colors.primary,
|
||||||
|
},
|
||||||
|
logoContainer: {
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
appLogo: {
|
||||||
|
height: normalize(170),
|
||||||
|
width: '100%',
|
||||||
|
resizeMode: 'contain',
|
||||||
|
marginTop: 40
|
||||||
|
},
|
||||||
|
titleContainer: {
|
||||||
|
alignSelf: 'center',
|
||||||
|
},
|
||||||
|
titleText: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: '500',
|
||||||
|
color: GlobalTheme.colors.black,
|
||||||
|
textAlign: 'center'
|
||||||
|
},
|
||||||
|
btnbg: {
|
||||||
|
backgroundColor: GlobalTheme.colors.secondary, borderRadius: GlobalTheme.borderRadius.md
|
||||||
|
},
|
||||||
|
btntext: {
|
||||||
|
color: GlobalTheme.colors.white,
|
||||||
|
fontSize: GlobalTheme.typography.fontSize.medium
|
||||||
|
},
|
||||||
|
otp_inputStyle: {
|
||||||
|
textAlign: 'center',
|
||||||
|
backgroundColor: 'red',
|
||||||
|
width: 100,
|
||||||
|
borderRadius: 4,
|
||||||
|
paddingVertical: 10,
|
||||||
|
paddingHorizontal: 15,
|
||||||
|
height: 50,
|
||||||
|
color: 'red',
|
||||||
|
marginBottom: 10,
|
||||||
|
marginRight: 10,
|
||||||
|
fontSize: 25,
|
||||||
|
},
|
||||||
|
// OTP
|
||||||
|
pinCodeContainer: {
|
||||||
|
width: 45,
|
||||||
|
height: 55,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: '#D8E3F1',
|
||||||
|
borderRadius: 8,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
},
|
||||||
|
activePinCodeContainer: {
|
||||||
|
borderColor: GlobalTheme.colors.primary,
|
||||||
|
borderWidth: 2,
|
||||||
|
},
|
||||||
|
filledPinCodeContainer: {
|
||||||
|
backgroundColor: '#D8E3F1',
|
||||||
|
},
|
||||||
|
disabledPinCodeContainer: {
|
||||||
|
backgroundColor: '#f0f0f0',
|
||||||
|
borderColor: '#ddd',
|
||||||
|
},
|
||||||
|
pinCodeText: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#333',
|
||||||
|
},
|
||||||
|
focusStick: {
|
||||||
|
height: 2,
|
||||||
|
width: 20,
|
||||||
|
backgroundColor: GlobalTheme.colors.primary,
|
||||||
|
marginTop: 4,
|
||||||
|
},
|
||||||
|
placeholderText: {
|
||||||
|
color: '#aaa',
|
||||||
|
fontSize: 18,
|
||||||
|
},
|
||||||
|
resendText: {
|
||||||
|
color: GlobalTheme.colors.primary,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
fontSize: 14,
|
||||||
|
marginTop: 20,
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
timerText: {
|
||||||
|
color: 'gray',
|
||||||
|
fontSize: 14,
|
||||||
|
marginTop: 20,
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
resendOTP: {
|
||||||
|
color: GlobalTheme.colors.secondary, fontWeight: GlobalTheme.typography.fontWeight.medium, fontSize: GlobalTheme.typography.fontSize.small
|
||||||
|
},
|
||||||
|
iconStyle: {
|
||||||
|
height: 20,
|
||||||
|
width: 20,
|
||||||
|
resizeMode: 'contain',
|
||||||
|
tintColor: GlobalTheme.colors.white
|
||||||
|
},
|
||||||
|
backIconText: { fontSize: GlobalTheme.typography.fontSize.small, color: GlobalTheme.colors.white, fontWeight: GlobalTheme.typography.fontWeight.medium, marginLeft: 8 },
|
||||||
|
backTextView: {
|
||||||
|
flexDirection: 'row', alignItems: 'center', paddingTop: 20, paddingHorizontal: 10
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
backgroundColor: GlobalTheme.colors.white,
|
||||||
|
borderTopLeftRadius: GlobalTheme.borderRadius.xxlg || normalize(20),
|
||||||
|
borderTopRightRadius: GlobalTheme.borderRadius.xxlg || normalize(20),
|
||||||
|
padding: normalize(20),
|
||||||
|
width: width,
|
||||||
|
alignSelf: 'center',
|
||||||
|
// marginTop: normalize(30),
|
||||||
|
shadowColor: '#000',
|
||||||
|
shadowOpacity: 0.05,
|
||||||
|
shadowOffset: { width: 0, height: 4 },
|
||||||
|
shadowRadius: 8,
|
||||||
|
elevation: 4,
|
||||||
|
flex: 1,
|
||||||
|
minHeight : height * 0.7
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
marginTop: 60,
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
footerImage: {
|
||||||
|
width: '100%',
|
||||||
|
height: normalize(80),
|
||||||
|
resizeMode: 'contain',
|
||||||
|
marginTop: normalize(160),
|
||||||
|
},
|
||||||
|
AuthBottomBG: {
|
||||||
|
width: '100%',
|
||||||
|
resizeMode: 'contain',
|
||||||
|
height: normalize(270),
|
||||||
|
justifyContent: 'center',
|
||||||
|
marginTop: normalize(-40),
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
>>>>>>> dabur-store-dna
|
||||||
|
|||||||
@@ -0,0 +1,406 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { View, Text, TouchableOpacity, ScrollView, Image, Modal, Platform, StyleSheet, Alert } from 'react-native';
|
||||||
|
import { useRoute, useNavigation } from '@react-navigation/native';
|
||||||
|
import { post } from '../../../api/ApiService';
|
||||||
|
import IMAGES from '../../../constants/Images';
|
||||||
|
import { GlobalTheme } from '../../../theme';
|
||||||
|
import Loader from '../../../constants/Loader';
|
||||||
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||||
|
import { toastError } from '../../../constants/Toast';
|
||||||
|
|
||||||
|
const Details = () => {
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const navigation = useNavigation();
|
||||||
|
|
||||||
|
const { selectedDetails = [], storeData, year, month, mainTabIndex } = route.params || {};
|
||||||
|
const [modalGraphData, setModalGraphData] = useState({});
|
||||||
|
const [activePromoTab, setActivePromoTab] = useState('Executed');
|
||||||
|
const [allCatData, setAllCatData] = useState([])
|
||||||
|
const [selectedCategoryData, setSelectedCategoryData] = useState([]);
|
||||||
|
const [categoryModalVisible, setCategoryModalVisible] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedDetails.length > 0) {
|
||||||
|
fetchDetailGraphs(selectedDetails);
|
||||||
|
}
|
||||||
|
}, [selectedDetails]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getAllCatData();
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const getAllCatData = () => {
|
||||||
|
let data = {
|
||||||
|
parameters: {
|
||||||
|
projectid: 41654,
|
||||||
|
year: year,
|
||||||
|
monthno: month,
|
||||||
|
storeid: storeData?.StoreId
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiUrl = mainTabIndex === 0
|
||||||
|
? 'https://dax.parinaam.in/execute/dabur/detmtd/oos_sku_list_for_all_visits_mtd'
|
||||||
|
: 'https://dax.parinaam.in/execute/dabur/detlsv/oos_sku_list_on_lsv';
|
||||||
|
|
||||||
|
post(apiUrl, data)
|
||||||
|
.then(res => {
|
||||||
|
setAllCatData(res?.data);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log('Error =>', err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchDetailGraphs = async (detailPages) => {
|
||||||
|
try {
|
||||||
|
const resultMap = {};
|
||||||
|
for (let item of detailPages) {
|
||||||
|
const response = await post(item.GraphUrl, {
|
||||||
|
parameters: {
|
||||||
|
projectid: 41654,
|
||||||
|
year: year,
|
||||||
|
monthno: month,
|
||||||
|
storeid: storeData?.StoreId
|
||||||
|
},
|
||||||
|
});
|
||||||
|
resultMap[item.GraphUrl] = response?.data || [];
|
||||||
|
}
|
||||||
|
setModalGraphData(resultMap);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("❌ Error fetching detail graphs:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const showCategoryDetails = (data) => {
|
||||||
|
setCategoryModalVisible(!categoryModalVisible)
|
||||||
|
// Filter SKUs from allCatData where the category name matches
|
||||||
|
const filteredCategory = allCatData.filter(item =>
|
||||||
|
item.Product_CategoryCategory_Name === data.Product_CategoryCategory_Name
|
||||||
|
);
|
||||||
|
// Save for display
|
||||||
|
setSelectedCategoryData(filteredCategory);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isOSATab = selectedDetails.some(item => item.GraphTitle === "OSA - Category");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={{ flex: 1, backgroundColor: '#113F8C' }}>
|
||||||
|
<View style={{ flex: 1, backgroundColor: '#fff' }}>
|
||||||
|
{/* Header */}
|
||||||
|
<View style={styled.header}>
|
||||||
|
<TouchableOpacity onPress={() => navigation.goBack()} style={{ padding: 5 }}>
|
||||||
|
<Image source={IMAGES.backIcon} style={{ height: 20, width: 20, tintColor: '#fff' }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Text style={{ color: '#fff', fontSize: 20, fontWeight: 'bold' }}>Details</Text>
|
||||||
|
<View style={{ width: 25 }} /> {/* spacer */}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<ScrollView style={{ padding: 20 }}>
|
||||||
|
{selectedDetails.map((detail, index) => {
|
||||||
|
const values = modalGraphData[detail.GraphUrl] || [];
|
||||||
|
|
||||||
|
if (!modalGraphData[detail.GraphUrl]) {
|
||||||
|
return (
|
||||||
|
<View key={index} style={{ flex: 1, marginBottom: 20 }}>
|
||||||
|
<Loader visible={true} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (detail.GraphType) {
|
||||||
|
case 'Table':
|
||||||
|
// Check if it's the Promotion table
|
||||||
|
const isPromotionTable =
|
||||||
|
values.length > 0 &&
|
||||||
|
values[0].hasOwnProperty('Product_CategoryCategory_Name') &&
|
||||||
|
values[0].hasOwnProperty('Promotion_MasterPromotion_Definition');
|
||||||
|
|
||||||
|
if (isPromotionTable) {
|
||||||
|
// Filter data based on active tab
|
||||||
|
const filteredValues = values.filter(row =>
|
||||||
|
activePromoTab === 'Executed'
|
||||||
|
? row.Executed?.toLowerCase() === 'yes'
|
||||||
|
: row.Executed?.toLowerCase() === 'no'
|
||||||
|
);
|
||||||
|
// Group data by Product_CategoryCategory_Name
|
||||||
|
const groupedData = filteredValues.reduce((acc, curr) => {
|
||||||
|
const category = curr.Product_CategoryCategory_Name || 'Unknown';
|
||||||
|
if (!acc[category]) acc[category] = [];
|
||||||
|
acc[category].push(curr);
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View key={index} style={{ marginBottom: 10 }}>
|
||||||
|
|
||||||
|
{/* Horizontal Tabs - show once at top */}
|
||||||
|
{index === 0 && ( // ensures only first promotion table renders the toggle
|
||||||
|
<View style={{ flexDirection: 'row', marginBottom: 20 }}>
|
||||||
|
{['Executed', 'Not Executed'].map(tab => {
|
||||||
|
const isSelected = activePromoTab === tab;
|
||||||
|
return (
|
||||||
|
<TouchableOpacity
|
||||||
|
key={tab}
|
||||||
|
onPress={() => setActivePromoTab(tab)}
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
paddingVertical: 10,
|
||||||
|
backgroundColor: isSelected ? '#113F8C' : '#E3EBF8',
|
||||||
|
borderRadius: 8,
|
||||||
|
marginHorizontal: 5,
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={{ color: isSelected ? '#fff' : '#000', fontWeight: '600' }}>
|
||||||
|
{tab}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* No data message */}
|
||||||
|
<View style={{}}>
|
||||||
|
{filteredValues.length === 0 ? (
|
||||||
|
<View style={{ marginTop: 0, backgroundColor: 'red' }} />
|
||||||
|
) : (
|
||||||
|
Object.keys(groupedData).map((categoryName, catIdx) => (
|
||||||
|
<View key={catIdx} style={{ marginBottom: 20, }}>
|
||||||
|
{/* Category Header */}
|
||||||
|
<View style={{ backgroundColor: '#E8F0FF', padding: 8, borderRadius: 6 }}>
|
||||||
|
<Text style={{ fontSize: 15, fontWeight: '700', color: '#113F8C' }}>
|
||||||
|
{String(categoryName)}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Table Header */}
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
backgroundColor: '#f5f5f5',
|
||||||
|
paddingVertical: 8,
|
||||||
|
paddingHorizontal: 9,
|
||||||
|
borderTopLeftRadius: 8,
|
||||||
|
borderTopRightRadius: 8,
|
||||||
|
marginTop: 5
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={{ color: '#000', fontWeight: 'bold', width: '80%' }}>
|
||||||
|
Definition
|
||||||
|
</Text>
|
||||||
|
<Text style={{ color: '#000', fontWeight: 'bold', width: '20%', textAlign: 'center' }}>
|
||||||
|
Executed
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Table Rows */}
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
borderBottomLeftRadius: 8,
|
||||||
|
borderBottomRightRadius: 8,
|
||||||
|
shadowColor: '#000',
|
||||||
|
shadowOffset: { width: 0, height: 1 },
|
||||||
|
shadowOpacity: 0.1,
|
||||||
|
shadowRadius: 2,
|
||||||
|
elevation: 2
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{groupedData[categoryName].map((row, rowIdx) => (
|
||||||
|
<View
|
||||||
|
key={rowIdx}
|
||||||
|
style={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
paddingVertical: 8,
|
||||||
|
borderBottomWidth: rowIdx === groupedData[categoryName].length - 1 ? 0 : 1,
|
||||||
|
borderColor: '#eee'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={{ color: '#000', width: '80%' }}>
|
||||||
|
{String(row.Promotion_MasterPromotion_Definition) || '-'}
|
||||||
|
</Text>
|
||||||
|
<Text style={{ color: '#000', width: '20%', textAlign: 'center' }}>
|
||||||
|
{row.Executed || '-'}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let displayKey = null;
|
||||||
|
let presentKey = null;
|
||||||
|
if (values.length > 0) {
|
||||||
|
const presentKeys = Object.keys(values[0]).filter(k =>
|
||||||
|
(typeof values[0][k] === 'string' && ['Yes', 'No'].includes(values[0][k])) ||
|
||||||
|
typeof values[0][k] === 'boolean' ||
|
||||||
|
typeof values[0][k] === 'number'
|
||||||
|
);
|
||||||
|
presentKey = presentKeys.length > 0 ? presentKeys[0] : null;
|
||||||
|
const displayKeys = Object.keys(values[0]).filter(k => k !== presentKey && typeof values[0][k] === 'string');
|
||||||
|
displayKey = displayKeys.length > 0 ? displayKeys[0] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View key={index} style={{ marginBottom: 30 }}>
|
||||||
|
<Text style={{ color: '#000', fontSize: 16, fontWeight: '600', marginBottom: 10 }}>
|
||||||
|
{detail.GraphTitle}
|
||||||
|
|
||||||
|
</Text>
|
||||||
|
<View style={styled.categoryHeader}>
|
||||||
|
<Text style={{ color: '#000', fontWeight: 'bold', width: '80%' }}>
|
||||||
|
{displayKey ? displayKey.replace(/_/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2') : ''}
|
||||||
|
</Text>
|
||||||
|
<Text style={{ color: '#000', fontWeight: 'bold', width: '20%', textAlign: 'center' }}>
|
||||||
|
{presentKey ? presentKey.replace(/_/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2') : ''}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styled.itemContainer}>
|
||||||
|
{values.map((row, idx) => {
|
||||||
|
const presentKeys = Object.keys(row).filter(k =>
|
||||||
|
(typeof row[k] === 'string' && ['Yes', 'No'].includes(row[k])) ||
|
||||||
|
typeof row[k] === 'boolean' ||
|
||||||
|
typeof row[k] === 'number'
|
||||||
|
);
|
||||||
|
const presentKey = presentKeys.length > 0 ? presentKeys[0] : null;
|
||||||
|
const displayKeys = Object.keys(row).filter(k => k !== presentKey && typeof row[k] === 'string');
|
||||||
|
const displayKey = displayKeys.length > 0 ? displayKeys[0] : null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
key={idx}
|
||||||
|
style={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
paddingVertical: 8,
|
||||||
|
borderBottomWidth: idx === values.length - 1 ? 0 : 1,
|
||||||
|
borderColor: '#eee',
|
||||||
|
}}>
|
||||||
|
<Text style={{ color: '#000', width: '80%' }}>{row[displayKey] || '--'}</Text>
|
||||||
|
<TouchableOpacity disabled={isOSATab ? false : true}
|
||||||
|
onPress={() => {
|
||||||
|
if (row[presentKey] == 100 || row[presentKey] == '100') {
|
||||||
|
toastError('Alert', 'No Data Available')
|
||||||
|
} else {
|
||||||
|
showCategoryDetails(row)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{ width: '20%', }}>
|
||||||
|
<Text style={{ color: '#113F8C', textAlign: 'center', fontWeight: '500' }}>
|
||||||
|
{presentKey ? (
|
||||||
|
typeof row[presentKey] === 'string' && ['Yes', 'No'].includes(row[presentKey]) ? row[presentKey] :
|
||||||
|
typeof row[presentKey] === 'boolean' ? (row[presentKey] ? 'Yes' : 'No') :
|
||||||
|
typeof row[presentKey] === 'number' ? row[presentKey].toFixed(2) : row[presentKey] || '-'
|
||||||
|
) : '-'}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<View key={index} style={{ marginBottom: 20 }}>
|
||||||
|
<Text>Unsupported GraphType: {detail.GraphType}</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
visible={categoryModalVisible}
|
||||||
|
animationType="slide"
|
||||||
|
onRequestClose={() => setCategoryModalVisible(false)}
|
||||||
|
>
|
||||||
|
<View style={{ flex: 1, }}>
|
||||||
|
{/* Header */}
|
||||||
|
<View style={{ height: Platform.OS === 'ios' ? 55 : 0, backgroundColor: '#113F8C' }} />
|
||||||
|
|
||||||
|
<View style={{ width: '100%', backgroundColor: '#113F8C', borderBottomWidth: 1, borderColor: 'gray', padding: 5, paddingHorizontal: 20, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
|
<View style={{ width: '93%', alignItems: 'center' }}>
|
||||||
|
<Text style={{ color: '#fff', fontSize: 20, fontWeight: 'bold', marginBottom: 10, alignSelf: 'center' }}>{selectedCategoryData[0]?.Product_CategoryCategory_Name || 'Category'}</Text>
|
||||||
|
</View>
|
||||||
|
<TouchableOpacity onPress={() => setCategoryModalVisible(false)} style={{ width: '7%', alignItems: 'center' }}>
|
||||||
|
<Image source={IMAGES.crossIcon} style={{ height: 25, width: 25, resizeMode: 'contain' }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* SKU List */}
|
||||||
|
<ScrollView contentContainerStyle={{ padding: 15 }}>
|
||||||
|
{/* <Text style={{ color: '#000', fontSize: 16, fontWeight: 'bold', marginBottom: 5 }}>OOS SKU details</Text> */}
|
||||||
|
{selectedCategoryData.map((item, idx) => (
|
||||||
|
<View
|
||||||
|
key={idx}
|
||||||
|
style={{
|
||||||
|
marginTop: 2,
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
paddingVertical: 8,
|
||||||
|
borderBottomWidth: idx === selectedCategoryData.length - 1 ? 0 : 1,
|
||||||
|
borderColor: '#eee',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={{ color: '#000', width: '80%' }}>
|
||||||
|
{item.Product_MasterProduct_Name}
|
||||||
|
</Text>
|
||||||
|
{/* <Text style={{ color: '#000', width: '20%', textAlign: 'center' }}>
|
||||||
|
{item['#_of_OOS_SKU_for_all_visits']}
|
||||||
|
</Text> */}
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styled = StyleSheet.create({
|
||||||
|
header: {
|
||||||
|
width: '100%',
|
||||||
|
backgroundColor: '#113F8C',
|
||||||
|
padding: 10,
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
categoryHeader: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
backgroundColor: '#EDEDED',
|
||||||
|
paddingVertical: 8,
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
borderTopLeftRadius: 8,
|
||||||
|
borderTopRightRadius: 8,
|
||||||
|
},
|
||||||
|
itemContainer: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
borderBottomLeftRadius: 8,
|
||||||
|
borderBottomRightRadius: 8,
|
||||||
|
shadowColor: '#000',
|
||||||
|
shadowOffset: { width: 0, height: 1 },
|
||||||
|
shadowOpacity: 0.1,
|
||||||
|
shadowRadius: 2,
|
||||||
|
elevation: 2
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export default Details;
|
||||||
@@ -0,0 +1,431 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { View, Text, TouchableOpacity, ScrollView, Image, Modal, Platform, StyleSheet, Alert } from 'react-native';
|
||||||
|
import { useRoute, useNavigation } from '@react-navigation/native';
|
||||||
|
import { post } from '../../../api/ApiService';
|
||||||
|
import IMAGES from '../../../constants/Images';
|
||||||
|
import { GlobalTheme } from '../../../theme';
|
||||||
|
import Loader from '../../../constants/Loader';
|
||||||
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||||
|
import { toastError } from '../../../constants/Toast';
|
||||||
|
|
||||||
|
const Details = () => {
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const navigation = useNavigation();
|
||||||
|
|
||||||
|
const { selectedDetails = [], storeData, year, month, mainTabIndex } = route.params || {};
|
||||||
|
const [modalGraphData, setModalGraphData] = useState({});
|
||||||
|
const [activePromoTab, setActivePromoTab] = useState('Executed');
|
||||||
|
const [allCatData, setAllCatData] = useState([])
|
||||||
|
const [selectedCategoryData, setSelectedCategoryData] = useState([]);
|
||||||
|
const [categoryModalVisible, setCategoryModalVisible] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedDetails.length > 0) {
|
||||||
|
fetchDetailGraphs(selectedDetails);
|
||||||
|
}
|
||||||
|
}, [selectedDetails]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getAllCatData();
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const getAllCatData = () => {
|
||||||
|
let data = {
|
||||||
|
parameters: {
|
||||||
|
projectid: 41654,
|
||||||
|
year: year,
|
||||||
|
monthno: month,
|
||||||
|
storeid: storeData?.StoreId
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiUrl = mainTabIndex === 0
|
||||||
|
? 'https://dax.parinaam.in/execute/dabur/detmtd/oos_sku_list_for_all_visits_mtd'
|
||||||
|
: 'https://dax.parinaam.in/execute/dabur/detlsv/oos_sku_list_on_lsv';
|
||||||
|
|
||||||
|
post(apiUrl, data)
|
||||||
|
.then(res => {
|
||||||
|
setAllCatData(res?.data);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log('Error =>', err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchDetailGraphs = async (detailPages) => {
|
||||||
|
try {
|
||||||
|
const resultMap = {};
|
||||||
|
for (let item of detailPages) {
|
||||||
|
const response = await post(item.GraphUrl, {
|
||||||
|
parameters: {
|
||||||
|
projectid: 41654,
|
||||||
|
year: year,
|
||||||
|
monthno: month,
|
||||||
|
storeid: storeData?.StoreId
|
||||||
|
},
|
||||||
|
});
|
||||||
|
resultMap[item.GraphUrl] = response?.data || [];
|
||||||
|
}
|
||||||
|
setModalGraphData(resultMap);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("❌ Error fetching detail graphs:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const showCategoryDetails = (data) => {
|
||||||
|
setCategoryModalVisible(!categoryModalVisible)
|
||||||
|
// Filter SKUs from allCatData where the category name matches
|
||||||
|
const filteredCategory = allCatData.filter(item =>
|
||||||
|
item.Product_CategoryCategory_Name === data.Product_CategoryCategory_Name
|
||||||
|
);
|
||||||
|
// Save for display
|
||||||
|
setSelectedCategoryData(filteredCategory);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isOSATab = selectedDetails.some(item => item.GraphTitle === "OSA - Category");
|
||||||
|
console.log('isOSATab----',isOSATab);
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={{ flex: 1, backgroundColor: '#113F8C' }}>
|
||||||
|
<View style={{ flex: 1, backgroundColor: '#fff' }}>
|
||||||
|
{/* Header */}
|
||||||
|
<View style={styled.header}>
|
||||||
|
<TouchableOpacity onPress={() => navigation.goBack()} style={{ padding: 5 }}>
|
||||||
|
<Image source={IMAGES.backIcon} style={{ height: 20, width: 20, tintColor: '#fff' }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Text style={{ color: '#fff', fontSize: 20, fontWeight: 'bold' }}>Details</Text>
|
||||||
|
<View style={{ width: 25 }} />
|
||||||
|
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<ScrollView style={{ padding: 20 }}>
|
||||||
|
{selectedDetails && selectedDetails.length > 0 ? selectedDetails.map((detail, index) => {
|
||||||
|
const values = modalGraphData[detail.GraphUrl] || [];
|
||||||
|
|
||||||
|
if (!modalGraphData[detail.GraphUrl]) {
|
||||||
|
return (
|
||||||
|
<View key={index} style={{ flex: 1, marginBottom: 20 }}>
|
||||||
|
<Loader visible={true} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (detail.GraphType) {
|
||||||
|
case 'Table':
|
||||||
|
// Check if it's the Promotion table
|
||||||
|
const isPromotionTable =
|
||||||
|
values.length > 0 &&
|
||||||
|
values[0].hasOwnProperty('Product_CategoryCategory_Name') &&
|
||||||
|
values[0].hasOwnProperty('Promotion_MasterPromotion_Definition');
|
||||||
|
|
||||||
|
if (isPromotionTable) {
|
||||||
|
// Filter data based on active tab
|
||||||
|
const filteredValues = values.filter(row =>
|
||||||
|
activePromoTab === 'Executed'
|
||||||
|
? row.Executed?.toLowerCase() === 'yes'
|
||||||
|
: row.Executed?.toLowerCase() === 'no'
|
||||||
|
);
|
||||||
|
// Group data by Product_CategoryCategory_Name
|
||||||
|
const groupedData = filteredValues.reduce((acc, curr) => {
|
||||||
|
const category = curr.Product_CategoryCategory_Name || 'Unknown';
|
||||||
|
if (!acc[category]) acc[category] = [];
|
||||||
|
acc[category].push(curr);
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View key={index} style={{ marginBottom: 10 }}>
|
||||||
|
{/* Horizontal Tabs - show once at top */}
|
||||||
|
{index === 0 && ( // ensures only first promotion table renders the toggle
|
||||||
|
<View style={{ flexDirection: 'row', marginBottom: 20 }}>
|
||||||
|
{['Executed', 'Not Executed'].map(tab => {
|
||||||
|
const isSelected = activePromoTab === tab;
|
||||||
|
return (
|
||||||
|
<TouchableOpacity
|
||||||
|
key={tab}
|
||||||
|
onPress={() => setActivePromoTab(tab)}
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
paddingVertical: 10,
|
||||||
|
backgroundColor: isSelected ? '#113F8C' : '#E3EBF8',
|
||||||
|
borderRadius: 8,
|
||||||
|
marginHorizontal: 5,
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={{ color: isSelected ? '#fff' : '#000', fontWeight: '600' }}>
|
||||||
|
{tab}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* No data message */}
|
||||||
|
<View style={{}}>
|
||||||
|
{filteredValues.length === 0 ? (
|
||||||
|
<View style={{ marginTop: 0, backgroundColor: 'red' }} />
|
||||||
|
) : (
|
||||||
|
Object.keys(groupedData).map((categoryName, catIdx) => (
|
||||||
|
<View key={catIdx} style={{ marginBottom: 20 }}>
|
||||||
|
{/* Category Header */}
|
||||||
|
<View style={{ backgroundColor: '#E8F0FF', padding: 8, borderRadius: 6 }}>
|
||||||
|
<Text style={{ fontSize: 15, fontWeight: '700', color: '#113F8C' }}>
|
||||||
|
{String(categoryName)}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Table Header */}
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
backgroundColor: '#f5f5f5',
|
||||||
|
paddingVertical: 8,
|
||||||
|
paddingHorizontal: 9,
|
||||||
|
borderTopLeftRadius: 8,
|
||||||
|
borderTopRightRadius: 8,
|
||||||
|
marginTop: 5
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={{ color: '#000', fontWeight: 'bold', width: '80%' }}>
|
||||||
|
Definition
|
||||||
|
</Text>
|
||||||
|
<Text style={{ color: '#000', fontWeight: 'bold', width: '20%', textAlign: 'center' }}>
|
||||||
|
Executed
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Table Rows */}
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
borderBottomLeftRadius: 8,
|
||||||
|
borderBottomRightRadius: 8,
|
||||||
|
shadowColor: '#000',
|
||||||
|
shadowOffset: { width: 0, height: 1 },
|
||||||
|
shadowOpacity: 0.1,
|
||||||
|
shadowRadius: 2,
|
||||||
|
elevation: 2
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{groupedData[categoryName].map((row, rowIdx) => (
|
||||||
|
<View
|
||||||
|
key={rowIdx}
|
||||||
|
style={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
paddingVertical: 8,
|
||||||
|
borderBottomWidth: rowIdx === groupedData[categoryName].length - 1 ? 0 : 1,
|
||||||
|
borderColor: '#eee'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={{ color: '#000', width: '80%' }}>
|
||||||
|
{String(row.Promotion_MasterPromotion_Definition) || '-'}
|
||||||
|
</Text>
|
||||||
|
<Text style={{ color: '#000', width: '20%', textAlign: 'center' }}>
|
||||||
|
{row.Executed || '-'}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let displayKey = null;
|
||||||
|
let presentKey = null;
|
||||||
|
if (values.length > 0) {
|
||||||
|
const presentKeys = Object.keys(values[0]).filter(k =>
|
||||||
|
(typeof values[0][k] === 'string' && ['Yes', 'No'].includes(values[0][k])) ||
|
||||||
|
typeof values[0][k] === 'boolean' ||
|
||||||
|
typeof values[0][k] === 'number'
|
||||||
|
);
|
||||||
|
presentKey = presentKeys.length > 0 ? presentKeys[0] : null;
|
||||||
|
const displayKeys = Object.keys(values[0]).filter(k => k !== presentKey && typeof values[0][k] === 'string');
|
||||||
|
displayKey = displayKeys.length > 0 ? displayKeys[0] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View key={index} style={{ marginBottom: 30 }}>
|
||||||
|
|
||||||
|
<Text style={{ marginTop: 10, color: '#000', fontSize: 16, fontWeight: '600', marginBottom: 10 }}>
|
||||||
|
{detail.GraphTitle}
|
||||||
|
|
||||||
|
</Text>
|
||||||
|
<View style={styled.categoryHeader}>
|
||||||
|
<Text style={{ color: '#000', fontWeight: 'bold', width: '80%' }}>
|
||||||
|
{displayKey ? displayKey.replace(/_/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2') : ''}
|
||||||
|
</Text>
|
||||||
|
<Text style={{ color: '#000', fontWeight: 'bold', width: '20%', textAlign: 'center' }}>
|
||||||
|
{presentKey ? presentKey.replace(/_/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2') : ''}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styled.itemContainer}>
|
||||||
|
{values.map((row, idx) => {
|
||||||
|
const presentKeys = Object.keys(row).filter(k =>
|
||||||
|
(typeof row[k] === 'string' && ['Yes', 'No'].includes(row[k])) ||
|
||||||
|
typeof row[k] === 'boolean' ||
|
||||||
|
typeof row[k] === 'number'
|
||||||
|
);
|
||||||
|
const presentKey = presentKeys.length > 0 ? presentKeys[0] : null;
|
||||||
|
const displayKeys = Object.keys(row).filter(k => k !== presentKey && typeof row[k] === 'string');
|
||||||
|
const displayKey = displayKeys.length > 0 ? displayKeys[0] : null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
key={idx}
|
||||||
|
style={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
paddingVertical: 8,
|
||||||
|
borderBottomWidth: idx === values.length - 1 ? 0 : 1,
|
||||||
|
borderColor: '#eee',
|
||||||
|
}}>
|
||||||
|
<Text style={{ color: '#000', width: '80%' }}>{row[displayKey] || '--'}</Text>
|
||||||
|
|
||||||
|
<TouchableOpacity disabled={isOSATab ? false : true}
|
||||||
|
onPress={() => {
|
||||||
|
if (row[presentKey] == 100 || row[presentKey] == '100') {
|
||||||
|
toastError('Alert', 'No Data Available')
|
||||||
|
} else {
|
||||||
|
showCategoryDetails(row)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{ width: '20%', }}>
|
||||||
|
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||||
|
<Text style={{ color: '#113F8C', textAlign: 'center', fontWeight: '500' }}>
|
||||||
|
{presentKey ? (
|
||||||
|
typeof row[presentKey] === 'string' && ['Yes', 'No'].includes(row[presentKey]) ? row[presentKey] :
|
||||||
|
typeof row[presentKey] === 'boolean' ? (row[presentKey] ? 'Yes' : 'No') :
|
||||||
|
typeof row[presentKey] === 'number' ? row[presentKey].toFixed(2) : row[presentKey] || '-'
|
||||||
|
) : '-'}
|
||||||
|
</Text>
|
||||||
|
{ isOSATab && row[presentKey] != 100 || isOSATab && row[presentKey] != '100'? <Image source={IMAGES.rightArrowIcon} style={{marginLeft:6, height: 12, width: 12, resizeMode: 'contain' }} /> :null}
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<View key={index} style={{ marginBottom: 20 }}>
|
||||||
|
<Text>Unsupported GraphType: {detail.GraphType}</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}) :
|
||||||
|
<Loader visible={true} />
|
||||||
|
}
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
visible={categoryModalVisible}
|
||||||
|
animationType="slide"
|
||||||
|
onRequestClose={() => setCategoryModalVisible(false)}
|
||||||
|
>
|
||||||
|
<View style={{ flex: 1, }}>
|
||||||
|
{/* Header */}
|
||||||
|
<View style={{ height: Platform.OS === 'ios' ? 55 : 0, backgroundColor: '#113F8C' }} />
|
||||||
|
|
||||||
|
<View style={{ width: '100%', backgroundColor: '#113F8C', borderBottomWidth: 1, borderColor: 'gray', padding: 5, paddingHorizontal: 20, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
|
<View style={{ width: '93%', alignItems: 'center' }}>
|
||||||
|
<Text style={{ color: '#fff', fontSize: 20, fontWeight: 'bold', marginBottom: 10, alignSelf: 'center' }}>{selectedCategoryData[0]?.Product_CategoryCategory_Name || 'Category'}</Text>
|
||||||
|
</View>
|
||||||
|
<TouchableOpacity onPress={() => setCategoryModalVisible(false)} style={{ width: '7%', alignItems: 'center' }}>
|
||||||
|
<Image source={IMAGES.crossIcon} style={{ height: 25, width: 25, resizeMode: 'contain' }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={{ borderTopLeftRadius: 10, borderTopRightRadius: 10, marginTop: 15, marginHorizontal: 15, backgroundColor: '#eee', padding: 10, borderWidth: 1, borderColor: 'gray' }}>
|
||||||
|
<Text style={{ color: '#000', fontSize: 16, fontWeight: '500' }}>{'Out of Stock SKUs:'}</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* SKU List */}
|
||||||
|
<ScrollView contentContainerStyle={{
|
||||||
|
marginHorizontal: 15,
|
||||||
|
borderBottomWidth: 0.5,
|
||||||
|
borderLeftWidth: 0.5,
|
||||||
|
borderRightWidth: 0.5,
|
||||||
|
borderColor: 'gray',
|
||||||
|
borderBottomEndRadius: 10,
|
||||||
|
borderBottomLeftRadius: 10,
|
||||||
|
}}>
|
||||||
|
{/* <Text style={{ color: '#000', fontSize: 16, fontWeight: 'bold', marginBottom: 5 }}>OOS SKU details</Text> */}
|
||||||
|
{selectedCategoryData.map((item, idx) => (
|
||||||
|
<View
|
||||||
|
key={idx}
|
||||||
|
style={{
|
||||||
|
marginTop: 2,
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
paddingVertical: 8,
|
||||||
|
borderBottomWidth: idx === selectedCategoryData.length - 1 ? 0 : 1,
|
||||||
|
borderColor: '#eee',
|
||||||
|
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View style={{ flexDirection: 'row' }}>
|
||||||
|
<Text style={{ color: '#000', marginLeft: 10 }}>{idx + 1}. </Text>
|
||||||
|
<Text style={{ color: '#000', }}>
|
||||||
|
{item.Product_MasterProduct_Name}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
{/* <Text style={{ color: '#000', width: '20%', textAlign: 'center' }}>
|
||||||
|
{item['#_of_OOS_SKU_for_all_visits']}
|
||||||
|
</Text> */}
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styled = StyleSheet.create({
|
||||||
|
header: {
|
||||||
|
width: '100%',
|
||||||
|
backgroundColor: '#113F8C',
|
||||||
|
padding: 10,
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
categoryHeader: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
backgroundColor: '#EDEDED',
|
||||||
|
paddingVertical: 8,
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
borderTopLeftRadius: 8,
|
||||||
|
borderTopRightRadius: 8,
|
||||||
|
},
|
||||||
|
itemContainer: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
borderBottomLeftRadius: 8,
|
||||||
|
borderBottomRightRadius: 8,
|
||||||
|
shadowColor: '#000',
|
||||||
|
shadowOffset: { width: 0, height: 1 },
|
||||||
|
shadowOpacity: 0.1,
|
||||||
|
shadowRadius: 2,
|
||||||
|
elevation: 2
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export default Details;
|
||||||
@@ -0,0 +1,318 @@
|
|||||||
|
{
|
||||||
|
"subTabs": [
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"TabName": "PSS Score",
|
||||||
|
"TabRow": 1,
|
||||||
|
"TabCol": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 2,
|
||||||
|
"TabName": "SOS Actual",
|
||||||
|
"TabRow": 1,
|
||||||
|
"TabCol": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 3,
|
||||||
|
"TabName": "SOS Compliance",
|
||||||
|
"TabRow": 1,
|
||||||
|
"TabCol": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 4,
|
||||||
|
"TabName": "OSA",
|
||||||
|
"TabRow": 1,
|
||||||
|
"TabCol": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 5,
|
||||||
|
"TabName": "Asset",
|
||||||
|
"TabRow": 1,
|
||||||
|
"TabCol": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 6,
|
||||||
|
"TabName": "Promotion",
|
||||||
|
"TabRow": 1,
|
||||||
|
"TabCol": 6
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"graphDetails": [
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"GraphId": 1,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "PSS Score",
|
||||||
|
"GraphUrl": "http://localhost:3000/MTD/PSSScore",
|
||||||
|
"GraphBackground": "#F4EAFF",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"GraphId": 2,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "SOS Actual",
|
||||||
|
"GraphUrl": "http://localhost:3000/MTD/SOSActual",
|
||||||
|
"GraphBackground": "#FFF3ED",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"GraphId": 3,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "SOS Compliance",
|
||||||
|
"GraphUrl": "http://localhost:3000/MTD/SOSCompliance",
|
||||||
|
"GraphBackground": "#FFFEF0",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"GraphId": 4,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "OSA",
|
||||||
|
"GraphUrl": "http://localhost:3000/MTD/OSA",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"GraphId": 5,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "Asset",
|
||||||
|
"GraphUrl": "http://localhost:3000/MTD/Asset",
|
||||||
|
"GraphBackground": "#EBECFF",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"GraphId": 6,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "Promotion",
|
||||||
|
"GraphUrl": "http://localhost:3000/MTD/Promotion",
|
||||||
|
"GraphBackground": "#FFFEF0",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 2,
|
||||||
|
"GraphId": 1,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "SOS Actual",
|
||||||
|
"GraphUrl": "http://localhost:3000/MTD/SOSActual",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 2,
|
||||||
|
"GraphId": 2,
|
||||||
|
"GraphType": "BarGraph",
|
||||||
|
"GraphTitle": "SOS Actual Trend",
|
||||||
|
"GraphUrl": "http://localhost:3000/MTD/SOSActualTrend",
|
||||||
|
"GraphBackground": "#F4EAFF",
|
||||||
|
"GraphOptions": {
|
||||||
|
"axisX": "month",
|
||||||
|
"axisY": "score",
|
||||||
|
"labelShow": 1,
|
||||||
|
"barColors": [
|
||||||
|
"#ffaa11",
|
||||||
|
"#ffbb11",
|
||||||
|
"#ffcc11"
|
||||||
|
],
|
||||||
|
"gridLinesH": 1,
|
||||||
|
"gridLinesV": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 3,
|
||||||
|
"GraphId": 3,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "SOS Compliance",
|
||||||
|
"GraphUrl": "http://localhost:3000/MTD/SOSActual",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 3,
|
||||||
|
"GraphId": 4,
|
||||||
|
"GraphType": "BarGraph",
|
||||||
|
"GraphTitle": "SOS Compliance Trend",
|
||||||
|
"GraphUrl": "http://localhost:3000/MTD/SOSActualTrend",
|
||||||
|
"GraphBackground": "#fff",
|
||||||
|
"GraphOptions": {
|
||||||
|
"axisX": "month",
|
||||||
|
"axisY": "score",
|
||||||
|
"labelShow": 1,
|
||||||
|
"barColors": [
|
||||||
|
"#ffaa11",
|
||||||
|
"#ffbb11",
|
||||||
|
"#ffcc11"
|
||||||
|
],
|
||||||
|
"gridLinesH": 1,
|
||||||
|
"gridLinesV": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 5,
|
||||||
|
"GraphId": 5,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "Asset",
|
||||||
|
"GraphUrl": "http://localhost:3000/MTD/SOSActual",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 5,
|
||||||
|
"GraphId": 6,
|
||||||
|
"GraphType": "Table",
|
||||||
|
"GraphTitle": "Asset Details",
|
||||||
|
"GraphUrl": "http://localhost:3000/MTD/SOSActual",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 4,
|
||||||
|
"GraphId": 7,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "OSA",
|
||||||
|
"GraphUrl": "http://localhost:3000/MTD/SOSActual",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 4,
|
||||||
|
"GraphId": 8,
|
||||||
|
"GraphType": "PieChart",
|
||||||
|
"GraphTitle": "OSA",
|
||||||
|
"GraphUrl": "http://localhost:3000/MTD/SOSActual",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 6,
|
||||||
|
"GraphId": 9,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "Promotion",
|
||||||
|
"GraphUrl": "http://localhost:3000/MTD/SOSActual",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 6,
|
||||||
|
"GraphId": 10,
|
||||||
|
"GraphType": "LineChart",
|
||||||
|
"GraphTitle": "Promotion",
|
||||||
|
"GraphUrl": "http://localhost:3000/MTD/SOSActual",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"TabId": 3,
|
||||||
|
"GraphId": 3,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "SOS Compliance",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/SOS_Compliance_Perc",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {},
|
||||||
|
"clickable": 1,
|
||||||
|
"DetailsPage": [
|
||||||
|
{
|
||||||
|
"TabId": 3,
|
||||||
|
"GraphId": 3,
|
||||||
|
"GraphType": "Table",
|
||||||
|
"GraphTitle": "SOS Compliance - Category",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/sos_sompliance_perc_on_category",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 3,
|
||||||
|
"GraphId": 4,
|
||||||
|
"GraphType": "BarGraph",
|
||||||
|
"GraphTitle": "SOS Compliance Trend",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/sos_compliance_trend_perc_mtd",
|
||||||
|
"GraphBackground": "#fff",
|
||||||
|
"GraphOptions": {
|
||||||
|
"axisX": "month",
|
||||||
|
"axisY": "score",
|
||||||
|
"labelShow": 1,
|
||||||
|
"barColors": [
|
||||||
|
"#11a4ff",
|
||||||
|
"#0ea3e3",
|
||||||
|
"#0b9ddb"
|
||||||
|
],
|
||||||
|
"gridLinesH": 1,
|
||||||
|
"gridLinesV": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"TabId": 3,
|
||||||
|
"GraphId": 3,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "SOS Compliance",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/sos_compliance_lsv_perc",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {},
|
||||||
|
"clickable": 1,
|
||||||
|
"DetailsPage": [
|
||||||
|
{
|
||||||
|
"TabId": 3,
|
||||||
|
"GraphId": 3,
|
||||||
|
"GraphType": "Table",
|
||||||
|
"GraphTitle": "SOS Actual - Category",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detlsv/sos_compliance_lsv_perc_on_category",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 3,
|
||||||
|
"GraphId": 4,
|
||||||
|
"GraphType": "BarGraph",
|
||||||
|
"GraphTitle": "SOS Compliance Trend",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/sos_compliance_trend_lsv_perc",
|
||||||
|
"GraphBackground": "#fff",
|
||||||
|
"GraphOptions": {
|
||||||
|
"axisX": "month",
|
||||||
|
"axisY": "score",
|
||||||
|
"labelShow": 1,
|
||||||
|
"barColors": [
|
||||||
|
"#11a4ff",
|
||||||
|
"#0ea3e3",
|
||||||
|
"#0b9ddb"
|
||||||
|
],
|
||||||
|
"gridLinesH": 1,
|
||||||
|
"gridLinesV": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
@@ -0,0 +1,906 @@
|
|||||||
|
import { View, Text, StyleSheet, Image, TouchableOpacity, Dimensions, TextInput, ScrollView, FlatList, Button, Alert, Modal, TouchableWithoutFeedback, StatusBar } from 'react-native'
|
||||||
|
import React, { useEffect, useRef, useState } from 'react'
|
||||||
|
import RBSheet from 'react-native-raw-bottom-sheet';
|
||||||
|
import { styles } from './style';
|
||||||
|
import LinearGradient from 'react-native-linear-gradient';
|
||||||
|
import CustomHeader from '../../../components/CustomHeader';
|
||||||
|
import IMAGES from '../../../constants/Images';
|
||||||
|
import CustomButton from '../../../components/CustomButton';
|
||||||
|
import CustomDropdown from '../../../components/CustomDropdown';
|
||||||
|
import { GlobalTheme } from '../../../theme';
|
||||||
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||||
|
|
||||||
|
import displayData from './display.json'
|
||||||
|
import { BarChart, LineChart, PieChart } from 'react-native-chart-kit';
|
||||||
|
import { getDownloadJson } from '../../../constants/function';
|
||||||
|
import db, { getAllFromTable } from '../../../constants/database';
|
||||||
|
import { post } from '../../../api/ApiService';
|
||||||
|
import { ApiURL } from '../../../api/ApiConstant';
|
||||||
|
|
||||||
|
import mainDisplayJson from './mainDisplay.json'
|
||||||
|
|
||||||
|
const Dashboard = (props) => {
|
||||||
|
|
||||||
|
const { navigation } = props;
|
||||||
|
const screenHeight = Dimensions.get('screen').height;
|
||||||
|
const screenWidth = Dimensions.get('screen').width;
|
||||||
|
const refRBSheet = useRef();
|
||||||
|
const [isStoreSelected, setIsStoreSelected] = useState(false)
|
||||||
|
const [searchResult, setSearchResult] = useState(false)
|
||||||
|
const [storeData, setStoreData] = useState({})
|
||||||
|
const [mainTab, setMainTab] = useState('mtd')
|
||||||
|
const [activeTab, setActiveTab] = useState(displayData?.subTabs?.[0]?.TabId || 1)
|
||||||
|
const [state, setState] = useState(null);
|
||||||
|
const [year, setYear] = useState(null)
|
||||||
|
const [month, setMonth] = useState(null)
|
||||||
|
const [city, setCity] = useState(null);
|
||||||
|
const [asmArea, setAsmArea] = useState(null);
|
||||||
|
const scrollViewRef = useRef(null);
|
||||||
|
const [showButton, setShowButton] = useState(false);
|
||||||
|
const [modalVisible, setModalVisible] = useState(false);
|
||||||
|
|
||||||
|
|
||||||
|
// Handle scroll event to show/hide button
|
||||||
|
const handleScroll = (event) => {
|
||||||
|
const offsetY = event.nativeEvent.contentOffset.y;
|
||||||
|
setShowButton(offsetY > 0); // Show button only if not at the top
|
||||||
|
};
|
||||||
|
|
||||||
|
const openBottomSheet = () => {
|
||||||
|
refRBSheet.current.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onSelectStore = (item) => {
|
||||||
|
setStoreData(item)
|
||||||
|
setIsStoreSelected(true)
|
||||||
|
refRBSheet.current.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{ label: 'Delhi', value: '1' },
|
||||||
|
{ label: 'Mumbai', value: '2' },
|
||||||
|
];
|
||||||
|
const cityData = [
|
||||||
|
{ label: 'Okhla', value: '1' },
|
||||||
|
{ label: 'Kalkaji', value: '2' },
|
||||||
|
{ label: 'South Ex.', value: '3' },
|
||||||
|
];
|
||||||
|
const storeJson = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Banarasi & Sons",
|
||||||
|
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||||
|
status: "pending"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Gupta store & Sons",
|
||||||
|
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||||
|
status: "completed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "Bansal General store",
|
||||||
|
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||||
|
status: "completed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "Mohan Mahalaxmi store",
|
||||||
|
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||||
|
status: "completed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: "Chawla Store",
|
||||||
|
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||||
|
status: "completed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
name: "Chawla Store",
|
||||||
|
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||||
|
status: "completed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
name: "Chawla Store",
|
||||||
|
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||||
|
status: "completed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
name: "Chawla Store",
|
||||||
|
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||||
|
status: "completed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 9,
|
||||||
|
name: "Chawla Store",
|
||||||
|
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||||
|
status: "completed"
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
];
|
||||||
|
const visitedStoreData = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Chawla Store",
|
||||||
|
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||||
|
status: "pending"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Mohan Mahalaxmi store",
|
||||||
|
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||||
|
status: "completed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "Bansal General store",
|
||||||
|
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||||
|
status: "completed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "Bansal General store",
|
||||||
|
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||||
|
status: "completed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: "Bansal General store",
|
||||||
|
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||||
|
status: "completed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
name: "Bansal General store",
|
||||||
|
address: "G-8, Mahakavi Goswami Tulsidas Marg, Paraag Vihar, Press Colony, Hari Nagar, New Delhi, 110027",
|
||||||
|
status: "completed"
|
||||||
|
},
|
||||||
|
|
||||||
|
];
|
||||||
|
const monthData = [
|
||||||
|
{ label: 'January', value: '1' },
|
||||||
|
{ label: 'February', value: '2' },
|
||||||
|
{ label: 'March', value: '3' },
|
||||||
|
{ label: 'April', value: '4' },
|
||||||
|
{ label: 'May', value: '5' },
|
||||||
|
{ label: 'June', value: '6' },
|
||||||
|
{ label: 'July', value: '7' },
|
||||||
|
{ label: 'August', value: '8' },
|
||||||
|
{ label: 'September', value: '9' },
|
||||||
|
{ label: 'October', value: '10' },
|
||||||
|
{ label: 'November', value: '11' },
|
||||||
|
{ label: 'December', value: '12' },
|
||||||
|
];
|
||||||
|
const yearData = [
|
||||||
|
{ label: '2025', value: '2025' },
|
||||||
|
{ label: '2024', value: '2024' },
|
||||||
|
{ label: '2023', value: '2023' },
|
||||||
|
{ label: '2022', value: '2022' },
|
||||||
|
{ label: '2021', value: '2021' },
|
||||||
|
{ label: '2020', value: '2020' },
|
||||||
|
{ label: '2019', value: '2019' },
|
||||||
|
{ label: '2018', value: '2018' },
|
||||||
|
{ label: '2017', value: '2017' },
|
||||||
|
{ label: '2016', value: '2016' },
|
||||||
|
{ label: '2015', value: '2015' },
|
||||||
|
];
|
||||||
|
const assetData = [
|
||||||
|
{
|
||||||
|
"section": "Asset%",
|
||||||
|
"data": [
|
||||||
|
{ "display": "Real Endcap", "present": "No" },
|
||||||
|
{ "display": "Honey Parasite", "present": "Yes" },
|
||||||
|
{ "display": "Odonil Floor Stack", "present": "YHes" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"section": "Additional Visibility",
|
||||||
|
"data": [
|
||||||
|
{ "display": "Active 1 Ltr Endcap", "present": "Yes" },
|
||||||
|
{ "display": "Chyawanprash Stack", "present": "Yes" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"section": "Promotion",
|
||||||
|
"data": [
|
||||||
|
{ "display": "Activ 100% Juice", "present": "Yes" },
|
||||||
|
{ "display": "Airfresher", "present": "No" },
|
||||||
|
{ "display": "BABY CARE", "present": "No" },
|
||||||
|
{ "display": "Chyawanprash", "present": "No" },
|
||||||
|
{ "display": "Hair Oil", "present": "No" },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
const PieData = [
|
||||||
|
{
|
||||||
|
name: "Seoul",
|
||||||
|
population: 21500000,
|
||||||
|
color: "rgba(131, 167, 234, 1)",
|
||||||
|
legendFontColor: "#7F7F7F",
|
||||||
|
legendFontSize: 15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Toronto",
|
||||||
|
population: 2800000,
|
||||||
|
color: "#F00",
|
||||||
|
legendFontColor: "#7F7F7F",
|
||||||
|
legendFontSize: 15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Beijing",
|
||||||
|
population: 527612,
|
||||||
|
color: "red",
|
||||||
|
legendFontColor: "#7F7F7F",
|
||||||
|
legendFontSize: 15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "New York",
|
||||||
|
population: 8538000,
|
||||||
|
color: "#ffffff",
|
||||||
|
legendFontColor: "#7F7F7F",
|
||||||
|
legendFontSize: 15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Moscow",
|
||||||
|
population: 11920000,
|
||||||
|
color: "rgb(0, 0, 255)",
|
||||||
|
legendFontColor: "#7F7F7F",
|
||||||
|
legendFontSize: 15
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const barData = {
|
||||||
|
labels: ["Jan", "Feb", "March", "April",],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
data: [20, 45, 28, 80]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const chartConfig = {
|
||||||
|
backgroundColor: '#ffffff',
|
||||||
|
backgroundGradientFrom: '#ffffff',
|
||||||
|
backgroundGradientTo: '#ffffff',
|
||||||
|
fillShadowGradientFrom: '#FF8C61', // For bar colors
|
||||||
|
fillShadowGradientTo: '#FF8C61',
|
||||||
|
fillShadowGradientFromOpacity: 1,
|
||||||
|
fillShadowGradientToOpacity: 1,
|
||||||
|
decimalPlaces: 0,
|
||||||
|
color: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`, // Text color
|
||||||
|
labelColor: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
|
||||||
|
// barPercentage: 0.5,
|
||||||
|
barPercentage: 1,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSelectSubTab = (item) => {
|
||||||
|
setActiveTab(item?.TabId)
|
||||||
|
}
|
||||||
|
|
||||||
|
const filteredGraphs = displayData?.graphDetails?.filter(graph => graph.TabId === activeTab);
|
||||||
|
const firstItem = filteredGraphs?.[0];
|
||||||
|
const restItems = filteredGraphs?.slice(1);
|
||||||
|
|
||||||
|
const renderItem = ({ item }) => {
|
||||||
|
switch (item.GraphType) {
|
||||||
|
case "ScoreCard":
|
||||||
|
return (
|
||||||
|
<View style={[styles.percentBox, { backgroundColor: item.GraphBackground }]}>
|
||||||
|
<Text style={styles.boxText}>{item.GraphTitle}</Text>
|
||||||
|
<Text style={[styles.boxText, { fontWeight: '500', fontSize: 24, marginTop: 10 }]}>{"45%"}</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
|
case "BarGraph":
|
||||||
|
const barData = {
|
||||||
|
labels: ["Jan", "Feb", "Mar", "Apr"],
|
||||||
|
datasets: [{ data: [35, 45, 20, 55] }]
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<View style={{ padding: 10, backgroundColor: '', borderRadius: 8 }}>
|
||||||
|
<Text style={{ fontSize: 16, fontWeight: '600', marginBottom: 10 }}>
|
||||||
|
SOS Compliance Trend
|
||||||
|
</Text>
|
||||||
|
<BarChart
|
||||||
|
data={barData}
|
||||||
|
width={screenWidth - 40}
|
||||||
|
height={220}
|
||||||
|
yAxisSuffix="%"
|
||||||
|
chartConfig={chartConfig}
|
||||||
|
fromZero
|
||||||
|
showValuesOnTopOfBars
|
||||||
|
withInnerLines
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
|
case "Table":
|
||||||
|
return (
|
||||||
|
<View style={{ flex: 1, }}>
|
||||||
|
<ScrollView>
|
||||||
|
<View style={{ flexDirection: 'row', borderWidth: 1, borderColor: '#EAEAEA', alignItems: 'center', alignSelf: 'flex-start', padding: 5, borderRadius: 15 }}>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.subTab, { backgroundColor: '#113F8C' }]}>
|
||||||
|
<Text style={[styles.tabText, { color: "#fff" }]}>{'Asset'}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.subTab, { backgroundColor: '#113F8C' }]}>
|
||||||
|
<Text style={[styles.tabText, { color: "#fff" }]}>{'Asset Details'}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{assetData && assetData.map((table, index) => (
|
||||||
|
<View key={index} style={{ marginTop: 10 }}>
|
||||||
|
<Text style={{ fontSize: 16, color: '#000', fontWeight: '500' }}>{table.section}</Text>
|
||||||
|
|
||||||
|
<View style={{ marginTop: 5, backgroundColor: '#fff', elevation: 5, padding: 10, borderRadius: 10 }}>
|
||||||
|
<View style={{ flexDirection: 'row', borderBottomWidth: 1, borderColor: '#E0E0E0', paddingBottom: 7, }}>
|
||||||
|
<Text style={{ width: '50%', color: '#676767', fontSize: 14 }}>Display</Text>
|
||||||
|
<Text style={{ width: '50%', color: '#676767', fontSize: 14 }}>Present</Text>
|
||||||
|
</View>
|
||||||
|
{
|
||||||
|
table && table.data.map((item) => (
|
||||||
|
<View style={{ marginTop: 3, flexDirection: 'row', paddingBottom: 7, borderBottomWidth: 1, borderColor: '#E0E0E0', }}>
|
||||||
|
<Text style={{ width: '50%', color: '#000', fontSize: 14, }}>{item.display}</Text>
|
||||||
|
<Text style={{ width: '50%', color: '#000', fontSize: 14, }}>{item?.present}</Text>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
))}
|
||||||
|
<View style={{ marginBottom: 500 }} />
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
|
||||||
|
case "LineChart":
|
||||||
|
return (
|
||||||
|
<View style={{ flex: 1, }}>
|
||||||
|
<Text>Bezier Line Chart</Text>
|
||||||
|
<LineChart
|
||||||
|
data={{
|
||||||
|
labels: ["January", "February", "March", "April", "May", "June"],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
data: [
|
||||||
|
Math.random() * 100,
|
||||||
|
Math.random() * 100,
|
||||||
|
Math.random() * 100,
|
||||||
|
Math.random() * 100,
|
||||||
|
Math.random() * 100,
|
||||||
|
Math.random() * 100
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}}
|
||||||
|
width={Dimensions.get("window").width} // from react-native
|
||||||
|
height={220}
|
||||||
|
yAxisLabel="$"
|
||||||
|
yAxisSuffix="k"
|
||||||
|
yAxisInterval={1} // optional, defaults to 1
|
||||||
|
chartConfig={{
|
||||||
|
backgroundColor: "#e26a00",
|
||||||
|
backgroundGradientFrom: "lgray",
|
||||||
|
backgroundGradientTo: "lightblue",
|
||||||
|
decimalPlaces: 2, // optional, defaults to 2dp
|
||||||
|
color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
|
||||||
|
labelColor: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
|
||||||
|
style: {
|
||||||
|
borderRadius: 16
|
||||||
|
},
|
||||||
|
propsForDots: {
|
||||||
|
r: "6",
|
||||||
|
strokeWidth: "2",
|
||||||
|
stroke: "#ffa726"
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
bezier
|
||||||
|
style={{
|
||||||
|
marginVertical: 8,
|
||||||
|
borderRadius: 16
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
case "PieChart":
|
||||||
|
return (
|
||||||
|
<View style={{ flex: 1, }}>
|
||||||
|
<PieChart
|
||||||
|
data={PieData}
|
||||||
|
width={screenWidth}
|
||||||
|
height={220}
|
||||||
|
chartConfig={chartConfig}
|
||||||
|
accessor={"population"}
|
||||||
|
backgroundColor={"transparent"}
|
||||||
|
paddingLeft={"15"}
|
||||||
|
center={[10, 50]}
|
||||||
|
absolute
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<View style={[styles.percentBox, { backgroundColor: "#f8d7da", padding: 10, marginVertical: 5 }]}>
|
||||||
|
<Text style={[styles.boxText, { color: "#721c24" }]}>
|
||||||
|
Unsupported Graph Type: {item.GraphType}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// download data
|
||||||
|
useEffect(() => {
|
||||||
|
const init = async () => {
|
||||||
|
await getData(); // <-- Only dynamic live data
|
||||||
|
};
|
||||||
|
init();
|
||||||
|
|
||||||
|
getTabData()
|
||||||
|
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Insert fallback mock data if empty
|
||||||
|
const insertMasterSurveyQuestion = (data_arr = []) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!Array.isArray(data_arr) || data_arr.length === 0) {
|
||||||
|
resolve(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const escape = str => (str || '').toString().replace(/'/g, "''");
|
||||||
|
|
||||||
|
const values = data_arr.map(item => {
|
||||||
|
const {
|
||||||
|
MenuId, SurveyId, SurveyName, CategoryId, Category, CategorySequence,
|
||||||
|
QuestionId, Question, QuestionType, QuestionImageAllow, QEnable,
|
||||||
|
LengthValidation, MinLength, MaxLength, OTP, DateRange, QuestionSequence,
|
||||||
|
AnswerId, Answer, ImageAllow1, ImageAllow2, Image1Mandatory, Image2Mandatory,
|
||||||
|
QuestionImageMandatory, EnableQuestion, DisableQuestion, AnswerSequence,
|
||||||
|
ShowCat, SubCategoryId, SubCategory, SubCategorySequence,
|
||||||
|
QuestionTypeNew, CalFormula, RefImage, QuestionRefImage
|
||||||
|
} = item;
|
||||||
|
|
||||||
|
return `(
|
||||||
|
'${MenuId}', '${SurveyId}', '${escape(SurveyName)}', '${CategoryId}', '${escape(Category)}',
|
||||||
|
'${CategorySequence}', '${QuestionId}', '${escape(Question)}', '${escape(QuestionType)}',
|
||||||
|
'${QuestionImageAllow ? 1 : 0}', '${QEnable ? 1 : 0}', '${LengthValidation ? 1 : 0}',
|
||||||
|
'${MinLength}', '${MaxLength}', '${OTP ? 1 : 0}', '${escape(DateRange)}',
|
||||||
|
'${QuestionSequence}', '${AnswerId}', '${escape(Answer)}',
|
||||||
|
'${ImageAllow1 ? 1 : 0}', '${ImageAllow2 ? 1 : 0}', '${Image1Mandatory ? 1 : 0}',
|
||||||
|
'${Image2Mandatory ? 1 : 0}', '${QuestionImageMandatory ? 1 : 0}',
|
||||||
|
'${escape(EnableQuestion)}', '${escape(DisableQuestion)}', '${AnswerSequence}',
|
||||||
|
'${ShowCat ? 1 : 0}', '${SubCategoryId}', '${escape(SubCategory)}',
|
||||||
|
'${SubCategorySequence}', '${escape(QuestionTypeNew)}', '${escape(CalFormula)}',
|
||||||
|
'${escape(RefImage)}', '${escape(QuestionRefImage)}'
|
||||||
|
)`;
|
||||||
|
});
|
||||||
|
|
||||||
|
const sql = `
|
||||||
|
INSERT INTO FeedbackCategory (
|
||||||
|
MenuId, SurveyId, SurveyName, CategoryId, Category, CategorySequence,
|
||||||
|
QuestionId, Question, QuestionType, QuestionImageAllow, QEnable,
|
||||||
|
LengthValidation, MinLength, MaxLength, OTP, DateRange, QuestionSequence,
|
||||||
|
AnswerId, Answer, ImageAllow1, ImageAllow2, Image1Mandatory, Image2Mandatory,
|
||||||
|
QuestionImageMandatory, EnableQuestion, DisableQuestion, AnswerSequence,
|
||||||
|
ShowCat, SubCategoryId, SubCategory, SubCategorySequence,
|
||||||
|
QuestionTypeNew, CalFormula, RefImage,QuestionRefImage
|
||||||
|
) VALUES ${values.join(',')}
|
||||||
|
`;
|
||||||
|
|
||||||
|
db.transaction(tx => {
|
||||||
|
tx.executeSql(`DELETE FROM FeedbackCategory`, [], () => {
|
||||||
|
tx.executeSql(sql, [], () => {
|
||||||
|
console.log('FeedbackCategory inserted successfully');
|
||||||
|
resolve(true);
|
||||||
|
}, (err) => {
|
||||||
|
console.log('Insert error in FeedbackCategory:', err);
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
}, (err) => {
|
||||||
|
console.log('Delete error before insert FeedbackCategory:', err);
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
async function getData() {
|
||||||
|
try {
|
||||||
|
const data1 = {
|
||||||
|
Downloadtype: "Master_SurveyQuestion",
|
||||||
|
Param1: "",
|
||||||
|
Param2: "",
|
||||||
|
username: "testmer",
|
||||||
|
};
|
||||||
|
|
||||||
|
const url = "https://di1.parinaam.in/Webservice/GenericService.svc/DownloadJson";
|
||||||
|
console.log("Downloading from:", url, data1);
|
||||||
|
|
||||||
|
const res = await getDownloadJson(url, data1);
|
||||||
|
console.log('Response:', res);
|
||||||
|
|
||||||
|
if (res?.Master_SurveyQuestion?.length) {
|
||||||
|
const data = res.Master_SurveyQuestion || [];
|
||||||
|
console.log("Inserting downloaded data into FeedbackCategory...");
|
||||||
|
const all = await getAllFromTable('FeedbackCategory');
|
||||||
|
if (all?.length === 0) {
|
||||||
|
console.log("Table empty. Inserting fallback mock data...");
|
||||||
|
await insertMasterSurveyQuestion(data);
|
||||||
|
} else {
|
||||||
|
console.log("FeedbackCategory table already has data.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log("No Master_SurveyQuestion data found in response");
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("Dashboard feedback survey download error:", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// end download data.
|
||||||
|
|
||||||
|
const getTabData = () => {
|
||||||
|
let params = {
|
||||||
|
"parameters": {
|
||||||
|
"projectid": 41654,
|
||||||
|
"year": 2025,
|
||||||
|
"monthno": 6,
|
||||||
|
"storeid": 2702
|
||||||
|
}
|
||||||
|
}
|
||||||
|
post(ApiURL.pssscoreApi, params)
|
||||||
|
.then(res => {
|
||||||
|
console.log('psscoreApi res==>', res);
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={{ flex: 1, backgroundColor: GlobalTheme.colors.primary }}>
|
||||||
|
<View style={{ flex: 1, backgroundColor: '#fff' }}>
|
||||||
|
{!isStoreSelected ?
|
||||||
|
<CustomHeader
|
||||||
|
title=" Dashboard"
|
||||||
|
rightIcon={IMAGES.menuIcon}
|
||||||
|
onRightPress={() => setModalVisible(true)}
|
||||||
|
/>
|
||||||
|
:
|
||||||
|
<CustomHeader
|
||||||
|
title="Dashboard"
|
||||||
|
leftIcon={IMAGES.backIcon}
|
||||||
|
onLeftPress={() => setIsStoreSelected(false)}
|
||||||
|
rightIcon={IMAGES.menuIcon}
|
||||||
|
onRightPress={() => setModalVisible(true)}
|
||||||
|
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
|
{/* MAIN DASHBOARD */}
|
||||||
|
{!isStoreSelected ? (
|
||||||
|
<View style={{ flex: 1 }} >
|
||||||
|
|
||||||
|
<TouchableOpacity onPress={() => openBottomSheet()} activeOpacity={0.8} style={styles.selectCard}>
|
||||||
|
<Image source={IMAGES.reportIcon} style={styles.iconStyle} />
|
||||||
|
<Text style={styles.storeText}> Select Store:</Text>
|
||||||
|
<Image source={IMAGES.downIcon} style={{ height: 20, width: 20, resizeMode: 'contain' }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Text style={styles.selectStoreText}>Select a store to view it's data.</Text>
|
||||||
|
|
||||||
|
<LinearGradient
|
||||||
|
colors={['#D8E7FF', '#FFFFFF',]}
|
||||||
|
start={{ x: 0, y: 0 }}
|
||||||
|
end={{ x: 1, y: 1 }}
|
||||||
|
style={styles.storeGredient}>
|
||||||
|
|
||||||
|
<View style={styles.todayStoreCard}>
|
||||||
|
|
||||||
|
<View style={{ marginLeft: 5, flexDirection: 'row', padding: 10, alignItems: 'center' }}>
|
||||||
|
<View style={{ backgroundColor: '#E3EBF8', padding: 5, borderRadius: 7 }}>
|
||||||
|
<Image source={IMAGES.storeIcon} style={{ height: 18, width: 18 }} />
|
||||||
|
</View>
|
||||||
|
<Text style={styles.todayStoreText}>Today's store</Text>
|
||||||
|
</View>
|
||||||
|
<View style={{ borderBottomWidth: 1.5, borderColor: '#E3EBF8' }} />
|
||||||
|
|
||||||
|
<View style={[styles.row, { paddingHorizontal: 10 }]}>
|
||||||
|
<View style={{ width: '48%', alignItems: 'center' }}>
|
||||||
|
<Text style={{ color: '#000', fontSize: 20, fontWeight: 'bold' }}>1</Text>
|
||||||
|
<Text style={{ color: '#808CA3', fontSize: 15, fontWeight: '400' }}>View</Text>
|
||||||
|
</View>
|
||||||
|
<View style={{ borderWidth: 1, height: 50, borderColor: '#E3EBF8' }} />
|
||||||
|
<View style={{ width: '48%', alignItems: 'center' }}>
|
||||||
|
<Text style={{ color: '#000', fontSize: 20, fontWeight: 'bold', textAlign: 'right' }}>2</Text>
|
||||||
|
<Text style={{ color: '#808CA3', fontSize: 15, fontWeight: '400', textAlign: 'right' }}>Feedback</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<ScrollView showsVerticalScrollIndicator={false}>
|
||||||
|
<View style={{ marginTop: 5, marginHorizontal: 10 }}>
|
||||||
|
{visitedStoreData && visitedStoreData.map(store => (
|
||||||
|
<TouchableOpacity onPress={() => navigation.navigate("FeedbackCategories")}
|
||||||
|
key={store.id} style={styles.storeCard}>
|
||||||
|
<View style={[styles.row, { margin: 0 }]}>
|
||||||
|
<Text style={styles.cardTextBold}>{store.name}</Text>
|
||||||
|
{store?.status === 'completed' ?
|
||||||
|
<Image source={IMAGES.greenTick} style={{ height: 20, width: 20 }} />
|
||||||
|
:
|
||||||
|
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||||
|
<View style={{ backgroundColor: '#FFF8CD', padding: 5, paddingHorizontal: 7, borderRadius: 15 }}>
|
||||||
|
<Text style={{ color: 'orange', fontSize: 13, fontWeight: '500' }}>Pending</Text>
|
||||||
|
</View>
|
||||||
|
<Image source={IMAGES.rightArrowIcon} style={{ marginLeft: 10, height: 20, width: 20, resizeMode: 'contain', tintColor: '#97ADD6' }} />
|
||||||
|
</View>
|
||||||
|
}
|
||||||
|
</View>
|
||||||
|
<Text style={styles.cardText}>{store.address}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</LinearGradient>
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
// STORE DASHBOARD
|
||||||
|
<View style={styles.mainContainer}>
|
||||||
|
<View style={styles.row}>
|
||||||
|
<View style={styles.selectedStoreText}>
|
||||||
|
<Text style={styles.storeNameText}> {storeData?.name}</Text>
|
||||||
|
<TouchableOpacity onPress={() => openBottomSheet()} style={styles.filterIcon}>
|
||||||
|
<Image source={IMAGES.filterIcon} style={{ height: 18, width: 18 }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
<TouchableOpacity onPress={() => navigation.navigate('StoreInfo')} style={{ width: '25%', alignItems: 'flex-end' }}>
|
||||||
|
<Text style={styles.storeInfoText}>Store info</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Year & Month Selector */}
|
||||||
|
<View style={{ flexDirection: 'row', alignItems: 'center', marginHorizontal: 10, marginTop: 5 }}>
|
||||||
|
<View style={{ width: 100, }}>
|
||||||
|
<CustomDropdown
|
||||||
|
data={yearData}
|
||||||
|
value={year}
|
||||||
|
placeholder='Year'
|
||||||
|
onChange={item => setYear(item.value)}
|
||||||
|
containerStyle={styles.yearDropDown}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<View style={{ width: 120, marginHorizontal: 10, }}>
|
||||||
|
<CustomDropdown
|
||||||
|
data={monthData}
|
||||||
|
value={month}
|
||||||
|
placeholder='Month'
|
||||||
|
onChange={item => setMonth(item.value)}
|
||||||
|
containerStyle={[styles.yearDropDown, { width: 120 }]}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<CustomButton title={'Show'}
|
||||||
|
style={styles.btnbg}
|
||||||
|
textstyle={styles.btntext}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<View style={styles.seperator} />
|
||||||
|
|
||||||
|
{/* Main Tab */}
|
||||||
|
<View style={{ flexDirection: 'row' }}>
|
||||||
|
<TouchableOpacity onPress={() => setMainTab('mtd')}
|
||||||
|
style={[styles.mtdTab, { borderBottomWidth: mainTab === 'mtd' ? 3 : 0, backgroundColor: mainTab === 'mtd' ? '#EFF6FF' : '#fff' }]} >
|
||||||
|
<Text style={[styles.mtdTabText, { color: mainTab === 'mtd' ? '#113F8C' : '#000', }]}>MTD</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity onPress={() => setMainTab('lastVisit')}
|
||||||
|
style={[styles.mtdTab, { borderBottomWidth: mainTab === 'lastVisit' ? 3 : 0, backgroundColor: mainTab === 'lastVisit' ? '#EFF6FF' : '#fff' }]} >
|
||||||
|
<Text style={[styles.mtdTabText, { color: mainTab === 'lastVisit' ? '#113F8C' : '#000' }]}>Last Visit</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* <View style={{ flexDirection: 'row' }}>
|
||||||
|
|
||||||
|
{mainDisplayJson && mainDisplayJson?.Tabs.map((item, index) => (
|
||||||
|
<TouchableOpacity onPress={() => setMainTab('mtd')}
|
||||||
|
style={[styles.mtdTab, { borderBottomWidth: mainTab === 'mtd' ? 3 : 0, backgroundColor: mainTab === 'mtd' ? '#EFF6FF' : '#fff' }]} >
|
||||||
|
<Text style={[styles.mtdTabText, { color: mainTab === 'mtd' ? '#113F8C' : '#000', }]}>MTD</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
))}
|
||||||
|
|
||||||
|
</View> */}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{/* Sub Tab */}
|
||||||
|
<View style={styles.subTabView}>
|
||||||
|
<FlatList
|
||||||
|
data={displayData?.subTabs}
|
||||||
|
horizontal
|
||||||
|
keyExtractor={(item) => item.TabId}
|
||||||
|
showsHorizontalScrollIndicator={false}
|
||||||
|
contentContainerStyle={{ paddingHorizontal: 10 }}
|
||||||
|
renderItem={({ item }) => {
|
||||||
|
const isSelected = activeTab === item.TabId;
|
||||||
|
return (
|
||||||
|
<TouchableOpacity onPress={() => onSelectSubTab(item)}
|
||||||
|
style={[styles.subTab, { backgroundColor: isSelected ? '#113F8C' : '#fff' }]}>
|
||||||
|
<Text style={[styles.tabText, { color: isSelected ? "#fff" : "#000" }]}>{item.TabName}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Boxes */}
|
||||||
|
<View style={{ margin: 10 }}>
|
||||||
|
{/* First full-width item */}
|
||||||
|
{firstItem && (
|
||||||
|
<View style={[styles.percentBox, { backgroundColor: firstItem.GraphBackground, width: '100%', elevation: 0 },]}>
|
||||||
|
<Text style={styles.boxText}>{firstItem.GraphTitle}</Text>
|
||||||
|
<Text style={[styles.boxText, { fontWeight: '500', fontSize: 24, marginTop: 10 }]}>{"45%"}</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<FlatList
|
||||||
|
data={restItems}
|
||||||
|
keyExtractor={(item, index) => `${item.GraphId}-${index}`}
|
||||||
|
renderItem={renderItem}
|
||||||
|
numColumns={2}
|
||||||
|
columnWrapperStyle={{ justifyContent: 'space-between', marginTop: 10 }}
|
||||||
|
contentContainerStyle={{ paddingHorizontal: 2, paddingVertical: 2 }}
|
||||||
|
showsVerticalScrollIndicator={false}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Pop-up Modal */}
|
||||||
|
<Modal transparent visible={modalVisible} animationType="fade" >
|
||||||
|
<TouchableOpacity style={styles.modalOverlay} activeOpacity={0.1} onPress={() => setModalVisible(false)}>
|
||||||
|
<View style={styles.modalContainer}>
|
||||||
|
<TouchableOpacity onPress={() => { navigation.navigate('FeedbackCategories'), setModalVisible(false) }} style={{ padding: 15 }}>
|
||||||
|
<Text style={{}}>Feedback and Rating</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<View style={{ borderBottomWidth: 1, borderColor: '#D8E3F1' }} />
|
||||||
|
<TouchableOpacity onPress={() => setModalVisible(false)} style={{ padding: 15 }}>
|
||||||
|
<Text style={{}}>Dashboard</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
|
{/* Bottom Sheet */}
|
||||||
|
<RBSheet
|
||||||
|
ref={refRBSheet}
|
||||||
|
useNativeDriver={true}
|
||||||
|
customStyles={{
|
||||||
|
wrapper: {
|
||||||
|
backgroundColor: 'rgba(0,0,0,0.2)',
|
||||||
|
},
|
||||||
|
container: {
|
||||||
|
height: '86%',
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
borderTopLeftRadius: 20,
|
||||||
|
borderTopRightRadius: 20,
|
||||||
|
paddingBottom: 10,
|
||||||
|
},
|
||||||
|
draggableIcon: {
|
||||||
|
backgroundColor: 'gray',
|
||||||
|
},
|
||||||
|
|
||||||
|
}}
|
||||||
|
customModalProps={{
|
||||||
|
animationType: 'slide',
|
||||||
|
statusBarTranslucent: true,
|
||||||
|
|
||||||
|
}}
|
||||||
|
customAvoidingViewProps={{
|
||||||
|
enabled: false,
|
||||||
|
}}>
|
||||||
|
<View style={{ flex: 1, }}>
|
||||||
|
<View style={styles.header}>
|
||||||
|
<Text style={{ color: '#000', fontWeight: '500', fontSize: 16 }}>Select Store</Text>
|
||||||
|
<TouchableOpacity onPress={() => refRBSheet.current.close()}>
|
||||||
|
<Image source={IMAGES.crossIcon} style={styles.iconStyle} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
<View style={{ marginVertical: 0, borderBottomWidth: 1, borderColor: '#ccc' }} />
|
||||||
|
|
||||||
|
<ScrollView showsVerticalScrollIndicator={false}
|
||||||
|
ref={scrollViewRef}
|
||||||
|
onScroll={handleScroll} >
|
||||||
|
<View style={{ flex: 1, margin: 15, }}>
|
||||||
|
<View style={[styles.row, {}]}>
|
||||||
|
<Text style={styles.dropHeaderText}>State</Text>
|
||||||
|
<Text style={styles.dropHeaderText}> City</Text>
|
||||||
|
<Text style={styles.dropHeaderText}> ASM Area</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Dropdown */}
|
||||||
|
<View style={{ marginTop: 5, flexDirection: 'row', alignItems: 'center' }}>
|
||||||
|
<CustomDropdown
|
||||||
|
data={data}
|
||||||
|
value={state}
|
||||||
|
onChange={item => setState(item.value)}
|
||||||
|
containerStyle={{ flex: 1, }}
|
||||||
|
/>
|
||||||
|
<CustomDropdown
|
||||||
|
data={cityData}
|
||||||
|
value={city}
|
||||||
|
onChange={item => setCity(item.value)}
|
||||||
|
containerStyle={{ flex: 1, marginHorizontal: 10 }}
|
||||||
|
/>
|
||||||
|
<CustomDropdown
|
||||||
|
data={cityData}
|
||||||
|
value={asmArea}
|
||||||
|
onChange={item => setAsmArea(item.value)}
|
||||||
|
containerStyle={{ flex: 1, }}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={[styles.searchBox, { marginTop: 20 }]}>
|
||||||
|
{/* <Image source={IMAGES.searchIcon} style={{ height: 15, width: 15 }} /> */}
|
||||||
|
<TextInput
|
||||||
|
style={styles.inputStyle}
|
||||||
|
placeholder='Search store...'
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={{ marginTop: 20 }}>
|
||||||
|
<CustomButton title={'Apply'} onPress={() => setSearchResult(!searchResult)}
|
||||||
|
style={{ backgroundColor: GlobalTheme.colors.secondary, borderRadius: GlobalTheme.borderRadius.md }}
|
||||||
|
textstyle={{ color: GlobalTheme.colors.white, fontSize: GlobalTheme.typography.fontSize.medium }}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
{searchResult ?
|
||||||
|
<View style={{ marginBottom: 70 }}>
|
||||||
|
<View style={{ marginTop: 20 }}>
|
||||||
|
<Text style={{ color: '#000', fontSize: 14 }}>11 Store</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{storeJson && storeJson.map(store => (
|
||||||
|
<TouchableOpacity onPress={() => onSelectStore(store)}
|
||||||
|
key={store.id} style={styles.storeCard}>
|
||||||
|
<Text style={styles.cardTextBold}>{store.name}</Text>
|
||||||
|
<Text style={styles.cardText}>{store.address}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
))}
|
||||||
|
|
||||||
|
|
||||||
|
</View>
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
{showButton && (
|
||||||
|
<TouchableOpacity style={styles.floatingBtn} onPress={() => { scrollViewRef.current?.scrollTo({ y: 0, animated: true }) }}>
|
||||||
|
<Image source={IMAGES.upArrow} style={{ height: 15, width: 15 }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
)}
|
||||||
|
|
||||||
|
</View>
|
||||||
|
|
||||||
|
</RBSheet>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
</SafeAreaView>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Dashboard
|
||||||
|
|
||||||
@@ -0,0 +1,631 @@
|
|||||||
|
{
|
||||||
|
"Tabs": [
|
||||||
|
{
|
||||||
|
"MainTabId": 1,
|
||||||
|
"MainTabName": "MTD",
|
||||||
|
"MainTabData": {
|
||||||
|
"subTabs": [
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"TabName": "PSS Score",
|
||||||
|
"TabRow": 1,
|
||||||
|
"TabCol": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 2,
|
||||||
|
"TabName": "PSS Trend",
|
||||||
|
"TabRow": 1,
|
||||||
|
"TabCol": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 3,
|
||||||
|
"TabName": "SOS Actual",
|
||||||
|
"TabRow": 1,
|
||||||
|
"TabCol": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 4,
|
||||||
|
"TabName": "OSA",
|
||||||
|
"TabRow": 1,
|
||||||
|
"TabCol": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 5,
|
||||||
|
"TabName": "Asset",
|
||||||
|
"TabRow": 1,
|
||||||
|
"TabCol": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 6,
|
||||||
|
"TabName": "Promotion",
|
||||||
|
"TabRow": 1,
|
||||||
|
"TabCol": 6
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"graphDetails": [
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"GraphId": 1,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "PSS Score",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/pssscore",
|
||||||
|
"GraphBackground": "#C3D7FF",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"GraphId": 2,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "SOS Actual",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/SOS_Actual_Perc",
|
||||||
|
"GraphBackground": "#E2C8FE",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"GraphId": 4,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "OSA",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/OSA_Perc",
|
||||||
|
"GraphBackground": "#FFF9A1",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"GraphId": 5,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "Asset",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/Asset_Perc",
|
||||||
|
"GraphBackground": "#A2F3DE",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"GraphId": 6,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "Promotion",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/Promotion_Perc",
|
||||||
|
"GraphBackground": "#BFC2FF",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"TabId": 2,
|
||||||
|
"GraphId": 1,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "PSS Score",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/SOS_Actual_Perc",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {},
|
||||||
|
"clickable": 0,
|
||||||
|
"DetailsPage": [
|
||||||
|
{
|
||||||
|
"TabId": 2,
|
||||||
|
"GraphId": 1,
|
||||||
|
"GraphType": "Table",
|
||||||
|
"GraphTitle": "PSS - Category",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/sos_actual_perc_on_category",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 2,
|
||||||
|
"GraphId": 2,
|
||||||
|
"GraphType": "BarGraph",
|
||||||
|
"GraphTitle": "PSS Trend",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/sos_actual_trend_perc_mtd",
|
||||||
|
"GraphBackground": "#F4EAFF",
|
||||||
|
"GraphOptions": {
|
||||||
|
"axisX": "month",
|
||||||
|
"axisY": "score",
|
||||||
|
"labelShow": 1,
|
||||||
|
"barColors": [
|
||||||
|
"#11a4ff",
|
||||||
|
"#0ea3e3",
|
||||||
|
"#0b9ddb"
|
||||||
|
],
|
||||||
|
"gridLinesH": 0,
|
||||||
|
"gridLinesV": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"TabId": 3,
|
||||||
|
"GraphId": 3,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "SOS Actual",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/SOS_Actual_Perc",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {},
|
||||||
|
"clickable": 1,
|
||||||
|
"DetailsPage": [
|
||||||
|
{
|
||||||
|
"TabId": 2,
|
||||||
|
"GraphId": 1,
|
||||||
|
"GraphType": "Table",
|
||||||
|
"GraphTitle": "SOS - Category",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/sos_actual_perc_on_category",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 3,
|
||||||
|
"GraphId": 4,
|
||||||
|
"GraphType": "BarGraph",
|
||||||
|
"GraphTitle": "SOS Actual Trend",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/sos_actual_trend_perc_mtd",
|
||||||
|
"GraphBackground": "#F4EAFF",
|
||||||
|
"GraphOptions": {
|
||||||
|
"axisX": "month",
|
||||||
|
"axisY": "score",
|
||||||
|
"labelShow": 1,
|
||||||
|
"barColors": [
|
||||||
|
"#11a4ff",
|
||||||
|
"#0ea3e3",
|
||||||
|
"#0b9ddb"
|
||||||
|
],
|
||||||
|
"gridLinesH": 0,
|
||||||
|
"gridLinesV": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"TabId": 4,
|
||||||
|
"GraphId": 5,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "OSA",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/OSA_Perc",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {},
|
||||||
|
"clickable": 1,
|
||||||
|
"DetailsPage": [
|
||||||
|
{
|
||||||
|
"TabId": 3,
|
||||||
|
"GraphId": 3,
|
||||||
|
"GraphType": "Table",
|
||||||
|
"GraphTitle": "OSA - Category",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/osa_perc_on_category",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 4,
|
||||||
|
"GraphId": 6,
|
||||||
|
"GraphType": "BarGraph",
|
||||||
|
"GraphTitle": "OSA",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/osa_trend_perc_mtd",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"TabId": 5,
|
||||||
|
"GraphId": 7,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "Asset",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/Asset_Perc",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {},
|
||||||
|
"clickable": 1,
|
||||||
|
"DetailsPage": [
|
||||||
|
{
|
||||||
|
"TabId": 5,
|
||||||
|
"GraphId": 5,
|
||||||
|
"GraphType": "Table",
|
||||||
|
"GraphTitle": "Visibility",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/asset_availability_mtd",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 5,
|
||||||
|
"GraphId": 5,
|
||||||
|
"GraphType": "Table",
|
||||||
|
"GraphTitle": "Additional Visibility",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/additional_visibility_mtd",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 5,
|
||||||
|
"GraphId": 8,
|
||||||
|
"GraphType": "BarGraph",
|
||||||
|
"GraphTitle": "Asset Details",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/asset_trend_perc_mtd",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"TabId": 6,
|
||||||
|
"GraphId": 9,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "Promotion",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/Promotion_Perc",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {},
|
||||||
|
"clickable": 1,
|
||||||
|
"DetailsPage": [
|
||||||
|
{
|
||||||
|
"TabId": 6,
|
||||||
|
"GraphId": 9,
|
||||||
|
"GraphType": "Table",
|
||||||
|
"GraphTitle": "Promotion Not Executed",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/promotion_not_executed_mtd",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 6,
|
||||||
|
"GraphId": 10,
|
||||||
|
"GraphType": "Table",
|
||||||
|
"GraphTitle": "Promotion executed",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/promotion_executed_mtd",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 6,
|
||||||
|
"GraphId": 11,
|
||||||
|
"GraphType": "BarGraph",
|
||||||
|
"GraphTitle": "Promotion",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/promotion_trend_perc_mtd",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"MainTabId": 2,
|
||||||
|
"MainTabName": "Last Visit",
|
||||||
|
"MainTabData": {
|
||||||
|
"subTabs": [
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"TabName": "PSS Score",
|
||||||
|
"TabRow": 1,
|
||||||
|
"TabCol": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 2,
|
||||||
|
"TabName": "SOS Actual",
|
||||||
|
"TabRow": 1,
|
||||||
|
"TabCol": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 4,
|
||||||
|
"TabName": "OSA",
|
||||||
|
"TabRow": 1,
|
||||||
|
"TabCol": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 5,
|
||||||
|
"TabName": "Asset",
|
||||||
|
"TabRow": 1,
|
||||||
|
"TabCol": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 6,
|
||||||
|
"TabName": "Promotion",
|
||||||
|
"TabRow": 1,
|
||||||
|
"TabCol": 6
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"graphDetails": [
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"GraphId": 1,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "PSS Score",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/PSS_Score_LSV_Perc",
|
||||||
|
"GraphBackground": "#E2C8FE",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"GraphId": 2,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "SOS Actual",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/sos_actual_lsv_perc",
|
||||||
|
"GraphBackground": "#E2C8FE",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"GraphId": 4,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "OSA",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/osa_lsv_perc",
|
||||||
|
"GraphBackground": "#FFF9A1",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"GraphId": 5,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "Asset",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/asset_lsv_perc",
|
||||||
|
"GraphBackground": "#A2F3DE",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 1,
|
||||||
|
"GraphId": 6,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "Promotion",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/promotion_lsv_perc",
|
||||||
|
"GraphBackground": "#BFC2FF",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"TabId": 2,
|
||||||
|
"GraphId": 1,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "PSS Score",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/mtd/SOS_Actual_Perc",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {},
|
||||||
|
"clickable": 0,
|
||||||
|
"DetailsPage": [
|
||||||
|
{
|
||||||
|
"TabId": 2,
|
||||||
|
"GraphId": 1,
|
||||||
|
"GraphType": "Table",
|
||||||
|
"GraphTitle": "PSS - Category",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detmtd/sos_actual_perc_on_category",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"TabId": 2,
|
||||||
|
"GraphId": 2,
|
||||||
|
"GraphType": "BarGraph",
|
||||||
|
"GraphTitle": "PSS Trend",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpimtd/sos_actual_trend_perc_mtd",
|
||||||
|
"GraphBackground": "#F4EAFF",
|
||||||
|
"GraphOptions": {
|
||||||
|
"axisX": "month",
|
||||||
|
"axisY": "score",
|
||||||
|
"labelShow": 1,
|
||||||
|
"barColors": [
|
||||||
|
"#11a4ff",
|
||||||
|
"#0ea3e3",
|
||||||
|
"#0b9ddb"
|
||||||
|
],
|
||||||
|
"gridLinesH": 0,
|
||||||
|
"gridLinesV": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"TabId": 3,
|
||||||
|
"GraphId": 3,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "SOS Actual",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/sos_actual_lsv_perc",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {},
|
||||||
|
"clickable": 1,
|
||||||
|
"DetailsPage": [
|
||||||
|
{
|
||||||
|
"TabId": 2,
|
||||||
|
"GraphId": 1,
|
||||||
|
"GraphType": "Table",
|
||||||
|
"GraphTitle": "SOS Actual - Category",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detlsv/sos_actual_lsv_perc_on_category",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 3,
|
||||||
|
"GraphId": 4,
|
||||||
|
"GraphType": "BarGraph",
|
||||||
|
"GraphTitle": "SOS Actual Trend",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/sos_actual_trend_lsv_perc",
|
||||||
|
"GraphBackground": "#F4EAFF",
|
||||||
|
"GraphOptions": {
|
||||||
|
"axisX": "month",
|
||||||
|
"axisY": "score",
|
||||||
|
"labelShow": 1,
|
||||||
|
"barColors": [
|
||||||
|
"#11a4ff",
|
||||||
|
"#0ea3e3",
|
||||||
|
"#0b9ddb"
|
||||||
|
],
|
||||||
|
"gridLinesH": 1,
|
||||||
|
"gridLinesV": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"TabId": 4,
|
||||||
|
"GraphId": 5,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "OSA",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/osa_lsv_perc",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {},
|
||||||
|
"clickable": 1,
|
||||||
|
"DetailsPage": [
|
||||||
|
{
|
||||||
|
"TabId": 4,
|
||||||
|
"GraphId": 7,
|
||||||
|
"GraphType": "Table",
|
||||||
|
"GraphTitle": "OSA - Category",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detlsv/osa_lsv_perc_on_category",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 4,
|
||||||
|
"GraphId": 6,
|
||||||
|
"GraphType": "BarGraph",
|
||||||
|
"GraphTitle": "OSA Trend",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/osa_trend_lsv_perc",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"TabId": 5,
|
||||||
|
"GraphId": 7,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "Asset",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/asset_lsv_perc",
|
||||||
|
"GraphBa ckground": "#ECFFFA",
|
||||||
|
"GraphOptions": {},
|
||||||
|
"clickable": 1,
|
||||||
|
"DetailsPage": [
|
||||||
|
{
|
||||||
|
"TabId": 5,
|
||||||
|
"GraphId": 5,
|
||||||
|
"GraphType": "Table",
|
||||||
|
"GraphTitle": "Visibility",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/asset_availability_lsv",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 5,
|
||||||
|
"GraphId": 5,
|
||||||
|
"GraphType": "Table",
|
||||||
|
"GraphTitle": "Additional Visibility",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/additional_visibility_lsv",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 5,
|
||||||
|
"GraphId": 8,
|
||||||
|
"GraphType": "BarGraph",
|
||||||
|
"GraphTitle": "Asset Trend",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/asset_trend_lsv_perc",
|
||||||
|
"GraphBackground": "#fff",
|
||||||
|
"GraphOptions": {
|
||||||
|
"axisX": "month",
|
||||||
|
"axisY": "score",
|
||||||
|
"labelShow": 1,
|
||||||
|
"barColors": [
|
||||||
|
"#11a4ff",
|
||||||
|
"#0ea3e3",
|
||||||
|
"#0b9ddb"
|
||||||
|
],
|
||||||
|
"gridLinesH": 1,
|
||||||
|
"gridLinesV": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"TabId": 6,
|
||||||
|
"GraphId": 9,
|
||||||
|
"GraphType": "ScoreCard",
|
||||||
|
"GraphTitle": "Promotion",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/lsv/promotion_lsv_perc",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {},
|
||||||
|
"clickable": 1,
|
||||||
|
"DetailsPage": [
|
||||||
|
{
|
||||||
|
"TabId": 6,
|
||||||
|
"GraphId": 9,
|
||||||
|
"GraphType": "Table",
|
||||||
|
"GraphTitle": "Promotion Not Executed",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detlsv/promotion_not_executed_lsv",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 6,
|
||||||
|
"GraphId": 10,
|
||||||
|
"GraphType": "Table",
|
||||||
|
"GraphTitle": "Promotion executed",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/detlsv/promotion_executed_lsv",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TabId": 6,
|
||||||
|
"GraphId": 11,
|
||||||
|
"GraphType": "BarGraph",
|
||||||
|
"GraphTitle": "Promotion",
|
||||||
|
"GraphUrl": "https://dax.parinaam.in/execute/dabur/kpilsv/promotion_trend_lsv_perc",
|
||||||
|
"GraphBackground": "#ECFFFA",
|
||||||
|
"GraphOptions": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||