@controleonline/ui-common 1.2.70 → 1.2.71
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 +31 -28
- package/src/api/index.js +237 -37
- package/src/react/components/AddImportModal.js +1 -1
- package/src/react/components/AnimatedModal.js +171 -0
- package/src/react/components/AnimatedModal.styles.js +21 -0
- package/src/react/components/AppTypeSwitcher.js +164 -0
- package/src/react/components/AppTypeSwitcher.styles.js +109 -0
- package/src/react/components/BackgroundRuntimeBridge.js +5 -4
- package/src/react/components/BottomNavigationBar.js +86 -31
- package/src/react/components/BottomNavigationBar.styles.js +118 -110
- package/src/react/components/DefaultProvider.native.js +68 -66
- package/src/react/components/DefaultProvider.web.js +44 -42
- package/src/react/components/DeliveryPushBridge.native.js +2 -2
- package/src/react/components/DeviceAlertSoundService.js +3 -3
- package/src/react/components/KioskModeBridge.js +2 -2
- package/src/react/components/LauncherModeBridge.js +2 -2
- package/src/react/components/ManagerPushBridge.native.js +2 -2
- package/src/react/components/RemoteCheckoutService.js +28 -20
- package/src/react/components/RuntimeBottomNavigationBar.js +146 -119
- package/src/react/components/RuntimeInfoFooter.js +37 -9
- package/src/react/components/StateStore.js +258 -0
- package/src/react/components/WebsocketListener.native.js +11 -11
- package/src/react/config/deviceConfigBootstrap.js +66 -27
- package/src/react/css/orders.js +72 -0
- package/src/react/pages/SettingsPage/PaymentTypesByWalletTab.js +484 -454
- package/src/react/pages/SettingsPage/index.js +1266 -1167
- package/src/react/print/providers/local.js +1 -1
- package/src/react/router/publicRoutes.js +25 -0
- package/src/react/services/Cielo/Checkout.js +39 -0
- package/src/react/services/Cielo/Cielo.js +193 -0
- package/src/react/services/Cielo/Print.js +7 -0
- package/src/react/services/InfinitePay/Checkout.js +33 -0
- package/src/react/services/InfinitePay/InfinitePay.js +24 -0
- package/src/react/{utils → services}/paymentGatewayExecution.js +91 -91
- package/src/react/styles/global.js +115 -0
- package/src/react/utils/fileUrl.js +182 -16
- package/src/react/utils/menuNavigation.js +31 -0
- package/src/react/utils/orderIdentity.js +277 -0
- package/src/react/utils/remotePayment.js +115 -61
- package/src/react/utils/runtimeMenu.js +35 -3
- package/src/react/utils/shopConfig.js +50 -24
- package/src/react/utils/shopFranchises.js +56 -22
- package/src/react/utils/socketRuntimePipeline.js +14 -14
- package/src/store/configs/index.js +2 -2
- package/src/tests/react/api/loadSmokeIndex.test.js +75 -0
- package/src/tests/react/config/deviceConfigBootstrap.test.js +47 -0
- package/src/tests/react/print/localPrintProvider.test.js +1 -1
- package/src/tests/react/services/Cielo.test.js +190 -0
- package/src/tests/react/utils/fileUrl.test.js +62 -0
- package/src/tests/react/utils/importStatus.test.js +2 -2
- package/src/tests/react/utils/orderIdentity.test.js +139 -0
- package/src/tests/react/utils/remotePayment.test.js +62 -0
- package/src/tests/react/utils/runtimeFooter.test.js +4 -6
- package/src/tests/react/utils/runtimeLanguage.test.js +2 -2
- package/src/tests/react/utils/runtimeMenu.test.js +23 -3
- package/src/tests/react/utils/shopConfig.test.js +74 -0
- package/src/tests/react/utils/shopFranchises.test.js +79 -12
- package/src/tests/react/utils/translate.test.mjs +166 -102
- package/src/utils/formatter.js +18 -0
- package/src/utils/integrationConfigs.js +80 -79
- package/src/utils/translate.js +125 -30
|
@@ -1,61 +1,115 @@
|
|
|
1
|
-
import {getPaymentOptionId, getPaymentOptionLabel} from './paymentOptions';
|
|
2
|
-
|
|
3
|
-
export const REMOTE_PAYMENT_MESSAGE_STORE = 'invoice';
|
|
4
|
-
export const REMOTE_PAYMENT_REQUEST_ACTION = 'pay';
|
|
5
|
-
export const REMOTE_PAYMENT_RESULT_ACTION = 'pay-result';
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
1
|
+
import {getPaymentOptionId, getPaymentOptionLabel} from './paymentOptions';
|
|
2
|
+
|
|
3
|
+
export const REMOTE_PAYMENT_MESSAGE_STORE = 'invoice';
|
|
4
|
+
export const REMOTE_PAYMENT_REQUEST_ACTION = 'pay';
|
|
5
|
+
export const REMOTE_PAYMENT_RESULT_ACTION = 'pay-result';
|
|
6
|
+
export const REMOTE_PAYMENT_STATUS_SUCCESS = 'success';
|
|
7
|
+
export const REMOTE_PAYMENT_STATUS_ERROR = 'error';
|
|
8
|
+
export const REMOTE_PAYMENT_STATUS_CANCELED = 'canceled';
|
|
9
|
+
|
|
10
|
+
const normalizeText = value => String(value || '').trim();
|
|
11
|
+
|
|
12
|
+
const normalizeSearchText = value =>
|
|
13
|
+
normalizeText(value)
|
|
14
|
+
.normalize('NFD')
|
|
15
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
16
|
+
.toLowerCase();
|
|
17
|
+
|
|
18
|
+
const EXPLICIT_CANCELLATION_STATUSES = new Set([
|
|
19
|
+
'cancel',
|
|
20
|
+
'canceled',
|
|
21
|
+
'cancelled',
|
|
22
|
+
]);
|
|
23
|
+
|
|
24
|
+
const isCancellationErrorText = value => {
|
|
25
|
+
const text = normalizeSearchText(value);
|
|
26
|
+
|
|
27
|
+
if (!text || /(?:nao|not) (?:foi )?(?:possivel )?cancel/.test(text)) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
/\bcancelad[ao]s?\b/.test(text) ||
|
|
33
|
+
/\bcancell?ed\b/.test(text) ||
|
|
34
|
+
/\bcancelamento\b.*\b(?:usuario|cliente)\b/.test(text)
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/*
|
|
39
|
+
* @agents A customer cancellation is a neutral terminal outcome. Older remote
|
|
40
|
+
* devices reported it as status=error, so keep the text fallback until every
|
|
41
|
+
* deployed device sends the canonical canceled status.
|
|
42
|
+
*/
|
|
43
|
+
export const normalizeRemotePaymentResultStatus = ({status, error} = {}) => {
|
|
44
|
+
const normalizedStatus = normalizeText(status).toLowerCase();
|
|
45
|
+
|
|
46
|
+
if (normalizedStatus === REMOTE_PAYMENT_STATUS_SUCCESS) {
|
|
47
|
+
return REMOTE_PAYMENT_STATUS_SUCCESS;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (
|
|
51
|
+
EXPLICIT_CANCELLATION_STATUSES.has(normalizedStatus) ||
|
|
52
|
+
isCancellationErrorText(error)
|
|
53
|
+
) {
|
|
54
|
+
return REMOTE_PAYMENT_STATUS_CANCELED;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return REMOTE_PAYMENT_STATUS_ERROR;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const isRemotePaymentCancellation = result =>
|
|
61
|
+
normalizeRemotePaymentResultStatus(result) === REMOTE_PAYMENT_STATUS_CANCELED;
|
|
62
|
+
|
|
63
|
+
const normalizeOrderId = value => normalizeText(value).replace(/\D/g, '');
|
|
64
|
+
|
|
65
|
+
export const normalizeRemotePaymentRequestKey = value => normalizeText(value);
|
|
66
|
+
|
|
67
|
+
export const buildRemotePaymentRequestKey = ({
|
|
68
|
+
orderId,
|
|
69
|
+
payment,
|
|
70
|
+
targetDeviceId,
|
|
71
|
+
}) =>
|
|
72
|
+
[
|
|
73
|
+
normalizeOrderId(orderId) || 'order',
|
|
74
|
+
normalizeText(targetDeviceId) || 'device',
|
|
75
|
+
getPaymentOptionId(payment) || 'payment',
|
|
76
|
+
Date.now().toString(),
|
|
77
|
+
].join(':');
|
|
78
|
+
|
|
79
|
+
export const isRemotePaymentRequestMessage = message =>
|
|
80
|
+
normalizeText(message?.action).toLowerCase() ===
|
|
81
|
+
REMOTE_PAYMENT_REQUEST_ACTION;
|
|
82
|
+
|
|
83
|
+
export const isRemotePaymentResultMessage = message =>
|
|
84
|
+
normalizeText(message?.action).toLowerCase() ===
|
|
85
|
+
REMOTE_PAYMENT_RESULT_ACTION;
|
|
86
|
+
|
|
87
|
+
export const buildRemotePaymentResultMessage = ({
|
|
88
|
+
destinationDeviceId,
|
|
89
|
+
error = '',
|
|
90
|
+
invoice = null,
|
|
91
|
+
orderId,
|
|
92
|
+
paidAmount = 0,
|
|
93
|
+
payment = null,
|
|
94
|
+
requestKey,
|
|
95
|
+
status = 'error',
|
|
96
|
+
targetDeviceId,
|
|
97
|
+
targetDeviceLabel = '',
|
|
98
|
+
targetGateway = '',
|
|
99
|
+
total = 0,
|
|
100
|
+
}) => ({
|
|
101
|
+
destination: normalizeText(destinationDeviceId),
|
|
102
|
+
store: REMOTE_PAYMENT_MESSAGE_STORE,
|
|
103
|
+
action: REMOTE_PAYMENT_RESULT_ACTION,
|
|
104
|
+
requestKey: normalizeRemotePaymentRequestKey(requestKey),
|
|
105
|
+
status: normalizeRemotePaymentResultStatus({status, error}),
|
|
106
|
+
order: normalizeOrderId(orderId),
|
|
107
|
+
total: Number(total || 0),
|
|
108
|
+
paidAmount: Number(paidAmount || 0),
|
|
109
|
+
paymentLabel: getPaymentOptionLabel(payment),
|
|
110
|
+
targetDeviceId: normalizeText(targetDeviceId),
|
|
111
|
+
targetDeviceLabel: normalizeText(targetDeviceLabel),
|
|
112
|
+
targetGateway: normalizeText(targetGateway),
|
|
113
|
+
...(invoice ? {invoice} : {}),
|
|
114
|
+
...(error ? {error: normalizeText(error)} : {}),
|
|
115
|
+
});
|
|
@@ -126,8 +126,36 @@ const MANAGER_RUNTIME_MENU_FALLBACK = [
|
|
|
126
126
|
sortOrder: 60,
|
|
127
127
|
},
|
|
128
128
|
],
|
|
129
|
-
},
|
|
130
|
-
];
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
|
|
132
|
+
const ADMIN_RUNTIME_MENU_FALLBACK = [
|
|
133
|
+
{
|
|
134
|
+
id: 'admin-configuracoes',
|
|
135
|
+
label: 'Configuracoes',
|
|
136
|
+
icon: 'settings',
|
|
137
|
+
menus: [
|
|
138
|
+
{
|
|
139
|
+
id: 'menu_access',
|
|
140
|
+
menuKey: 'menu_access',
|
|
141
|
+
label: 'Menus por perfil',
|
|
142
|
+
route: 'MenuAccessConfigPage',
|
|
143
|
+
icon: 'list',
|
|
144
|
+
color: '#64748B',
|
|
145
|
+
sortOrder: 10,
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
id: 'test_results',
|
|
149
|
+
menuKey: 'test_results',
|
|
150
|
+
label: 'Resultados de testes',
|
|
151
|
+
route: 'TestsPlaygroundPage',
|
|
152
|
+
icon: 'clipboard',
|
|
153
|
+
color: '#0EA5E9',
|
|
154
|
+
sortOrder: 20,
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
},
|
|
158
|
+
];
|
|
131
159
|
|
|
132
160
|
const cloneRuntimeMenuModules = modules =>
|
|
133
161
|
(Array.isArray(modules) ? modules : []).map(module => ({
|
|
@@ -177,7 +205,11 @@ export const normalizeRuntimeMenuResponse = (
|
|
|
177
205
|
if (allowFallback && normalizedAppType === 'MANAGER') {
|
|
178
206
|
return cloneRuntimeMenuModules(MANAGER_RUNTIME_MENU_FALLBACK);
|
|
179
207
|
}
|
|
180
|
-
|
|
208
|
+
|
|
209
|
+
if (allowFallback && normalizedAppType === 'ADMIN') {
|
|
210
|
+
return cloneRuntimeMenuModules(ADMIN_RUNTIME_MENU_FALLBACK);
|
|
211
|
+
}
|
|
212
|
+
|
|
181
213
|
return [];
|
|
182
214
|
};
|
|
183
215
|
|
|
@@ -46,12 +46,14 @@ export const SHOP_FRANCHISE_VISIBLE_ADDRESS_IDS_CONFIG_KEY =
|
|
|
46
46
|
'shop-franchise-visible-address-ids';
|
|
47
47
|
export const SHOP_LOYALTY_COUPONS_ENABLED_CONFIG_KEY =
|
|
48
48
|
'shop-loyalty-coupons-enabled';
|
|
49
|
-
export const SHOP_LOYALTY_PRODUCT_IDS_CONFIG_KEY =
|
|
50
|
-
'shop-loyalty-product-ids';
|
|
51
|
-
export const SHOP_LOYALTY_REQUIRED_SALES_CONFIG_KEY =
|
|
52
|
-
'shop-loyalty-required-sales';
|
|
53
|
-
export const SHOP_LOYALTY_GIFT_PRODUCT_ID_CONFIG_KEY =
|
|
54
|
-
'shop-loyalty-gift-product-id';
|
|
49
|
+
export const SHOP_LOYALTY_PRODUCT_IDS_CONFIG_KEY =
|
|
50
|
+
'shop-loyalty-product-ids';
|
|
51
|
+
export const SHOP_LOYALTY_REQUIRED_SALES_CONFIG_KEY =
|
|
52
|
+
'shop-loyalty-required-sales';
|
|
53
|
+
export const SHOP_LOYALTY_GIFT_PRODUCT_ID_CONFIG_KEY =
|
|
54
|
+
'shop-loyalty-gift-product-id';
|
|
55
|
+
export const SHOP_LOYALTY_STAMP_ICON_URL_CONFIG_KEY =
|
|
56
|
+
'shop-loyalty-stamp-icon-url';
|
|
55
57
|
|
|
56
58
|
export const normalizeShopEntityId = value => {
|
|
57
59
|
if (!value) {
|
|
@@ -218,11 +220,11 @@ export const normalizeShopPrimaryEntry = (
|
|
|
218
220
|
return enabledOptions[0] || '';
|
|
219
221
|
};
|
|
220
222
|
|
|
221
|
-
export const resolveShopSettings = configs => {
|
|
222
|
-
const configMap =
|
|
223
|
-
configs && typeof configs === 'object' && !Array.isArray(configs)
|
|
224
|
-
? configs
|
|
225
|
-
: {};
|
|
223
|
+
export const resolveShopSettings = configs => {
|
|
224
|
+
const configMap =
|
|
225
|
+
configs && typeof configs === 'object' && !Array.isArray(configs)
|
|
226
|
+
? configs
|
|
227
|
+
: {};
|
|
226
228
|
|
|
227
229
|
const salesPageEnabled = normalizeBooleanConfig(
|
|
228
230
|
configMap[SHOP_SALES_PAGE_ENABLED_CONFIG_KEY],
|
|
@@ -241,11 +243,11 @@ export const resolveShopSettings = configs => {
|
|
|
241
243
|
configMap[SHOP_LOYALTY_COUPONS_ENABLED_CONFIG_KEY],
|
|
242
244
|
);
|
|
243
245
|
|
|
244
|
-
return {
|
|
245
|
-
salesPageEnabled,
|
|
246
|
-
franchiseLocatorEnabled,
|
|
247
|
-
loyaltyCouponsEnabled,
|
|
248
|
-
enabledHomeOptions,
|
|
246
|
+
return {
|
|
247
|
+
salesPageEnabled,
|
|
248
|
+
franchiseLocatorEnabled,
|
|
249
|
+
loyaltyCouponsEnabled,
|
|
250
|
+
enabledHomeOptions,
|
|
249
251
|
primaryEntry: normalizeShopPrimaryEntry(
|
|
250
252
|
configMap[SHOP_PRIMARY_ENTRY_CONFIG_KEY],
|
|
251
253
|
{
|
|
@@ -284,11 +286,35 @@ export const resolveShopSettings = configs => {
|
|
|
284
286
|
loyaltyProductIds: normalizeShopEntityIds(
|
|
285
287
|
configMap[SHOP_LOYALTY_PRODUCT_IDS_CONFIG_KEY],
|
|
286
288
|
),
|
|
287
|
-
loyaltyRequiredSales: normalizeShopLoyaltyRequiredSales(
|
|
288
|
-
configMap[SHOP_LOYALTY_REQUIRED_SALES_CONFIG_KEY],
|
|
289
|
-
),
|
|
290
|
-
loyaltyGiftProductId: normalizeShopEntityId(
|
|
291
|
-
configMap[SHOP_LOYALTY_GIFT_PRODUCT_ID_CONFIG_KEY],
|
|
292
|
-
),
|
|
293
|
-
|
|
294
|
-
|
|
289
|
+
loyaltyRequiredSales: normalizeShopLoyaltyRequiredSales(
|
|
290
|
+
configMap[SHOP_LOYALTY_REQUIRED_SALES_CONFIG_KEY],
|
|
291
|
+
),
|
|
292
|
+
loyaltyGiftProductId: normalizeShopEntityId(
|
|
293
|
+
configMap[SHOP_LOYALTY_GIFT_PRODUCT_ID_CONFIG_KEY],
|
|
294
|
+
),
|
|
295
|
+
loyaltyStampIconUrl: normalizeShopTextConfig(
|
|
296
|
+
configMap[SHOP_LOYALTY_STAMP_ICON_URL_CONFIG_KEY],
|
|
297
|
+
),
|
|
298
|
+
};
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
export const saveAndUpdateConfigValue = ({
|
|
302
|
+
configKey,
|
|
303
|
+
nextValue,
|
|
304
|
+
saveConfig,
|
|
305
|
+
setValue,
|
|
306
|
+
}) => {
|
|
307
|
+
setValue(nextValue);
|
|
308
|
+
return saveConfig(configKey, nextValue);
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
export const toggleAndSaveBooleanConfig = ({
|
|
312
|
+
configKey,
|
|
313
|
+
currentValue,
|
|
314
|
+
saveConfig,
|
|
315
|
+
setValue,
|
|
316
|
+
}) => {
|
|
317
|
+
const nextValue = !Boolean(currentValue);
|
|
318
|
+
setValue(nextValue);
|
|
319
|
+
return saveConfig(configKey, nextValue ? '1' : '0');
|
|
320
|
+
};
|
|
@@ -10,12 +10,21 @@ export const SHOP_FRANCHISE_PAGE_SIZE = 50;
|
|
|
10
10
|
|
|
11
11
|
const normalizeItemsPerPage = value =>
|
|
12
12
|
Math.max(1, Math.min(SHOP_FRANCHISE_PAGE_SIZE, Number(value) || SHOP_FRANCHISE_PAGE_SIZE));
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
|
|
14
|
+
const normalizeFranchiseDirectoryItem = company => ({
|
|
15
|
+
...company,
|
|
16
|
+
shopAddresses: Array.isArray(company?.shopAddresses)
|
|
17
|
+
? company.shopAddresses
|
|
18
|
+
: Array.isArray(company?.address)
|
|
19
|
+
? company.address
|
|
20
|
+
: [],
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const sortByLabel = (left, right) =>
|
|
24
|
+
String(left || '')
|
|
25
|
+
.localeCompare(String(right || ''), 'pt-BR', {
|
|
26
|
+
sensitivity: 'base',
|
|
27
|
+
});
|
|
19
28
|
|
|
20
29
|
export const resolveFranchiseCompanyLabel = company =>
|
|
21
30
|
String(company?.alias || company?.name || '').trim() ||
|
|
@@ -49,14 +58,46 @@ export const fetchShopFranchiseCompanies = async ({
|
|
|
49
58
|
const items = extractCollectionItems(response);
|
|
50
59
|
|
|
51
60
|
return items
|
|
52
|
-
.map(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
.map(normalizeFranchiseDirectoryItem)
|
|
62
|
+
.sort((left, right) =>
|
|
63
|
+
sortByLabel(
|
|
64
|
+
resolveFranchiseCompanyLabel(left),
|
|
65
|
+
resolveFranchiseCompanyLabel(right),
|
|
66
|
+
),
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const fetchAllShopFranchiseDirectory = async ({
|
|
71
|
+
companyId,
|
|
72
|
+
publicDirectory = false,
|
|
73
|
+
search = '',
|
|
74
|
+
itemsPerPage = SHOP_FRANCHISE_PAGE_SIZE,
|
|
75
|
+
} = {}) => {
|
|
76
|
+
const normalizedItemsPerPage = normalizeItemsPerPage(itemsPerPage);
|
|
77
|
+
const items = [];
|
|
78
|
+
let page = 1;
|
|
79
|
+
|
|
80
|
+
while (true) {
|
|
81
|
+
const pageItems = await fetchShopFranchiseCompanies({
|
|
82
|
+
companyId,
|
|
83
|
+
publicDirectory,
|
|
84
|
+
search,
|
|
85
|
+
page,
|
|
86
|
+
itemsPerPage: normalizedItemsPerPage,
|
|
87
|
+
});
|
|
88
|
+
const normalizedPageItems = Array.isArray(pageItems) ? pageItems : [];
|
|
89
|
+
|
|
90
|
+
items.push(...normalizedPageItems);
|
|
91
|
+
|
|
92
|
+
if (normalizedPageItems.length < normalizedItemsPerPage) {
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
page += 1;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return items
|
|
100
|
+
.map(normalizeFranchiseDirectoryItem)
|
|
60
101
|
.sort((left, right) =>
|
|
61
102
|
sortByLabel(
|
|
62
103
|
resolveFranchiseCompanyLabel(left),
|
|
@@ -102,13 +143,6 @@ export const fetchShopFranchiseDirectory = async ({
|
|
|
102
143
|
itemsPerPage,
|
|
103
144
|
});
|
|
104
145
|
|
|
105
|
-
return companies.map(
|
|
106
|
-
...company,
|
|
107
|
-
shopAddresses: Array.isArray(company?.shopAddresses)
|
|
108
|
-
? company.shopAddresses
|
|
109
|
-
: Array.isArray(company?.address)
|
|
110
|
-
? company.address
|
|
111
|
-
: [],
|
|
112
|
-
}));
|
|
146
|
+
return companies.map(normalizeFranchiseDirectoryItem);
|
|
113
147
|
};
|
|
114
148
|
// TODO(store-first): quando este arquivo for mexido, mover a leitura para stores, remover api.fetch e evitar repassar dados em objetos quando o store ja resolver isso.
|
|
@@ -104,15 +104,15 @@ const createSocketRuntimePipeline = ({
|
|
|
104
104
|
: 'socket:open'
|
|
105
105
|
: `socket:${normalizedStatus || 'off'}`;
|
|
106
106
|
|
|
107
|
-
const
|
|
108
|
-
socketConnected && socketIdentified
|
|
109
|
-
? '
|
|
110
|
-
: (socketConnected ||
|
|
111
|
-
['connecting', 'identifying', 'open', 'reconnecting'].includes(
|
|
112
|
-
normalizedStatus,
|
|
113
|
-
))
|
|
114
|
-
? '
|
|
115
|
-
: '
|
|
107
|
+
const indicatorTone =
|
|
108
|
+
socketConnected && socketIdentified
|
|
109
|
+
? 'success'
|
|
110
|
+
: (socketConnected ||
|
|
111
|
+
['connecting', 'identifying', 'open', 'reconnecting'].includes(
|
|
112
|
+
normalizedStatus,
|
|
113
|
+
))
|
|
114
|
+
? 'warning'
|
|
115
|
+
: 'error';
|
|
116
116
|
|
|
117
117
|
const lastSocketStores = Array.isArray(state?.lastStores)
|
|
118
118
|
? state.lastStores.filter(Boolean).join(', ')
|
|
@@ -122,11 +122,11 @@ const createSocketRuntimePipeline = ({
|
|
|
122
122
|
: '';
|
|
123
123
|
|
|
124
124
|
runtimeDebugActions.setFooterEntry({
|
|
125
|
-
key: 'socket',
|
|
126
|
-
order: 10,
|
|
127
|
-
|
|
128
|
-
updatedAt: state?.updatedAt || new Date().toISOString(),
|
|
129
|
-
lines: [
|
|
125
|
+
key: 'socket',
|
|
126
|
+
order: 10,
|
|
127
|
+
indicatorTone,
|
|
128
|
+
updatedAt: state?.updatedAt || new Date().toISOString(),
|
|
129
|
+
lines: [
|
|
130
130
|
`Realtime ${stateLabel} | empresa: ${normalizeText(
|
|
131
131
|
getCurrentCompanyId(),
|
|
132
132
|
) || '--'} | device: ${truncateText(
|
|
@@ -6,8 +6,8 @@ import * as customActions from './customActions';
|
|
|
6
6
|
export default {
|
|
7
7
|
namespaced: true,
|
|
8
8
|
state: {
|
|
9
|
-
item: null, //Don
|
|
10
|
-
items: null, //Don
|
|
9
|
+
item: null, //Don't Touch plz....
|
|
10
|
+
items: null, //Don't Touch plz....
|
|
11
11
|
resourceEndpoint: 'configs',
|
|
12
12
|
isLoading: false,
|
|
13
13
|
isSaving: false,
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const {afterAll, afterEach, beforeEach, describe, expect, it} = global;
|
|
2
|
+
const {jest} = require('@jest/globals');
|
|
3
|
+
|
|
4
|
+
jest.mock('react-native', () => ({
|
|
5
|
+
Platform: {
|
|
6
|
+
OS: 'web',
|
|
7
|
+
select: options => options.web || options.default || options.ios || options.android,
|
|
8
|
+
},
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
const originalLocalStorage = global.localStorage;
|
|
12
|
+
|
|
13
|
+
global.localStorage = {
|
|
14
|
+
clear: jest.fn(),
|
|
15
|
+
getItem: jest.fn(() => '{}'),
|
|
16
|
+
removeItem: jest.fn(),
|
|
17
|
+
setItem: jest.fn(),
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const {api} = require('@controleonline/ui-common/src/api');
|
|
21
|
+
|
|
22
|
+
describe('smoke api helper', () => {
|
|
23
|
+
const originalFetch = global.fetch;
|
|
24
|
+
const originalGetToken = api.getToken;
|
|
25
|
+
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
global.fetch = jest.fn();
|
|
28
|
+
api.getToken = jest.fn().mockResolvedValue('session-token');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
global.fetch = originalFetch;
|
|
33
|
+
api.getToken = originalGetToken;
|
|
34
|
+
jest.restoreAllMocks();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
afterAll(() => {
|
|
38
|
+
global.localStorage = originalLocalStorage;
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('loads the smoke index from the canonical /tests endpoint and sends the app-domain', async () => {
|
|
42
|
+
global.fetch.mockResolvedValue({
|
|
43
|
+
ok: true,
|
|
44
|
+
status: 200,
|
|
45
|
+
statusText: 'OK',
|
|
46
|
+
text: async () =>
|
|
47
|
+
JSON.stringify({
|
|
48
|
+
status: 'idle',
|
|
49
|
+
summary: {
|
|
50
|
+
types: {total: 0, passed: 0, failed: 0},
|
|
51
|
+
suites: {total: 0, passed: 0, failed: 0},
|
|
52
|
+
tests: {total: 0, passed: 0, failed: 0},
|
|
53
|
+
},
|
|
54
|
+
types: [],
|
|
55
|
+
suites: [],
|
|
56
|
+
}),
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const response = await api.loadSmokeIndex({
|
|
60
|
+
apiBaseUrl: 'https://smoke.example.test',
|
|
61
|
+
domain: 'https://admin.controleonline.com/tests-playground',
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
expect(global.fetch).toHaveBeenCalledTimes(1);
|
|
65
|
+
|
|
66
|
+
const [url, options] = global.fetch.mock.calls[0];
|
|
67
|
+
expect(url).toBe('https://smoke.example.test/tests');
|
|
68
|
+
expect(options.headers.get('App-Domain')).toBe('admin.controleonline.com');
|
|
69
|
+
expect(options.headers.get('API-TOKEN')).toBe('session-token');
|
|
70
|
+
expect(options.headers.get('X-API-KEY')).toBeNull();
|
|
71
|
+
expect(options.headers.get('Accept')).toBe('application/ld+json');
|
|
72
|
+
expect(options.headers.get('Content-Type')).toBe('application/ld+json');
|
|
73
|
+
expect(response.status).toBe('idle');
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -18,6 +18,8 @@ const {
|
|
|
18
18
|
POS_CASH_MANAGEMENT_MODE_CONFIG_KEY,
|
|
19
19
|
POS_DELIVERY_ENABLED_CONFIG_KEY,
|
|
20
20
|
POS_OPERATION_MODE_CONFIG_KEY,
|
|
21
|
+
POS_CHECK_ORDER_TYPE_CONFIG_KEY,
|
|
22
|
+
POS_CHECK_ORDER_TYPE_STAMP,
|
|
21
23
|
isPosSingleItemMode,
|
|
22
24
|
isPosAutoPrintEnabled,
|
|
23
25
|
isPosCashRegisterClosed,
|
|
@@ -30,9 +32,11 @@ const {
|
|
|
30
32
|
isDisplaySideBreakEnabled,
|
|
31
33
|
normalizeDisplaySize,
|
|
32
34
|
resolveDisplaySize,
|
|
35
|
+
resolvePosCheckOrderTypeForShop,
|
|
33
36
|
resolvePosCashManagementMode,
|
|
34
37
|
resolvePosOperationMode,
|
|
35
38
|
resolvePosPrintMode,
|
|
39
|
+
resolvePosCheckOrderType,
|
|
36
40
|
shouldEnableAndroidKioskMode,
|
|
37
41
|
shouldEnableAndroidLauncherMode,
|
|
38
42
|
shouldUsePosCashRegisterLifecycle,
|
|
@@ -179,6 +183,49 @@ describe('deviceConfigBootstrap POS operation helpers', () => {
|
|
|
179
183
|
).toBe(false)
|
|
180
184
|
})
|
|
181
185
|
|
|
186
|
+
it('normalizes stamp linked order types for the POS config', () => {
|
|
187
|
+
expect(
|
|
188
|
+
resolvePosCheckOrderType({
|
|
189
|
+
[POS_CHECK_ORDER_TYPE_CONFIG_KEY]: 'stamp',
|
|
190
|
+
}),
|
|
191
|
+
).toBe(POS_CHECK_ORDER_TYPE_STAMP)
|
|
192
|
+
expect(
|
|
193
|
+
resolvePosCheckOrderType({
|
|
194
|
+
[POS_CHECK_ORDER_TYPE_CONFIG_KEY]: 'carimbo',
|
|
195
|
+
}),
|
|
196
|
+
).toBe(POS_CHECK_ORDER_TYPE_STAMP)
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
it('disables stamp when shop loyalty coupons are off', () => {
|
|
200
|
+
expect(
|
|
201
|
+
resolvePosCheckOrderTypeForShop(
|
|
202
|
+
{
|
|
203
|
+
[POS_CHECK_ORDER_TYPE_CONFIG_KEY]: 'stamp',
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
'shop-loyalty-coupons-enabled': '0',
|
|
207
|
+
},
|
|
208
|
+
),
|
|
209
|
+
).toBe('none')
|
|
210
|
+
|
|
211
|
+
expect(
|
|
212
|
+
resolvePosCheckOrderTypeForShop(
|
|
213
|
+
{
|
|
214
|
+
[POS_CHECK_ORDER_TYPE_CONFIG_KEY]: 'stamp',
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
'shop-loyalty-coupons-enabled': '1',
|
|
218
|
+
},
|
|
219
|
+
),
|
|
220
|
+
).toBe(POS_CHECK_ORDER_TYPE_STAMP)
|
|
221
|
+
|
|
222
|
+
expect(
|
|
223
|
+
resolvePosCheckOrderTypeForShop({
|
|
224
|
+
[POS_CHECK_ORDER_TYPE_CONFIG_KEY]: 'stamp',
|
|
225
|
+
}),
|
|
226
|
+
).toBe(POS_CHECK_ORDER_TYPE_STAMP)
|
|
227
|
+
})
|
|
228
|
+
|
|
182
229
|
it('defaults display size to 5 and clamps the configured range to 1..10', () => {
|
|
183
230
|
expect(resolveDisplaySize({})).toBe(DISPLAY_SIZE_DEFAULT)
|
|
184
231
|
expect(
|
|
@@ -2,7 +2,7 @@ const {jest} = require('@jest/globals')
|
|
|
2
2
|
|
|
3
3
|
const mockPrint = jest.fn()
|
|
4
4
|
|
|
5
|
-
jest.mock('
|
|
5
|
+
jest.mock('../../../react/services/Cielo/Print', () => ({
|
|
6
6
|
CieloPrint: jest.fn().mockImplementation(() => ({
|
|
7
7
|
print: mockPrint,
|
|
8
8
|
})),
|