@propel-nsl/propel-react-native-sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/fonts/Lexend-Black.ttf +0 -0
- package/assets/fonts/Lexend-Bold.ttf +0 -0
- package/assets/fonts/Lexend-ExtraBold.ttf +0 -0
- package/assets/fonts/Lexend-ExtraLight.ttf +0 -0
- package/assets/fonts/Lexend-Light.ttf +0 -0
- package/assets/fonts/Lexend-Medium.ttf +0 -0
- package/assets/fonts/Lexend-Regular.ttf +0 -0
- package/assets/fonts/Lexend-SemiBold.ttf +0 -0
- package/assets/fonts/Lexend-Thin.ttf +0 -0
- package/assets/images/HomeGoods.png +0 -0
- package/assets/images/accessories.png +0 -0
- package/assets/images/amazon.png +0 -0
- package/assets/images/apnaClubLogo.png +0 -0
- package/assets/images/apparel.png +0 -0
- package/assets/images/backgroundblue.png +0 -0
- package/assets/images/bannerCard.png +0 -0
- package/assets/images/bottomWave.png +0 -0
- package/assets/images/coin_1_1.png +0 -0
- package/assets/images/flipkart.png +0 -0
- package/assets/images/frame_1171278967.png +0 -0
- package/assets/images/gift.png +0 -0
- package/assets/images/herobanner.png +0 -0
- package/assets/images/hinduPencilsLogo.png +0 -0
- package/assets/images/icons/addwhiteicon.png +0 -0
- package/assets/images/icons/arrow-back.png +0 -0
- package/assets/images/icons/arrowgreen.png +0 -0
- package/assets/images/icons/arrowred.png +0 -0
- package/assets/images/icons/arrowright.png +0 -0
- package/assets/images/icons/arrowup.png +0 -0
- package/assets/images/icons/blackarrowdown.png +0 -0
- package/assets/images/icons/blackarrowup.png +0 -0
- package/assets/images/icons/blackcross.png +0 -0
- package/assets/images/icons/call.png +0 -0
- package/assets/images/icons/camera.png +0 -0
- package/assets/images/icons/cart.png +0 -0
- package/assets/images/icons/chat.png +0 -0
- package/assets/images/icons/circleblack.png +0 -0
- package/assets/images/icons/copy.png +0 -0
- package/assets/images/icons/cross.png +0 -0
- package/assets/images/icons/delete.png +0 -0
- package/assets/images/icons/delivery.png +0 -0
- package/assets/images/icons/eVoucher.png +0 -0
- package/assets/images/icons/editIcon.png +0 -0
- package/assets/images/icons/email.png +0 -0
- package/assets/images/icons/eye.png +0 -0
- package/assets/images/icons/faq.png +0 -0
- package/assets/images/icons/filtericon.png +0 -0
- package/assets/images/icons/greyDownArrow.png +0 -0
- package/assets/images/icons/help.png +0 -0
- package/assets/images/icons/home.png +0 -0
- package/assets/images/icons/homeinactive.png +0 -0
- package/assets/images/icons/i_blackicon.png +0 -0
- package/assets/images/icons/i_icon.png +0 -0
- package/assets/images/icons/location.png +0 -0
- package/assets/images/icons/logout.png +0 -0
- package/assets/images/icons/minus.png +0 -0
- package/assets/images/icons/myOrders.png +0 -0
- package/assets/images/icons/orders.png +0 -0
- package/assets/images/icons/pencillogo.png +0 -0
- package/assets/images/icons/pending.png +0 -0
- package/assets/images/icons/plus.png +0 -0
- package/assets/images/icons/redCross.png +0 -0
- package/assets/images/icons/redCrossicon.png +0 -0
- package/assets/images/icons/redWarningicon.png +0 -0
- package/assets/images/icons/redeem.png +0 -0
- package/assets/images/icons/redeemactive.png +0 -0
- package/assets/images/icons/redemptionHistory.png +0 -0
- package/assets/images/icons/redhelpicon.png +0 -0
- package/assets/images/icons/search.png +0 -0
- package/assets/images/icons/stopwatch.png +0 -0
- package/assets/images/icons/successTick.gif +0 -0
- package/assets/images/icons/tick.png +0 -0
- package/assets/images/icons/tnc.png +0 -0
- package/assets/images/icons/user.png +0 -0
- package/assets/images/icons/userredicon.png +0 -0
- package/assets/images/icons/wavecorner.png +0 -0
- package/assets/images/logo.png +0 -0
- package/assets/images/myntra_copy.png +0 -0
- package/assets/images/nike.png +0 -0
- package/assets/images/oq3p0u0_1.png +0 -0
- package/assets/images/profileicon.png +0 -0
- package/assets/images/topWave.png +0 -0
- package/assets/images/zagglePropelLogo.png +0 -0
- package/index.ts +23 -0
- package/lib/index.ts +25 -0
- package/package.json +70 -0
- package/src/PropelSDKScreen.tsx +98 -0
- package/src/SDKApp.tsx +540 -0
- package/src/bridge/SDKBridge.ts +104 -0
- package/src/bridge/index.ts +3 -0
- package/src/components/SDKBackHandler.tsx +187 -0
- package/src/components/SDKProfile.tsx +87 -0
- package/src/components/SDKProfileWrapper.tsx +51 -0
- package/src/constants.ts +10 -0
- package/src/contexts/SDKContext.tsx +72 -0
- package/src/hooks/useSDKBackNavigation.ts +61 -0
- package/src/navigation/SDKMainTabNavigator.tsx +315 -0
- package/src/navigation/SDKNavigator.tsx +41 -0
- package/src/redux/store.ts +32 -0
- package/src/screens/Dashboard/index.tsx +531 -0
- package/src/screens/Dashboard/styles.ts +512 -0
- package/src/screens/DeliveryAddress/index.tsx +221 -0
- package/src/screens/DeliveryAddress/styles.ts +122 -0
- package/src/screens/E-Vouchers/index.tsx +157 -0
- package/src/screens/E-Vouchers/styles.ts +106 -0
- package/src/screens/Faq/Faq.constants.ts +164 -0
- package/src/screens/Faq/index.tsx +114 -0
- package/src/screens/Faq/styles.ts +131 -0
- package/src/screens/Help/index.tsx +128 -0
- package/src/screens/Help/styles.ts +121 -0
- package/src/screens/Login/index.tsx +215 -0
- package/src/screens/Login/styles.ts +134 -0
- package/src/screens/MyCart/MyCart.constants.ts +13 -0
- package/src/screens/MyCart/index.tsx +318 -0
- package/src/screens/MyCart/styles.ts +249 -0
- package/src/screens/MyOrders/index.tsx +87 -0
- package/src/screens/MyOrders/styles.ts +281 -0
- package/src/screens/MyProfile/index.tsx +72 -0
- package/src/screens/MyProfile/styles.ts +47 -0
- package/src/screens/NewDeliveryAddress/index.tsx +360 -0
- package/src/screens/NewDeliveryAddress/styles.ts +68 -0
- package/src/screens/Onboarding/index.tsx +57 -0
- package/src/screens/Onboarding/styles.ts +60 -0
- package/src/screens/OrdersDetails/index.tsx +333 -0
- package/src/screens/OrdersDetails/styles.ts +262 -0
- package/src/screens/OtpVerification/index.tsx +283 -0
- package/src/screens/OtpVerification/styles.ts +197 -0
- package/src/screens/PaymentMethod/index.tsx +389 -0
- package/src/screens/PaymentMethod/styles.ts +246 -0
- package/src/screens/PointsLog/index.tsx +286 -0
- package/src/screens/PointsLog/styles.ts +156 -0
- package/src/screens/ProductDetails/index.tsx +682 -0
- package/src/screens/ProductDetails/styles.ts +372 -0
- package/src/screens/Profile/index.tsx +368 -0
- package/src/screens/Profile/styles.ts +158 -0
- package/src/screens/RedemptionHistory/RedemptionHistory.constants.ts +4 -0
- package/src/screens/RedemptionHistory/index.tsx +304 -0
- package/src/screens/RedemptionHistory/styles.ts +84 -0
- package/src/screens/Reedem/index.tsx +345 -0
- package/src/screens/Reedem/styles.ts +269 -0
- package/src/screens/TnC/TnC.constants.ts +169 -0
- package/src/screens/TnC/index.tsx +83 -0
- package/src/screens/TnC/styles.ts +88 -0
- package/src/screens/TransactionSuccessful/index.tsx +77 -0
- package/src/screens/TransactionSuccessful/styles.ts +77 -0
- package/src/screens/Verification/index.tsx +58 -0
- package/src/screens/Verification/styles.ts +74 -0
- package/src/screens/index.ts +23 -0
- package/src/types/index.ts +46 -0
- package/src-app/components/AmountBreakDownModal/index.tsx +86 -0
- package/src-app/components/AmountBreakDownModal/styles.ts +110 -0
- package/src-app/components/BottomNavIcons.tsx +125 -0
- package/src-app/components/Button.tsx +120 -0
- package/src-app/components/Card.tsx +47 -0
- package/src-app/components/ConfirmPopup/ConfirmPopup.constants.ts +25 -0
- package/src-app/components/ConfirmPopup/index.tsx +48 -0
- package/src-app/components/ConfirmPopup/styles.ts +167 -0
- package/src-app/components/CustomButton/index.tsx +67 -0
- package/src-app/components/CustomButton/styles.ts +44 -0
- package/src-app/components/CustomCard/index.tsx +221 -0
- package/src-app/components/CustomCard/styles.ts +184 -0
- package/src-app/components/CustomError/index.tsx +54 -0
- package/src-app/components/CustomError/styles.ts +41 -0
- package/src-app/components/CustomImage/index.tsx +37 -0
- package/src-app/components/CustomImage/styles.ts +5 -0
- package/src-app/components/CustomLoader/index.tsx +45 -0
- package/src-app/components/CustomLoader/styles.ts +35 -0
- package/src-app/components/CustomMessagePopUp/index.tsx +51 -0
- package/src-app/components/CustomMessagePopUp/styles.ts +74 -0
- package/src-app/components/CustomProductCard/index.tsx +13 -0
- package/src-app/components/CustomProductCard/styles.ts +5 -0
- package/src-app/components/FilterModal.tsx +372 -0
- package/src-app/components/Footer/index.tsx +23 -0
- package/src-app/components/Footer/styles.ts +37 -0
- package/src-app/components/Icon.tsx +80 -0
- package/src-app/components/Logout/index.tsx +82 -0
- package/src-app/components/Logout/styles.ts +116 -0
- package/src-app/components/MobileHeader.tsx +141 -0
- package/src-app/components/NoDataFound/index.tsx +18 -0
- package/src-app/components/NoDataFound/styles.ts +26 -0
- package/src-app/components/OTPModal.tsx +747 -0
- package/src-app/components/ProfileField.tsx +47 -0
- package/src-app/components/QuantityModal/index.tsx +113 -0
- package/src-app/components/QuantityModal/styles.ts +84 -0
- package/src-app/components/TabBarIcons.tsx +110 -0
- package/src-app/components/TextInput.tsx +79 -0
- package/src-app/components/ToastConfig.tsx +60 -0
- package/src-app/components/index.ts +18 -0
- package/src-app/config/env.ts +22 -0
- package/src-app/constants/Fonts.ts +12 -0
- package/src-app/constants/Formatter.ts +39 -0
- package/src-app/constants/HtmlSanitization.ts +46 -0
- package/src-app/constants/Images.ts +81 -0
- package/src-app/constants/Labels.ts +8 -0
- package/src-app/constants/Messages.ts +108 -0
- package/src-app/constants/Routes.ts +17 -0
- package/src-app/constants/Scaling.ts +5 -0
- package/src-app/constants/Text.ts +8 -0
- package/src-app/constants/offSets.ts +18 -0
- package/src-app/hooks/useAppDispatch.ts +4 -0
- package/src-app/hooks/useAppSelector.ts +4 -0
- package/src-app/hooks/useBackHandler.ts +47 -0
- package/src-app/hooks/useScreenBackHandler.ts +91 -0
- package/src-app/navigation/AppNavigator.tsx +34 -0
- package/src-app/navigation/MainTabNavigator.tsx +294 -0
- package/src-app/redux/authSaga.ts +605 -0
- package/src-app/redux/authSlice.ts +754 -0
- package/src-app/redux/rootSaga.ts +6 -0
- package/src-app/redux/store.ts +25 -0
- package/src-app/services/api.ts +14 -0
- package/src-app/services/endpoints.ts +33 -0
- package/src-app/services/index.ts +574 -0
- package/src-app/services/sdkCredentials.ts +44 -0
- package/src-app/styles/colors.ts +85 -0
- package/src-app/styles/shared.ts +112 -0
- package/src-app/types/authTypes.ts +155 -0
- package/src-app/types/navigation.ts +99 -0
- package/src-app/utils/Validation.ts +48 -0
- package/src-app/utils/filterPins.ts +29 -0
- package/src-app/utils/navigationUtils.ts +43 -0
- package/src-app/utils/useHardwareBack.ts +21 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK Main Tab Navigator
|
|
3
|
+
*
|
|
4
|
+
* Architecture: Tab Navigator with hidden screens + integrated back handler
|
|
5
|
+
*
|
|
6
|
+
* All screens are registered as tabs (some hidden) so navigation.navigate() works
|
|
7
|
+
* from any screen. Back handler is integrated to handle hardware back press.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import React from 'react';
|
|
11
|
+
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
|
12
|
+
import { createStackNavigator } from '@react-navigation/stack';
|
|
13
|
+
import { View, StyleSheet, Dimensions, Platform, Keyboard, TouchableOpacity, Text } from 'react-native';
|
|
14
|
+
import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
15
|
+
import { useNavigation, CommonActions, getFocusedRouteNameFromRoute } from '@react-navigation/native';
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
Dashboard,
|
|
19
|
+
DeliveryAddress,
|
|
20
|
+
FAQ,
|
|
21
|
+
Help,
|
|
22
|
+
MyCart,
|
|
23
|
+
MyEVouchers,
|
|
24
|
+
MyOrders,
|
|
25
|
+
NewDeliveryAddress,
|
|
26
|
+
PaymentMethod,
|
|
27
|
+
PointsLog,
|
|
28
|
+
ProductDetail,
|
|
29
|
+
Redeem,
|
|
30
|
+
RedemptionHistory,
|
|
31
|
+
TnC,
|
|
32
|
+
TransactionSuccessful,
|
|
33
|
+
} from '../screens';
|
|
34
|
+
import OrderDetails from '../screens/OrdersDetails';
|
|
35
|
+
import { CustomImage } from 'src-app/components';
|
|
36
|
+
import Images from 'src-app/constants/Images';
|
|
37
|
+
import { SCALE, VSCALE } from 'src-app/constants/Scaling';
|
|
38
|
+
import SDKProfileWrapper from '../components/SDKProfileWrapper';
|
|
39
|
+
|
|
40
|
+
const Tab = createBottomTabNavigator<any>();
|
|
41
|
+
const Stack = createStackNavigator<any>();
|
|
42
|
+
|
|
43
|
+
const { height: screenHeight, width: screenWidth } = Dimensions.get('window');
|
|
44
|
+
|
|
45
|
+
// Main visible tabs
|
|
46
|
+
const MAIN_TABS = ['DashboardTab', 'Redeem', 'Profile', 'Help'];
|
|
47
|
+
|
|
48
|
+
// Hidden screens (registered as tabs but not shown in tab bar)
|
|
49
|
+
const HIDDEN_SCREENS = [
|
|
50
|
+
'RedemptionHistory', 'MyOrders', 'OrderDetails', 'FAQ', 'TnC',
|
|
51
|
+
'ProductDetail', 'MyEVouchers', 'MyCart', 'PointsLog',
|
|
52
|
+
'DeliveryAddress', 'NewDeliveryAddress', 'PaymentMethod', 'TransactionSuccessful'
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
const getTabBarHeight = (): number => {
|
|
56
|
+
if (Platform.OS === 'ios') {
|
|
57
|
+
return screenHeight > 800 ? VSCALE(40) : VSCALE(45);
|
|
58
|
+
}
|
|
59
|
+
if (Platform.OS === 'android') {
|
|
60
|
+
return screenHeight > 800 ? VSCALE(35) : VSCALE(55);
|
|
61
|
+
}
|
|
62
|
+
return VSCALE(50);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// DashboardStack - contains Dashboard and its nested screens
|
|
66
|
+
const DashboardStack = () => (
|
|
67
|
+
<Stack.Navigator screenOptions={{ headerShown: false, gestureEnabled: false }}>
|
|
68
|
+
<Stack.Screen name="Dashboard" component={Dashboard} />
|
|
69
|
+
<Stack.Screen name="RedemptionHistory" component={RedemptionHistory} />
|
|
70
|
+
<Stack.Screen name="MyOrders" component={MyOrders} />
|
|
71
|
+
<Stack.Screen name="OrderDetails" component={OrderDetails as any} />
|
|
72
|
+
<Stack.Screen name="FAQ" component={FAQ} />
|
|
73
|
+
<Stack.Screen name="TnC" component={TnC} />
|
|
74
|
+
<Stack.Screen name="ProductDetail" component={ProductDetail} />
|
|
75
|
+
<Stack.Screen name="MyEVouchers" component={MyEVouchers} />
|
|
76
|
+
<Stack.Screen name="MyCart" component={MyCart} />
|
|
77
|
+
<Stack.Screen name="PointsLog" component={PointsLog} />
|
|
78
|
+
<Stack.Screen name="DeliveryAddress" component={DeliveryAddress} />
|
|
79
|
+
<Stack.Screen name="NewDeliveryAddress" component={NewDeliveryAddress as any} />
|
|
80
|
+
<Stack.Screen name="PaymentMethod" component={PaymentMethod} />
|
|
81
|
+
<Stack.Screen name="TransactionSuccessful" component={TransactionSuccessful} />
|
|
82
|
+
</Stack.Navigator>
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
// Custom Tab Bar Component - only shows 4 main tabs
|
|
86
|
+
const CustomTabBar = ({ state, descriptors, navigation }: any) => {
|
|
87
|
+
const insets = useSafeAreaInsets();
|
|
88
|
+
const iconSize = SCALE(18);
|
|
89
|
+
|
|
90
|
+
// Filter to only show main tabs
|
|
91
|
+
const visibleRoutes = state.routes.filter((route: any) => MAIN_TABS.includes(route.name));
|
|
92
|
+
|
|
93
|
+
const getIcon = (routeName: string, focused: boolean) => {
|
|
94
|
+
if (routeName === 'DashboardTab') {
|
|
95
|
+
return focused ? Images.homeActive : Images.homeInactive;
|
|
96
|
+
}
|
|
97
|
+
if (routeName === 'Redeem') {
|
|
98
|
+
return focused ? Images.redeemActive : Images.redeemInactive;
|
|
99
|
+
}
|
|
100
|
+
if (routeName === 'Profile') {
|
|
101
|
+
return focused ? Images.userRed : Images.user;
|
|
102
|
+
}
|
|
103
|
+
if (routeName === 'Help') {
|
|
104
|
+
return focused ? Images.help : Images.help;
|
|
105
|
+
}
|
|
106
|
+
return Images.homeInactive;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const getLabel = (routeName: string) => {
|
|
110
|
+
if (routeName === 'DashboardTab') return 'Home';
|
|
111
|
+
if (routeName === 'Redeem') return 'Redeem';
|
|
112
|
+
if (routeName === 'Profile') return 'My Account';
|
|
113
|
+
if (routeName === 'Help') return 'Help';
|
|
114
|
+
return routeName;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<View style={[styles.customTabBar, {
|
|
119
|
+
paddingBottom: Math.max(VSCALE(8), insets.bottom + VSCALE(4)),
|
|
120
|
+
height: getTabBarHeight() + Math.max(insets.bottom, VSCALE(8)),
|
|
121
|
+
}]}>
|
|
122
|
+
{visibleRoutes.map((route: any) => {
|
|
123
|
+
const originalIndex = state.routes.findIndex((r: any) => r.key === route.key);
|
|
124
|
+
const isFocused = state.index === originalIndex;
|
|
125
|
+
|
|
126
|
+
const onPress = () => {
|
|
127
|
+
const event = navigation.emit({
|
|
128
|
+
type: 'tabPress',
|
|
129
|
+
target: route.key,
|
|
130
|
+
canPreventDefault: true,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
if (!isFocused && !event.defaultPrevented) {
|
|
134
|
+
// Reset DashboardTab to Dashboard screen when switching to it
|
|
135
|
+
if (route.name === 'DashboardTab') {
|
|
136
|
+
navigation.dispatch(
|
|
137
|
+
CommonActions.navigate({
|
|
138
|
+
name: 'DashboardTab',
|
|
139
|
+
params: { screen: 'Dashboard' },
|
|
140
|
+
})
|
|
141
|
+
);
|
|
142
|
+
} else {
|
|
143
|
+
navigation.navigate(route.name);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<TouchableOpacity
|
|
150
|
+
key={route.key}
|
|
151
|
+
activeOpacity={0.7}
|
|
152
|
+
onPress={onPress}
|
|
153
|
+
style={styles.tabItem}
|
|
154
|
+
>
|
|
155
|
+
<View style={styles.tabItemContent}>
|
|
156
|
+
<CustomImage
|
|
157
|
+
source={getIcon(route.name, isFocused)}
|
|
158
|
+
imgStyle={{ width: iconSize, height: iconSize }}
|
|
159
|
+
/>
|
|
160
|
+
<Text
|
|
161
|
+
style={[
|
|
162
|
+
styles.tabLabel,
|
|
163
|
+
{ color: isFocused ? '#DC291E' : '#1F2937' }
|
|
164
|
+
]}
|
|
165
|
+
>
|
|
166
|
+
{getLabel(route.name)}
|
|
167
|
+
</Text>
|
|
168
|
+
</View>
|
|
169
|
+
</TouchableOpacity>
|
|
170
|
+
);
|
|
171
|
+
})}
|
|
172
|
+
</View>
|
|
173
|
+
);
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
interface SDKMainTabNavigatorProps {
|
|
177
|
+
initialTab?: string;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const SDKMainTabNavigator: React.FC<SDKMainTabNavigatorProps> = ({ initialTab }) => {
|
|
181
|
+
const [keyboardVisible, setKeyboardVisible] = React.useState(false);
|
|
182
|
+
|
|
183
|
+
// Determine initial route
|
|
184
|
+
const getInitialRouteName = (): string => {
|
|
185
|
+
if (!initialTab) return 'DashboardTab';
|
|
186
|
+
|
|
187
|
+
const normalized = initialTab.toLowerCase();
|
|
188
|
+
// Match dashboard variants
|
|
189
|
+
if (
|
|
190
|
+
normalized === 'dashboard' ||
|
|
191
|
+
normalized === 'dashboard-screen' ||
|
|
192
|
+
normalized === 'dashboard_screen' ||
|
|
193
|
+
normalized === 'dashboardscreen' ||
|
|
194
|
+
normalized === 'home'
|
|
195
|
+
) {
|
|
196
|
+
return 'DashboardTab';
|
|
197
|
+
}
|
|
198
|
+
// Match exact 'redeem' or redeem-screen variants, but NOT redemptionhistory/redemption-history
|
|
199
|
+
if (
|
|
200
|
+
normalized === 'redeem' ||
|
|
201
|
+
normalized === 'redeem-screen' ||
|
|
202
|
+
normalized === 'redeem_screen' ||
|
|
203
|
+
normalized === 'redeemscreen'
|
|
204
|
+
) {
|
|
205
|
+
return 'Redeem';
|
|
206
|
+
}
|
|
207
|
+
if (normalized === 'profile') {
|
|
208
|
+
return 'Profile';
|
|
209
|
+
}
|
|
210
|
+
if (normalized === 'help') {
|
|
211
|
+
return 'Help';
|
|
212
|
+
}
|
|
213
|
+
// For deep link targets like RedemptionHistory, keep DashboardTab as initial
|
|
214
|
+
// The deep link navigation in SDKApp.tsx will handle navigating to the target screen
|
|
215
|
+
return 'DashboardTab';
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const initialRouteName = getInitialRouteName();
|
|
219
|
+
|
|
220
|
+
// Keyboard listener
|
|
221
|
+
React.useEffect(() => {
|
|
222
|
+
const showListener = Keyboard.addListener('keyboardDidShow', () => setKeyboardVisible(true));
|
|
223
|
+
const hideListener = Keyboard.addListener('keyboardDidHide', () => setKeyboardVisible(false));
|
|
224
|
+
return () => {
|
|
225
|
+
showListener.remove();
|
|
226
|
+
hideListener.remove();
|
|
227
|
+
};
|
|
228
|
+
}, []);
|
|
229
|
+
|
|
230
|
+
return (
|
|
231
|
+
<SafeAreaView style={styles.container} edges={['bottom']}>
|
|
232
|
+
<View style={styles.mainContainer}>
|
|
233
|
+
<Tab.Navigator
|
|
234
|
+
initialRouteName={initialRouteName}
|
|
235
|
+
backBehavior="history"
|
|
236
|
+
tabBar={(props) => keyboardVisible ? null : <CustomTabBar {...props} />}
|
|
237
|
+
screenOptions={({ route }) => {
|
|
238
|
+
const routeName = getFocusedRouteNameFromRoute(route) ?? '';
|
|
239
|
+
const hideOnScreens = ['TnC', 'FAQ', 'TransactionSuccessful', 'RedemptionHistory', 'MyOrders', 'ProductDetail', 'MyCart', 'OrderDetails'];
|
|
240
|
+
|
|
241
|
+
return {
|
|
242
|
+
headerShown: false,
|
|
243
|
+
tabBarStyle: hideOnScreens.includes(routeName)
|
|
244
|
+
? { display: 'none' as const }
|
|
245
|
+
: undefined,
|
|
246
|
+
};
|
|
247
|
+
}}
|
|
248
|
+
>
|
|
249
|
+
{/* Main visible tabs */}
|
|
250
|
+
<Tab.Screen name="DashboardTab" component={DashboardStack} options={{ tabBarLabel: 'Home' }} />
|
|
251
|
+
<Tab.Screen name="Redeem" component={Redeem} options={{ tabBarLabel: 'Redeem' }} />
|
|
252
|
+
<Tab.Screen name="Profile" component={SDKProfileWrapper} options={{ tabBarLabel: 'My Account' }} />
|
|
253
|
+
<Tab.Screen name="Help" component={Help} options={{ tabBarLabel: 'Help' }} />
|
|
254
|
+
|
|
255
|
+
{/* Hidden screens - accessible via navigation but not shown in tab bar */}
|
|
256
|
+
<Tab.Screen name="RedemptionHistory" component={RedemptionHistory} options={{ tabBarButton: () => null }} />
|
|
257
|
+
<Tab.Screen name="MyOrders" component={MyOrders} options={{ tabBarButton: () => null }} />
|
|
258
|
+
<Tab.Screen name="OrderDetails" component={OrderDetails as any} options={{ tabBarButton: () => null }} />
|
|
259
|
+
<Tab.Screen name="FAQ" component={FAQ} options={{ tabBarButton: () => null }} />
|
|
260
|
+
<Tab.Screen name="TnC" component={TnC} options={{ tabBarButton: () => null }} />
|
|
261
|
+
<Tab.Screen name="ProductDetail" component={ProductDetail} options={{ tabBarButton: () => null }} />
|
|
262
|
+
<Tab.Screen name="MyEVouchers" component={MyEVouchers} options={{ tabBarButton: () => null }} />
|
|
263
|
+
<Tab.Screen name="MyCart" component={MyCart} options={{ tabBarButton: () => null }} />
|
|
264
|
+
<Tab.Screen name="PointsLog" component={PointsLog} options={{ tabBarButton: () => null }} />
|
|
265
|
+
<Tab.Screen name="DeliveryAddress" component={DeliveryAddress} options={{ tabBarButton: () => null }} />
|
|
266
|
+
<Tab.Screen name="NewDeliveryAddress" component={NewDeliveryAddress as any} options={{ tabBarButton: () => null }} />
|
|
267
|
+
<Tab.Screen name="PaymentMethod" component={PaymentMethod} options={{ tabBarButton: () => null }} />
|
|
268
|
+
<Tab.Screen name="TransactionSuccessful" component={TransactionSuccessful} options={{ tabBarButton: () => null }} />
|
|
269
|
+
</Tab.Navigator>
|
|
270
|
+
</View>
|
|
271
|
+
</SafeAreaView>
|
|
272
|
+
);
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
const styles = StyleSheet.create({
|
|
276
|
+
container: {
|
|
277
|
+
flex: 1,
|
|
278
|
+
backgroundColor: 'white',
|
|
279
|
+
width: screenWidth,
|
|
280
|
+
},
|
|
281
|
+
mainContainer: {
|
|
282
|
+
flex: 1,
|
|
283
|
+
backgroundColor: 'white',
|
|
284
|
+
width: screenWidth,
|
|
285
|
+
},
|
|
286
|
+
customTabBar: {
|
|
287
|
+
flexDirection: 'row',
|
|
288
|
+
width: screenWidth,
|
|
289
|
+
backgroundColor: '#FFFFFF',
|
|
290
|
+
borderTopWidth: 1,
|
|
291
|
+
borderTopColor: '#E5E7EB',
|
|
292
|
+
paddingTop: VSCALE(8),
|
|
293
|
+
},
|
|
294
|
+
tabItem: {
|
|
295
|
+
flex: 1,
|
|
296
|
+
alignItems: 'center',
|
|
297
|
+
justifyContent: 'center',
|
|
298
|
+
minHeight: VSCALE(45),
|
|
299
|
+
},
|
|
300
|
+
tabItemContent: {
|
|
301
|
+
alignItems: 'center',
|
|
302
|
+
justifyContent: 'center',
|
|
303
|
+
},
|
|
304
|
+
tabLabel: {
|
|
305
|
+
fontSize: SCALE(10),
|
|
306
|
+
marginTop: VSCALE(3),
|
|
307
|
+
fontWeight: '400',
|
|
308
|
+
},
|
|
309
|
+
iconContainer: {
|
|
310
|
+
justifyContent: 'center',
|
|
311
|
+
alignItems: 'center',
|
|
312
|
+
},
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
export default SDKMainTabNavigator;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK Navigator
|
|
3
|
+
*
|
|
4
|
+
* Navigation structure for the SDK.
|
|
5
|
+
* Uses a Stack Navigator wrapping SDKMainTabNavigator.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import { createStackNavigator } from '@react-navigation/stack';
|
|
10
|
+
import { SDKParams } from '../types';
|
|
11
|
+
import SDKMainTabNavigator from './SDKMainTabNavigator';
|
|
12
|
+
import SDKBackHandler from '../components/SDKBackHandler';
|
|
13
|
+
|
|
14
|
+
const Stack = createStackNavigator<any>();
|
|
15
|
+
|
|
16
|
+
interface SDKNavigatorProps {
|
|
17
|
+
initialParams: SDKParams;
|
|
18
|
+
initialRouteOverride?: string; // Override initial route for deep linking
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const SDKNavigator: React.FC<SDKNavigatorProps> = ({ initialParams, initialRouteOverride }) => {
|
|
22
|
+
console.log('🔍 SDKNavigator: initialRouteOverride=', initialRouteOverride);
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<SDKBackHandler>
|
|
26
|
+
<Stack.Navigator
|
|
27
|
+
screenOptions={{
|
|
28
|
+
headerShown: false,
|
|
29
|
+
gestureEnabled: false,
|
|
30
|
+
}}
|
|
31
|
+
initialRouteName="MainTabs"
|
|
32
|
+
>
|
|
33
|
+
<Stack.Screen name="MainTabs" options={{ gestureEnabled: false }}>
|
|
34
|
+
{() => <SDKMainTabNavigator initialTab={initialRouteOverride} />}
|
|
35
|
+
</Stack.Screen>
|
|
36
|
+
</Stack.Navigator>
|
|
37
|
+
</SDKBackHandler>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default SDKNavigator;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redux Store for SDK
|
|
3
|
+
*
|
|
4
|
+
* This is a copy/adaptation of the main app's store.
|
|
5
|
+
* The SDK should have its own isolated Redux store.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { configureStore } from '@reduxjs/toolkit';
|
|
9
|
+
import authReducer from 'src-app/redux/authSlice';
|
|
10
|
+
import rootSaga from 'src-app/redux/rootSaga';
|
|
11
|
+
|
|
12
|
+
const createSagaMiddleware = require('redux-saga').default;
|
|
13
|
+
const sagaMiddleware = createSagaMiddleware();
|
|
14
|
+
|
|
15
|
+
export const store = configureStore({
|
|
16
|
+
reducer: {
|
|
17
|
+
auth: authReducer,
|
|
18
|
+
},
|
|
19
|
+
middleware: getDefaultMiddleware =>
|
|
20
|
+
getDefaultMiddleware({
|
|
21
|
+
thunk: false,
|
|
22
|
+
serializableCheck: {
|
|
23
|
+
ignoredActions: ['auth/uploadProfileImageRequest'],
|
|
24
|
+
ignoredActionPaths: ['payload'],
|
|
25
|
+
},
|
|
26
|
+
}).concat(sagaMiddleware),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
sagaMiddleware.run(rootSaga);
|
|
30
|
+
|
|
31
|
+
export type RootState = ReturnType<typeof store.getState>;
|
|
32
|
+
export type AppDispatch = typeof store.dispatch;
|