@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,430 @@
1
+ import {useIsFocused, useNavigation} from '@react-navigation/native';
2
+ import {NativeStackNavigationProp} from '@react-navigation/native-stack';
3
+ import React, {useEffect, useRef} from 'react';
4
+ import {ActivityIndicator, StyleSheet, View} from 'react-native';
5
+ import {SkypeIndicator} from 'react-native-indicators';
6
+ import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
7
+ import {LoadState} from '../../../types';
8
+ import {Container} from '../../common/components/Container';
9
+ import {FlatListWrapper} from '../../common/components/FlatListWrapper';
10
+ import {ImageResources} from '../../common/ImageResources.g';
11
+ import {useTranslation} from '../../common/localization/LocalizationProvider';
12
+ import {CommonSizes} from '../../core/theme/commonSizes';
13
+ import {scaleHeight, scaleWidth} from '../../core/theme/scaling';
14
+ import {useTheme} from '../../core/theme/ThemeProvider';
15
+ import {Header} from '../../navigation/HeaderComponents';
16
+ import {RootStackParamList} from '../../navigation/types';
17
+ import {useHistoryData} from './hooks/useHistoryData';
18
+ import moment from 'moment';
19
+ import {RTLAwareText} from '../../common/components/RTLAwareText';
20
+ import {
21
+ RTLAwareTouchableOpacity,
22
+ RTLAwareView,
23
+ } from '../../common/components/RTLAwareView';
24
+ import {createThemedStyles} from '../../core/theme/commonStyles';
25
+ import {onBeePrint, onPrint} from '../../utils/SunmiPrinter';
26
+
27
+ export function checkNumber(value: string) {
28
+ if (
29
+ value.length === 11 &&
30
+ (value.startsWith('010') ||
31
+ value.startsWith('011') ||
32
+ value.startsWith('012') ||
33
+ value.startsWith('015') ||
34
+ value.startsWith('022'))
35
+ ) {
36
+ return true;
37
+ }
38
+ return false;
39
+ }
40
+
41
+ export function History(): JSX.Element {
42
+ const t = useTranslation();
43
+ const {
44
+ isLoading,
45
+ refreshData,
46
+ fetchInitialData,
47
+ history,
48
+ fetchData,
49
+ setPage,
50
+ page,
51
+ hasMore,
52
+ } = useHistoryData();
53
+
54
+ const prepareData = (item: any): Array<any> => {
55
+ let newData = [];
56
+
57
+ newData.push({
58
+ image: true,
59
+ });
60
+
61
+ newData.push({
62
+ middle: item?.serviceName,
63
+ });
64
+
65
+ if (item?.customerNumber) {
66
+ newData.push({
67
+ left: item?.customerNumber,
68
+ right: 'رقم العميل',
69
+ });
70
+ }
71
+ if (!item?.customerNumber && item?.input_params && item?.input_params[0]) {
72
+ let inputParams = item?.input_params;
73
+ let phoneNumber = inputParams.find((item: any) => {
74
+ if (checkNumber(item?.value)) {
75
+ return item;
76
+ } else if (
77
+ item?.key === 'phone_number' ||
78
+ item?.key === 'TelephoneNumber' ||
79
+ item?.key === 'adslPhoneNumber'
80
+ ) {
81
+ return item;
82
+ }
83
+ });
84
+ if (phoneNumber) {
85
+ newData.push({
86
+ right: 'رقم العميل',
87
+ left: phoneNumber.value,
88
+ });
89
+ }
90
+ }
91
+
92
+ newData.push({
93
+ left: item?.amount?.toString() + ' EGP',
94
+ right: 'القيمة',
95
+ });
96
+
97
+ if (item?.convenience?.toString() !== '0') {
98
+ newData.push({
99
+ left: item?.convenience?.toString() + ' EGP',
100
+ right: 'تكلفه الخدمة',
101
+ });
102
+ }
103
+
104
+ newData.push({
105
+ left: item?.totalAmount?.toString() + ' EGP',
106
+ right: 'الإجمالي',
107
+ });
108
+
109
+ newData.push({
110
+ left: item?.transaction_serial_num,
111
+ right: 'رقم العملية',
112
+ rightWidth: 130,
113
+ });
114
+
115
+ newData.push({
116
+ left: item?.beeRefNumber ? item?.beeRefNumber : '---',
117
+ right: 'الرقم المرجعي',
118
+ rightWidth: 130,
119
+ });
120
+
121
+ newData.push({
122
+ left: moment().locale('en').format('DD/MM/YYYY - HH:mm'),
123
+ right: 'الوقت',
124
+ });
125
+
126
+ if (item?.voucherDetails && item?.voucherDetails[0]) {
127
+ let voucherData = item?.voucherDetails[0];
128
+
129
+ let code = voucherData?.filter(
130
+ (item: any) => item?.key == 'code' || item?.key == 'pin_code',
131
+ )[0]?.value;
132
+ let expiry_timestamp = voucherData?.filter(
133
+ (item: any) => item?.key == 'expiry_timestamp',
134
+ )[0]?.value;
135
+ let serial = voucherData?.filter(
136
+ (item: any) =>
137
+ item?.key == 'serial_number' || item?.key == 'track_number',
138
+ )[0]?.value;
139
+
140
+ if (serial) {
141
+ newData.push({
142
+ left: serial,
143
+ right: 'الرقم المسلسل',
144
+ });
145
+ }
146
+
147
+ if (code) {
148
+ if (!code?.includes('-')) {
149
+ code = code?.replace(/\D/g, '');
150
+ code = code?.replace(/(.{4})/g, '$1-');
151
+ var lastDash = code.lastIndexOf('-');
152
+ code = code?.substr(0, lastDash);
153
+ code = code?.trim();
154
+ }
155
+
156
+ newData.push({
157
+ middle: 'كود الشحن' + '\n' + code,
158
+ fontSize: 26,
159
+ });
160
+ }
161
+ // else {
162
+ // newData.push({
163
+ // middle: payData?.error ? '*** عملية فاشلة ***' : '*** عملية ناجحة ***',
164
+ // });
165
+ // }
166
+ if (expiry_timestamp) {
167
+ newData.push({
168
+ left: moment(expiry_timestamp, 'DD.MM.YYYY')
169
+ .locale('en')
170
+ .format('DD/MM/YYYY'),
171
+ right: 'صالح حتي',
172
+ });
173
+ }
174
+ }
175
+ // else {
176
+ // newData.push({
177
+ // middle: payData?.error ? '*** عملية فاشلة ***' : '*** عملية ناجحة ***',
178
+ // });
179
+ // }
180
+
181
+ if (item?.voucherDetails && item?.voucherDetails[0]) {
182
+ let voucherData = item?.voucherDetails[0];
183
+
184
+ let name = voucherData?.filter((item: any) => item?.key == 'name')[0]
185
+ ?.value;
186
+ let address = voucherData?.filter(
187
+ (item: any) => item?.key == 'address',
188
+ )[0]?.value;
189
+ let day_code = voucherData?.filter(
190
+ (item: any) => item?.key == 'day_code',
191
+ )[0]?.value;
192
+
193
+ if (name) {
194
+ newData.push({
195
+ right: 'اسم العميل',
196
+ left: name,
197
+ });
198
+ }
199
+ if (address) {
200
+ newData.push({
201
+ right: 'العنوان',
202
+ left: address,
203
+ });
204
+ }
205
+ }
206
+
207
+ if (item?.explain) {
208
+ newData.push({
209
+ line: true,
210
+ });
211
+ newData.push({
212
+ middleEnd: item?.explain + '\n',
213
+ fontSize: 23,
214
+ });
215
+
216
+ newData.push({
217
+ line: true,
218
+ });
219
+ }
220
+
221
+ if (item?.note) {
222
+ newData.push({
223
+ middle: item?.note + '\n',
224
+ });
225
+ }
226
+
227
+ if (!!item?.info_text) {
228
+ newData.push({
229
+ line: true,
230
+ });
231
+ newData.push({
232
+ middle: t('info_text', 'pos'),
233
+ });
234
+ newData.push({
235
+ middle: item?.info_text,
236
+ });
237
+ }
238
+
239
+ newData.push({
240
+ line: true,
241
+ });
242
+
243
+ newData.push({
244
+ powered: item?.powered_by
245
+ ? item?.powered_by?.includes('Powered By')
246
+ ? item?.powered_by
247
+ : `Powered By ${item?.powered_by}`
248
+ : 'Powered By Masary',
249
+ fontSize: 24,
250
+ });
251
+
252
+ return newData;
253
+ };
254
+
255
+ const navigation =
256
+ useNavigation<NativeStackNavigationProp<RootStackParamList>>();
257
+ const {theme} = useTheme();
258
+ const scroll = useRef<KeyboardAwareScrollView>(null);
259
+ const isFocused = useIsFocused();
260
+ useEffect(() => {
261
+ if (isFocused) {
262
+ fetchInitialData();
263
+ }
264
+ }, [isFocused]);
265
+
266
+ const fetchNextPage = () => {
267
+ if (hasMore) {
268
+ setPage(page + 1);
269
+ fetchData(page + 1);
270
+ }
271
+ };
272
+
273
+ return (
274
+ <Container
275
+ ref={scroll}
276
+ testID={'HistoryScreenID'}
277
+ contentContainerStyle={styles.contentContainer}
278
+ style={styles.container}
279
+ backgroundImage={ImageResources[`${theme.mode}_background_1`]}
280
+ withoutPadding
281
+ withoutScroll
282
+ backgroundColor={theme.colors.background}>
283
+ <Header />
284
+ <FlatListWrapper
285
+ onRefresh={refreshData}
286
+ onEndReached={fetchNextPage}
287
+ onEndReachedThreshold={0.5}
288
+ style={{
289
+ flex: 1,
290
+ width: '100%',
291
+ }}
292
+ contentContainerStyle={{
293
+ flexGrow: 1,
294
+ paddingBottom: scaleHeight(200),
295
+ }}
296
+ ItemSeparatorComponent={() => (
297
+ <View style={{height: CommonSizes.spacing.large}} />
298
+ )}
299
+ keyExtractor={item => item.id}
300
+ loadState={LoadState.needLoad}
301
+ data={history}
302
+ ListFooterComponent={() => {
303
+ return (
304
+ isLoading && (
305
+ <ActivityIndicator
306
+ color={theme.colors.indigoBlue}
307
+ size={25}
308
+ style={{marginTop: 5}}
309
+ />
310
+ )
311
+ );
312
+ }}
313
+ renderItem={({item, index}) => {
314
+ return (
315
+ <RTLAwareTouchableOpacity
316
+ disabled={
317
+ item.sender_identifier === 'Neo_Comm' ||
318
+ item.status === 'Failed'
319
+ }
320
+ onPress={async () => {
321
+ if (item.receiver_name.includes('BeeAggregatorMerchant')) {
322
+ const preparedData = prepareData(item);
323
+ onBeePrint(preparedData);
324
+ } else {
325
+ navigation.navigate('ReceiptScreen', {
326
+ type: 'history',
327
+ historyID: item.transaction_reference_num,
328
+ });
329
+ }
330
+ }}
331
+ style={{
332
+ width: '100%',
333
+ backgroundColor: theme.colors.surface,
334
+ ...createThemedStyles(theme).dropShadow,
335
+ flexDirection: 'row',
336
+ borderRadius: CommonSizes.borderRadius.medium,
337
+ paddingHorizontal: CommonSizes.spacing.extraLargePlus,
338
+ paddingVertical: CommonSizes.spacing.largePlus,
339
+ justifyContent: 'space-between',
340
+ }}>
341
+ <RTLAwareView style={{alignItems: 'flex-end'}}>
342
+ <RTLAwareText
343
+ style={{
344
+ ...theme.text.body2,
345
+ color:
346
+ item.status === 'Failed'
347
+ ? theme.colors.red
348
+ : theme.colors.mutedLavender,
349
+ }}>
350
+ {`EGP ${
351
+ item.status === 'Failed'
352
+ ? '0'
353
+ : item?.totalAmount ||
354
+ Number(item?.amount) + Number(item?.convenience)
355
+ }`}
356
+ </RTLAwareText>
357
+ <RTLAwareText
358
+ style={{
359
+ ...theme.text.navBar,
360
+ color:
361
+ item.status === 'Failed'
362
+ ? theme.colors.red
363
+ : theme.colors.mutedLavender,
364
+ }}>
365
+ {`${moment(item?.createdAt).format('DD-MM-YYYY | hh:mm A')}`}
366
+ </RTLAwareText>
367
+ </RTLAwareView>
368
+ <RTLAwareText
369
+ style={{
370
+ ...theme.text.body2,
371
+ width: '50%',
372
+ alignSelf: 'center',
373
+ color:
374
+ item.status === 'Failed'
375
+ ? theme.colors.red
376
+ : theme.colors.mutedLavender,
377
+ }}>
378
+ {item.sender_identifier === 'Neo_Comm'
379
+ ? t('commission')
380
+ : item?.meta?.serviceName || item?.serviceName}
381
+ </RTLAwareText>
382
+ </RTLAwareTouchableOpacity>
383
+ );
384
+ }}
385
+ />
386
+ </Container>
387
+ );
388
+ }
389
+
390
+ const styles = StyleSheet.create({
391
+ container: {
392
+ flexGrow: 1,
393
+ justifyContent: 'flex-start',
394
+ alignItems: 'center',
395
+ },
396
+ contentContainer: {
397
+ flexGrow: 1,
398
+ },
399
+ searchBar: {
400
+ width: '90%',
401
+ alignSelf: 'center',
402
+ marginTop: CommonSizes.spacing.medium,
403
+ },
404
+ formContainer: {
405
+ alignItems: 'center',
406
+ paddingHorizontal: CommonSizes.spacing.large,
407
+ gap: CommonSizes.spacing.large,
408
+ },
409
+ balanceSection: {
410
+ alignItems: 'center',
411
+ justifyContent: 'space-evenly',
412
+ gap: CommonSizes.spacing.large,
413
+ },
414
+ seeMoreSection: {
415
+ alignItems: 'center',
416
+ gap: CommonSizes.spacing.large,
417
+ alignSelf: 'center',
418
+ },
419
+ sectionImage: {
420
+ width: scaleWidth(120),
421
+ height: scaleHeight(70),
422
+ },
423
+ amountText: {
424
+ textAlign: 'left',
425
+ },
426
+ balanceCard: {
427
+ width: '100%',
428
+ borderRadius: CommonSizes.spacing.huge,
429
+ },
430
+ });
@@ -0,0 +1,49 @@
1
+ import {useState} from 'react';
2
+ import {useAppDispatch, useAppSelector} from '../../../core/store/reduxHelpers';
3
+ import {RootState} from '../../../core/store/rootReducer';
4
+ import {fetchHistory} from '../../../core/store/user/userActions';
5
+ import {clearHistory} from '../../../core/store/user/userSlice';
6
+ export function useHistoryData() {
7
+ const [isLoading, setIsLoading] = useState(false);
8
+ const dispatch = useAppDispatch();
9
+ const {history} = useAppSelector((state: RootState) => state.user);
10
+ const [page, setPage] = useState(1);
11
+ const [hasMore, setHasMore] = useState(true);
12
+
13
+ const fetchData = async (selectedPage: number) => {
14
+ setIsLoading(true);
15
+ try {
16
+ const res = await dispatch(
17
+ fetchHistory({data: {page: selectedPage, limit: 10}}),
18
+ );
19
+ if (res.type.includes('fulfilled')) {
20
+ setHasMore(res.payload.pagination.hasNextPage);
21
+ }
22
+ } catch (error) {
23
+ console.error('Error fetching history data:', error);
24
+ } finally {
25
+ setIsLoading(false);
26
+ }
27
+ };
28
+
29
+ const fetchInitialData = async () => {
30
+ dispatch(clearHistory());
31
+ setPage(1);
32
+ fetchData(1);
33
+ };
34
+
35
+ const refreshData = () => {
36
+ fetchInitialData();
37
+ };
38
+
39
+ return {
40
+ isLoading,
41
+ refreshData,
42
+ history,
43
+ setPage,
44
+ page,
45
+ fetchData,
46
+ fetchInitialData,
47
+ hasMore,
48
+ };
49
+ }
@@ -0,0 +1,7 @@
1
+ export interface CarouselItem {
2
+ id: string;
3
+ title: string;
4
+ subtitle?: string;
5
+ imageUrl: string;
6
+ onPress?: (item: CarouselItem) => void;
7
+ }