@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
@@ -1,39 +1,34 @@
1
- import {useState, useEffect} from 'react';
2
- import {CarouselItem} from '../types';
3
-
1
+ import {useState} from 'react';
2
+ import {getCategories} from '../../../core/store/Categories/categoryActions';
3
+ import {clearSelectedCategory} from '../../../core/store/Categories/categorySlice';
4
+ import {getHomeProviders} from '../../../core/store/Providers/providersActions';
5
+ import {useAppDispatch, useAppSelector} from '../../../core/store/reduxHelpers';
6
+ import {RootState} from '../../../core/store/rootReducer';
7
+ import {getBalance} from '../../../core/store/user/userActions';
8
+ import {clearSelectedProvider} from '../../../core/store/Providers/providersSlice';
4
9
  export function useHomeData() {
5
10
  const [isLoading, setIsLoading] = useState(false);
6
- const [featuredItems, setFeaturedItems] = useState<CarouselItem[]>([]);
7
- const [trendingItems, setTrendingItems] = useState<CarouselItem[]>([]);
8
- const [newItems, setNewItems] = useState<CarouselItem[]>([]);
9
- const [recommendedItems, setRecommendedItems] = useState<CarouselItem[]>([]);
11
+ const dispatch = useAppDispatch();
12
+ const {categories, loadState} = useAppSelector(
13
+ (state: RootState) => state.categories,
14
+ );
15
+ const [isPayByCodeModalVisible, setIsPayByCodeModalVisible] = useState(false);
16
+ const {homeProviders} = useAppSelector((state: RootState) => state.providers);
17
+ const {user} = useAppSelector((state: RootState) => state.user);
10
18
 
11
19
  const fetchData = async () => {
12
20
  setIsLoading(true);
13
21
  try {
14
- // Simulate API calls
15
- // Replace with actual API calls in production
16
- setFeaturedItems([
17
- {
18
- id: '1',
19
- title: 'Featured Item 1',
20
- subtitle: 'Discover amazing features',
21
- imageUrl: 'https://picsum.photos/800/400',
22
- },
23
- // Add more items...
24
- ]);
25
-
26
- setTrendingItems([
27
- {
28
- id: '1',
29
- title: 'Trending Item 1',
30
- subtitle: 'Hot right now',
31
- imageUrl: 'https://picsum.photos/700/400',
32
- },
33
- // Add more items...
34
- ]);
35
-
36
- // Similar for newItems and recommendedItems...
22
+ const balance = await dispatch(getBalance());
23
+ if (balance.type.includes('fulfilled')) {
24
+ const categoryResponse = await dispatch(
25
+ getCategories({data: {limit: 30}}),
26
+ );
27
+ if (categoryResponse.type.includes('fulfilled')) {
28
+ const category_id = categoryResponse?.payload?.categories?.[0]?.id;
29
+ await dispatch(getHomeProviders({data: {category_id: category_id}}));
30
+ }
31
+ }
37
32
  } catch (error) {
38
33
  console.error('Error fetching home data:', error);
39
34
  } finally {
@@ -45,16 +40,15 @@ export function useHomeData() {
45
40
  fetchData();
46
41
  };
47
42
 
48
- useEffect(() => {
49
- fetchData();
50
- }, []);
51
-
52
43
  return {
53
44
  isLoading,
54
- featuredItems,
55
- trendingItems,
56
- newItems,
57
- recommendedItems,
58
45
  refreshData,
46
+ fetchData,
47
+ categories,
48
+ user,
49
+ homeProviders,
50
+ loadState,
51
+ isPayByCodeModalVisible,
52
+ setIsPayByCodeModalVisible,
59
53
  };
60
54
  }
@@ -0,0 +1,24 @@
1
+ // Authentication Screens
2
+ export {Login} from './Login/Login';
3
+ export {OTPScreen as OTP} from './OTP/OTPScreen';
4
+ export {ForceChangePasswordScreen as ForceChangePassword} from './ForceChangePassword/ForceChangePasswordScreen';
5
+
6
+ // Main Navigation Screens
7
+ export {HomeScreen as Home} from './home/HomeScreen';
8
+ export {Profile} from './profile/Profile';
9
+ export {Splash} from './splash/Splash';
10
+
11
+ // Service Related Screens
12
+ export {Categories} from './Categories/Categories';
13
+ export {Services} from './Services/Services';
14
+ export {SingleService} from './SingleService/SingleService';
15
+ export {Providers} from './Providers/Providers';
16
+ export {InquiredBill} from './InquiredBill/InquiredBill';
17
+ export {PaymentConfirmation} from './PaymentConfirmation/PaymentConfirmation';
18
+
19
+ // History and Receipt Screens
20
+ export {History} from './History/History';
21
+ export {Favorites} from './Favorites/Favorites';
22
+
23
+ // Device and Card Related Screens
24
+ export {ReceiptScreen} from './ReceiptScreen/ReceiptScreen';
@@ -1,5 +1,293 @@
1
- import React from 'react';
1
+ import React, {useState} from 'react';
2
+ import {
3
+ ScrollView,
4
+ StyleSheet,
5
+ Switch,
6
+ TouchableOpacity,
7
+ View,
8
+ Text,
9
+ Alert,
10
+ Image,
11
+ } from 'react-native';
12
+ import {ImageResources} from '../../common/ImageResources.g';
13
+ import {Container} from '../../common/components/Container';
14
+ import {RTLAwareText} from '../../common/components/RTLAwareText';
15
+ import {RTLAwareView} from '../../common/components/RTLAwareView';
16
+ import {
17
+ useLocalization,
18
+ useRTL,
19
+ useTranslation,
20
+ } from '../../common/localization/LocalizationProvider';
21
+ import {Languages} from '../../common/localization/localization';
22
+ import {useTheme} from '../../core/theme/ThemeProvider';
23
+ import {Theme} from '../../core/theme/types';
24
+ import {scaleWidth, scaleHeight} from '../../core/theme/scaling';
25
+ import {useAppDispatch, useAppSelector} from '../../core/store/reduxHelpers';
26
+ import {setProvidersLogout} from '../../core/store/Providers/providersSlice';
27
+ import {setServiceLogout} from '../../core/store/Services/servicesSlice';
28
+ import {setCategoriesLogout} from '../../core/store/Categories/categorySlice';
29
+ import {setLogout} from '../../core/store/user/userSlice';
30
+ import DeviceInfo from 'react-native-device-info';
31
+
32
+ function SwitchButton({
33
+ onValueChange,
34
+ value,
35
+ }: {
36
+ onValueChange: () => void;
37
+ value: boolean;
38
+ }) {
39
+ const {theme} = useTheme();
40
+ return (
41
+ <TouchableOpacity
42
+ onPressIn={() => {
43
+ onValueChange();
44
+ }}
45
+ style={{
46
+ width: scaleWidth(100),
47
+ height: scaleHeight(53),
48
+ backgroundColor: theme.colors.mutedLavender,
49
+ borderRadius: theme.borderRadius.xl,
50
+ paddingHorizontal: scaleWidth(5),
51
+ justifyContent: 'center',
52
+ alignItems: 'center',
53
+ }}>
54
+ <View
55
+ style={{
56
+ width: scaleWidth(42),
57
+ height: scaleWidth(42),
58
+ backgroundColor: theme.colors.indigoBlue,
59
+ borderRadius: theme.borderRadius.xl,
60
+ alignSelf: value ? 'flex-end' : 'flex-start',
61
+ }}
62
+ />
63
+ </TouchableOpacity>
64
+ );
65
+ }
2
66
 
3
67
  export function Profile(): JSX.Element {
4
- return <></>;
68
+ const {theme, toggleTheme} = useTheme();
69
+ const {currentLanguage, changeLanguage} = useLocalization();
70
+ const t = useTranslation();
71
+ const isRTL = useRTL();
72
+ const isArabic = currentLanguage === Languages.ar;
73
+ const isDarkMode = theme.mode === 'dark';
74
+ const {language: storedLanguage} = useAppSelector(state => state.app);
75
+ const dispatch = useAppDispatch();
76
+
77
+ const styles = createStyles(theme);
78
+
79
+ const handleLanguageToggle = () => {
80
+ const newLanguage = isArabic ? Languages.en : Languages.ar;
81
+
82
+ Alert.alert(
83
+ t('languageChangeTitle', 'profile'),
84
+ t('languageChangeMessage', 'profile'),
85
+ [
86
+ {
87
+ text: t('cancel', 'common'),
88
+ style: 'cancel',
89
+ },
90
+ {
91
+ text: t('change', 'common'),
92
+ onPress: () => changeLanguage(newLanguage),
93
+ },
94
+ ],
95
+ {cancelable: true},
96
+ );
97
+ };
98
+
99
+ function logout(): any {
100
+ throw new Error('Function not implemented.');
101
+ }
102
+
103
+ return (
104
+ <Container
105
+ backgroundImage={ImageResources[`${theme.mode}_background_1`]}
106
+ withoutPadding
107
+ backgroundColor={theme.colors.background}>
108
+ <ScrollView showsVerticalScrollIndicator={false}>
109
+ <View style={styles.titleSection}>
110
+ <RTLAwareText style={styles.mainTitle}>
111
+ {t('account', 'profile')}
112
+ </RTLAwareText>
113
+ </View>
114
+
115
+ <View style={styles.menuSection}>
116
+ <TouchableOpacity style={styles.menuItem}>
117
+ <View style={styles.menuItemLeft}>
118
+ <Image source={ImageResources.account} style={styles.menuIcon} />
119
+ <RTLAwareText style={theme.text.header2}>
120
+ {t('editProfile', 'profile')}
121
+ </RTLAwareText>
122
+ </View>
123
+ </TouchableOpacity>
124
+
125
+ <RTLAwareView style={styles.menuItem}>
126
+ <View
127
+ style={{
128
+ flexDirection: 'row',
129
+ alignItems: 'center',
130
+ justifyContent: 'space-between',
131
+ }}>
132
+ <Image
133
+ source={ImageResources.en}
134
+ style={{
135
+ ...styles.menuIcon,
136
+ marginRight: scaleWidth(10),
137
+ width: scaleWidth(48),
138
+ height: scaleWidth(48),
139
+ }}
140
+ />
141
+ <SwitchButton
142
+ onValueChange={handleLanguageToggle}
143
+ value={isArabic}
144
+ />
145
+ <Image
146
+ tintColor={theme.colors.tintColor}
147
+ source={ImageResources.ar}
148
+ style={{
149
+ ...styles.menuIcon,
150
+ marginLeft: scaleWidth(10),
151
+ width: scaleWidth(48),
152
+ height: scaleWidth(48),
153
+ }}
154
+ />
155
+ </View>
156
+ <View style={styles.menuItemLeft}>
157
+ <Image
158
+ tintColor={theme.colors.tintColor}
159
+ source={ImageResources.language}
160
+ style={styles.menuIcon}
161
+ />
162
+ <RTLAwareText style={theme.text.header2}>
163
+ {t('language', 'profile')}
164
+ </RTLAwareText>
165
+ </View>
166
+ </RTLAwareView>
167
+
168
+ <RTLAwareView style={styles.menuItem}>
169
+ <View
170
+ style={{
171
+ flexDirection: 'row',
172
+ alignItems: 'center',
173
+ justifyContent: 'space-between',
174
+ }}>
175
+ <Image
176
+ tintColor={theme.colors.tintColor}
177
+ source={ImageResources.light}
178
+ style={{
179
+ ...styles.menuIcon,
180
+ marginRight: scaleWidth(10),
181
+ width: scaleWidth(48),
182
+ height: scaleWidth(48),
183
+ }}
184
+ />
185
+ <SwitchButton onValueChange={toggleTheme} value={isDarkMode} />
186
+ <Image
187
+ tintColor={theme.colors.tintColor}
188
+ source={ImageResources.dark}
189
+ style={{
190
+ ...styles.menuIcon,
191
+ marginLeft: scaleWidth(10),
192
+ width: scaleWidth(48),
193
+ height: scaleWidth(48),
194
+ }}
195
+ />
196
+ </View>
197
+ <View style={styles.menuItemLeft}>
198
+ <Image
199
+ tintColor={theme.colors.tintColor}
200
+ source={ImageResources.display}
201
+ style={styles.menuIcon}
202
+ />
203
+ <RTLAwareText style={theme.text.header2}>
204
+ {t('darkMode', 'profile')}
205
+ </RTLAwareText>
206
+ </View>
207
+ </RTLAwareView>
208
+
209
+ <TouchableOpacity
210
+ onPressIn={() => {
211
+ dispatch(setProvidersLogout());
212
+ dispatch(setServiceLogout());
213
+ dispatch(setCategoriesLogout());
214
+ dispatch(setLogout());
215
+ }}
216
+ style={styles.menuItem}>
217
+ <View style={styles.menuItemLeft}>
218
+ <Image
219
+ source={ImageResources.services}
220
+ style={[styles.menuIcon, styles.logoutIcon]}
221
+ />
222
+ <RTLAwareText style={[theme.text.header2, styles.logoutText]}>
223
+ {t('logout', 'profile')}
224
+ </RTLAwareText>
225
+ </View>
226
+ </TouchableOpacity>
227
+ </View>
228
+ <RTLAwareText style={{...theme.text.body1, alignSelf: 'center'}}>
229
+ {DeviceInfo.getVersion()}
230
+ </RTLAwareText>
231
+ </ScrollView>
232
+ </Container>
233
+ );
5
234
  }
235
+
236
+ const createStyles = (theme: Theme) =>
237
+ StyleSheet.create({
238
+ titleSection: {
239
+ paddingHorizontal: scaleWidth(20),
240
+ paddingTop: scaleWidth(20),
241
+ paddingBottom: scaleWidth(10),
242
+ },
243
+ mainTitle: {
244
+ ...theme.text.header1,
245
+ marginBottom: scaleWidth(10),
246
+ },
247
+ menuSection: {
248
+ paddingHorizontal: scaleWidth(20),
249
+ paddingVertical: scaleWidth(10),
250
+ },
251
+ menuItem: {
252
+ flexDirection: 'row',
253
+ justifyContent: 'space-between',
254
+ alignItems: 'center',
255
+ paddingVertical: scaleWidth(15),
256
+ borderBottomWidth: 1,
257
+ borderBottomColor: theme.colors.shadow,
258
+ },
259
+ menuItemLeft: {
260
+ flexDirection: 'row',
261
+ alignItems: 'center',
262
+ },
263
+ menuIcon: {
264
+ width: scaleWidth(71),
265
+ height: scaleWidth(71),
266
+ marginRight: scaleWidth(15),
267
+ tintColor: theme.colors.tintColor,
268
+ resizeMode: 'contain',
269
+ },
270
+ menuText: {
271
+ ...theme.text.body1,
272
+ },
273
+ logoutText: {
274
+ color: theme.colors.red,
275
+ },
276
+ logoutIcon: {
277
+ tintColor: theme.colors.red,
278
+ },
279
+ languageOptions: {
280
+ flexDirection: 'row',
281
+ marginTop: scaleWidth(10),
282
+ },
283
+ languageOption: {
284
+ marginRight: scaleWidth(20),
285
+ paddingVertical: scaleWidth(5),
286
+ paddingHorizontal: scaleWidth(10),
287
+ borderRadius: theme.borderRadius.sm,
288
+ },
289
+ activeLanguage: {
290
+ backgroundColor: theme.colors.indigoBlue,
291
+ color: theme.colors.white,
292
+ },
293
+ });
@@ -0,0 +1,268 @@
1
+ import {NativeModules, Platform} from 'react-native';
2
+
3
+ const {SunmiPrinterInternal} = NativeModules;
4
+
5
+ // Create a wrapper with error handling
6
+ const SunmiPrinterInternalWrapper = {
7
+ // Check if the module is available
8
+ isAvailable: () => {
9
+ return (
10
+ !!SunmiPrinterInternal &&
11
+ typeof SunmiPrinterInternal === 'object' &&
12
+ Object.keys(SunmiPrinterInternal).length > 0
13
+ );
14
+ },
15
+
16
+ // Get the status of the printer
17
+ getStatus: async () => {
18
+ if (!SunmiPrinterInternalWrapper.isAvailable()) {
19
+ console.error('SunmiPrinterInternal module is not available');
20
+ return {
21
+ connected: false,
22
+ error: 'SunmiPrinterInternal module is not available',
23
+ };
24
+ }
25
+
26
+ try {
27
+ if (SunmiPrinterInternal.getStatus) {
28
+ return await SunmiPrinterInternal.getStatus();
29
+ } else {
30
+ return {
31
+ connected: false,
32
+ error: 'getStatus method is not available',
33
+ };
34
+ }
35
+ } catch (error) {
36
+ console.error('Error getting printer status:', error);
37
+ return {
38
+ connected: false,
39
+ error: error.message || 'Unknown error',
40
+ };
41
+ }
42
+ },
43
+
44
+ // Print text
45
+ printText: async text => {
46
+ if (!SunmiPrinterInternalWrapper.isAvailable()) {
47
+ console.error('SunmiPrinterInternal module is not available');
48
+ throw new Error('SunmiPrinterInternal module is not available');
49
+ }
50
+
51
+ if (!SunmiPrinterInternal.printText) {
52
+ console.error('printText method is not available');
53
+ throw new Error('printText method is not available');
54
+ }
55
+
56
+ try {
57
+ return await SunmiPrinterInternal.printText(text);
58
+ } catch (error) {
59
+ console.error('Error printing text:', error);
60
+ throw error;
61
+ }
62
+ },
63
+
64
+ // Print text with font
65
+ printTextWithFont: async (text, typeface = '', fontSize = 24) => {
66
+ if (!SunmiPrinterInternalWrapper.isAvailable()) {
67
+ console.error('SunmiPrinterInternal module is not available');
68
+ throw new Error('SunmiPrinterInternal module is not available');
69
+ }
70
+
71
+ if (!SunmiPrinterInternal.printTextWithFont) {
72
+ console.error('printTextWithFont method is not available');
73
+ throw new Error('printTextWithFont method is not available');
74
+ }
75
+
76
+ try {
77
+ return await SunmiPrinterInternal.printTextWithFont(
78
+ text,
79
+ typeface,
80
+ fontSize,
81
+ );
82
+ } catch (error) {
83
+ console.error('Error printing text with font:', error);
84
+ throw error;
85
+ }
86
+ },
87
+
88
+ // Print bold text
89
+ printBoldText: async text => {
90
+ if (!SunmiPrinterInternalWrapper.isAvailable()) {
91
+ console.error('SunmiPrinterInternal module is not available');
92
+ throw new Error('SunmiPrinterInternal module is not available');
93
+ }
94
+
95
+ if (!SunmiPrinterInternal.printBoldText) {
96
+ console.error('printBoldText method is not available');
97
+ throw new Error('printBoldText method is not available');
98
+ }
99
+
100
+ try {
101
+ return await SunmiPrinterInternal.printBoldText(text);
102
+ } catch (error) {
103
+ console.error('Error printing bold text:', error);
104
+ throw error;
105
+ }
106
+ },
107
+
108
+ // Print barcode
109
+ printBarCode: async (
110
+ data,
111
+ symbology = 8,
112
+ height = 80,
113
+ width = 2,
114
+ textPosition = 2,
115
+ ) => {
116
+ if (!SunmiPrinterInternalWrapper.isAvailable()) {
117
+ console.error('SunmiPrinterInternal module is not available');
118
+ throw new Error('SunmiPrinterInternal module is not available');
119
+ }
120
+
121
+ if (!SunmiPrinterInternal.printBarCode) {
122
+ console.error('printBarCode method is not available');
123
+ throw new Error('printBarCode method is not available');
124
+ }
125
+
126
+ try {
127
+ return await SunmiPrinterInternal.printBarCode(
128
+ data,
129
+ symbology,
130
+ height,
131
+ width,
132
+ textPosition,
133
+ );
134
+ } catch (error) {
135
+ console.error('Error printing barcode:', error);
136
+ throw error;
137
+ }
138
+ },
139
+
140
+ // Print QR code
141
+ printQRCode: async (data, moduleSize = 8, errorLevel = 0) => {
142
+ if (!SunmiPrinterInternalWrapper.isAvailable()) {
143
+ console.error('SunmiPrinterInternal module is not available');
144
+ throw new Error('SunmiPrinterInternal module is not available');
145
+ }
146
+
147
+ if (!SunmiPrinterInternal.printQRCode) {
148
+ console.error('printQRCode method is not available');
149
+ throw new Error('printQRCode method is not available');
150
+ }
151
+
152
+ try {
153
+ return await SunmiPrinterInternal.printQRCode(
154
+ data,
155
+ moduleSize,
156
+ errorLevel,
157
+ );
158
+ } catch (error) {
159
+ console.error('Error printing QR code:', error);
160
+ throw error;
161
+ }
162
+ },
163
+
164
+ // Print image
165
+ printImage: async base64Image => {
166
+ if (!SunmiPrinterInternalWrapper.isAvailable()) {
167
+ console.error('SunmiPrinterInternal module is not available');
168
+ throw new Error('SunmiPrinterInternal module is not available');
169
+ }
170
+
171
+ if (!SunmiPrinterInternal.printImage) {
172
+ console.error('printImage method is not available');
173
+ throw new Error('printImage method is not available');
174
+ }
175
+
176
+ try {
177
+ return await SunmiPrinterInternal.printImage(base64Image);
178
+ } catch (error) {
179
+ console.error('Error printing image:', error);
180
+ throw error;
181
+ }
182
+ },
183
+
184
+ // Line wrap
185
+ lineWrap: async (lines = 3) => {
186
+ if (!SunmiPrinterInternalWrapper.isAvailable()) {
187
+ console.error('SunmiPrinterInternal module is not available');
188
+ throw new Error('SunmiPrinterInternal module is not available');
189
+ }
190
+
191
+ if (!SunmiPrinterInternal.lineWrap) {
192
+ console.error('lineWrap method is not available');
193
+ throw new Error('lineWrap method is not available');
194
+ }
195
+
196
+ try {
197
+ return await SunmiPrinterInternal.lineWrap(lines);
198
+ } catch (error) {
199
+ console.error('Error line wrapping:', error);
200
+ throw error;
201
+ }
202
+ },
203
+
204
+ // Cut paper
205
+ cutPaper: async () => {
206
+ if (!SunmiPrinterInternalWrapper.isAvailable()) {
207
+ console.error('SunmiPrinterInternal module is not available');
208
+ throw new Error('SunmiPrinterInternal module is not available');
209
+ }
210
+
211
+ if (!SunmiPrinterInternal.cutPaper) {
212
+ console.error('cutPaper method is not available');
213
+ throw new Error('cutPaper method is not available');
214
+ }
215
+
216
+ try {
217
+ return await SunmiPrinterInternal.cutPaper();
218
+ } catch (error) {
219
+ console.error('Error cutting paper:', error);
220
+ throw error;
221
+ }
222
+ },
223
+
224
+ // Print receipt
225
+ printReceipt: async receiptData => {
226
+ if (!SunmiPrinterInternalWrapper.isAvailable()) {
227
+ console.error('SunmiPrinterInternal module is not available');
228
+ throw new Error('SunmiPrinterInternal module is not available');
229
+ }
230
+
231
+ try {
232
+ // Print header
233
+ await SunmiPrinterInternalWrapper.printBoldText(receiptData.header);
234
+ await SunmiPrinterInternalWrapper.lineWrap(1);
235
+
236
+ // Print items
237
+ for (const item of receiptData.items) {
238
+ await SunmiPrinterInternalWrapper.printText(
239
+ `${item.name} x${item.quantity} $${item.price}`,
240
+ );
241
+ }
242
+
243
+ await SunmiPrinterInternalWrapper.lineWrap(1);
244
+
245
+ // Print total
246
+ await SunmiPrinterInternalWrapper.printBoldText(
247
+ `Total: $${receiptData.total}`,
248
+ );
249
+
250
+ // Print footer
251
+ await SunmiPrinterInternalWrapper.lineWrap(2);
252
+ await SunmiPrinterInternalWrapper.printText(receiptData.footer);
253
+
254
+ // Cut paper
255
+ await SunmiPrinterInternalWrapper.lineWrap(3);
256
+ if (SunmiPrinterInternal.cutPaper) {
257
+ await SunmiPrinterInternalWrapper.cutPaper();
258
+ }
259
+
260
+ return true;
261
+ } catch (error) {
262
+ console.error('Error printing receipt:', error);
263
+ throw error;
264
+ }
265
+ },
266
+ };
267
+
268
+ export default SunmiPrinterInternalWrapper;
@@ -0,0 +1,20 @@
1
+ declare module 'SunmiPrepaid' {
2
+ interface PrepaidResponse {
3
+ success: boolean;
4
+ message: string;
5
+ }
6
+
7
+ interface ServiceStatus {
8
+ isInitialized: boolean;
9
+ }
10
+
11
+ export interface SunmiPrepaidInterface {
12
+ initializePrepaid(): Promise<PrepaidResponse>;
13
+ initializeUtilityType(utilityType: string): Promise<PrepaidResponse>;
14
+ forceCardFacadeDetection(): Promise<PrepaidResponse>;
15
+ getServiceStatus(): Promise<ServiceStatus>;
16
+ }
17
+
18
+ const SunmiPrepaid: SunmiPrepaidInterface;
19
+ export default SunmiPrepaid;
20
+ }