@fadyshawky/react-native-magic 2.0.4 → 2.0.5

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 (110) hide show
  1. package/package.json +1 -1
  2. package/template/src/common/ImageResources.g.ts +33 -1
  3. package/template/src/common/components/Background.tsx +3 -1
  4. package/template/src/common/components/Container.tsx +1 -1
  5. package/template/src/common/components/OTPInput.tsx +3 -2
  6. package/template/src/common/components/PrimaryButton.tsx +23 -23
  7. package/template/src/common/components/PrimaryTextInput.tsx +189 -199
  8. package/template/src/common/components/RadioIcon.tsx +4 -4
  9. package/template/src/common/components/SafeText.tsx +41 -0
  10. package/template/src/common/components/SearchBar.tsx +19 -17
  11. package/template/src/common/components/TryAgain.tsx +3 -3
  12. package/template/src/common/localization/localization.ts +10 -0
  13. package/template/src/common/localization/translations/commonLocalization.ts +97 -0
  14. package/template/src/common/localization/translations/homeLocalization.ts +24 -0
  15. package/template/src/common/localization/translations/loginLocalization.ts +28 -2
  16. package/template/src/common/localization/translations/mainNavigationLocalization.ts +30 -0
  17. package/template/src/common/localization/translations/navigationLocalization.ts +48 -0
  18. package/template/src/common/localization/translations/otpLocalization.ts +28 -0
  19. package/template/src/common/localization/translations/passwordLocalization.ts +54 -0
  20. package/template/src/common/localization/translations/posLocalization.ts +196 -0
  21. package/template/src/common/utils/FeesCaalculation.tsx +37 -0
  22. package/template/src/common/utils/index.tsx +11 -0
  23. package/template/src/common/utils/printData.tsx +161 -0
  24. package/template/src/common/validations/errorValidations.ts +3 -2
  25. package/template/src/components/PrinterExample.js +226 -0
  26. package/template/src/core/api/serverHeaders.ts +62 -1
  27. package/template/src/core/store/Categories/categoryActions.ts +33 -0
  28. package/template/src/core/store/Categories/categorySlice.ts +75 -0
  29. package/template/src/core/store/Categories/categoryState.ts +41 -0
  30. package/template/src/core/store/Providers/providersActions.ts +102 -0
  31. package/template/src/core/store/Providers/providersSlice.ts +136 -0
  32. package/template/src/core/store/Providers/providersState.ts +37 -0
  33. package/template/src/core/store/Services/servicesActions.ts +191 -0
  34. package/template/src/core/store/Services/servicesSlice.ts +205 -0
  35. package/template/src/core/store/Services/servicesState.ts +466 -0
  36. package/template/src/core/store/app/appSlice.ts +13 -5
  37. package/template/src/core/store/app/appState.ts +10 -2
  38. package/template/src/core/store/rootReducer.ts +6 -1
  39. package/template/src/core/store/store.tsx +55 -2
  40. package/template/src/core/store/user/userActions.ts +164 -26
  41. package/template/src/core/store/user/userSlice.ts +193 -21
  42. package/template/src/core/store/user/userState.ts +148 -25
  43. package/template/src/core/theme/colors.ts +70 -94
  44. package/template/src/core/theme/commonConsts.ts +1 -1
  45. package/template/src/core/theme/commonSizes.ts +94 -119
  46. package/template/src/core/theme/commonStyles.ts +22 -22
  47. package/template/src/core/theme/fonts.ts +14 -13
  48. package/template/src/core/theme/themes.ts +75 -386
  49. package/template/src/core/theme/types.ts +15 -201
  50. package/template/src/core/utils/stringUtils.ts +114 -0
  51. package/template/src/modules/SunmiCard.js +212 -0
  52. package/template/src/modules/SunmiPrepaid.ts +122 -0
  53. package/template/src/navigation/AuthStack.tsx +8 -0
  54. package/template/src/navigation/HeaderComponents.tsx +76 -1
  55. package/template/src/navigation/MainNavigation.tsx +3 -1
  56. package/template/src/navigation/MainStack.tsx +130 -56
  57. package/template/src/navigation/TabBar.tsx +111 -59
  58. package/template/src/navigation/types.ts +24 -0
  59. package/template/src/screens/Categories/Categories.tsx +141 -0
  60. package/template/src/screens/Categories/hooks/useCategoriesData.ts +33 -0
  61. package/template/src/screens/Categories/types.ts +7 -0
  62. package/template/src/screens/Favorites/Favorites.tsx +130 -0
  63. package/template/src/screens/ForceChangePassword/ForceChangePasswordScreen.tsx +155 -0
  64. package/template/src/screens/History/History.tsx +430 -0
  65. package/template/src/screens/History/hooks/useHistoryData.ts +49 -0
  66. package/template/src/screens/History/types.ts +7 -0
  67. package/template/src/screens/InquiredBill/InquiredBill.tsx +443 -0
  68. package/template/src/screens/InquiredBill/hooks/useInquiredData.ts +91 -0
  69. package/template/src/screens/Login/Login.tsx +85 -85
  70. package/template/src/screens/OTP/OTPScreen.tsx +170 -0
  71. package/template/src/screens/PaymentConfirmation/PaymentConfirmation.tsx +326 -0
  72. package/template/src/screens/Providers/Providers.tsx +166 -0
  73. package/template/src/screens/Providers/hooks/useProvidersData.ts +33 -0
  74. package/template/src/screens/Providers/types.ts +7 -0
  75. package/template/src/screens/ReceiptScreen/ReceiptScreen.tsx +181 -0
  76. package/template/src/screens/ReceiptScreen/hooks/useReceiptData.ts +46 -0
  77. package/template/src/screens/ReceiptScreen/utils/utils.tsx +156 -0
  78. package/template/src/screens/Services/Services.tsx +144 -0
  79. package/template/src/screens/Services/hooks/useServicesData.ts +41 -0
  80. package/template/src/screens/SingleService/Components/FawryInputs.tsx +446 -0
  81. package/template/src/screens/SingleService/SingleService.tsx +229 -0
  82. package/template/src/screens/SingleService/hooks/useServiceData.ts +164 -0
  83. package/template/src/screens/home/Components/PayByCode.tsx +129 -0
  84. package/template/src/screens/home/HomeScreen.tsx +268 -77
  85. package/template/src/screens/home/hooks/useHomeData.ts +32 -38
  86. package/template/src/screens/index.tsx +24 -0
  87. package/template/src/screens/profile/Profile.tsx +290 -2
  88. package/template/src/services/SunmiPrinterInternal.js +268 -0
  89. package/template/src/types/sunmiPrepaid.d.ts +20 -0
  90. package/template/src/utils/SunmiPrinter.ts +442 -0
  91. package/template/src/utils/feesCalculator.ts +92 -0
  92. package/template/src/common/components/Stepper.tsx +0 -153
  93. package/template/src/common/components/Svg.tsx +0 -25
  94. package/template/src/common/hooks/useDebounce.ts +0 -17
  95. package/template/src/common/hooks/usePrevious.ts +0 -11
  96. package/template/src/common/localization/intlFormatter.ts +0 -37
  97. package/template/src/common/urls/emailUrl.ts +0 -20
  98. package/template/src/common/urls/mapUrl.ts +0 -22
  99. package/template/src/common/utils/listHandlers.ts +0 -30
  100. package/template/src/common/utils/serializeQueryParams.ts +0 -10
  101. package/template/src/common/validations/hooks/useDatesError.ts +0 -40
  102. package/template/src/common/validations/profileValidations.ts +0 -30
  103. package/template/src/core/theme/shadows.ts +0 -135
  104. package/template/src/navigation/TopTabBar.tsx +0 -77
  105. package/template/src/screens/Settings/Settings.tsx +0 -5
  106. package/template/src/screens/home/components/CarouselSection.tsx +0 -79
  107. package/template/src/screens/home/components/FeaturedCarousel.tsx +0 -128
  108. package/template/src/screens/main/Main.tsx +0 -5
  109. package/template/src/screens/registration/RegistrationScreen.tsx +0 -198
  110. package/template/src/screens/resetPassword/ForgotPasswordScreen.tsx +0 -129
@@ -0,0 +1,446 @@
1
+ import React, {Dispatch, SetStateAction, useEffect, useState} from 'react';
2
+ import {Image, StyleSheet, Text, TouchableOpacity, View} from 'react-native';
3
+ import {LoadState} from '../../../../types';
4
+ import {FlatListWrapper} from '../../../common/components/FlatListWrapper';
5
+ import {PrimaryTextInput} from '../../../common/components/PrimaryTextInput';
6
+ import {RTLAwareText} from '../../../common/components/RTLAwareText';
7
+ import {RTLAwareView} from '../../../common/components/RTLAwareView';
8
+ import {ImageResources} from '../../../common/ImageResources.g';
9
+ import {useTranslation} from '../../../common/localization/LocalizationProvider';
10
+ import {initFees} from '../../../common/utils/FeesCaalculation';
11
+ import {useInputError} from '../../../common/validations/hooks/useInputError';
12
+ import {useAppSelector} from '../../../core/store/reduxHelpers';
13
+ import {RootState} from '../../../core/store/rootReducer';
14
+ import {
15
+ BillTypeRefKeyEntity1,
16
+ PaymentRanges,
17
+ } from '../../../core/store/Services/servicesState';
18
+ import {CommonSizes} from '../../../core/theme/commonSizes';
19
+ import {scaleHeight, scaleWidth} from '../../../core/theme/scaling';
20
+ import {useTheme} from '../../../core/theme/ThemeProvider';
21
+ import {useFeesCalculation} from '../../../utils/feesCalculator';
22
+
23
+ interface AmountInputProps {
24
+ currencyCode: string;
25
+ value: string;
26
+ setVatValue: Dispatch<SetStateAction<string>>;
27
+ vatValue: string;
28
+ setAmount: Dispatch<SetStateAction<string>>;
29
+ vat_value: number | null;
30
+ low: string;
31
+ high: string;
32
+ }
33
+
34
+ interface PaymentRangeButtonProps {
35
+ amount: string;
36
+ isSelected: boolean;
37
+ onPress: () => void;
38
+ disabled?: boolean;
39
+ }
40
+
41
+ interface FawryInputsProps {
42
+ setFawryInputParameters: Dispatch<SetStateAction<any>>;
43
+ fawryInputParameters: any;
44
+ selectedPaymentRange: string;
45
+ setSelectedPaymentRange: Dispatch<SetStateAction<string>>;
46
+ quantity: string;
47
+ setQuantity: Dispatch<SetStateAction<string>>;
48
+ vatValue: string;
49
+ setVatValue: Dispatch<SetStateAction<string>>;
50
+ fees: number;
51
+ }
52
+
53
+ const AmountInput: React.FC<AmountInputProps> = ({
54
+ currencyCode,
55
+ value,
56
+ setVatValue,
57
+ vatValue,
58
+ setAmount,
59
+ vat_value,
60
+ low,
61
+ high,
62
+ }) => {
63
+ const {theme} = useTheme();
64
+ const t = useTranslation();
65
+
66
+ const {calculateFromAmount, calculateFromVat} = useFeesCalculation(
67
+ value,
68
+ vat_value || 0,
69
+ currencyCode,
70
+ vatValue,
71
+ setVatValue,
72
+ setAmount,
73
+ );
74
+
75
+ const handleAmountChange = (text: string) => {
76
+ const sanitizedText = text.replace(/[^0-9.]/g, '');
77
+ setAmount(sanitizedText);
78
+ calculateFromAmount(sanitizedText);
79
+ };
80
+
81
+ const handleVatValueChange = (text: string) => {
82
+ const sanitizedText = text.replace(/[^0-9.]/g, '');
83
+ setVatValue(sanitizedText);
84
+ calculateFromVat(sanitizedText);
85
+ };
86
+
87
+ return (
88
+ <RTLAwareView style={styles.amountInputWrapper}>
89
+ <RTLAwareView
90
+ style={[
91
+ styles.amountInputContainer,
92
+ vat_value ? styles.amountInputContainer : styles.fullWidthInput,
93
+ ]}>
94
+ <PrimaryTextInput
95
+ onChangeText={vat_value ? handleVatValueChange : handleAmountChange}
96
+ width={vat_value ? '45%' : '100%'}
97
+ placeholder={t('voucher', 'common')}
98
+ keyboardType={'numeric'}
99
+ value={vat_value ? vatValue : value}
100
+ />
101
+ {vat_value && (
102
+ <>
103
+ <Image source={ImageResources.arrows} style={styles.arrowsImage} />
104
+ <PrimaryTextInput
105
+ onChangeText={handleAmountChange}
106
+ width={vat_value ? '45%' : '100%'}
107
+ placeholder={t('amountToPay', 'common')}
108
+ keyboardType={'numeric'}
109
+ value={value}
110
+ />
111
+ </>
112
+ )}
113
+ </RTLAwareView>
114
+ <RTLAwareText style={theme.text.body2}>
115
+ {`${low} ${currencyCode} - ${high} ${currencyCode}`}
116
+ </RTLAwareText>
117
+ </RTLAwareView>
118
+ );
119
+ };
120
+
121
+ const PaymentRangeButton: React.FC<PaymentRangeButtonProps> = ({
122
+ amount,
123
+ isSelected,
124
+ onPress,
125
+ disabled,
126
+ }) => {
127
+ const {theme} = useTheme();
128
+ return (
129
+ <TouchableOpacity
130
+ disabled={disabled}
131
+ style={[
132
+ styles.paymentRangeButton,
133
+ isSelected && styles.selectedPaymentRangeButton,
134
+ {borderColor: theme.colors.indigoBlue},
135
+ ]}
136
+ onPress={onPress}>
137
+ <Text style={theme.text.header2}>{amount}</Text>
138
+ </TouchableOpacity>
139
+ );
140
+ };
141
+
142
+ export function FawryInputs({
143
+ setFawryInputParameters,
144
+ fawryInputParameters,
145
+ selectedPaymentRange,
146
+ setVatValue,
147
+ vatValue,
148
+ setSelectedPaymentRange,
149
+ quantity,
150
+ setQuantity,
151
+ fees,
152
+ }: FawryInputsProps): JSX.Element {
153
+ const [selectedEnum, setEnum] = useState<number | null>(null);
154
+ const {theme} = useTheme();
155
+ const t = useTranslation();
156
+ const {service} = useAppSelector((state: RootState) => state.services);
157
+
158
+ const paymentRanges = service?.PaymentRanges as PaymentRanges | null;
159
+ const hasEnums = service?.BillTypeExtraRefKeys?.BillTypeRefKey?.some(
160
+ k => k.EnumValues,
161
+ );
162
+ const amountInput =
163
+ !hasEnums &&
164
+ paymentRanges?.PaymentRangeType?.find(
165
+ item => item?.Lower?.Amt !== item?.Upper?.Amt,
166
+ );
167
+
168
+ const {calculateFromAmount} = useFeesCalculation(
169
+ selectedPaymentRange,
170
+ service?.vat_value || 0,
171
+ amountInput?.Lower?.CurCode || '',
172
+ vatValue,
173
+ setVatValue,
174
+ setSelectedPaymentRange,
175
+ );
176
+
177
+ useEffect(() => {
178
+ if (paymentRanges?.PaymentRangeType?.length === 1) {
179
+ setSelectedPaymentRange(
180
+ paymentRanges?.PaymentRangeType?.[0]?.Lower?.Amt?.toString() || '',
181
+ );
182
+ }
183
+ }, []);
184
+
185
+ const handlePaymentRangeSelect = (amount: string) => {
186
+ setSelectedPaymentRange(amount);
187
+ calculateFromAmount(amount);
188
+ };
189
+
190
+ const {error: acctError} = useInputError(
191
+ fawryInputParameters?.BillingAcct as string,
192
+ () => '',
193
+ );
194
+
195
+ return (
196
+ <>
197
+ {service?.AcctInputMethod !== 'SC' &&
198
+ service?.AcctInputMethod !== 'PSAG' &&
199
+ service?.AcctInputMethod !== 'GASSC' &&
200
+ service?.PmtType !== 'VOCH' && (
201
+ <PrimaryTextInput
202
+ regex={
203
+ service?.BillingActRegEX
204
+ ? new RegExp(service.BillingActRegEX)
205
+ : undefined
206
+ }
207
+ regexErrorMessage={t('invalidAccountNumber', 'common')}
208
+ placeholder={service?.BillTypeAcctLabel || ''}
209
+ value={(fawryInputParameters?.BillingAcct as string) || ''}
210
+ keyboardType={
211
+ service?.AcctInputMethod === 'KB' ? 'default' : 'numeric'
212
+ }
213
+ onChangeText={text => {
214
+ setFawryInputParameters({
215
+ ...fawryInputParameters,
216
+ BillingAcct: text,
217
+ });
218
+ }}
219
+ />
220
+ )}
221
+
222
+ {amountInput && (
223
+ <>
224
+ <AmountInput
225
+ vat_value={!!service?.vat_value ? service.vat_value : 0}
226
+ setVatValue={setVatValue}
227
+ vatValue={vatValue}
228
+ currencyCode={amountInput?.Lower?.CurCode || ''}
229
+ value={selectedPaymentRange}
230
+ setAmount={setSelectedPaymentRange}
231
+ low={amountInput?.Lower?.Amt?.toString() || ''}
232
+ high={amountInput?.Upper?.Amt?.toString() || ''}
233
+ />
234
+ </>
235
+ )}
236
+
237
+ {service?.PmtType !== 'POST' && fees > 0 && (
238
+ <RTLAwareText style={[theme.text.body2, styles.serviceCost]}>
239
+ {`${t('serviceCost', 'pos')}: EGP ${fees}`}
240
+ </RTLAwareText>
241
+ )}
242
+ {service?.BillTypeExtraRefKeys?.BillTypeRefKey?.filter(
243
+ k => k.InputMethod === 'KP' || k.InputMethod === 'KB',
244
+ ).map((item, index) => {
245
+ return item?.EnumValues ? (
246
+ <FlatListWrapper
247
+ scrollEnabled={false}
248
+ numColumns={3}
249
+ keyExtractor={(_, index) => index.toString()}
250
+ loadState={LoadState.needLoad}
251
+ contentContainerStyle={styles.flatListContainer}
252
+ ItemSeparatorComponent={() => <View style={styles.separator} />}
253
+ data={item?.EnumValues?.EnumValue}
254
+ renderItem={({item: ser, index: ind}) => (
255
+ <TouchableOpacity
256
+ disabled={selectedEnum !== null && selectedEnum !== ind}
257
+ style={[
258
+ styles.enumButton,
259
+ ind === selectedEnum && styles.selectedEnumButton,
260
+ {
261
+ borderColor: theme.colors.indigoBlue,
262
+ marginHorizontal: ind % 2 !== 0 ? scaleWidth(16) : 0,
263
+ },
264
+ ]}
265
+ onPress={() => {
266
+ if (selectedEnum === ind) {
267
+ setEnum(null);
268
+ if (ser?.Amount) {
269
+ handlePaymentRangeSelect(null);
270
+ }
271
+ setFawryInputParameters({
272
+ ...fawryInputParameters,
273
+ ExtraBillingAcctKey:
274
+ fawryInputParameters.ExtraBillingAcctKey.map(
275
+ (k: any) => {
276
+ if (k.Key === item.Key) {
277
+ return {...k, Value: undefined};
278
+ }
279
+ return k;
280
+ },
281
+ ),
282
+ });
283
+ } else {
284
+ setEnum(ind);
285
+ if (ser?.Amount) {
286
+ handlePaymentRangeSelect(ser.Amount);
287
+ }
288
+ setFawryInputParameters({
289
+ ...fawryInputParameters,
290
+ ExtraBillingAcctKey:
291
+ fawryInputParameters.ExtraBillingAcctKey.map(
292
+ (k: any) => {
293
+ if (k.Key === item.Key) {
294
+ return {...k, Value: ser?.Value};
295
+ }
296
+ return k;
297
+ },
298
+ ),
299
+ });
300
+ }
301
+ }}>
302
+ <Text style={[theme.text.body2, styles.enumButtonText]}>
303
+ {ser?.Alias}
304
+ </Text>
305
+ </TouchableOpacity>
306
+ )}
307
+ />
308
+ ) : (
309
+ <PrimaryTextInput
310
+ regex={
311
+ (item as BillTypeRefKeyEntity1)?.RegEX
312
+ ? new RegExp((item as BillTypeRefKeyEntity1).RegEX || '')
313
+ : undefined
314
+ }
315
+ regexErrorMessage={t('invalid_format', 'common')}
316
+ keyboardType={item?.InputMethod === 'KB' ? 'default' : 'numeric'}
317
+ placeholder={`${item?.Label} ${
318
+ item?.Required ? '' : t('optional', 'common')
319
+ }`}
320
+ value={
321
+ fawryInputParameters.ExtraBillingAcctKey?.[index]?.Value as string
322
+ }
323
+ onChangeText={text => {
324
+ const tmp = [...fawryInputParameters.ExtraBillingAcctKey];
325
+ tmp[index].Value = text;
326
+ setFawryInputParameters({
327
+ ...fawryInputParameters,
328
+ ExtraBillingAcctKey: tmp,
329
+ });
330
+ }}
331
+ />
332
+ );
333
+ })}
334
+
335
+ {paymentRanges?.PaymentRangeType && (
336
+ <FlatListWrapper
337
+ scrollEnabled={false}
338
+ numColumns={3}
339
+ keyExtractor={(_, index) => index.toString()}
340
+ loadState={LoadState.needLoad}
341
+ contentContainerStyle={styles.flatListContainer}
342
+ ItemSeparatorComponent={() => <View style={styles.separator} />}
343
+ data={paymentRanges.PaymentRangeType.filter(
344
+ item => item?.Lower?.Amt === item?.Upper?.Amt,
345
+ )}
346
+ renderItem={({item, index}) => (
347
+ <PaymentRangeButton
348
+ amount={item?.Lower?.Amt?.toString() || ''}
349
+ isSelected={selectedPaymentRange === item?.Lower?.Amt?.toString()}
350
+ onPress={() => {
351
+ if (selectedPaymentRange !== item?.Lower?.Amt?.toString()) {
352
+ handlePaymentRangeSelect(item?.Lower?.Amt?.toString() || '');
353
+ } else {
354
+ setSelectedPaymentRange('');
355
+ setVatValue('');
356
+ }
357
+ }}
358
+ disabled={
359
+ (amountInput &&
360
+ !!selectedPaymentRange &&
361
+ selectedPaymentRange !== item?.Lower?.Amt?.toString()) ||
362
+ (!!selectedPaymentRange &&
363
+ selectedPaymentRange !== item?.Lower?.Amt?.toString())
364
+ }
365
+ />
366
+ )}
367
+ />
368
+ )}
369
+ {service?.PmtType === 'VOCH' && (
370
+ <>
371
+ <PrimaryTextInput
372
+ placeholder={t('quantity', 'common')}
373
+ value={quantity}
374
+ onChangeText={text => {
375
+ const maxQuantity = 5; // Default max quantity
376
+ if (Number(text) <= maxQuantity) {
377
+ setQuantity(text);
378
+ }
379
+ }}
380
+ />
381
+ <RTLAwareText style={theme.text.body1}>
382
+ {`${t('quantity', 'common')}: 1-5`}
383
+ </RTLAwareText>
384
+ </>
385
+ )}
386
+ </>
387
+ );
388
+ }
389
+
390
+ const styles = StyleSheet.create({
391
+ amountInputWrapper: {
392
+ alignItems: 'center',
393
+ gap: scaleHeight(16),
394
+ },
395
+ amountInputContainer: {
396
+ flexDirection: 'row',
397
+ alignItems: 'center',
398
+ justifyContent: 'space-between',
399
+ width: '100%',
400
+ },
401
+ fullWidthInput: {
402
+ justifyContent: 'center',
403
+ },
404
+ arrowsImage: {
405
+ width: 24,
406
+ height: 24,
407
+ resizeMode: 'contain',
408
+ },
409
+ serviceCost: {
410
+ alignSelf: 'center',
411
+ },
412
+ flatListContainer: {
413
+ paddingHorizontal: 0,
414
+ },
415
+ separator: {
416
+ height: scaleHeight(16),
417
+ },
418
+ enumButton: {
419
+ width: scaleWidth(177),
420
+ height: scaleHeight(180),
421
+ backgroundColor: 'transparent',
422
+ borderRadius: CommonSizes.borderRadius.huge,
423
+ alignItems: 'center',
424
+ justifyContent: 'center',
425
+ borderWidth: 0,
426
+ },
427
+ selectedEnumButton: {
428
+ borderWidth: 1,
429
+ },
430
+ enumButtonText: {
431
+ textAlign: 'center',
432
+ },
433
+ paymentRangeButton: {
434
+ width: scaleWidth(177),
435
+ height: scaleHeight(126),
436
+ backgroundColor: 'transparent',
437
+ borderRadius: CommonSizes.borderRadius.huge,
438
+ alignItems: 'center',
439
+ justifyContent: 'center',
440
+ marginLeft: scaleWidth(16),
441
+ borderWidth: 0,
442
+ },
443
+ selectedPaymentRangeButton: {
444
+ borderWidth: 1,
445
+ },
446
+ });
@@ -0,0 +1,229 @@
1
+ import {
2
+ RouteProp,
3
+ useIsFocused,
4
+ useNavigation,
5
+ useRoute,
6
+ } from '@react-navigation/native';
7
+ import {NativeStackNavigationProp} from '@react-navigation/native-stack';
8
+ import React, {useEffect, useRef} from 'react';
9
+ import {Image, StyleSheet, Text} from 'react-native';
10
+ import {SkypeIndicator} from 'react-native-indicators';
11
+ import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
12
+ import {ButtonType} from '../../../types';
13
+ import {Container} from '../../common/components/Container';
14
+ import {PrimaryButton} from '../../common/components/PrimaryButton';
15
+ import {ImageResources} from '../../common/ImageResources.g';
16
+ import {useTranslation} from '../../common/localization/LocalizationProvider';
17
+ import {useAppDispatch, useAppSelector} from '../../core/store/reduxHelpers';
18
+ import {RootState} from '../../core/store/rootReducer';
19
+ import {clearService} from '../../core/store/Services/servicesSlice';
20
+ import {CommonSizes} from '../../core/theme/commonSizes';
21
+ import {scaleHeight, scaleWidth} from '../../core/theme/scaling';
22
+ import {useTheme} from '../../core/theme/ThemeProvider';
23
+ import {HeaderBack} from '../../navigation/HeaderComponents';
24
+ import {RootStackParamList} from '../../navigation/types';
25
+ import {FawryInputs} from './Components/FawryInputs';
26
+ import {useServiceData} from './hooks/useServiceData';
27
+ import SunmiPrepaid from '../../modules/SunmiPrepaid';
28
+
29
+ export function SingleService(): JSX.Element {
30
+ const {theme} = useTheme();
31
+ const scroll = useRef<KeyboardAwareScrollView>(null);
32
+ const navigation =
33
+ useNavigation<NativeStackNavigationProp<RootStackParamList>>();
34
+ const {service} = useAppSelector((state: RootState) => state.services);
35
+ console.log('service: ', service);
36
+
37
+ const t = useTranslation();
38
+
39
+ const dispatch = useAppDispatch();
40
+
41
+ const params =
42
+ useRoute<RouteProp<RootStackParamList, 'SingleService'>>()?.params;
43
+
44
+ const {
45
+ fawryInputParameters,
46
+ setFawryInputParameters,
47
+ fetchData,
48
+ isLoading,
49
+ setSelectedPaymentRange,
50
+ selectedPaymentRange,
51
+ quantity,
52
+ setQuantity,
53
+ vatValue,
54
+ setVatValue,
55
+ selectedProvider,
56
+ handleEnquireService,
57
+ fees,
58
+ setCustomProperties,
59
+ } = useServiceData(params?.serviceID as string);
60
+
61
+ const isFocused = useIsFocused();
62
+
63
+ const readCardMetadata = async () => {
64
+ try {
65
+ const response = await SunmiPrepaid.readCardMetadata(
66
+ service?.BillTypeExtraRefKeys?.BillTypeRefKey,
67
+ service?.AcctInputMethod as string,
68
+ );
69
+
70
+ setFawryInputParameters({
71
+ ...fawryInputParameters,
72
+ BillingAcct: response.billingAcct,
73
+ ExtraBillingAcctKey:
74
+ service?.AcctInputMethod === 'GASSC'
75
+ ? []
76
+ : response.extraBillingAcctKey || [],
77
+ });
78
+
79
+ setCustomProperties(response.customProperties);
80
+ } catch (error) {
81
+ console.log('error', error);
82
+ }
83
+ };
84
+
85
+ useEffect(() => {
86
+ if (isFocused) {
87
+ fetchData();
88
+ }
89
+
90
+ return () => {
91
+ setQuantity('1');
92
+ setSelectedPaymentRange(null);
93
+ setVatValue('');
94
+ setFawryInputParameters({
95
+ BillingAcct: '',
96
+ ExtraBillingAcctKey:
97
+ service?.BillTypeExtraRefKeys?.BillTypeRefKey?.map(i => {
98
+ return {...i, Value: ''};
99
+ }) || [],
100
+ });
101
+ };
102
+ }, [isFocused]);
103
+
104
+ useEffect(() => {
105
+ if (
106
+ service?.AcctInputMethod === 'SC' ||
107
+ service?.AcctInputMethod === 'WSC' ||
108
+ service?.AcctInputMethod === 'GASSC'
109
+ ) {
110
+ console.log('service?.AcctInputMethod', service?.AcctInputMethod);
111
+ readCardMetadata();
112
+ }
113
+ }, [service]);
114
+
115
+ return (
116
+ <Container
117
+ ref={scroll}
118
+ testID={'ServiceScreenID'}
119
+ contentContainerStyle={styles.contentContainer}
120
+ style={styles.container}
121
+ backgroundImage={ImageResources[`${theme.mode}_background_1`]}
122
+ withoutPadding
123
+ extendedBackground
124
+ bounces={true}
125
+ backgroundColor={theme.colors.background}>
126
+ {isLoading ? (
127
+ <SkypeIndicator size={80} color={theme.colors.mutedLavender} />
128
+ ) : (
129
+ <>
130
+ <HeaderBack
131
+ onPress={() => {
132
+ navigation.goBack();
133
+ dispatch(clearService());
134
+ }}
135
+ />
136
+ <Text style={{...theme.text.header1, alignSelf: 'center'}}>
137
+ {service?.Name}
138
+ </Text>
139
+ <Image
140
+ source={{uri: selectedProvider.img_url as string}}
141
+ style={styles.sectionImage}
142
+ />
143
+ {/* <BeeInputs /> */}
144
+ <FawryInputs
145
+ setQuantity={setQuantity}
146
+ quantity={quantity}
147
+ setFawryInputParameters={setFawryInputParameters}
148
+ fawryInputParameters={fawryInputParameters}
149
+ selectedPaymentRange={selectedPaymentRange}
150
+ setSelectedPaymentRange={setSelectedPaymentRange}
151
+ vatValue={vatValue}
152
+ setVatValue={setVatValue}
153
+ fees={fees}
154
+ />
155
+ <PrimaryButton
156
+ label={t('submit', 'common')}
157
+ isLoading={isLoading}
158
+ disabled={
159
+ isLoading ||
160
+ (service?.PmtType !== 'POST' && !selectedPaymentRange)
161
+ }
162
+ onPressIn={() => {
163
+ handleEnquireService();
164
+ }}
165
+ style={{alignSelf: 'flex-end'}}
166
+ type={ButtonType.solid}
167
+ />
168
+ <PrimaryButton
169
+ label={t('backToHome', 'common')}
170
+ onPress={() => {
171
+ navigation.reset({
172
+ index: 0,
173
+ routes: [{name: 'Main'}],
174
+ });
175
+ }}
176
+ style={{alignSelf: 'flex-end'}}
177
+ type={ButtonType.outlineNegative}
178
+ />
179
+ </>
180
+ )}
181
+ </Container>
182
+ );
183
+ }
184
+
185
+ const styles = StyleSheet.create({
186
+ container: {
187
+ flexGrow: 1,
188
+ paddingBottom: scaleHeight(130),
189
+ borderTopRightRadius: CommonSizes.spacing.large,
190
+ borderTopLeftRadius: CommonSizes.spacing.large,
191
+ paddingHorizontal: CommonSizes.spacing.large,
192
+ gap: CommonSizes.spacing.extraLarge,
193
+ justifyContent: 'flex-start',
194
+ },
195
+ contentContainer: {
196
+ flexGrow: 1,
197
+ },
198
+ formContainer: {
199
+ alignItems: 'center',
200
+ paddingHorizontal: CommonSizes.spacing.large,
201
+ gap: CommonSizes.spacing.large,
202
+ },
203
+ balanceSection: {
204
+ alignItems: 'center',
205
+ justifyContent: 'space-evenly',
206
+ gap: CommonSizes.spacing.large,
207
+ },
208
+ seeMoreSection: {
209
+ alignItems: 'center',
210
+ gap: CommonSizes.spacing.large,
211
+ alignSelf: 'center',
212
+ },
213
+ sectionImage: {
214
+ width: scaleWidth(150),
215
+ height: scaleHeight(150),
216
+ alignSelf: 'center',
217
+ resizeMode: 'contain',
218
+ },
219
+ amountText: {
220
+ textAlign: 'left',
221
+ },
222
+ balanceCard: {
223
+ width: '100%',
224
+ flexDirection: 'row',
225
+ justifyContent: 'space-evenly',
226
+ paddingVertical: CommonSizes.spacing.large,
227
+ borderRadius: CommonSizes.spacing.huge,
228
+ },
229
+ });