@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.
Files changed (221) hide show
  1. package/assets/fonts/Lexend-Black.ttf +0 -0
  2. package/assets/fonts/Lexend-Bold.ttf +0 -0
  3. package/assets/fonts/Lexend-ExtraBold.ttf +0 -0
  4. package/assets/fonts/Lexend-ExtraLight.ttf +0 -0
  5. package/assets/fonts/Lexend-Light.ttf +0 -0
  6. package/assets/fonts/Lexend-Medium.ttf +0 -0
  7. package/assets/fonts/Lexend-Regular.ttf +0 -0
  8. package/assets/fonts/Lexend-SemiBold.ttf +0 -0
  9. package/assets/fonts/Lexend-Thin.ttf +0 -0
  10. package/assets/images/HomeGoods.png +0 -0
  11. package/assets/images/accessories.png +0 -0
  12. package/assets/images/amazon.png +0 -0
  13. package/assets/images/apnaClubLogo.png +0 -0
  14. package/assets/images/apparel.png +0 -0
  15. package/assets/images/backgroundblue.png +0 -0
  16. package/assets/images/bannerCard.png +0 -0
  17. package/assets/images/bottomWave.png +0 -0
  18. package/assets/images/coin_1_1.png +0 -0
  19. package/assets/images/flipkart.png +0 -0
  20. package/assets/images/frame_1171278967.png +0 -0
  21. package/assets/images/gift.png +0 -0
  22. package/assets/images/herobanner.png +0 -0
  23. package/assets/images/hinduPencilsLogo.png +0 -0
  24. package/assets/images/icons/addwhiteicon.png +0 -0
  25. package/assets/images/icons/arrow-back.png +0 -0
  26. package/assets/images/icons/arrowgreen.png +0 -0
  27. package/assets/images/icons/arrowred.png +0 -0
  28. package/assets/images/icons/arrowright.png +0 -0
  29. package/assets/images/icons/arrowup.png +0 -0
  30. package/assets/images/icons/blackarrowdown.png +0 -0
  31. package/assets/images/icons/blackarrowup.png +0 -0
  32. package/assets/images/icons/blackcross.png +0 -0
  33. package/assets/images/icons/call.png +0 -0
  34. package/assets/images/icons/camera.png +0 -0
  35. package/assets/images/icons/cart.png +0 -0
  36. package/assets/images/icons/chat.png +0 -0
  37. package/assets/images/icons/circleblack.png +0 -0
  38. package/assets/images/icons/copy.png +0 -0
  39. package/assets/images/icons/cross.png +0 -0
  40. package/assets/images/icons/delete.png +0 -0
  41. package/assets/images/icons/delivery.png +0 -0
  42. package/assets/images/icons/eVoucher.png +0 -0
  43. package/assets/images/icons/editIcon.png +0 -0
  44. package/assets/images/icons/email.png +0 -0
  45. package/assets/images/icons/eye.png +0 -0
  46. package/assets/images/icons/faq.png +0 -0
  47. package/assets/images/icons/filtericon.png +0 -0
  48. package/assets/images/icons/greyDownArrow.png +0 -0
  49. package/assets/images/icons/help.png +0 -0
  50. package/assets/images/icons/home.png +0 -0
  51. package/assets/images/icons/homeinactive.png +0 -0
  52. package/assets/images/icons/i_blackicon.png +0 -0
  53. package/assets/images/icons/i_icon.png +0 -0
  54. package/assets/images/icons/location.png +0 -0
  55. package/assets/images/icons/logout.png +0 -0
  56. package/assets/images/icons/minus.png +0 -0
  57. package/assets/images/icons/myOrders.png +0 -0
  58. package/assets/images/icons/orders.png +0 -0
  59. package/assets/images/icons/pencillogo.png +0 -0
  60. package/assets/images/icons/pending.png +0 -0
  61. package/assets/images/icons/plus.png +0 -0
  62. package/assets/images/icons/redCross.png +0 -0
  63. package/assets/images/icons/redCrossicon.png +0 -0
  64. package/assets/images/icons/redWarningicon.png +0 -0
  65. package/assets/images/icons/redeem.png +0 -0
  66. package/assets/images/icons/redeemactive.png +0 -0
  67. package/assets/images/icons/redemptionHistory.png +0 -0
  68. package/assets/images/icons/redhelpicon.png +0 -0
  69. package/assets/images/icons/search.png +0 -0
  70. package/assets/images/icons/stopwatch.png +0 -0
  71. package/assets/images/icons/successTick.gif +0 -0
  72. package/assets/images/icons/tick.png +0 -0
  73. package/assets/images/icons/tnc.png +0 -0
  74. package/assets/images/icons/user.png +0 -0
  75. package/assets/images/icons/userredicon.png +0 -0
  76. package/assets/images/icons/wavecorner.png +0 -0
  77. package/assets/images/logo.png +0 -0
  78. package/assets/images/myntra_copy.png +0 -0
  79. package/assets/images/nike.png +0 -0
  80. package/assets/images/oq3p0u0_1.png +0 -0
  81. package/assets/images/profileicon.png +0 -0
  82. package/assets/images/topWave.png +0 -0
  83. package/assets/images/zagglePropelLogo.png +0 -0
  84. package/index.ts +23 -0
  85. package/lib/index.ts +25 -0
  86. package/package.json +70 -0
  87. package/src/PropelSDKScreen.tsx +98 -0
  88. package/src/SDKApp.tsx +540 -0
  89. package/src/bridge/SDKBridge.ts +104 -0
  90. package/src/bridge/index.ts +3 -0
  91. package/src/components/SDKBackHandler.tsx +187 -0
  92. package/src/components/SDKProfile.tsx +87 -0
  93. package/src/components/SDKProfileWrapper.tsx +51 -0
  94. package/src/constants.ts +10 -0
  95. package/src/contexts/SDKContext.tsx +72 -0
  96. package/src/hooks/useSDKBackNavigation.ts +61 -0
  97. package/src/navigation/SDKMainTabNavigator.tsx +315 -0
  98. package/src/navigation/SDKNavigator.tsx +41 -0
  99. package/src/redux/store.ts +32 -0
  100. package/src/screens/Dashboard/index.tsx +531 -0
  101. package/src/screens/Dashboard/styles.ts +512 -0
  102. package/src/screens/DeliveryAddress/index.tsx +221 -0
  103. package/src/screens/DeliveryAddress/styles.ts +122 -0
  104. package/src/screens/E-Vouchers/index.tsx +157 -0
  105. package/src/screens/E-Vouchers/styles.ts +106 -0
  106. package/src/screens/Faq/Faq.constants.ts +164 -0
  107. package/src/screens/Faq/index.tsx +114 -0
  108. package/src/screens/Faq/styles.ts +131 -0
  109. package/src/screens/Help/index.tsx +128 -0
  110. package/src/screens/Help/styles.ts +121 -0
  111. package/src/screens/Login/index.tsx +215 -0
  112. package/src/screens/Login/styles.ts +134 -0
  113. package/src/screens/MyCart/MyCart.constants.ts +13 -0
  114. package/src/screens/MyCart/index.tsx +318 -0
  115. package/src/screens/MyCart/styles.ts +249 -0
  116. package/src/screens/MyOrders/index.tsx +87 -0
  117. package/src/screens/MyOrders/styles.ts +281 -0
  118. package/src/screens/MyProfile/index.tsx +72 -0
  119. package/src/screens/MyProfile/styles.ts +47 -0
  120. package/src/screens/NewDeliveryAddress/index.tsx +360 -0
  121. package/src/screens/NewDeliveryAddress/styles.ts +68 -0
  122. package/src/screens/Onboarding/index.tsx +57 -0
  123. package/src/screens/Onboarding/styles.ts +60 -0
  124. package/src/screens/OrdersDetails/index.tsx +333 -0
  125. package/src/screens/OrdersDetails/styles.ts +262 -0
  126. package/src/screens/OtpVerification/index.tsx +283 -0
  127. package/src/screens/OtpVerification/styles.ts +197 -0
  128. package/src/screens/PaymentMethod/index.tsx +389 -0
  129. package/src/screens/PaymentMethod/styles.ts +246 -0
  130. package/src/screens/PointsLog/index.tsx +286 -0
  131. package/src/screens/PointsLog/styles.ts +156 -0
  132. package/src/screens/ProductDetails/index.tsx +682 -0
  133. package/src/screens/ProductDetails/styles.ts +372 -0
  134. package/src/screens/Profile/index.tsx +368 -0
  135. package/src/screens/Profile/styles.ts +158 -0
  136. package/src/screens/RedemptionHistory/RedemptionHistory.constants.ts +4 -0
  137. package/src/screens/RedemptionHistory/index.tsx +304 -0
  138. package/src/screens/RedemptionHistory/styles.ts +84 -0
  139. package/src/screens/Reedem/index.tsx +345 -0
  140. package/src/screens/Reedem/styles.ts +269 -0
  141. package/src/screens/TnC/TnC.constants.ts +169 -0
  142. package/src/screens/TnC/index.tsx +83 -0
  143. package/src/screens/TnC/styles.ts +88 -0
  144. package/src/screens/TransactionSuccessful/index.tsx +77 -0
  145. package/src/screens/TransactionSuccessful/styles.ts +77 -0
  146. package/src/screens/Verification/index.tsx +58 -0
  147. package/src/screens/Verification/styles.ts +74 -0
  148. package/src/screens/index.ts +23 -0
  149. package/src/types/index.ts +46 -0
  150. package/src-app/components/AmountBreakDownModal/index.tsx +86 -0
  151. package/src-app/components/AmountBreakDownModal/styles.ts +110 -0
  152. package/src-app/components/BottomNavIcons.tsx +125 -0
  153. package/src-app/components/Button.tsx +120 -0
  154. package/src-app/components/Card.tsx +47 -0
  155. package/src-app/components/ConfirmPopup/ConfirmPopup.constants.ts +25 -0
  156. package/src-app/components/ConfirmPopup/index.tsx +48 -0
  157. package/src-app/components/ConfirmPopup/styles.ts +167 -0
  158. package/src-app/components/CustomButton/index.tsx +67 -0
  159. package/src-app/components/CustomButton/styles.ts +44 -0
  160. package/src-app/components/CustomCard/index.tsx +221 -0
  161. package/src-app/components/CustomCard/styles.ts +184 -0
  162. package/src-app/components/CustomError/index.tsx +54 -0
  163. package/src-app/components/CustomError/styles.ts +41 -0
  164. package/src-app/components/CustomImage/index.tsx +37 -0
  165. package/src-app/components/CustomImage/styles.ts +5 -0
  166. package/src-app/components/CustomLoader/index.tsx +45 -0
  167. package/src-app/components/CustomLoader/styles.ts +35 -0
  168. package/src-app/components/CustomMessagePopUp/index.tsx +51 -0
  169. package/src-app/components/CustomMessagePopUp/styles.ts +74 -0
  170. package/src-app/components/CustomProductCard/index.tsx +13 -0
  171. package/src-app/components/CustomProductCard/styles.ts +5 -0
  172. package/src-app/components/FilterModal.tsx +372 -0
  173. package/src-app/components/Footer/index.tsx +23 -0
  174. package/src-app/components/Footer/styles.ts +37 -0
  175. package/src-app/components/Icon.tsx +80 -0
  176. package/src-app/components/Logout/index.tsx +82 -0
  177. package/src-app/components/Logout/styles.ts +116 -0
  178. package/src-app/components/MobileHeader.tsx +141 -0
  179. package/src-app/components/NoDataFound/index.tsx +18 -0
  180. package/src-app/components/NoDataFound/styles.ts +26 -0
  181. package/src-app/components/OTPModal.tsx +747 -0
  182. package/src-app/components/ProfileField.tsx +47 -0
  183. package/src-app/components/QuantityModal/index.tsx +113 -0
  184. package/src-app/components/QuantityModal/styles.ts +84 -0
  185. package/src-app/components/TabBarIcons.tsx +110 -0
  186. package/src-app/components/TextInput.tsx +79 -0
  187. package/src-app/components/ToastConfig.tsx +60 -0
  188. package/src-app/components/index.ts +18 -0
  189. package/src-app/config/env.ts +22 -0
  190. package/src-app/constants/Fonts.ts +12 -0
  191. package/src-app/constants/Formatter.ts +39 -0
  192. package/src-app/constants/HtmlSanitization.ts +46 -0
  193. package/src-app/constants/Images.ts +81 -0
  194. package/src-app/constants/Labels.ts +8 -0
  195. package/src-app/constants/Messages.ts +108 -0
  196. package/src-app/constants/Routes.ts +17 -0
  197. package/src-app/constants/Scaling.ts +5 -0
  198. package/src-app/constants/Text.ts +8 -0
  199. package/src-app/constants/offSets.ts +18 -0
  200. package/src-app/hooks/useAppDispatch.ts +4 -0
  201. package/src-app/hooks/useAppSelector.ts +4 -0
  202. package/src-app/hooks/useBackHandler.ts +47 -0
  203. package/src-app/hooks/useScreenBackHandler.ts +91 -0
  204. package/src-app/navigation/AppNavigator.tsx +34 -0
  205. package/src-app/navigation/MainTabNavigator.tsx +294 -0
  206. package/src-app/redux/authSaga.ts +605 -0
  207. package/src-app/redux/authSlice.ts +754 -0
  208. package/src-app/redux/rootSaga.ts +6 -0
  209. package/src-app/redux/store.ts +25 -0
  210. package/src-app/services/api.ts +14 -0
  211. package/src-app/services/endpoints.ts +33 -0
  212. package/src-app/services/index.ts +574 -0
  213. package/src-app/services/sdkCredentials.ts +44 -0
  214. package/src-app/styles/colors.ts +85 -0
  215. package/src-app/styles/shared.ts +112 -0
  216. package/src-app/types/authTypes.ts +155 -0
  217. package/src-app/types/navigation.ts +99 -0
  218. package/src-app/utils/Validation.ts +48 -0
  219. package/src-app/utils/filterPins.ts +29 -0
  220. package/src-app/utils/navigationUtils.ts +43 -0
  221. package/src-app/utils/useHardwareBack.ts +21 -0
@@ -0,0 +1,747 @@
1
+ // import React, { useState, useRef, useEffect } from 'react';
2
+ // import {
3
+ // View,
4
+ // Text,
5
+ // StyleSheet,
6
+ // Modal,
7
+ // TouchableOpacity,
8
+ // Animated,
9
+ // TouchableWithoutFeedback,
10
+ // Dimensions,
11
+ // KeyboardAvoidingView,
12
+ // Platform,
13
+ // ScrollView,
14
+ // } from 'react-native';
15
+ // import { OtpInput } from 'react-native-otp-entry';
16
+ // import { useAppSelector } from '../hooks/useAppSelector';
17
+ // import { RootState } from '../redux/store';
18
+ // import CustomButton from './CustomButton';
19
+ // import FontFamily from '../constants/Fonts';
20
+ // import CustomError from './CustomError';
21
+ // import {
22
+ // DIDNT_RECEIVE_OTP,
23
+ // ENTER_4_DIGIT_CODE,
24
+ // OTP,
25
+ // OTP_DIGIT,
26
+ // OTP_LENGTH,
27
+ // OTP_SENT,
28
+ // RESEND_OTP,
29
+ // TEXT,
30
+ // } from '../constants/Messages';
31
+ // import { colors } from '../styles/colors';
32
+
33
+ // const { height: screenHeight } = Dimensions.get('window');
34
+
35
+ // interface OTPModalProps {
36
+ // visible: boolean;
37
+ // onClose: () => void;
38
+ // onVerify: (otp: string) => void;
39
+ // onNavigateToOrders: () => void;
40
+ // phoneNumber?: string;
41
+ // onResend?: () => void;
42
+ // resetOtpTrigger?: number;
43
+ // otpLength?: number;
44
+ // screen?: string;
45
+ // }
46
+
47
+ // function maskPhoneNumber(phone: string): string {
48
+ // if (!phone) return '';
49
+ // const clean = phone.replace(/\D/g, '');
50
+ // if (clean.length <= 4) return clean;
51
+ // if (clean.length <= 6) {
52
+ // return clean;
53
+ // }
54
+ // const first2 = clean.slice(0, 2);
55
+ // const last2 = clean.slice(-2);
56
+ // const maskedLength = clean.length - 4;
57
+ // return `${first2}${'*'.repeat(maskedLength)}${last2}`;
58
+ // }
59
+
60
+ // const OTPModal: React.FC<OTPModalProps> = ({
61
+ // visible,
62
+ // onClose,
63
+ // onVerify,
64
+ // onNavigateToOrders,
65
+ // phoneNumber,
66
+ // onResend,
67
+ // resetOtpTrigger,
68
+ // otpLength = 6,
69
+ // screen,
70
+ // }) => {
71
+ // const [countdown, setCountdown] = useState(60);
72
+ // const slideAnim = useRef(new Animated.Value(screenHeight)).current;
73
+ // const {
74
+ // mobileNumber: reduxMobileNumber,
75
+ // myOrdersValidateOtpError,
76
+ // validateEVouchersError,
77
+ // } = useAppSelector((state: RootState) => state.auth);
78
+ // const displayNumber = phoneNumber || reduxMobileNumber || '';
79
+ // const [newOtp, setNewOtp] = useState('');
80
+
81
+ // useEffect(() => {
82
+ // if (visible) {
83
+ // setCountdown(60);
84
+ // setNewOtp('');
85
+ // Animated.timing(slideAnim, {
86
+ // toValue: 0,
87
+ // duration: 300,
88
+ // useNativeDriver: true,
89
+ // }).start();
90
+ // } else {
91
+ // Animated.timing(slideAnim, {
92
+ // toValue: screenHeight,
93
+ // duration: 300,
94
+ // useNativeDriver: true,
95
+ // }).start();
96
+ // }
97
+ // }, [visible]);
98
+
99
+ // useEffect(() => {
100
+ // let timer: NodeJS.Timeout;
101
+ // if (visible && countdown > 0) {
102
+ // timer = setTimeout(() => setCountdown(countdown - 1), 1000);
103
+ // }
104
+ // return () => clearTimeout(timer);
105
+ // }, [visible, countdown]);
106
+
107
+ // const handleVerify = () => {
108
+ // onVerify(newOtp);
109
+ // };
110
+
111
+ // const handleResendOTP = () => {
112
+ // setCountdown(60);
113
+ // setNewOtp('');
114
+ // onResend?.();
115
+ // };
116
+
117
+ // const formatTime = (seconds: number) => {
118
+ // const mins = Math.floor(seconds / 60);
119
+ // const secs = seconds % 60;
120
+ // return `${mins.toString().padStart(2, '0')} : ${secs
121
+ // .toString()
122
+ // .padStart(2, '0')}`;
123
+ // };
124
+
125
+ // if (!visible) return null;
126
+
127
+ // return (
128
+ // <Modal
129
+ // transparent
130
+ // visible={visible}
131
+ // animationType="none"
132
+ // onRequestClose={onClose}
133
+ // statusBarTranslucent
134
+ // >
135
+ // <TouchableWithoutFeedback onPress={onClose}>
136
+ // <View style={styles.overlay}>
137
+ // <TouchableWithoutFeedback>
138
+ // {/* ⬇️ KeyboardAvoidingView makes the sheet rise with the keyboard */}
139
+ // <KeyboardAvoidingView
140
+ // behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
141
+ // keyboardVerticalOffset={Platform.OS === 'ios' ? 12 : 0}
142
+ // style={{ width: '100%' }}
143
+ // >
144
+ // <Animated.View
145
+ // style={[
146
+ // styles.modalContainer,
147
+ // {
148
+ // transform: [{ translateY: slideAnim }],
149
+ // height: myOrdersValidateOtpError ? 370 : 334,
150
+ // },
151
+ // ]}
152
+ // >
153
+ // <ScrollView
154
+ // keyboardShouldPersistTaps="handled"
155
+ // contentContainerStyle={styles.sheetContent}
156
+ // showsVerticalScrollIndicator={false}
157
+ // >
158
+ // <View style={styles.handleBar} />
159
+
160
+ // {(myOrdersValidateOtpError || validateEVouchersError) && (
161
+ // <CustomError
162
+ // message={
163
+ // myOrdersValidateOtpError || validateEVouchersError || ''
164
+ // }
165
+ // />
166
+ // )}
167
+
168
+ // <Text style={styles.title}>{ENTER_4_DIGIT_CODE}</Text>
169
+
170
+ // <Text style={styles.subtitle}>
171
+ // {OTP_SENT} {maskPhoneNumber(displayNumber)}
172
+ // </Text>
173
+
174
+ // <OtpInput
175
+ // numberOfDigits={OTP_LENGTH}
176
+ // focusColor="green"
177
+ // autoFocus={false}
178
+ // hideStick={false}
179
+ // placeholder=""
180
+ // blurOnFilled={true}
181
+ // disabled={false}
182
+ // type="numeric"
183
+ // secureTextEntry={false}
184
+ // focusStickBlinkingDuration={500}
185
+ // onFocus={() => {}}
186
+ // onBlur={() => {}}
187
+ // onTextChange={setNewOtp}
188
+ // onFilled={() => {}}
189
+ // textInputProps={{
190
+ // accessibilityLabel: OTP,
191
+ // }}
192
+ // textProps={{
193
+ // accessibilityRole: TEXT,
194
+ // accessibilityLabel: OTP_DIGIT,
195
+ // allowFontScaling: false,
196
+ // }}
197
+ // theme={{
198
+ // containerStyle: styles.container,
199
+ // pinCodeContainerStyle: styles.pinCodeBox,
200
+ // pinCodeTextStyle: styles.pinCodeText,
201
+ // focusStickStyle: styles.focusStick,
202
+ // focusedPinCodeContainerStyle: styles.activePinBox,
203
+ // placeholderTextStyle: styles.placeholderTextStyle,
204
+ // disabledPinCodeContainerStyle:
205
+ // styles.disabledPinCodeContainer,
206
+ // }}
207
+ // />
208
+
209
+ // <View style={styles.resendContainer}>
210
+ // <View style={styles.resendTextContainer}>
211
+ // <Text style={styles.resendText}>{DIDNT_RECEIVE_OTP}</Text>
212
+ // {countdown > 0 ? (
213
+ // <Text style={styles.resendLinkDisabled}>{RESEND_OTP}</Text>
214
+ // ) : (
215
+ // <TouchableOpacity onPress={handleResendOTP}>
216
+ // <Text style={styles.resendLinkActive}>
217
+ // {RESEND_OTP}
218
+ // </Text>
219
+ // </TouchableOpacity>
220
+ // )}
221
+ // </View>
222
+ // <Text style={styles.countdown}>
223
+ // {formatTime(countdown)}
224
+ // </Text>
225
+ // </View>
226
+
227
+ // <CustomButton
228
+ // title="Verify"
229
+ // onPress={handleVerify}
230
+ // disabled={newOtp.length !== OTP_LENGTH}
231
+ // />
232
+ // </ScrollView>
233
+ // </Animated.View>
234
+ // </KeyboardAvoidingView>
235
+ // </TouchableWithoutFeedback>
236
+ // </View>
237
+ // </TouchableWithoutFeedback>
238
+ // </Modal>
239
+ // );
240
+ // };
241
+
242
+ // const styles = StyleSheet.create({
243
+ // overlay: {
244
+ // flex: 1,
245
+ // backgroundColor: 'rgba(0, 0, 0, 0.5)',
246
+ // justifyContent: 'flex-end',
247
+ // alignItems: 'center',
248
+ // },
249
+ // modalContainer: {
250
+ // width: 393,
251
+ // maxWidth: '100%',
252
+ // height: 334,
253
+ // backgroundColor: colors.background,
254
+ // borderTopLeftRadius: 30,
255
+ // borderTopRightRadius: 30,
256
+ // paddingHorizontal: 20,
257
+ // paddingTop: 18,
258
+ // paddingBottom: 36,
259
+ // maxHeight: screenHeight * 0.9,
260
+ // alignSelf: 'stretch',
261
+ // },
262
+ // sheetContent: {
263
+ // paddingBottom: 8,
264
+ // },
265
+ // handleBar: {
266
+ // width: 48,
267
+ // height: 4,
268
+ // backgroundColor: colors.outline,
269
+ // borderRadius: 6,
270
+ // alignSelf: 'center',
271
+ // marginBottom: 15,
272
+ // },
273
+ // title: {
274
+ // fontFamily: FontFamily.LEXEND_MEDIUM,
275
+ // fontSize: 16,
276
+ // fontWeight: '500',
277
+ // color: colors.black,
278
+ // textTransform: 'capitalize',
279
+ // marginBottom: 8,
280
+ // },
281
+ // subtitle: {
282
+ // fontFamily: FontFamily.LEXEND_REGULAR,
283
+ // fontSize: 12,
284
+ // fontWeight: '400',
285
+ // color: colors.onSurfaceVariant,
286
+ // lineHeight: 18,
287
+ // marginBottom: 24,
288
+ // },
289
+
290
+ // resendContainer: {
291
+ // flexDirection: 'row',
292
+ // justifyContent: 'space-between',
293
+ // alignItems: 'center',
294
+ // marginBottom: 32,
295
+ // },
296
+ // resendTextContainer: {
297
+ // flexDirection: 'row',
298
+ // alignItems: 'center',
299
+ // },
300
+ // resendText: {
301
+ // fontFamily: FontFamily.LEXEND_REGULAR,
302
+ // fontSize: 12,
303
+ // fontWeight: '400',
304
+ // color: colors.black,
305
+ // lineHeight: 18,
306
+ // },
307
+ // resendLink: {
308
+ // fontFamily: FontFamily.LEXEND_MEDIUM,
309
+ // fontSize: 12,
310
+ // fontWeight: '500',
311
+ // color: colors.red,
312
+ // lineHeight: 18,
313
+ // textDecorationLine: 'underline',
314
+ // marginLeft: 6,
315
+ // },
316
+ // resendLinkActive: {
317
+ // fontFamily: FontFamily.LEXEND_MEDIUM,
318
+ // fontSize: 12,
319
+ // fontWeight: '500',
320
+ // color: colors.red,
321
+ // lineHeight: 18,
322
+ // textDecorationLine: 'underline',
323
+ // marginLeft: 6,
324
+ // },
325
+ // countdown: {
326
+ // fontFamily: FontFamily.LEXEND_REGULAR,
327
+ // fontSize: 12,
328
+ // fontWeight: '400',
329
+ // color: colors.black,
330
+ // lineHeight: 18,
331
+ // },
332
+
333
+ // // OTP Input Styles
334
+ // container: {
335
+ // flexDirection: 'row',
336
+ // justifyContent: 'space-between',
337
+ // paddingHorizontal: 0,
338
+ // marginBottom: 16,
339
+ // },
340
+ // pinCodeBox: {
341
+ // width: 49,
342
+ // height: 62,
343
+ // borderWidth: 1,
344
+ // borderRadius: 12,
345
+ // borderColor: colors.outline,
346
+ // justifyContent: 'center',
347
+ // alignItems: 'center',
348
+ // backgroundColor: colors.background,
349
+ // },
350
+ // pinCodeText: {
351
+ // fontFamily: FontFamily.LEXEND_REGULAR,
352
+ // fontSize: 18,
353
+ // fontWeight: '400',
354
+ // color: colors.black,
355
+ // textAlign: 'center',
356
+ // },
357
+ // focusStick: {
358
+ // width: 2,
359
+ // height: 30,
360
+ // backgroundColor: colors.darkGrey,
361
+ // borderRadius: 1,
362
+ // },
363
+ // activePinBox: {
364
+ // borderColor: colors.darkGrey,
365
+ // borderWidth: 2,
366
+ // backgroundColor: colors.background,
367
+ // },
368
+
369
+ // disabledPinCodeContainer: {
370
+ // borderColor: colors.outlineVariant,
371
+ // borderWidth: 1,
372
+ // backgroundColor: colors.surface,
373
+ // opacity: 0.6,
374
+ // },
375
+ // placeholderTextStyle: {
376
+ // fontFamily: FontFamily.LEXEND_REGULAR,
377
+ // fontSize: 18,
378
+ // fontWeight: '400',
379
+ // color: colors.placeholderColor,
380
+ // textAlign: 'center',
381
+ // },
382
+ // resendLinkDisabled: {
383
+ // fontFamily: FontFamily.LEXEND_MEDIUM,
384
+ // fontSize: 12,
385
+ // fontWeight: '500',
386
+ // color: colors.onSurfaceVariant,
387
+ // lineHeight: 18,
388
+ // textDecorationLine: 'none',
389
+ // marginLeft: 6,
390
+ // },
391
+
392
+ // });
393
+
394
+ // export default OTPModal;
395
+
396
+
397
+
398
+
399
+
400
+ import React, { useState, useEffect } from 'react';
401
+ import {
402
+ View,
403
+ Text,
404
+ StyleSheet,
405
+ TouchableOpacity,
406
+ TouchableWithoutFeedback,
407
+ Dimensions,
408
+ ScrollView,
409
+ } from 'react-native';
410
+ import { OtpInput } from 'react-native-otp-entry';
411
+ import { useAppSelector } from '../hooks/useAppSelector';
412
+ import { RootState } from '../redux/store';
413
+ import CustomButton from './CustomButton';
414
+ import FontFamily from '../constants/Fonts';
415
+ import CustomError from './CustomError';
416
+ import {
417
+ DIDNT_RECEIVE_OTP,
418
+ ENTER_4_DIGIT_CODE,
419
+ OTP_LENGTH,
420
+ OTP_SENT,
421
+ RESEND_OTP,
422
+ } from '../constants/Messages';
423
+ import { colors } from '../styles/colors';
424
+
425
+ const { height: screenHeight, width: screenWidth } = Dimensions.get('window');
426
+
427
+ interface OTPModalProps {
428
+ visible: boolean;
429
+ onClose: () => void;
430
+ onVerify: (otp: string) => void;
431
+ onNavigateToOrders: () => void;
432
+ phoneNumber?: string;
433
+ onResend?: () => void;
434
+ resetOtpTrigger?: number;
435
+ otpLength?: number;
436
+ screen?: string;
437
+ }
438
+
439
+ function maskPhoneNumber(phone: string): string {
440
+ if (!phone) return '';
441
+ const clean = phone.replace(/\D/g, '');
442
+ if (clean.length <= 4) return clean;
443
+ if (clean.length <= 6) {
444
+ return clean;
445
+ }
446
+ const first2 = clean.slice(0, 2);
447
+ const last2 = clean.slice(-2);
448
+ const maskedLength = clean.length - 4;
449
+ return `${first2}${'*'.repeat(maskedLength)}${last2}`;
450
+ }
451
+
452
+ const OTPModal: React.FC<OTPModalProps> = ({
453
+ visible,
454
+ onClose,
455
+ onVerify,
456
+ onNavigateToOrders,
457
+ phoneNumber,
458
+ onResend,
459
+ resetOtpTrigger,
460
+ otpLength = 6,
461
+ screen,
462
+ }) => {
463
+ const [countdown, setCountdown] = useState(60);
464
+ const {
465
+ mobileNumber: reduxMobileNumber,
466
+ myOrdersValidateOtpError,
467
+ validateEVouchersError,
468
+ myOrdersValidateOtpLoading,
469
+ validateEVouchersLoading,
470
+ } = useAppSelector((state: RootState) => state.auth);
471
+
472
+ const isVerifying = myOrdersValidateOtpLoading || validateEVouchersLoading;
473
+ const displayNumber = phoneNumber || reduxMobileNumber || '';
474
+ const [newOtp, setNewOtp] = useState('');
475
+
476
+ console.log("newOtp...",newOtp?.length);
477
+
478
+
479
+ useEffect(() => {
480
+ if (visible) {
481
+ setCountdown(60);
482
+ setNewOtp('');
483
+ }
484
+ }, [visible]);
485
+
486
+ useEffect(() => {
487
+ let timer: ReturnType<typeof setTimeout>;
488
+ if (visible && countdown > 0) {
489
+ timer = setTimeout(() => setCountdown(countdown - 1), 1000);
490
+ }
491
+ return () => clearTimeout(timer);
492
+ }, [visible, countdown]);
493
+
494
+ const handleVerify = () => {
495
+ console.log('🔍 OTPModal handleVerify called with OTP:', newOtp);
496
+ onVerify(newOtp);
497
+ };
498
+
499
+ const handleResendOTP = () => {
500
+ setCountdown(60);
501
+ setNewOtp('');
502
+ onResend?.();
503
+ };
504
+
505
+ const formatTime = (seconds: number) => {
506
+ const mins = Math.floor(seconds / 60);
507
+ const secs = seconds % 60;
508
+ return `${mins.toString().padStart(2, '0')} : ${secs
509
+ .toString()
510
+ .padStart(2, '0')}`;
511
+ };
512
+
513
+
514
+ if (!visible) {
515
+ console.log('🔍 OTPModal not visible, returning null');
516
+ return null;
517
+ }
518
+
519
+
520
+ // Use absolute positioning instead of Modal for AAR compatibility
521
+ return (
522
+ <View style={styles.absoluteContainer} pointerEvents="box-none">
523
+ <TouchableWithoutFeedback onPress={onClose}>
524
+ <View style={styles.overlay} />
525
+ </TouchableWithoutFeedback>
526
+
527
+ <View style={styles.modalContainer}>
528
+ <ScrollView
529
+ keyboardShouldPersistTaps="handled"
530
+ style={styles.scrollView}
531
+ contentContainerStyle={[styles.sheetContent, styles.scrollContent]}
532
+ showsVerticalScrollIndicator={false}
533
+ nestedScrollEnabled
534
+ >
535
+ <View style={styles.handleBar} />
536
+
537
+ {(myOrdersValidateOtpError || validateEVouchersError) && (
538
+ <CustomError
539
+ message={
540
+ myOrdersValidateOtpError ||
541
+ validateEVouchersError ||
542
+ ''
543
+ }
544
+ />
545
+ )}
546
+
547
+ <Text style={styles.title}>{ENTER_4_DIGIT_CODE}</Text>
548
+
549
+ <Text style={styles.subtitle}>
550
+ {OTP_SENT} {maskPhoneNumber(displayNumber)}
551
+ </Text>
552
+
553
+ <OtpInput
554
+ numberOfDigits={OTP_LENGTH}
555
+ onTextChange={setNewOtp}
556
+ theme={{
557
+ containerStyle: styles.container,
558
+ pinCodeContainerStyle: styles.pinCodeBox,
559
+ pinCodeTextStyle: styles.pinCodeText,
560
+ focusedPinCodeContainerStyle: styles.activePinBox,
561
+ }}
562
+ />
563
+
564
+ <View style={styles.resendContainer}>
565
+ <View style={styles.resendTextContainer}>
566
+ <Text style={styles.resendText}>
567
+ {DIDNT_RECEIVE_OTP}
568
+ </Text>
569
+
570
+ {countdown > 0 ? (
571
+ <Text style={styles.resendLinkDisabled}>
572
+ {RESEND_OTP}
573
+ </Text>
574
+ ) : (
575
+ <TouchableOpacity onPress={handleResendOTP}>
576
+ <Text style={styles.resendLinkActive}>
577
+ {RESEND_OTP}
578
+ </Text>
579
+ </TouchableOpacity>
580
+ )}
581
+ </View>
582
+
583
+ <Text style={styles.countdown}>
584
+ {formatTime(countdown)}
585
+ </Text>
586
+ </View>
587
+
588
+ <CustomButton
589
+ title="Verify"
590
+ onPress={handleVerify}
591
+ loading={isVerifying}
592
+ />
593
+ </ScrollView>
594
+ </View>
595
+ </View>
596
+ );
597
+
598
+ };
599
+
600
+ const styles = StyleSheet.create({
601
+ absoluteContainer: {
602
+ position: 'absolute',
603
+ top: 0,
604
+ left: 0,
605
+ right: 0,
606
+ bottom: 0,
607
+ width: screenWidth,
608
+ height: screenHeight,
609
+ justifyContent: 'flex-end',
610
+ zIndex: 50000,
611
+ elevation: 50000,
612
+ },
613
+ overlay: {
614
+ position: 'absolute',
615
+ top: 0,
616
+ left: 0,
617
+ right: 0,
618
+ bottom: 0,
619
+ backgroundColor: 'rgba(0, 0, 0, 0.7)',
620
+ },
621
+ modalContainer: {
622
+ backgroundColor: colors.background,
623
+ borderTopLeftRadius: 30,
624
+ borderTopRightRadius: 30,
625
+ paddingHorizontal: 20,
626
+ paddingTop: 18,
627
+ paddingBottom: 36,
628
+ maxHeight: screenHeight * 0.95,
629
+ minHeight: screenHeight * 0.6,
630
+ flexShrink: 1,
631
+ shadowColor: '#000',
632
+ shadowOffset: {
633
+ width: 0,
634
+ height: -2,
635
+ },
636
+ shadowOpacity: 0.25,
637
+ shadowRadius: 3.84,
638
+ elevation: 50001,
639
+ },
640
+ sheetContent: {
641
+ paddingBottom: 8,
642
+ },
643
+ scrollView: {
644
+ flexGrow: 0,
645
+ },
646
+ scrollContent: {
647
+ flexGrow: 1,
648
+ },
649
+ handleBar: {
650
+ width: 48,
651
+ height: 4,
652
+ backgroundColor: colors.outline,
653
+ borderRadius: 6,
654
+ alignSelf: 'center',
655
+ marginBottom: 15,
656
+ },
657
+ title: {
658
+ fontFamily: FontFamily.LEXEND_MEDIUM,
659
+ fontSize: 16,
660
+ fontWeight: '500',
661
+ color: colors.black,
662
+ textTransform: 'capitalize',
663
+ marginBottom: 8,
664
+ },
665
+ subtitle: {
666
+ fontFamily: FontFamily.LEXEND_REGULAR,
667
+ fontSize: 12,
668
+ fontWeight: '400',
669
+ color: colors.onSurfaceVariant,
670
+ lineHeight: 18,
671
+ marginBottom: 24,
672
+ },
673
+ resendContainer: {
674
+ flexDirection: 'row',
675
+ justifyContent: 'space-between',
676
+ alignItems: 'center',
677
+ marginBottom: 32,
678
+ },
679
+ resendTextContainer: {
680
+ flexDirection: 'row',
681
+ alignItems: 'center',
682
+ },
683
+ resendText: {
684
+ fontFamily: FontFamily.LEXEND_REGULAR,
685
+ fontSize: 12,
686
+ fontWeight: '400',
687
+ color: colors.black,
688
+ lineHeight: 18,
689
+ },
690
+ resendLinkActive: {
691
+ fontFamily: FontFamily.LEXEND_MEDIUM,
692
+ fontSize: 12,
693
+ fontWeight: '500',
694
+ color: colors.red,
695
+ lineHeight: 18,
696
+ textDecorationLine: 'underline',
697
+ marginLeft: 6,
698
+ },
699
+ countdown: {
700
+ fontFamily: FontFamily.LEXEND_REGULAR,
701
+ fontSize: 12,
702
+ fontWeight: '400',
703
+ color: colors.black,
704
+ lineHeight: 18,
705
+ },
706
+ // OTP Input Styles
707
+ container: {
708
+ flexDirection: 'row',
709
+ justifyContent: 'space-between',
710
+ paddingHorizontal: 0,
711
+ marginBottom: 16,
712
+ },
713
+ pinCodeBox: {
714
+ width: 49,
715
+ height: 62,
716
+ borderWidth: 1,
717
+ borderRadius: 12,
718
+ borderColor: colors.outline,
719
+ justifyContent: 'center',
720
+ alignItems: 'center',
721
+ backgroundColor: colors.background,
722
+ },
723
+ pinCodeText: {
724
+ fontFamily: FontFamily.LEXEND_REGULAR,
725
+ fontSize: 18,
726
+ fontWeight: '400',
727
+ color: colors.black,
728
+ textAlign: 'center',
729
+ },
730
+ activePinBox: {
731
+ borderColor: colors.darkGrey,
732
+ borderWidth: 2,
733
+ backgroundColor: colors.background,
734
+ },
735
+ resendLinkDisabled: {
736
+ fontFamily: FontFamily.LEXEND_MEDIUM,
737
+ fontSize: 12,
738
+ fontWeight: '500',
739
+ color: colors.onSurfaceVariant,
740
+ lineHeight: 18,
741
+ textDecorationLine: 'none',
742
+ marginLeft: 6,
743
+ },
744
+ });
745
+
746
+ export default OTPModal;
747
+