@fadyshawky/react-native-magic 2.0.5 → 2.0.6

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 (66) hide show
  1. package/package.json +1 -1
  2. package/template/App.tsx +28 -19
  3. package/template/ios/reactnativemagic/AppDelegate.mm +5 -0
  4. package/template/src/common/ImageResources.g.ts +1 -33
  5. package/template/src/common/components/Background.tsx +7 -7
  6. package/template/src/common/components/Container.tsx +7 -10
  7. package/template/src/common/localization/LocalizationProvider.tsx +14 -17
  8. package/template/src/common/localization/RTLInitializer.tsx +90 -0
  9. package/template/src/common/localization/intlFormatter.ts +37 -0
  10. package/template/src/common/localization/localization.ts +1 -3
  11. package/template/src/common/localization/translations/commonLocalization.ts +11 -81
  12. package/template/src/common/localization/translations/emptyLocalization.ts +6 -2
  13. package/template/src/common/localization/translations/errorsLocalization.ts +33 -13
  14. package/template/src/common/localization/translations/homeLocalization.ts +4 -24
  15. package/template/src/common/localization/translations/loginLocalization.ts +26 -29
  16. package/template/src/common/localization/translations/mainNavigationLocalization.ts +2 -2
  17. package/template/src/common/localization/translations/onboardingLocalization.ts +40 -9
  18. package/template/src/common/localization/translations/otpLocalization.ts +8 -8
  19. package/template/src/common/localization/translations/pagesLocalization.ts +13 -1
  20. package/template/src/common/localization/translations/passwordLocalization.ts +3 -3
  21. package/template/src/common/localization/translations/profileLocalization.ts +4 -4
  22. package/template/src/core/store/app/appState.ts +2 -2
  23. package/template/src/core/theme/colors.ts +106 -70
  24. package/template/src/core/theme/commonConsts.ts +1 -1
  25. package/template/src/core/theme/commonSizes.ts +119 -94
  26. package/template/src/core/theme/commonStyles.ts +22 -22
  27. package/template/src/core/theme/fonts.ts +13 -14
  28. package/template/src/core/theme/shadows.ts +135 -0
  29. package/template/src/core/theme/themes.ts +386 -75
  30. package/template/src/core/theme/types.ts +201 -15
  31. package/template/src/navigation/HeaderComponents.tsx +6 -30
  32. package/template/src/navigation/MainStack.tsx +6 -97
  33. package/template/src/screens/Login/Login.tsx +5 -7
  34. package/template/src/screens/OTP/OTPScreen.tsx +12 -13
  35. package/template/src/screens/home/HomeScreen.tsx +2 -295
  36. package/template/src/screens/profile/Profile.tsx +2 -290
  37. package/template/src/common/localization/translations/posLocalization.ts +0 -196
  38. package/template/src/components/PrinterExample.js +0 -226
  39. package/template/src/modules/SunmiCard.js +0 -212
  40. package/template/src/modules/SunmiPrepaid.ts +0 -122
  41. package/template/src/screens/Categories/Categories.tsx +0 -141
  42. package/template/src/screens/Categories/hooks/useCategoriesData.ts +0 -33
  43. package/template/src/screens/Categories/types.ts +0 -7
  44. package/template/src/screens/Favorites/Favorites.tsx +0 -130
  45. package/template/src/screens/ForceChangePassword/ForceChangePasswordScreen.tsx +0 -155
  46. package/template/src/screens/History/History.tsx +0 -430
  47. package/template/src/screens/History/hooks/useHistoryData.ts +0 -49
  48. package/template/src/screens/History/types.ts +0 -7
  49. package/template/src/screens/InquiredBill/InquiredBill.tsx +0 -443
  50. package/template/src/screens/InquiredBill/hooks/useInquiredData.ts +0 -91
  51. package/template/src/screens/PaymentConfirmation/PaymentConfirmation.tsx +0 -326
  52. package/template/src/screens/Providers/Providers.tsx +0 -166
  53. package/template/src/screens/Providers/hooks/useProvidersData.ts +0 -33
  54. package/template/src/screens/Providers/types.ts +0 -7
  55. package/template/src/screens/ReceiptScreen/ReceiptScreen.tsx +0 -181
  56. package/template/src/screens/ReceiptScreen/hooks/useReceiptData.ts +0 -46
  57. package/template/src/screens/ReceiptScreen/utils/utils.tsx +0 -156
  58. package/template/src/screens/Services/Services.tsx +0 -144
  59. package/template/src/screens/Services/hooks/useServicesData.ts +0 -41
  60. package/template/src/screens/SingleService/Components/FawryInputs.tsx +0 -446
  61. package/template/src/screens/SingleService/SingleService.tsx +0 -229
  62. package/template/src/screens/SingleService/hooks/useServiceData.ts +0 -164
  63. package/template/src/services/SunmiPrinterInternal.js +0 -268
  64. package/template/src/types/sunmiPrepaid.d.ts +0 -20
  65. package/template/src/utils/SunmiPrinter.ts +0 -442
  66. package/template/src/utils/feesCalculator.ts +0 -92
@@ -1,181 +0,0 @@
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 {ScrollView, StyleSheet, TextStyle, ViewStyle} 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 {RTLAwareText} from '../../common/components/RTLAwareText';
16
- import {RTLAwareView} from '../../common/components/RTLAwareView';
17
- import {normalizeAndTrimWhitespace} from '../../common/helpers/stringsHelpers';
18
- import {ImageResources} from '../../common/ImageResources.g';
19
- import {useTranslation} from '../../common/localization/LocalizationProvider';
20
- import {useAppDispatch} from '../../core/store/reduxHelpers';
21
- import {getBalance} from '../../core/store/user/userActions';
22
- import {CommonSizes} from '../../core/theme/commonSizes';
23
- import {createThemedStyles} from '../../core/theme/commonStyles';
24
- import {scaleHeight} from '../../core/theme/scaling';
25
- import {useTheme} from '../../core/theme/ThemeProvider';
26
- import {decryptTripleDES} from '../../core/utils/stringUtils';
27
- import {HeaderButton} from '../../navigation/HeaderComponents';
28
- import {RootStackParamList} from '../../navigation/types';
29
- import {onPrint} from '../../utils/SunmiPrinter';
30
- import {useReceiptData} from './hooks/useReceiptData';
31
- import {getSeparator, getTextStyle, getLabel} from './utils/utils';
32
- import {reverseService} from '../../core/store/Services/servicesActions';
33
-
34
- export function ReceiptScreen(): JSX.Element {
35
- const {theme} = useTheme();
36
- const navigation =
37
- useNavigation<NativeStackNavigationProp<RootStackParamList>>();
38
- const params =
39
- useRoute<RouteProp<RootStackParamList, 'ReceiptScreen'>>()?.params;
40
- const scroll = useRef<KeyboardAwareScrollView>(null);
41
- const t = useTranslation();
42
- const dispatch = useAppDispatch();
43
- const isFocused = useIsFocused();
44
-
45
- // Use combined hook
46
- const {fetchData, receiptData, service, isLoading} = useReceiptData(
47
- params?.type,
48
- params?.historyID,
49
- );
50
-
51
- useEffect(() => {
52
- if (params?.type === 'print') {
53
- // For print type, data is already in the store
54
- return;
55
- } else if (isFocused && params?.type === 'history') {
56
- fetchData();
57
- }
58
- }, [isFocused, params?.type]);
59
-
60
- const handlePrint = async () => {
61
- if (params?.type === 'print') {
62
- dispatch(getBalance());
63
- await onPrint(receiptData);
64
- setTimeout(() => {
65
- navigation.goBack();
66
- if (service?.PmtType === 'POST') {
67
- navigation.goBack();
68
- }
69
- navigation.goBack();
70
- }, 200);
71
- } else {
72
- onPrint(receiptData);
73
- }
74
- };
75
-
76
- const handleBackToHome = () => {
77
- navigation.reset({
78
- index: 0,
79
- routes: [{name: 'Main'}],
80
- });
81
- };
82
-
83
- return (
84
- <Container
85
- ref={scroll}
86
- testID={'ReceiptScreenID'}
87
- contentContainerStyle={styles.contentContainer}
88
- style={styles.container}
89
- backgroundImage={ImageResources.background_2}
90
- withoutPadding
91
- extendedBackground
92
- withoutScroll
93
- bounces={true}
94
- backgroundColor={theme.colors.background}>
95
- {isLoading ? (
96
- <SkypeIndicator size={80} color={theme.colors.mutedLavender} />
97
- ) : (
98
- <>
99
- <HeaderButton onPress={() => navigation.goBack()} />
100
- <ScrollView
101
- style={styles.scrollView}
102
- contentContainerStyle={[
103
- styles.scrollViewContent,
104
- {backgroundColor: theme.colors.surface},
105
- createThemedStyles(theme).dropShadow,
106
- ]}>
107
- {Array.isArray(receiptData) &&
108
- receiptData?.map((h, i) => (
109
- <RTLAwareView
110
- key={`${h.label}-${i}`}
111
- style={styles.receiptItem}>
112
- {getSeparator(h.type, theme)}
113
- <RTLAwareView
114
- style={getTextStyle(h.type, theme)?.container as ViewStyle}>
115
- <RTLAwareText
116
- style={getTextStyle(h.type, theme)?.value as TextStyle}>
117
- {h.label === 'VouchPIN'
118
- ? decryptTripleDES(
119
- h.value,
120
- '8pe/hqinrZQV6pHNkQ0WwbD0ZHkaAbbj',
121
- )
122
- : normalizeAndTrimWhitespace(h.value)}
123
- </RTLAwareText>
124
- {h.label &&
125
- h.label !== 'VouchPIN' &&
126
- getLabel(h.type, h.label, theme)}
127
- </RTLAwareView>
128
- </RTLAwareView>
129
- ))}
130
- </ScrollView>
131
- <PrimaryButton
132
- label={t('print', 'common')}
133
- type={ButtonType.solid}
134
- onPressIn={handlePrint}
135
- />
136
- {params?.type === 'print' && (
137
- <PrimaryButton
138
- label={t('backToHome', 'common')}
139
- onPress={handleBackToHome}
140
- style={styles.backToHomeButton}
141
- type={ButtonType.outlineNegative}
142
- />
143
- )}
144
- </>
145
- )}
146
- </Container>
147
- );
148
- }
149
-
150
- const styles = StyleSheet.create({
151
- container: {
152
- flexGrow: 1,
153
- paddingBottom: scaleHeight(20),
154
- borderTopRightRadius: CommonSizes.spacing.large,
155
- borderTopLeftRadius: CommonSizes.spacing.large,
156
- paddingHorizontal: CommonSizes.spacing.large,
157
- gap: CommonSizes.spacing.xl,
158
- justifyContent: 'flex-start',
159
- },
160
- contentContainer: {
161
- flexGrow: 1,
162
- },
163
- scrollView: {
164
- width: '100%',
165
- borderRadius: CommonSizes.borderRadius.medium,
166
- flexGrow: 1,
167
- },
168
- scrollViewContent: {
169
- paddingHorizontal: CommonSizes.spacing.huge,
170
- gap: CommonSizes.spacing.large,
171
- paddingVertical: CommonSizes.spacing.huge,
172
- flexGrow: 1,
173
- },
174
- receiptItem: {
175
- width: '100%',
176
- gap: CommonSizes.spacing.medium,
177
- },
178
- backToHomeButton: {
179
- alignSelf: 'flex-end',
180
- },
181
- });
@@ -1,46 +0,0 @@
1
- import {useState} from 'react';
2
- import {useAppSelector, useAppDispatch} from '../../../core/store/reduxHelpers';
3
- import {RootState} from '../../../core/store/rootReducer';
4
- import {fetchHistoryDetails} from '../../../core/store/user/userActions';
5
-
6
- type ReceiptType = 'print' | 'history';
7
-
8
- export function useReceiptData(type: ReceiptType, historyID?: string) {
9
- const [isLoading, setIsLoading] = useState(false);
10
- const dispatch = useAppDispatch();
11
-
12
- // Get data from services store for print type
13
- const {paymentResponse, service} = useAppSelector(
14
- (state: RootState) => state.services,
15
- );
16
-
17
- // State for history data
18
- const [historyDetails, setHistoryDetails] = useState<any[]>([]);
19
-
20
- const fetchData = async () => {
21
- setIsLoading(true);
22
- try {
23
- if (type === 'print') {
24
- // For print type, data is already in the store
25
- return;
26
- } else if (type === 'history' && historyID) {
27
- // For history type, fetch data from API
28
- const result = await dispatch(fetchHistoryDetails({trxRef: historyID}));
29
- if (fetchHistoryDetails.fulfilled.match(result)) {
30
- setHistoryDetails(result.payload.data);
31
- }
32
- }
33
- } catch (error) {
34
- console.error('Error fetching receipt data:', error);
35
- } finally {
36
- setIsLoading(false);
37
- }
38
- };
39
-
40
- return {
41
- fetchData,
42
- isLoading,
43
- receiptData: type === 'print' ? paymentResponse : historyDetails,
44
- service: type === 'print' ? service : undefined,
45
- };
46
- }
@@ -1,156 +0,0 @@
1
- import React from 'react';
2
- import {View, TextStyle, Image} from 'react-native';
3
- import {RTLAwareText} from '../../../common/components/RTLAwareText';
4
- import {CommonSizes} from '../../../core/theme/commonSizes';
5
- import {scaleWidth} from '../../../core/theme/scaling';
6
- import {ImageResources} from '../../../common/ImageResources.g';
7
- import {scaleHeight} from '../../../core/theme/scaling';
8
-
9
- export function getTextStyle(type: string, theme: any) {
10
- switch (type) {
11
- case 'body':
12
- return {
13
- value: {
14
- ...theme.text.body2,
15
- width: '60%',
16
- textAlign: 'left',
17
- },
18
- label: {
19
- ...theme.text.body2,
20
- width: '40%',
21
- textAlign: 'right',
22
- },
23
- container: {
24
- width: '100%',
25
- flexDirection: 'row',
26
- justifyContent: 'space-between',
27
- alignItems: 'center',
28
- },
29
- };
30
- case 'header1':
31
- return {
32
- value: {
33
- ...theme.text.body2,
34
- width: '100%',
35
- textAlign: 'center',
36
- },
37
- label: {},
38
- container: {
39
- width: '100%',
40
- justifyContent: 'center',
41
- alignItems: 'center',
42
- },
43
- };
44
- case 'header2':
45
- return {
46
- value: {
47
- ...theme.text.body2,
48
- width: '100%',
49
- textAlign: 'center',
50
- },
51
- label: {},
52
- container: {
53
- width: '100%',
54
- justifyContent: 'center',
55
- alignItems: 'center',
56
- },
57
- };
58
- case 'description':
59
- return {
60
- value: {
61
- ...theme.text.body2,
62
- width: '100%',
63
- textAlign: 'center',
64
- },
65
- label: {
66
- ...theme.text.body2,
67
- width: '100%',
68
- textAlign: 'center',
69
- },
70
- container: {
71
- width: '100%',
72
- justifyContent: 'center',
73
- alignItems: 'center',
74
- },
75
- };
76
- case 'body_title':
77
- return {
78
- value: {
79
- ...theme.text.body1,
80
- width: '60%',
81
- textAlign: 'left',
82
- },
83
- label: {
84
- ...theme.text.body1,
85
- width: '40%',
86
- textAlign: 'right',
87
- },
88
- container: {
89
- width: '100%',
90
- flexDirection: 'row',
91
- justifyContent: 'space-between',
92
- alignItems: 'center',
93
- },
94
- };
95
- }
96
- }
97
-
98
- export function getSeparator(type: string, theme: any) {
99
- switch (type) {
100
- default:
101
- return (
102
- <View
103
- style={{
104
- height: 2,
105
- width: '100%',
106
- backgroundColor: theme.colors.mutedLavender,
107
- marginVertical: CommonSizes.spacing.medium,
108
- }}
109
- />
110
- );
111
- case 'image':
112
- return (
113
- <Image
114
- style={{
115
- width: scaleWidth(292),
116
- height: scaleHeight(66),
117
- alignSelf: 'center',
118
- tintColor:
119
- theme.mode === 'dark'
120
- ? theme.colors.mutedLavender
121
- : theme.colors.black,
122
- }}
123
- source={ImageResources.receipt_logo}
124
- />
125
- );
126
- case 'body':
127
- return <></>;
128
- case 'header1':
129
- return <></>;
130
- case 'header2':
131
- return <></>;
132
- }
133
- }
134
-
135
- export function getLabel(type: string, label: string, theme: any) {
136
- switch (type) {
137
- default:
138
- return (
139
- <RTLAwareText style={getTextStyle(type, theme)?.label as TextStyle}>
140
- {label}
141
- </RTLAwareText>
142
- );
143
- case 'description':
144
- return !!!label ? (
145
- <></>
146
- ) : (
147
- <RTLAwareText style={getTextStyle(type, theme)?.label as TextStyle}>
148
- {label}
149
- </RTLAwareText>
150
- );
151
- case 'header1':
152
- return <></>;
153
- case 'header2':
154
- return <></>;
155
- }
156
- }
@@ -1,144 +0,0 @@
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 {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
10
- import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
11
- import {LoadState} from '../../../types';
12
- import {Container} from '../../common/components/Container';
13
- import {FlatListWrapper} from '../../common/components/FlatListWrapper';
14
- import {ImageResources} from '../../common/ImageResources.g';
15
- import {useAppDispatch} from '../../core/store/reduxHelpers';
16
- import {resetServices} from '../../core/store/Services/servicesSlice';
17
- import {CommonSizes} from '../../core/theme/commonSizes';
18
- import {createThemedStyles} from '../../core/theme/commonStyles';
19
- import {scaleHeight, scaleWidth} from '../../core/theme/scaling';
20
- import {useTheme} from '../../core/theme/ThemeProvider';
21
- import {HeaderBack} from '../../navigation/HeaderComponents';
22
- import {RootStackParamList} from '../../navigation/types';
23
- import {useServicesData} from './hooks/useServicesData';
24
- import {SkypeIndicator} from 'react-native-indicators';
25
-
26
- export function Services(): JSX.Element {
27
- const {theme} = useTheme();
28
- const scroll = useRef<KeyboardAwareScrollView>(null);
29
- const navigation =
30
- useNavigation<NativeStackNavigationProp<RootStackParamList>>();
31
-
32
- const dispatch = useAppDispatch();
33
-
34
- const {providerID} =
35
- useRoute<RouteProp<RootStackParamList, 'Services'>>().params;
36
- const {isLoading, refreshData, fetchData, services} =
37
- useServicesData(providerID);
38
- const isFocused = useIsFocused();
39
-
40
- useEffect(() => {
41
- if (isFocused) {
42
- fetchData();
43
- }
44
- }, [isFocused]);
45
- return (
46
- <Container
47
- ref={scroll}
48
- testID={'ServicesScreenID'}
49
- contentContainerStyle={styles.contentContainer}
50
- style={styles.container}
51
- backgroundImage={ImageResources[`${theme.mode}_background_1`]}
52
- withoutPadding
53
- extendedBackground
54
- withoutScroll
55
- backgroundColor={theme.colors.background}>
56
- {isLoading ? (
57
- <SkypeIndicator size={80} color={theme.colors.mutedLavender} />
58
- ) : (
59
- <>
60
- <HeaderBack
61
- onPress={() => {
62
- dispatch(resetServices());
63
- navigation.goBack();
64
- }}
65
- />
66
- <FlatListWrapper
67
- loadState={LoadState.allIsLoaded}
68
- contentContainerStyle={{paddingHorizontal: undefined}}
69
- data={services}
70
- keyExtractor={item => item.id?.toString() || item.Id?.toString()}
71
- ItemSeparatorComponent={() => (
72
- <View style={{height: theme.spacing.md}} />
73
- )}
74
- renderItem={({item}) => {
75
- return (
76
- <TouchableOpacity
77
- onPress={() => {
78
- navigation.navigate('SingleService', {serviceID: item.id});
79
- }}
80
- style={{
81
- paddingVertical: CommonSizes.spacing.large,
82
- borderWidth: 1,
83
- borderColor: theme.colors.indigoBlue,
84
- paddingHorizontal: CommonSizes.spacing.large,
85
- borderRadius: CommonSizes.borderRadius.large,
86
- backgroundColor: theme.colors.surface,
87
- ...createThemedStyles(theme).dropShadow,
88
- overflow: 'hidden',
89
- }}>
90
- <Text style={{...theme.text.header2, width: '100%'}}>
91
- {item.name || item.Name}
92
- </Text>
93
- </TouchableOpacity>
94
- );
95
- }}
96
- />
97
- </>
98
- )}
99
- </Container>
100
- );
101
- }
102
-
103
- const styles = StyleSheet.create({
104
- container: {
105
- flexGrow: 1,
106
- borderTopRightRadius: CommonSizes.spacing.large,
107
- borderTopLeftRadius: CommonSizes.spacing.large,
108
- paddingHorizontal: CommonSizes.spacing.large,
109
- gap: CommonSizes.spacing.large,
110
- justifyContent: 'flex-start',
111
- },
112
- contentContainer: {
113
- flexGrow: 1,
114
- },
115
- formContainer: {
116
- alignItems: 'center',
117
- paddingHorizontal: CommonSizes.spacing.large,
118
- gap: CommonSizes.spacing.large,
119
- },
120
- balanceSection: {
121
- alignItems: 'center',
122
- justifyContent: 'space-evenly',
123
- gap: CommonSizes.spacing.large,
124
- },
125
- seeMoreSection: {
126
- alignItems: 'center',
127
- gap: CommonSizes.spacing.large,
128
- alignSelf: 'center',
129
- },
130
- sectionImage: {
131
- width: scaleWidth(120),
132
- height: scaleHeight(70),
133
- },
134
- amountText: {
135
- textAlign: 'left',
136
- },
137
- balanceCard: {
138
- width: '100%',
139
- flexDirection: 'row',
140
- justifyContent: 'space-evenly',
141
- paddingVertical: CommonSizes.spacing.large,
142
- borderRadius: CommonSizes.spacing.huge,
143
- },
144
- });
@@ -1,41 +0,0 @@
1
- import {useState} from 'react';
2
- import {useAppDispatch, useAppSelector} from '../../../core/store/reduxHelpers';
3
- import {RootState} from '../../../core/store/rootReducer';
4
- import {getServices} from '../../../core/store/Services/servicesActions';
5
- export function useServicesData(providerID: string) {
6
- const [isLoading, setIsLoading] = useState(false);
7
- const dispatch = useAppDispatch();
8
- const {services} = useAppSelector((state: RootState) => state.services);
9
- const {selectedProvider} = useAppSelector(
10
- (state: RootState) => state.providers,
11
- );
12
- const {selectedCategory} = useAppSelector(
13
- (state: RootState) => state.categories,
14
- );
15
-
16
- const fetchData = async () => {
17
- setIsLoading(true);
18
- try {
19
- const data =
20
- selectedProvider?.provider === 'Fawry'
21
- ? {fawry_provider_id: providerID, category_id: selectedCategory?.id}
22
- : {bee_provider_id: providerID, category_id: selectedCategory?.id};
23
- const response = await dispatch(getServices({data}));
24
- } catch (error) {
25
- console.error('Error fetching services data:', error);
26
- } finally {
27
- setIsLoading(false);
28
- }
29
- };
30
-
31
- const refreshData = () => {
32
- fetchData();
33
- };
34
-
35
- return {
36
- isLoading,
37
- refreshData,
38
- fetchData,
39
- services,
40
- };
41
- }