@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.
- package/package.json +1 -1
- package/template/src/common/ImageResources.g.ts +33 -1
- package/template/src/common/components/Background.tsx +3 -1
- package/template/src/common/components/Container.tsx +1 -1
- package/template/src/common/components/OTPInput.tsx +3 -2
- package/template/src/common/components/PrimaryButton.tsx +23 -23
- package/template/src/common/components/PrimaryTextInput.tsx +189 -199
- package/template/src/common/components/RadioIcon.tsx +4 -4
- package/template/src/common/components/SafeText.tsx +41 -0
- package/template/src/common/components/SearchBar.tsx +19 -17
- package/template/src/common/components/TryAgain.tsx +3 -3
- package/template/src/common/localization/localization.ts +10 -0
- package/template/src/common/localization/translations/commonLocalization.ts +97 -0
- package/template/src/common/localization/translations/homeLocalization.ts +24 -0
- package/template/src/common/localization/translations/loginLocalization.ts +28 -2
- package/template/src/common/localization/translations/mainNavigationLocalization.ts +30 -0
- package/template/src/common/localization/translations/navigationLocalization.ts +48 -0
- package/template/src/common/localization/translations/otpLocalization.ts +28 -0
- package/template/src/common/localization/translations/passwordLocalization.ts +54 -0
- package/template/src/common/localization/translations/posLocalization.ts +196 -0
- package/template/src/common/utils/FeesCaalculation.tsx +37 -0
- package/template/src/common/utils/index.tsx +11 -0
- package/template/src/common/utils/printData.tsx +161 -0
- package/template/src/common/validations/errorValidations.ts +3 -2
- package/template/src/components/PrinterExample.js +226 -0
- package/template/src/core/api/serverHeaders.ts +62 -1
- package/template/src/core/store/Categories/categoryActions.ts +33 -0
- package/template/src/core/store/Categories/categorySlice.ts +75 -0
- package/template/src/core/store/Categories/categoryState.ts +41 -0
- package/template/src/core/store/Providers/providersActions.ts +102 -0
- package/template/src/core/store/Providers/providersSlice.ts +136 -0
- package/template/src/core/store/Providers/providersState.ts +37 -0
- package/template/src/core/store/Services/servicesActions.ts +191 -0
- package/template/src/core/store/Services/servicesSlice.ts +205 -0
- package/template/src/core/store/Services/servicesState.ts +466 -0
- package/template/src/core/store/app/appSlice.ts +13 -5
- package/template/src/core/store/app/appState.ts +10 -2
- package/template/src/core/store/rootReducer.ts +6 -1
- package/template/src/core/store/store.tsx +55 -2
- package/template/src/core/store/user/userActions.ts +164 -26
- package/template/src/core/store/user/userSlice.ts +193 -21
- package/template/src/core/store/user/userState.ts +148 -25
- package/template/src/core/theme/colors.ts +70 -94
- package/template/src/core/theme/commonConsts.ts +1 -1
- package/template/src/core/theme/commonSizes.ts +94 -119
- package/template/src/core/theme/commonStyles.ts +22 -22
- package/template/src/core/theme/fonts.ts +14 -13
- package/template/src/core/theme/themes.ts +75 -386
- package/template/src/core/theme/types.ts +15 -201
- package/template/src/core/utils/stringUtils.ts +114 -0
- package/template/src/modules/SunmiCard.js +212 -0
- package/template/src/modules/SunmiPrepaid.ts +122 -0
- package/template/src/navigation/AuthStack.tsx +8 -0
- package/template/src/navigation/HeaderComponents.tsx +76 -1
- package/template/src/navigation/MainNavigation.tsx +3 -1
- package/template/src/navigation/MainStack.tsx +130 -56
- package/template/src/navigation/TabBar.tsx +111 -59
- package/template/src/navigation/types.ts +24 -0
- package/template/src/screens/Categories/Categories.tsx +141 -0
- package/template/src/screens/Categories/hooks/useCategoriesData.ts +33 -0
- package/template/src/screens/Categories/types.ts +7 -0
- package/template/src/screens/Favorites/Favorites.tsx +130 -0
- package/template/src/screens/ForceChangePassword/ForceChangePasswordScreen.tsx +155 -0
- package/template/src/screens/History/History.tsx +430 -0
- package/template/src/screens/History/hooks/useHistoryData.ts +49 -0
- package/template/src/screens/History/types.ts +7 -0
- package/template/src/screens/InquiredBill/InquiredBill.tsx +443 -0
- package/template/src/screens/InquiredBill/hooks/useInquiredData.ts +91 -0
- package/template/src/screens/Login/Login.tsx +85 -85
- package/template/src/screens/OTP/OTPScreen.tsx +170 -0
- package/template/src/screens/PaymentConfirmation/PaymentConfirmation.tsx +326 -0
- package/template/src/screens/Providers/Providers.tsx +166 -0
- package/template/src/screens/Providers/hooks/useProvidersData.ts +33 -0
- package/template/src/screens/Providers/types.ts +7 -0
- package/template/src/screens/ReceiptScreen/ReceiptScreen.tsx +181 -0
- package/template/src/screens/ReceiptScreen/hooks/useReceiptData.ts +46 -0
- package/template/src/screens/ReceiptScreen/utils/utils.tsx +156 -0
- package/template/src/screens/Services/Services.tsx +144 -0
- package/template/src/screens/Services/hooks/useServicesData.ts +41 -0
- package/template/src/screens/SingleService/Components/FawryInputs.tsx +446 -0
- package/template/src/screens/SingleService/SingleService.tsx +229 -0
- package/template/src/screens/SingleService/hooks/useServiceData.ts +164 -0
- package/template/src/screens/home/Components/PayByCode.tsx +129 -0
- package/template/src/screens/home/HomeScreen.tsx +268 -77
- package/template/src/screens/home/hooks/useHomeData.ts +32 -38
- package/template/src/screens/index.tsx +24 -0
- package/template/src/screens/profile/Profile.tsx +290 -2
- package/template/src/services/SunmiPrinterInternal.js +268 -0
- package/template/src/types/sunmiPrepaid.d.ts +20 -0
- package/template/src/utils/SunmiPrinter.ts +442 -0
- package/template/src/utils/feesCalculator.ts +92 -0
- package/template/src/common/components/Stepper.tsx +0 -153
- package/template/src/common/components/Svg.tsx +0 -25
- package/template/src/common/hooks/useDebounce.ts +0 -17
- package/template/src/common/hooks/usePrevious.ts +0 -11
- package/template/src/common/localization/intlFormatter.ts +0 -37
- package/template/src/common/urls/emailUrl.ts +0 -20
- package/template/src/common/urls/mapUrl.ts +0 -22
- package/template/src/common/utils/listHandlers.ts +0 -30
- package/template/src/common/utils/serializeQueryParams.ts +0 -10
- package/template/src/common/validations/hooks/useDatesError.ts +0 -40
- package/template/src/common/validations/profileValidations.ts +0 -30
- package/template/src/core/theme/shadows.ts +0 -135
- package/template/src/navigation/TopTabBar.tsx +0 -77
- package/template/src/screens/Settings/Settings.tsx +0 -5
- package/template/src/screens/home/components/CarouselSection.tsx +0 -79
- package/template/src/screens/home/components/FeaturedCarousel.tsx +0 -128
- package/template/src/screens/main/Main.tsx +0 -5
- package/template/src/screens/registration/RegistrationScreen.tsx +0 -198
- package/template/src/screens/resetPassword/ForgotPasswordScreen.tsx +0 -129
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
import {Alert, NativeModules} from 'react-native';
|
|
2
|
+
import {normalizeAndTrimWhitespace} from '../common/helpers/stringsHelpers';
|
|
3
|
+
import {decryptTripleDES} from '../core/utils/stringUtils';
|
|
4
|
+
import StringBuilder from './stringBuilder';
|
|
5
|
+
const {SunmiPrinter} = NativeModules;
|
|
6
|
+
|
|
7
|
+
// Localized messages for printer status
|
|
8
|
+
const PRINTER_MESSAGES = {
|
|
9
|
+
en: {
|
|
10
|
+
printerStatus_1: 'The printer works normally',
|
|
11
|
+
printerStatus_2: 'Preparing printer',
|
|
12
|
+
printerStatus_3: 'Abnormal communication',
|
|
13
|
+
printerStatus_4: 'The printer is out of paper',
|
|
14
|
+
printerStatus_5: 'Printer overheated',
|
|
15
|
+
printerStatus_6: 'Printer cover is open',
|
|
16
|
+
printerStatus_7: 'Unknown printer error',
|
|
17
|
+
},
|
|
18
|
+
ar: {
|
|
19
|
+
printerStatus_1: 'الطابعة تعمل بشكل طبيعي',
|
|
20
|
+
printerStatus_2: 'جاري تجهيز الطابعة',
|
|
21
|
+
printerStatus_3: 'خطأ في الاتصال بالطابعة',
|
|
22
|
+
printerStatus_4: 'نفذ الورق من الطابعة',
|
|
23
|
+
printerStatus_5: 'الطابعة ساخنة جداً',
|
|
24
|
+
printerStatus_6: 'غطاء الطابعة مفتوح',
|
|
25
|
+
printerStatus_7: 'خطأ غير معروف في الطابعة',
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
interface PrintDataItem {
|
|
30
|
+
type:
|
|
31
|
+
| 'image'
|
|
32
|
+
| 'header1'
|
|
33
|
+
| 'header2'
|
|
34
|
+
| 'body'
|
|
35
|
+
| 'extra_description'
|
|
36
|
+
| 'body_title'
|
|
37
|
+
| 'description';
|
|
38
|
+
value: string;
|
|
39
|
+
label?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Get localized message based on current language
|
|
43
|
+
const getMessage = (key: keyof typeof PRINTER_MESSAGES.en) => {
|
|
44
|
+
// You can get the current language from your app's settings
|
|
45
|
+
// For now, we'll use Arabic as default
|
|
46
|
+
const currentLanguage = 'ar';
|
|
47
|
+
return PRINTER_MESSAGES[currentLanguage][key];
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
type StatusMessageKey =
|
|
51
|
+
| 'printerStatus_1'
|
|
52
|
+
| 'printerStatus_2'
|
|
53
|
+
| 'printerStatus_3'
|
|
54
|
+
| 'printerStatus_4'
|
|
55
|
+
| 'printerStatus_5'
|
|
56
|
+
| 'printerStatus_6'
|
|
57
|
+
| 'printerStatus_7';
|
|
58
|
+
|
|
59
|
+
function createRowSpaces(
|
|
60
|
+
fontSize: number,
|
|
61
|
+
leftText: string,
|
|
62
|
+
rightText: string,
|
|
63
|
+
) {
|
|
64
|
+
const paperWidth = 390;
|
|
65
|
+
// Calculate character width based on paper width and font size
|
|
66
|
+
const charWidth = 12 * (fontSize / 24); // Base char width is 12px at 24pt
|
|
67
|
+
const maxChars = Math.floor(paperWidth / charWidth);
|
|
68
|
+
|
|
69
|
+
// Format the text with proper spacing
|
|
70
|
+
let row = new StringBuilder();
|
|
71
|
+
|
|
72
|
+
// Truncate texts if they're too long (leaving space for at least 2 characters on each side)
|
|
73
|
+
const maxLeftWidth = maxChars; // Reserve at least 2 chars for right text
|
|
74
|
+
const maxRightWidth = maxChars; // Reserve at least 2 chars for left text
|
|
75
|
+
|
|
76
|
+
const leftPart =
|
|
77
|
+
leftText.length > maxLeftWidth
|
|
78
|
+
? leftText.substring(0, maxLeftWidth)
|
|
79
|
+
: leftText;
|
|
80
|
+
const rightPart =
|
|
81
|
+
rightText.length > maxRightWidth
|
|
82
|
+
? rightText.substring(0, maxRightWidth)
|
|
83
|
+
: rightText;
|
|
84
|
+
// Calculate spacing
|
|
85
|
+
const totalTextLength = leftPart.length + rightPart.length;
|
|
86
|
+
const spacesNeeded = maxChars - totalTextLength;
|
|
87
|
+
|
|
88
|
+
// Build the row with proper spacing
|
|
89
|
+
row.append(leftPart);
|
|
90
|
+
for (let i = 0; i < spacesNeeded; i++) {
|
|
91
|
+
row.append(' ');
|
|
92
|
+
}
|
|
93
|
+
row.append(rightPart);
|
|
94
|
+
|
|
95
|
+
return row.toString();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export const onBeePrint = async (data: any) => {
|
|
99
|
+
try {
|
|
100
|
+
await SunmiPrinter.prepare();
|
|
101
|
+
await SunmiPrinter.printerInit();
|
|
102
|
+
await SunmiPrinter.setFontStyle('bold', true);
|
|
103
|
+
|
|
104
|
+
const status = await SunmiPrinter.getPrinterStatus();
|
|
105
|
+
|
|
106
|
+
if (status !== 1) {
|
|
107
|
+
Alert.alert(
|
|
108
|
+
getMessage(`printerStatus_${status}` as StatusMessageKey) ||
|
|
109
|
+
getMessage('printerStatus_7'),
|
|
110
|
+
);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Print the logo at the top
|
|
115
|
+
|
|
116
|
+
let linesText = [];
|
|
117
|
+
let linesAligns = [];
|
|
118
|
+
let linesWidths = [];
|
|
119
|
+
let linesFontSizes = [];
|
|
120
|
+
|
|
121
|
+
for (let i = 0; i < data?.length; i++) {
|
|
122
|
+
if (data[i].image) {
|
|
123
|
+
if (linesText.length > 0) {
|
|
124
|
+
await SunmiPrinter.printColumnsText(
|
|
125
|
+
linesText,
|
|
126
|
+
linesWidths,
|
|
127
|
+
linesAligns,
|
|
128
|
+
linesFontSizes,
|
|
129
|
+
);
|
|
130
|
+
// Clear the arrays after printing
|
|
131
|
+
linesText = [];
|
|
132
|
+
linesAligns = [];
|
|
133
|
+
linesWidths = [];
|
|
134
|
+
linesFontSizes = [];
|
|
135
|
+
}
|
|
136
|
+
// Print the image
|
|
137
|
+
await printImage();
|
|
138
|
+
} else if (data[i].middle) {
|
|
139
|
+
linesText.push(`${data[i].middle}\n`);
|
|
140
|
+
linesAligns.push(1); // Center align
|
|
141
|
+
linesWidths.push(100);
|
|
142
|
+
linesFontSizes.push(34);
|
|
143
|
+
} else if (data[i].middleEnd) {
|
|
144
|
+
linesText.push(`${data[i].middleEnd}\n`);
|
|
145
|
+
linesAligns.push(1); // Center align
|
|
146
|
+
linesWidths.push(100);
|
|
147
|
+
linesFontSizes.push(data[i].fontSize || 34);
|
|
148
|
+
} else if (data[i].line) {
|
|
149
|
+
linesText.push(`--------------------------------\n`);
|
|
150
|
+
linesAligns.push(0); // Left align
|
|
151
|
+
linesWidths.push(384);
|
|
152
|
+
linesFontSizes.push(24);
|
|
153
|
+
} else if (data[i].powered) {
|
|
154
|
+
if (data[i].powered !== '-1') {
|
|
155
|
+
linesText.push(`${data[i].powered}\n`);
|
|
156
|
+
linesAligns.push(1); // Center align
|
|
157
|
+
linesWidths.push(100);
|
|
158
|
+
linesFontSizes.push(data[i].fontSize || 24);
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
const row = createRowSpaces(
|
|
162
|
+
24,
|
|
163
|
+
String(data[i].right) || '',
|
|
164
|
+
String(normalizeAndTrimWhitespace(data[i].left)) || '',
|
|
165
|
+
);
|
|
166
|
+
linesText.push(`${row}\n`);
|
|
167
|
+
linesAligns.push(1); // Center align
|
|
168
|
+
linesWidths.push(384);
|
|
169
|
+
linesFontSizes.push(24);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (linesText.length > 0) {
|
|
174
|
+
await SunmiPrinter.printColumnsText(
|
|
175
|
+
linesText,
|
|
176
|
+
linesWidths,
|
|
177
|
+
linesAligns,
|
|
178
|
+
linesFontSizes,
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Add minimal spacing at the end for paper cutting
|
|
183
|
+
await SunmiPrinter.lineWrap(3);
|
|
184
|
+
} catch (error) {
|
|
185
|
+
console.error('Printing error:', error);
|
|
186
|
+
|
|
187
|
+
// Display all keys and values from the error object
|
|
188
|
+
if (error && typeof error === 'object') {
|
|
189
|
+
console.error('Error details:');
|
|
190
|
+
for (const [key, value] of Object.entries(error)) {
|
|
191
|
+
console.error(`${key}: ${value}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
Alert.alert('Error', error.message || 'An unexpected error occurred');
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
export const onPrint = async (
|
|
200
|
+
data: {type: string; value: string; label?: string}[],
|
|
201
|
+
) => {
|
|
202
|
+
try {
|
|
203
|
+
// Initialize printer
|
|
204
|
+
await SunmiPrinter.prepare();
|
|
205
|
+
await SunmiPrinter.printerInit();
|
|
206
|
+
await SunmiPrinter.setFontStyle('bold', true);
|
|
207
|
+
|
|
208
|
+
const status = await SunmiPrinter.getPrinterStatus();
|
|
209
|
+
|
|
210
|
+
if (status !== 1) {
|
|
211
|
+
Alert.alert(
|
|
212
|
+
getMessage(`printerStatus_${status}` as StatusMessageKey) ||
|
|
213
|
+
getMessage('printerStatus_7'),
|
|
214
|
+
);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
let linesText = [];
|
|
219
|
+
let linesAligns = [];
|
|
220
|
+
let linesWidths = [];
|
|
221
|
+
let linesFontSizes = [];
|
|
222
|
+
|
|
223
|
+
for (let i = 0; i < data?.length; i++) {
|
|
224
|
+
if (data[i].type === 'image') {
|
|
225
|
+
// First print any accumulated text
|
|
226
|
+
if (linesText.length > 0) {
|
|
227
|
+
await SunmiPrinter.printColumnsText(
|
|
228
|
+
linesText,
|
|
229
|
+
linesWidths,
|
|
230
|
+
linesAligns,
|
|
231
|
+
linesFontSizes,
|
|
232
|
+
);
|
|
233
|
+
// Clear the arrays after printing
|
|
234
|
+
linesText = [];
|
|
235
|
+
linesAligns = [];
|
|
236
|
+
linesWidths = [];
|
|
237
|
+
linesFontSizes = [];
|
|
238
|
+
}
|
|
239
|
+
// Print the image
|
|
240
|
+
await printImage();
|
|
241
|
+
} else if (data[i].type === 'header1') {
|
|
242
|
+
linesText.push(`${normalizeAndTrimWhitespace(data[i].value)}\n`);
|
|
243
|
+
linesAligns.push(1);
|
|
244
|
+
linesWidths.push(100);
|
|
245
|
+
linesFontSizes.push(28);
|
|
246
|
+
} else if (data[i].type === 'header2') {
|
|
247
|
+
linesText.push(`${normalizeAndTrimWhitespace(data[i].value)}\n`);
|
|
248
|
+
linesAligns.push(1);
|
|
249
|
+
linesWidths.push(100);
|
|
250
|
+
linesFontSizes.push(28);
|
|
251
|
+
} else if (
|
|
252
|
+
data[i].type === 'body' ||
|
|
253
|
+
data[i].type === 'extra_description'
|
|
254
|
+
) {
|
|
255
|
+
const row = createRowSpaces(
|
|
256
|
+
24,
|
|
257
|
+
String(data[i].label) || '',
|
|
258
|
+
String(normalizeAndTrimWhitespace(data[i].value)) || '',
|
|
259
|
+
);
|
|
260
|
+
linesText.push(`${row}\n`);
|
|
261
|
+
linesAligns.push(1);
|
|
262
|
+
linesWidths.push(384);
|
|
263
|
+
linesFontSizes.push(24);
|
|
264
|
+
} else if (data[i].type === 'body_title') {
|
|
265
|
+
linesText.push(`--------------------------------\n`);
|
|
266
|
+
const row = createRowSpaces(
|
|
267
|
+
30,
|
|
268
|
+
String(data[i].label) || '',
|
|
269
|
+
String(normalizeAndTrimWhitespace(data[i].value)) || '',
|
|
270
|
+
);
|
|
271
|
+
linesText.push(`${row}\n`);
|
|
272
|
+
linesAligns.push(1);
|
|
273
|
+
linesAligns.push(1);
|
|
274
|
+
linesWidths.push(384);
|
|
275
|
+
linesWidths.push(384);
|
|
276
|
+
linesFontSizes.push(24);
|
|
277
|
+
linesFontSizes.push(30);
|
|
278
|
+
} else if (data[i].type === 'description') {
|
|
279
|
+
linesText.push(`--------------------------------\n`);
|
|
280
|
+
if (data[i].label && data[i].label !== 'VouchPIN') {
|
|
281
|
+
linesText.push(`${data[i].label}\n`);
|
|
282
|
+
linesAligns.push(1);
|
|
283
|
+
linesWidths.push(384);
|
|
284
|
+
linesFontSizes.push(24);
|
|
285
|
+
}
|
|
286
|
+
linesText.push(
|
|
287
|
+
`${
|
|
288
|
+
data[i].label === 'VouchPIN'
|
|
289
|
+
? decryptTripleDES(
|
|
290
|
+
data[i].value,
|
|
291
|
+
'8pe/hqinrZQV6pHNkQ0WwbD0ZHkaAbbj',
|
|
292
|
+
)
|
|
293
|
+
: normalizeAndTrimWhitespace(data[i].value)
|
|
294
|
+
}\n`,
|
|
295
|
+
);
|
|
296
|
+
linesAligns.push(1);
|
|
297
|
+
linesAligns.push(1);
|
|
298
|
+
linesWidths.push(384);
|
|
299
|
+
linesWidths.push(100);
|
|
300
|
+
linesFontSizes.push(24);
|
|
301
|
+
linesFontSizes.push(24);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Print any remaining text
|
|
306
|
+
if (linesText.length > 0) {
|
|
307
|
+
await SunmiPrinter.printColumnsText(
|
|
308
|
+
linesText,
|
|
309
|
+
linesWidths,
|
|
310
|
+
linesAligns,
|
|
311
|
+
linesFontSizes,
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Add minimal spacing at the end for paper cutting
|
|
316
|
+
await SunmiPrinter.lineWrap(3);
|
|
317
|
+
} catch (error) {
|
|
318
|
+
console.error('Printing error:', error);
|
|
319
|
+
|
|
320
|
+
// Display all keys and values from the error object
|
|
321
|
+
if (error && typeof error === 'object') {
|
|
322
|
+
console.error('Error details:');
|
|
323
|
+
for (const [key, value] of Object.entries(error)) {
|
|
324
|
+
console.error(`${key}: ${value}`);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Display a user-friendly alert with the error message
|
|
329
|
+
const errorMessage = error.message || 'An unexpected error occurred';
|
|
330
|
+
Alert.alert('Error', errorMessage);
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
// Helper function to print a single row with left and right aligned text
|
|
335
|
+
export const printRow = async (
|
|
336
|
+
leftText: string,
|
|
337
|
+
rightText: string,
|
|
338
|
+
fontSize = 24,
|
|
339
|
+
) => {
|
|
340
|
+
try {
|
|
341
|
+
await SunmiPrinter.printRowText(leftText || '', rightText || '', fontSize);
|
|
342
|
+
// Add a small line wrap after each row
|
|
343
|
+
await SunmiPrinter.lineWrap(1);
|
|
344
|
+
} catch (error) {
|
|
345
|
+
console.error('Row printing error:', error);
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
// Helper function to feed paper
|
|
350
|
+
export const feedPaper = async (lines = 1) => {
|
|
351
|
+
try {
|
|
352
|
+
await SunmiPrinter.lineWrap(lines);
|
|
353
|
+
} catch (error) {
|
|
354
|
+
console.error('Paper feed error:', error);
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
// Function to convert image to base64 and print it
|
|
359
|
+
export const printImage = async (width: number = 384) => {
|
|
360
|
+
try {
|
|
361
|
+
// Get the image dimensions
|
|
362
|
+
// const image = Image.resolveAssetSource(
|
|
363
|
+
// ImageResources.receipt_logo_transparent,
|
|
364
|
+
// );
|
|
365
|
+
|
|
366
|
+
// if (!image || !image.uri) {
|
|
367
|
+
// throw new Error('Image asset not found or URI is invalid');
|
|
368
|
+
// }
|
|
369
|
+
|
|
370
|
+
// // Convert image to base64
|
|
371
|
+
// const response = await fetch(image.uri);
|
|
372
|
+
// if (!response.ok) {
|
|
373
|
+
// throw new Error(`Failed to fetch image: ${response.statusText}`);
|
|
374
|
+
// }
|
|
375
|
+
|
|
376
|
+
// const blob = await response.blob();
|
|
377
|
+
// const base64 = await new Promise((resolve, reject) => {
|
|
378
|
+
// const reader = new FileReader();
|
|
379
|
+
// reader.onload = () => resolve(reader.result);
|
|
380
|
+
// reader.onerror = error => {
|
|
381
|
+
// console.error('FileReader error:', error);
|
|
382
|
+
// reject(error);
|
|
383
|
+
// };
|
|
384
|
+
// reader.readAsDataURL(blob);
|
|
385
|
+
// });
|
|
386
|
+
|
|
387
|
+
// Remove the data URL prefix (e.g., "data:image/png;base64,")
|
|
388
|
+
const base64Data =
|
|
389
|
+
'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';
|
|
390
|
+
|
|
391
|
+
// Print the image
|
|
392
|
+
await SunmiPrinter.printLogoText(base64Data, width);
|
|
393
|
+
await feedPaper(2); // Add some space after the image
|
|
394
|
+
} catch (error) {
|
|
395
|
+
console.error('Error printing image:', error);
|
|
396
|
+
|
|
397
|
+
// Display all keys and values from the error object
|
|
398
|
+
if (error && typeof error === 'object') {
|
|
399
|
+
console.error('Error details:');
|
|
400
|
+
for (const [key, value] of Object.entries(error)) {
|
|
401
|
+
console.error(`${key}: ${value}`);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
throw error;
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
export const SunmiPrinterModule = {
|
|
410
|
+
printColumnsText: async (
|
|
411
|
+
texts: string[],
|
|
412
|
+
widths: number[],
|
|
413
|
+
aligns: number[],
|
|
414
|
+
fontSizes: number[] = Array(texts.length).fill(24), // Default all to 24 if not provided
|
|
415
|
+
): Promise<void> => {
|
|
416
|
+
return new Promise((resolve, reject) => {
|
|
417
|
+
SunmiPrinter.printColumnsText(
|
|
418
|
+
texts,
|
|
419
|
+
widths,
|
|
420
|
+
aligns,
|
|
421
|
+
fontSizes,
|
|
422
|
+
(error: any) => {
|
|
423
|
+
if (error) {
|
|
424
|
+
reject(error);
|
|
425
|
+
} else {
|
|
426
|
+
resolve();
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
);
|
|
430
|
+
});
|
|
431
|
+
},
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
// Example function showing how to use printColumnsText with different font sizes
|
|
435
|
+
export const printExampleReceipt = async () => {
|
|
436
|
+
await SunmiPrinter.printColumnsText(
|
|
437
|
+
['Item\n', 'Price\n', 'Qty\n'],
|
|
438
|
+
[100, 100, 100],
|
|
439
|
+
[0, 2, 1], // 0=left, 1=center, 2=right
|
|
440
|
+
[24, 32, 24], // Different font sizes for each column
|
|
441
|
+
);
|
|
442
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import React, {Dispatch, SetStateAction} from 'react';
|
|
2
|
+
|
|
3
|
+
interface FeeTier {
|
|
4
|
+
LowerAmt: number;
|
|
5
|
+
UpperAmt: number;
|
|
6
|
+
FixedAmt: {
|
|
7
|
+
Amt: number;
|
|
8
|
+
CurCode: string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface FeesCalculationResult {
|
|
13
|
+
amount: number;
|
|
14
|
+
vat_value: number;
|
|
15
|
+
total: number;
|
|
16
|
+
currencyCode: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Calculate from amount to total (forward calculation)
|
|
20
|
+
export const calculateFeesForward = (
|
|
21
|
+
amount: string | number,
|
|
22
|
+
vat_value: number,
|
|
23
|
+
currencyCode: string,
|
|
24
|
+
): FeesCalculationResult => {
|
|
25
|
+
const numericAmount =
|
|
26
|
+
typeof amount === 'string' ? parseFloat(amount) || 0 : amount;
|
|
27
|
+
const total = numericAmount / vat_value;
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
amount: numericAmount,
|
|
31
|
+
vat_value,
|
|
32
|
+
total,
|
|
33
|
+
currencyCode,
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Calculate from total to amount (backward calculation)
|
|
38
|
+
export const calculateFeesBackward = (
|
|
39
|
+
total: string | number,
|
|
40
|
+
vat_value: number,
|
|
41
|
+
currencyCode: string,
|
|
42
|
+
): FeesCalculationResult => {
|
|
43
|
+
const numericTotal =
|
|
44
|
+
typeof total === 'string' ? parseFloat(total) || 0 : total;
|
|
45
|
+
const amount = numericTotal * vat_value;
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
amount,
|
|
49
|
+
vat_value,
|
|
50
|
+
total: numericTotal,
|
|
51
|
+
currencyCode,
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// Hook for bi-directional calculation
|
|
56
|
+
export const useFeesCalculation = (
|
|
57
|
+
amount: string,
|
|
58
|
+
vat_value: number,
|
|
59
|
+
currencyCode: string,
|
|
60
|
+
vatValue: string,
|
|
61
|
+
setVatValue: Dispatch<SetStateAction<string>>,
|
|
62
|
+
setAmount: Dispatch<SetStateAction<string>>,
|
|
63
|
+
) => {
|
|
64
|
+
const calculateFromAmount = (amountValue: string) => {
|
|
65
|
+
if (!amountValue || !vat_value) {
|
|
66
|
+
setVatValue('');
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const numericAmount = parseFloat(amountValue);
|
|
70
|
+
if (!isNaN(numericAmount)) {
|
|
71
|
+
const total = numericAmount / vat_value;
|
|
72
|
+
setVatValue(total.toFixed(1));
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const calculateFromVat = (vatVal: string) => {
|
|
77
|
+
if (!vatVal || !vat_value) {
|
|
78
|
+
setAmount('');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const numericTotal = parseFloat(vatVal);
|
|
82
|
+
if (!isNaN(numericTotal)) {
|
|
83
|
+
const calculatedAmount = numericTotal * vat_value;
|
|
84
|
+
setAmount(calculatedAmount.toFixed(1));
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
calculateFromAmount,
|
|
90
|
+
calculateFromVat,
|
|
91
|
+
};
|
|
92
|
+
};
|