@fadyshawky/react-native-magic 2.0.3 → 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,181 @@
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
+ });
@@ -0,0 +1,46 @@
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
+ }
@@ -0,0 +1,156 @@
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
+ }
@@ -0,0 +1,144 @@
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
+ });
@@ -0,0 +1,41 @@
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
+ }