store info - done

This commit is contained in:
2025-06-26 17:45:20 +05:30
parent 3096ec0333
commit 81a82d8124
7 changed files with 547 additions and 9 deletions
+3
View File
@@ -6,6 +6,7 @@ import Splash from '../screens/AuthScreen/Splash';
import Login from '../screens/AuthScreen/Login';
import VerifyOTP from '../screens/AuthScreen/VerifyOTP';
import { ToastComponent } from '../constants/Toast';
import StoreInfo from '../screens/MainScreen/StoreInfo';
const Stack = createNativeStackNavigator();
@@ -18,6 +19,8 @@ const Routes = () => {
<Stack.Screen name="Splash" component={Splash} />
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="VerifyOTP" component={VerifyOTP} />
<Stack.Screen name="StoreInfo" component={StoreInfo} />
</Stack.Navigator>
<ToastComponent />
</NavigationContainer>
+2 -2
View File
@@ -38,10 +38,10 @@ const VerifyOTP = ({ navigation }) => {
};
const handle_validate = () => {
toastError('Alert', "Please enter 6 digit PIN");
if (otp.length < 6) {
toastError('Alert', "Please enter 6 digit PIN");
} else {
navigation.navigate('');
navigation.navigate('StoreInfo');
}
}
@@ -0,0 +1,204 @@
import React, { useState } from 'react';
import {View,Text,TouchableOpacity,ScrollView,FlatList} from 'react-native';
import { styles } from './style';
import { horizonalLine, Screen } from '../../../theme/theme';
const storeinfodata = [
{
tabId: 0,
section: 'Store details',
items: [
{ brand: 'Store Name', value: 'Reliance Smart' },
{ brand: 'Store ID', value: '#98440' },
{ brand: 'Address', value: 'Rabindra Nagar, Delhi 110003' },
{ brand: 'City', value: 'Okhla' },
{ brand: 'Store Size', value: '15002000 sq ft' },
{ brand: 'Average Footfall', value: '10000' },
{ brand: 'Store age', value: '8' },
{ brand: 'Store Ranking', value: '24' },
],
},
{
tabId: 0,
section: 'Dabur Employees',
items: [
{ brand: 'RKAM', value: 'Rajesh Paal Singh' },
{ brand: 'SO', value: 'Soniya Singhal' },
],
},
{
tabId: 0,
section: '3P employees',
items: [
{ brand: 'Promoter Name', value: 'Payal Singh' },
{ brand: 'AM Name', value: 'Soniya Singhal' },
{ brand: 'Supervisor Name', value: 'Soniya Dhankar' },
{ brand: 'City', value: 'Okhla' },
{ brand: 'Promoter duration', value: '2 Year 7 months' },
{ brand: 'Average incentive', value: '5000' },
],
},
// Last Visit Details (tabId: 1)
{
tabId: 1,
section: 'Dabur employee',
items: [
{ brand: 'SO', name: 'Rajesh Paal Singh', date: '23/05/2025' },
{ brand: 'AH', name: 'Umesh Singh', date: '18/04/2025' },
{ brand: 'KAM', name: 'Rahul Tawde', date: '15/05/2025' },
{ brand: 'Others', name: 'Singhal Singh', date: '06/05/2025' },
],
},
{
tabId: 1,
section: '3P team',
items: [
{ brand: 'Supervisor', name: 'Ashish Talwar', date: '27/05/2025' },
{ brand: 'AM', name: 'Soniya Singhal', date: '23/05/2025' },
],
},
// Competition (tabId: 2)
{
tabId: 2,
section: 'Competition assets',
items: [
{ brand: 'Marico', value: 5 },
{ brand: 'Colgate', value: 1 },
{ brand: 'Godrej', value: 2 },
{ brand: 'HUL', value: 1 },
{ brand: 'XX', value: 2 },
],
},
{
tabId: 2,
section: 'Promoter details',
items: [
{ brand: 'Marico', value: 1 },
{ brand: 'Colgate', value: 1 },
{ brand: 'Godrej', value: 1 },
{ brand: 'HUL', value: 1 },
{ brand: 'XX', value: 0 },
],
},
];
const tabs = [
{ id: 0, title: 'Store Info' },
{ id: 1, title: 'Last visit details' },
{ id: 2, title: 'Competition' },
];
const RenderHeader = ({ columnCount }) => {
const colWidth = Screen.screenWidth * 0.95 / columnCount;
return (
<View style={{ flexDirection: 'row', paddingVertical: 6 }}>
<View style={{ width: colWidth }}>
<Text style={styles.subheaderText}>Brand</Text>
</View>
<View style={{ width: colWidth }}>
<Text style={styles.subheaderText}>Name</Text>
</View>
{columnCount === 3 && (
<View style={{ width: colWidth }}>
<Text style={styles.subheaderText}>Date</Text>
</View>
)}
</View>
);
};
const RenderItem = ({ item, columnCount }) => {
console.log("columnCount",columnCount)
const dynamicWidth = Screen.screenWidth * 0.95 / columnCount;
return (
<View>
<View style={styles.row}>
<View style={{ width: dynamicWidth}}>
<Text style={styles.brand}>{item.title || item.brand}:</Text>
</View>
<View style={{ width: dynamicWidth}}>
<Text style={styles.name}>{item.name || item.value}</Text>
</View>
{item.date && (
<View style={{ width: dynamicWidth}}>
<Text style={styles.date}>{item.date}</Text>
</View>
)}
</View>
<View style={[horizonalLine, { marginVertical: 4 }]} />
</View>
);
};
const SectionListView = ({ listData }) => (
<FlatList
data={listData}
keyExtractor={(item, index) => item.section + index}
contentContainerStyle={{ paddingBottom: 20 }}
ItemSeparatorComponent={() => <View style={{ paddingVertical: 5 }} />}
renderItem={({ item }) => {
const columnCount = item.items[0]?.date ? 3 : 2;
return (
<View style={styles.section}>
<Text style={styles.sectionTitle}>{item.section}</Text>
<View style={[horizonalLine, { marginVertical: 10 }]} />
<RenderHeader columnCount={columnCount} /> {/* Header Row */}
{item.items.map((subItem, index) => (
<RenderItem key={index} item={subItem} columnCount={columnCount} />
))}
</View>
);
}}
/>
);
const StoreInfo = () => {
const [selectedTab, setSelectedTab] = useState(0);
const filteredData = storeinfodata?.filter(item => item.tabId === selectedTab);
const selectedTabTitle = tabs.find(tab => tab.id === selectedTab)?.title ?? 'NA';
const renderTabContent = () => {
switch (selectedTab) {
case 0:
return <SectionListView listData={filteredData} />
case 1:
return <SectionListView listData={filteredData} />
case 2:
return <SectionListView listData={filteredData} />;
default:
return null;
}
};
return (
<View style={styles.container}>
<View style={styles.tabstyle}>
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
<View style={{ flexDirection: 'row' }}>
{tabs.map((tab) => (
<TouchableOpacity key={tab.id} style={styles.tabview} activeOpacity={1} onPress={() => setSelectedTab(tab.id)}>
<View style={selectedTab === tab.id ? styles.selecttabView : styles.unselecttabView}>
<Text style={[styles.tabtext,selectedTab === tab.id ? styles.selecttabText : styles.unselecttabText]}>
{tab.title}
</Text>
</View>
</TouchableOpacity>
))}
</View>
</ScrollView>
</View>
<ScrollView horizontal={false} style={{ flex: 1 }}>
<Text style={styles.headerText}>{selectedTabTitle} </Text>
<View style={{ width: '100%' }}>{renderTabContent()}</View>
</ScrollView>
</View>
);
};
export default StoreInfo;
+210
View File
@@ -0,0 +1,210 @@
import React, { useState , useRef} from 'react';
import {View,Text,TouchableOpacity,ScrollView,FlatList} from 'react-native';
import { styles } from './style';
import { horizonalLine, Screen } from '../../../theme/theme';
const storeinfodata = [
{
tabId: 0,
section: 'Store details',
items: [
{ brand: 'Store Name', name: 'Reliance Smart' },
{ brand: 'Store ID', name: '#98440' },
{ brand: 'Address', name: 'Rabindra Nagar, Delhi 110003' },
{ brand: 'City', name: 'Okhla' },
{ brand: 'Store Size', name: '15002000 sq ft' },
{ brand: 'Average Footfall', name: '10000' },
{ brand: 'Store age', name: '8' },
{ brand: 'Store Ranking', name: '24' },
],
},
{
tabId: 0,
section: 'Dabur Employees',
items: [
{ brand: 'RKAM', name: 'Rajesh Paal Singh' },
{ brand: 'SO', name: 'Soniya Singhal' },
],
},
{
tabId: 0,
section: '3P employees',
items: [
{ brand: 'Promoter Name', name: 'Payal Singh' },
{ brand: 'AM Name', name: 'Soniya Singhal' },
{ brand: 'Supervisor Name', name: 'Soniya Dhankar' },
{ brand: 'City', name: 'Okhla' },
{ brand: 'Promoter duration', name: '2 Year 7 months' },
{ brand: 'Average incentive', name: '5000' },
],
},
// Last Visit Details (tabId: 1)
{
tabId: 1,
section: 'Dabur employee',
items: [
{ brand: 'SO', name: 'Rajesh Paal Singh', date: '23/05/2025' , test : 'gxsjhxbas' },
{ brand: 'AH', name: 'Umesh Singh', date: '18/04/2025' },
{ brand: 'KAM', name: 'Rahul Tawde', date: '15/05/2025' },
{ brand: 'Others', name: 'Singhal Singh', date: '06/05/2025' },
],
},
{
tabId: 1,
section: '3P team',
items: [
{ brand: 'Supervisor', name: 'Ashish Talwar', date: '27/05/2025' },
{ brand: 'AM', name: 'Soniya Singhal', date: '23/05/2025' },
],
},
// Competition (tabId: 2)
{
tabId: 2,
section: 'Competition assets',
items: [
{ brand: 'Marico', value: 5 },
{ brand: 'Colgate', value: 1 },
{ brand: 'Godrej', value: 2 },
{ brand: 'HUL', value: 1 },
{ brand: 'XX', value: 2 },
],
},
{
tabId: 2,
section: 'Promoter details',
items: [
{ brand: 'Marico', value: 1 },
{ brand: 'Colgate', value: 1 },
{ brand: 'Godrej', value: 1 },
{ brand: 'HUL', value: 1 },
{ brand: 'XX', value: 0 },
],
},
];
const tabs = [
{ id: 0, title: 'Store Info' },
{ id: 1, title: 'Last visit details' },
{ id: 2, title: 'Competition' },
];
const RenderHeader = ({ columns }) => {
const colWidth = Screen.screenWidth * 0.95 / columns?.length;
return (
<View style={{ flexDirection: 'row', paddingVertical: 6 }}>
{columns.map((col, index) => (
<View key={index} style={{ width: colWidth }}>
<Text style={styles.subheaderText}>{col.toUpperCase()}</Text>
</View>
))}
</View>
);
};
const RenderItem = ({ item, columns }) => {
const colWidth = Screen.screenWidth * 0.95 / columns?.length;
return (
<View>
<View style={styles.row}>
{columns.map((key, index) => (
<View key={index} style={{ width: colWidth }}>
<Text style={styles.name}>{String(item[key] ?? '')}</Text>
</View>
))}
</View>
<View style={[horizonalLine, { marginVertical: 4 }]} />
</View>
);
};
const SectionListView = ({ listData }) => {
const scrollRef = useRef(null); // shared horizontal scroll ref
return (
<FlatList
data={listData}
keyExtractor={(item, index) => item.section + index}
contentContainerStyle={{ paddingBottom: 20 }}
ItemSeparatorComponent={() => <View style={{ paddingVertical: 5 }} />}
renderItem={({ item }) => {
const columns = Object.keys(item.items[0] || {}).filter(
key => item.items.some(obj => obj[key] !== undefined && obj[key] !== null)
);
return (
<View style={styles.section}>
<Text style={styles.sectionTitle}>{item.section}</Text>
<View style={[horizonalLine, { marginVertical: 10 }]} />
{/* Shared horizontal scroll view for header + rows */}
<ScrollView
horizontal
ref={scrollRef}
showsHorizontalScrollIndicator={false}
scrollEventThrottle={16}
>
<View>
<RenderHeader columns={columns} />
{item.items.map((subItem, index) => (
<RenderItem key={index} item={subItem} columns={columns} />
))}
</View>
</ScrollView>
</View>
);
}}
/>
);
};
const StoreInfo = () => {
const [selectedTab, setSelectedTab] = useState(0);
const filteredData = storeinfodata?.filter(item => item.tabId === selectedTab);
const selectedTabTitle = tabs?.find(tab => tab.id === selectedTab)?.title ?? 'NA';
const renderTabContent = () => {
switch (selectedTab) {
case 0:
return <SectionListView listData={filteredData} />
case 1:
return <SectionListView listData={filteredData} />
case 2:
return <SectionListView listData={filteredData} />;
default:
return null;
}
};
return (
<View style={styles.container}>
<View style={styles.tabstyle}>
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
<View style={{ flexDirection: 'row' }}>
{tabs?.map((tab) => (
<TouchableOpacity key={tab.id} style={styles.tabview} activeOpacity={1} onPress={() => setSelectedTab(tab.id)}>
<View style={selectedTab === tab.id ? styles.selecttabView : styles.unselecttabView}>
<Text style={[styles.tabtext,selectedTab === tab.id ? styles.selecttabText : styles.unselecttabText]}>
{tab.title}
</Text>
</View>
</TouchableOpacity>
))}
</View>
</ScrollView>
</View>
<ScrollView horizontal={false} style={{ flex: 1 }}>
<Text style={styles.headerText}>{selectedTabTitle} </Text>
<View style={{ width: '100%' }}>{renderTabContent()}</View>
</ScrollView>
</View>
);
};
export default StoreInfo;
+111
View File
@@ -0,0 +1,111 @@
import { StyleSheet } from 'react-native';
import { GlobalTheme, Screen, shadow } from '../../../theme';
export const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: GlobalTheme.colors.white,
paddingHorizontal: 10
},
// tabs
tabview: {
alignItems: 'center',
justifyContent: 'space-between',
marginVertical: 10,
flexDirection: 'row',
},
tabstyle: {
flexDirection: 'row',
justifyContent: 'space-between',
borderColor: GlobalTheme.colors.lightblue,
borderWidth: 1.5,
borderRadius: GlobalTheme.borderRadius.xxlg,
marginTop: 10,
paddingHorizontal: 10,
},
tabtext: {
overflow: 'hidden',
},
selecttabView: {
backgroundColor: GlobalTheme.colors.primary,
paddingVertical: 8,
paddingHorizontal: 15,
borderRadius: GlobalTheme.borderRadius.lgg
},
selecttabText: {
color: GlobalTheme.colors.white,
fontSize: GlobalTheme.typography.fontSize.small,
fontWeight: GlobalTheme.typography.fontWeight.regular,
textAlign: 'center'
},
unselecttabView: {
paddingVertical: 8,
paddingHorizontal: 15,
borderRadius: GlobalTheme.borderRadius.md
},
unselecttabText: {
color: GlobalTheme.colors.lightbluetext,
fontSize: GlobalTheme.typography.fontSize.xsmall,
fontWeight: GlobalTheme.typography.fontWeight.regular,
textAlign: 'center'
},
// comp
section: {
backgroundColor: GlobalTheme.colors.white,
padding: 12,
marginHorizontal: 5,
borderRadius: 8,
elevation: 2,
width: Screen.screenWidth * 0.92,
marginVertical: 5,
borderWidth: 1,
borderColor: GlobalTheme.colors.lightblueborder,
// ...shadow,
},
sectionTitle: {
fontWeight: GlobalTheme.typography.fontWeight.bold,
fontSize: GlobalTheme.typography.fontSize.small,
},
row: {
flexDirection: 'row',
justifyContent: 'space-between',
paddingVertical: 4
},
brand: {
fontSize: GlobalTheme.typography.fontSize.xsmall,
color: GlobalTheme.colors.black,
fontWeight: GlobalTheme.typography.fontWeight.medium,
},
value: {
fontSize: GlobalTheme.typography.fontSize.xsmall,
fontWeight: GlobalTheme.typography.fontWeight.medium,
},
name: {
fontSize: GlobalTheme.typography.fontSize.xsmall,
fontWeight: GlobalTheme.typography.fontWeight.regular,
flexWrap:'wrap'
},
date: {
fontSize: GlobalTheme.typography.fontSize.xsmall,
fontWeight: GlobalTheme.typography.fontWeight.regular,
flexWrap:'wrap'
},
subheaderText:{
fontSize: GlobalTheme.typography.fontSize.xsmall,
fontWeight: GlobalTheme.typography.fontWeight.regular,
flexWrap:'wrap',
color : GlobalTheme.colors.gray,
textTransform: 'capitalize',
},
headerText:{
fontSize: GlobalTheme.typography.fontSize.medium,
fontWeight: GlobalTheme.typography.fontWeight.medium,
flexWrap:'wrap',
color : GlobalTheme.colors.black,
paddingVertical:10,
paddingHorizontal:10
}
});
+2 -2
View File
@@ -1,4 +1,4 @@
import GlobalTheme from './theme';
import { shadow , Screen } from './theme';
import { shadow , Screen , horizonalLine } from './theme';
export {GlobalTheme, Screen , shadow};
export {GlobalTheme, Screen , shadow, horizonalLine};
+15 -5
View File
@@ -14,9 +14,10 @@ const GlobalTheme = {
// Primary Colors
primary: '#113F8C', // Main color for buttons, headers
secondary: '#2357C6',
lightbluetext:'#7F83AB',
text: '#333333', // Text color for most content
lightblue:'#EAF1FF',
lightblueborder:'#C6DBFF24',
lightblue:'#E2E7F2',
lightblueborder:'#ECECEC',
// Additional Colors
success: '#4caf50', // Success or positive action color
@@ -27,7 +28,7 @@ const GlobalTheme = {
// Grayscale
white: '#ffffff',
lightGray: '#F1F1F1',
gray: '#cccccc',
gray: '#676767',
darkGray: '#555555',
black: '#000000',
},
@@ -35,7 +36,8 @@ const GlobalTheme = {
// Define typography styles here (e.g., font family, sizes, line heights, etc.)
fontFamily: 'Regular',
fontSize: {
xsmall: 12,
xxsmall: 12,
xsmall :14,
small: 16,
medium: 18,
large: 20,
@@ -61,6 +63,8 @@ const GlobalTheme = {
lg: 15,
lgg: 20,
xlg: 25,
xxlg: 35,
},
// Add other global theme properties as needed
};
@@ -68,9 +72,15 @@ const GlobalTheme = {
export default GlobalTheme;
export const shadow = {
shadowColor: '#00000014',
shadowColor: '#00000029',
shadowOffset: {width: 5, height: 5},
shadowOpacity: 0.8,
shadowRadius: 10,
elevation: 20,
};
export const horizonalLine = {
backgroundColor :'#E2E7F2',
height:1.5,
width: '100%',
};