@controleonline/ui-common 1.2.70 → 1.2.75
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/.github/actions/workers/manager/action.yml +147 -0
- package/.github/actions/workers/qa/action.yml +44 -0
- package/.github/actions/workers/security/action.yml +44 -0
- package/.github/actions/workers/technical-documenter/action.yml +51 -0
- package/.github/workflows/manager-worker.yml +168 -0
- package/.github/workflows/publish-npm.yml +45 -0
- package/.gitmodules +3 -0
- package/AGENTS.md +6 -0
- package/README.md +14 -0
- package/package.json +32 -28
- package/src/api/fetch.js +1 -1
- package/src/api/index.js +328 -58
- package/src/react/components/AddImportModal.js +95 -111
- 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.config.js +211 -231
- package/src/react/components/BottomNavigationBar.js +86 -31
- package/src/react/components/BottomNavigationBar.styles.js +118 -110
- package/src/react/components/CategoryForm.js +52 -35
- package/src/react/components/DefaultProvider.native.js +194 -156
- package/src/react/components/DefaultProvider.web.js +188 -112
- 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/NetworkPrinterPreviewModal.js +249 -0
- package/src/react/components/NetworkPrinterPreviewModal.styles.js +159 -0
- package/src/react/components/RemoteCheckoutService.js +28 -20
- package/src/react/components/RuntimeBottomNavigationBar.js +146 -119
- package/src/react/components/RuntimeInfoFooter.js +137 -45
- package/src/react/components/RuntimeInfoFooter.styles.js +3 -0
- package/src/react/components/StateStore.js +258 -0
- package/src/react/components/UnifiedPaymentBar.js +7 -4
- package/src/react/components/UserAvatar.js +160 -0
- package/src/react/components/WebsocketListener.native.js +11 -11
- package/src/react/components/integrations/IntegrationHero/index.js +48 -0
- package/src/react/components/integrations/IntegrationHero/styles.js +57 -0
- package/src/react/components/integrations/IntegrationTabs/index.js +89 -0
- package/src/react/components/integrations/IntegrationTabs/styles.js +44 -0
- package/src/react/config/deviceConfigBootstrap.js +71 -30
- package/src/react/css/orders.js +72 -0
- package/src/react/pages/Connections.js +229 -0
- package/src/react/pages/Connections.styles.js +222 -0
- package/src/react/pages/DeviceDetailPage.js +2814 -0
- package/src/react/pages/DeviceDetailPage.styles.js +308 -0
- package/src/react/pages/Devices/currentDevice.js +194 -0
- package/src/react/pages/Devices/deviceTypes/DeviceGroupCard.js +257 -0
- package/src/react/pages/Devices/deviceTypes/all.js +23 -0
- package/src/react/pages/Devices/deviceTypes/device.js +25 -0
- package/src/react/pages/Devices/deviceTypes/deviceListHelpers.js +178 -0
- package/src/react/pages/Devices/deviceTypes/display.js +26 -0
- package/src/react/pages/Devices/deviceTypes/index.js +145 -0
- package/src/react/pages/Devices/deviceTypes/ipCamera.js +35 -0
- package/src/react/pages/Devices/deviceTypes/pdv.js +88 -0
- package/src/react/pages/Devices/deviceTypes/printer.js +37 -0
- package/src/react/pages/Devices/deviceTypes/shared.js +453 -0
- package/src/react/pages/Devices/deviceTypes/useDeviceNetworkConnectivity.js +145 -0
- package/src/react/pages/Devices.js +183 -0
- package/src/react/pages/Devices.styles.js +353 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99CatalogTab.js +219 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99OverviewTab.js +134 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99PreviewModal.js +173 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99ProductCard.js +1 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99QuickWalletModal.js +181 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99SettingsTab.js +306 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99StoreTab.js +417 -0
- package/src/react/pages/Food99IntegrationPage/index.js +1530 -0
- package/src/react/pages/Food99IntegrationPage/styles.js +792 -0
- package/src/react/pages/Food99IntegrationPage/utils.js +155 -0
- package/src/react/pages/Food99IntegrationPage.js +1 -0
- package/src/react/pages/Food99IntegrationPage.styles.js +1 -0
- package/src/react/pages/GenericLogPage.js +42 -167
- package/src/react/pages/IFoodIntegrationPage/components/IFoodCatalogTab.js +8 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodOperationsTab.js +420 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodOverviewTab.js +118 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodPreviewModal.js +103 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodProductCard.js +1 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodStoreTab.js +150 -0
- package/src/react/pages/IFoodIntegrationPage/index.js +1298 -0
- package/src/react/pages/IFoodIntegrationPage/styles.js +764 -0
- package/src/react/pages/IFoodIntegrationPage/utils.js +91 -0
- package/src/react/pages/IFoodIntegrationPage.js +1 -0
- package/src/react/pages/IFoodIntegrationPage.styles.js +1 -0
- package/src/react/pages/Imports.js +214 -166
- package/src/react/pages/IntegrationConfigPage.js +744 -0
- package/src/react/pages/IntegrationConfigPage.styles.js +269 -0
- package/src/react/pages/Integrations.js +299 -0
- package/src/react/pages/Integrations.styles.js +130 -0
- package/src/react/pages/ManagerOrderNotificationsPage.js +642 -0
- package/src/react/pages/MarketplaceIntegrationPage/components/MarketplaceProductCard.js +205 -0
- package/src/react/pages/MarketplaceIntegrationPage/components/RemoteMarketplaceMenuTab.js +335 -0
- package/src/react/pages/MarketplaceIntegrationPage/index.js +60 -0
- package/src/react/pages/MarketplaceIntegrationPage/utils.js +137 -0
- package/src/react/pages/MercadoLivreIntegrationPage.js +538 -0
- package/src/react/pages/PrinterDeviceDetailPage.js +1916 -0
- package/src/react/pages/PrinterDeviceDetailPage.styles.js +223 -0
- package/src/react/pages/PrinterDeviceFormPage.js +521 -0
- package/src/react/pages/PrinterDeviceFormPage.styles.js +159 -0
- package/src/react/pages/SettingsPage/PaymentTypesByWalletTab.js +484 -454
- package/src/react/pages/SettingsPage/index.js +1266 -1167
- package/src/react/pages/WhatsAppConnectionPage.js +459 -0
- package/src/react/pages/WhatsAppConnectionPage.styles.js +284 -0
- package/src/react/pages/integrationsCatalog.js +399 -0
- 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/categoryContexts.js +46 -0
- package/src/react/utils/entityDisplay.js +222 -217
- package/src/react/utils/fileUrl.js +201 -16
- package/src/react/utils/integrationPage.js +16 -0
- 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/runtimeFooter.js +40 -22
- package/src/react/utils/runtimeLanguage.js +50 -9
- package/src/react/utils/runtimeMenu.js +190 -98
- package/src/react/utils/runtimeZoom.js +43 -0
- package/src/react/utils/shopConfig.js +72 -34
- package/src/react/utils/shopFranchises.js +182 -23
- package/src/react/utils/socketRuntimePipeline.js +14 -14
- package/src/react/utils/storeColumns.js +23 -4
- package/src/react/utils/userAvatar.js +104 -0
- package/src/store/categories/index.js +48 -20
- package/src/store/configs/index.js +2 -2
- package/src/store/device_config/index.js +62 -21
- package/src/store/entity_log/index.js +22 -1
- package/src/store/imports/customActions.js +51 -0
- package/src/store/imports/index.js +89 -88
- package/src/store/status/index.js +11 -11
- package/src/store/themes/index.js +22 -0
- package/src/store/timezones/index.js +3 -1
- package/src/tests/browser/manager/connections.spec.js +143 -0
- package/src/tests/browser/manager/devices-current.spec.js +343 -0
- package/src/tests/browser/manager/mercado-livre-integration.spec.js +268 -0
- package/src/tests/react/api/deviceHeaders.test.js +114 -0
- package/src/tests/react/api/loadSmokeIndex.test.js +75 -0
- package/src/tests/react/components/AddImportModal.test.js +166 -0
- package/src/tests/react/components/BottomNavigationBar.config.test.js +20 -0
- package/src/tests/react/components/UserAvatar.test.js +52 -0
- package/src/tests/react/config/deviceConfigBootstrap.test.js +47 -0
- package/src/tests/react/pages/DevicePickerStyles.test.js +47 -0
- package/src/tests/react/pages/Devices/deviceListHelpers.test.js +39 -0
- package/src/tests/react/pages/DevicesCurrentDevice.test.js +198 -0
- package/src/tests/react/pages/connectionsHelpers.test.js +34 -0
- package/src/tests/react/pages/mercadoLivreIntegrationPageContract.test.mjs +16 -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/store/categoriesOrdering.test.js +26 -0
- package/src/tests/react/utils/appDomain.test.js +62 -0
- package/src/tests/react/utils/entityDisplay.test.js +2 -2
- package/src/tests/react/utils/fileUrl.test.js +62 -0
- package/src/tests/react/utils/formatter.test.mjs +33 -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 +32 -9
- package/src/tests/react/utils/runtimeLanguage.test.js +80 -10
- package/src/tests/react/utils/runtimeMenu.test.js +195 -111
- package/src/tests/react/utils/runtimeZoom.test.js +38 -0
- package/src/tests/react/utils/shopConfig.test.js +75 -0
- package/src/tests/react/utils/shopFranchises.test.js +122 -12
- package/src/tests/react/utils/translate.discovery.test.mjs +170 -0
- package/src/tests/react/utils/translate.test.helpers.mjs +152 -0
- package/src/tests/react/utils/translate.test.mjs +252 -396
- package/src/tests/react/utils/userAvatar.test.js +63 -0
- package/src/utils/appDomain.js +15 -4
- package/src/utils/formatter.js +122 -16
- package/src/utils/integrationConfigs.js +1 -0
- package/src/utils/translate.js +277 -398
- package/src/utils/translateDiscovery.js +96 -0
- package/src/utils/translateNormalize.js +33 -0
- package/src/utils/translatePending.js +92 -0
- package/src/utils/translateStorage.js +142 -0
- package/.github/agents/developer.agent.md +0 -30
- package/.github/agents/devops.agent.md +0 -30
- package/.github/agents/qa.agent.md +0 -30
- package/.github/agents/security.agent.md +0 -30
- package/.github/workflows/npmjs.yml +0 -35
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export const DEFAULT_RUNTIME_ZOOM_PERCENT = 100;
|
|
2
|
+
export const MIN_RUNTIME_ZOOM_PERCENT = 50;
|
|
3
|
+
export const MAX_RUNTIME_ZOOM_PERCENT = 150;
|
|
4
|
+
|
|
5
|
+
export const normalizeRuntimeZoomPercent = value => {
|
|
6
|
+
if (value === undefined || value === null || value === '') {
|
|
7
|
+
return DEFAULT_RUNTIME_ZOOM_PERCENT;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const numericValue = Number(String(value).replace('%', '').trim());
|
|
11
|
+
|
|
12
|
+
if (!Number.isFinite(numericValue)) {
|
|
13
|
+
return DEFAULT_RUNTIME_ZOOM_PERCENT;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return Math.min(
|
|
17
|
+
MAX_RUNTIME_ZOOM_PERCENT,
|
|
18
|
+
Math.max(MIN_RUNTIME_ZOOM_PERCENT, numericValue),
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const resolveRuntimeZoomScale = value =>
|
|
23
|
+
normalizeRuntimeZoomPercent(value) / 100;
|
|
24
|
+
|
|
25
|
+
export const buildRuntimeZoomStyle = (value, {isWeb = false} = {}) => {
|
|
26
|
+
const scale = resolveRuntimeZoomScale(value);
|
|
27
|
+
|
|
28
|
+
if (scale === 1) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (isWeb) {
|
|
33
|
+
return {zoom: scale};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const inverseSize = `${100 / scale}%`;
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
height: inverseSize,
|
|
40
|
+
transform: [{scale}],
|
|
41
|
+
width: inverseSize,
|
|
42
|
+
};
|
|
43
|
+
};
|
|
@@ -38,20 +38,29 @@ export const SHOP_CATALOG_PRODUCT_TYPES_CONFIG_KEY =
|
|
|
38
38
|
'shop-catalog-product-types';
|
|
39
39
|
export const SHOP_GOOGLE_MAPS_API_KEY_CONFIG_KEY =
|
|
40
40
|
'shop-google-maps-api-key';
|
|
41
|
-
export const SHOP_FRANCHISE_PIN_ICON_URL_CONFIG_KEY =
|
|
42
|
-
'shop-franchise-pin-icon-url';
|
|
43
41
|
export const SHOP_FRANCHISE_VISIBLE_COMPANY_IDS_CONFIG_KEY =
|
|
44
42
|
'shop-franchise-visible-company-ids';
|
|
45
|
-
export const SHOP_FRANCHISE_VISIBLE_ADDRESS_IDS_CONFIG_KEY =
|
|
46
|
-
'shop-franchise-visible-address-ids';
|
|
43
|
+
export const SHOP_FRANCHISE_VISIBLE_ADDRESS_IDS_CONFIG_KEY =
|
|
44
|
+
'shop-franchise-visible-address-ids';
|
|
45
|
+
export const SHOP_FRANCHISE_ADDRESS_CATEGORY_IDS_CONFIG_KEY =
|
|
46
|
+
'shop-franchise-address-category-ids';
|
|
47
|
+
export const SHOP_FRANCHISE_ADDRESS_CATEGORY_CONTEXT =
|
|
48
|
+
'shop-franchise-address';
|
|
47
49
|
export const SHOP_LOYALTY_COUPONS_ENABLED_CONFIG_KEY =
|
|
48
50
|
'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';
|
|
51
|
+
export const SHOP_LOYALTY_PRODUCT_IDS_CONFIG_KEY =
|
|
52
|
+
'shop-loyalty-product-ids';
|
|
53
|
+
export const SHOP_LOYALTY_REQUIRED_SALES_CONFIG_KEY =
|
|
54
|
+
'shop-loyalty-required-sales';
|
|
55
|
+
export const SHOP_LOYALTY_GIFT_PRODUCT_ID_CONFIG_KEY =
|
|
56
|
+
'shop-loyalty-gift-product-id';
|
|
57
|
+
export const SHOP_SHOWCASE_TYPE_SETTING_KEY = 'shop_type';
|
|
58
|
+
export const SHOP_SHOWCASE_TYPE_MENU = 'menu';
|
|
59
|
+
export const SHOP_SHOWCASE_TYPE_ECOMMERCE = 'ecommerce';
|
|
60
|
+
export const SHOP_SHOWCASE_TYPE_OPTIONS = [
|
|
61
|
+
SHOP_SHOWCASE_TYPE_MENU,
|
|
62
|
+
SHOP_SHOWCASE_TYPE_ECOMMERCE,
|
|
63
|
+
];
|
|
55
64
|
|
|
56
65
|
export const normalizeShopEntityId = value => {
|
|
57
66
|
if (!value) {
|
|
@@ -180,6 +189,14 @@ export const normalizeShopMoneyConfig = (value, fallback = 0) => {
|
|
|
180
189
|
|
|
181
190
|
return Number.isFinite(normalized) ? Math.max(0, normalized) : fallback;
|
|
182
191
|
};
|
|
192
|
+
|
|
193
|
+
export const normalizeShopShowcaseType = value => {
|
|
194
|
+
const normalized = String(value || '').trim().toLowerCase();
|
|
195
|
+
|
|
196
|
+
return SHOP_SHOWCASE_TYPE_OPTIONS.includes(normalized)
|
|
197
|
+
? normalized
|
|
198
|
+
: SHOP_SHOWCASE_TYPE_MENU;
|
|
199
|
+
};
|
|
183
200
|
|
|
184
201
|
export const getEnabledShopHomeOptions = ({
|
|
185
202
|
salesPageEnabled,
|
|
@@ -218,11 +235,11 @@ export const normalizeShopPrimaryEntry = (
|
|
|
218
235
|
return enabledOptions[0] || '';
|
|
219
236
|
};
|
|
220
237
|
|
|
221
|
-
export const resolveShopSettings = configs => {
|
|
222
|
-
const configMap =
|
|
223
|
-
configs && typeof configs === 'object' && !Array.isArray(configs)
|
|
224
|
-
? configs
|
|
225
|
-
: {};
|
|
238
|
+
export const resolveShopSettings = configs => {
|
|
239
|
+
const configMap =
|
|
240
|
+
configs && typeof configs === 'object' && !Array.isArray(configs)
|
|
241
|
+
? configs
|
|
242
|
+
: {};
|
|
226
243
|
|
|
227
244
|
const salesPageEnabled = normalizeBooleanConfig(
|
|
228
245
|
configMap[SHOP_SALES_PAGE_ENABLED_CONFIG_KEY],
|
|
@@ -241,11 +258,11 @@ export const resolveShopSettings = configs => {
|
|
|
241
258
|
configMap[SHOP_LOYALTY_COUPONS_ENABLED_CONFIG_KEY],
|
|
242
259
|
);
|
|
243
260
|
|
|
244
|
-
return {
|
|
245
|
-
salesPageEnabled,
|
|
246
|
-
franchiseLocatorEnabled,
|
|
247
|
-
loyaltyCouponsEnabled,
|
|
248
|
-
enabledHomeOptions,
|
|
261
|
+
return {
|
|
262
|
+
salesPageEnabled,
|
|
263
|
+
franchiseLocatorEnabled,
|
|
264
|
+
loyaltyCouponsEnabled,
|
|
265
|
+
enabledHomeOptions,
|
|
249
266
|
primaryEntry: normalizeShopPrimaryEntry(
|
|
250
267
|
configMap[SHOP_PRIMARY_ENTRY_CONFIG_KEY],
|
|
251
268
|
{
|
|
@@ -272,23 +289,44 @@ export const resolveShopSettings = configs => {
|
|
|
272
289
|
googleMapsApiKey: normalizeShopTextConfig(
|
|
273
290
|
configMap[SHOP_GOOGLE_MAPS_API_KEY_CONFIG_KEY],
|
|
274
291
|
),
|
|
275
|
-
franchisePinIconUrl: normalizeShopTextConfig(
|
|
276
|
-
configMap[SHOP_FRANCHISE_PIN_ICON_URL_CONFIG_KEY],
|
|
277
|
-
),
|
|
278
292
|
visibleFranchiseCompanyIds: normalizeShopEntityIds(
|
|
279
293
|
configMap[SHOP_FRANCHISE_VISIBLE_COMPANY_IDS_CONFIG_KEY],
|
|
280
294
|
),
|
|
281
|
-
visibleFranchiseAddressIds: normalizeShopEntityIds(
|
|
282
|
-
configMap[SHOP_FRANCHISE_VISIBLE_ADDRESS_IDS_CONFIG_KEY],
|
|
283
|
-
),
|
|
295
|
+
visibleFranchiseAddressIds: normalizeShopEntityIds(
|
|
296
|
+
configMap[SHOP_FRANCHISE_VISIBLE_ADDRESS_IDS_CONFIG_KEY],
|
|
297
|
+
),
|
|
298
|
+
franchiseAddressCategoryIds: normalizeShopEntityIds(
|
|
299
|
+
configMap[SHOP_FRANCHISE_ADDRESS_CATEGORY_IDS_CONFIG_KEY],
|
|
300
|
+
),
|
|
284
301
|
loyaltyProductIds: normalizeShopEntityIds(
|
|
285
302
|
configMap[SHOP_LOYALTY_PRODUCT_IDS_CONFIG_KEY],
|
|
286
303
|
),
|
|
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
|
-
};
|
|
304
|
+
loyaltyRequiredSales: normalizeShopLoyaltyRequiredSales(
|
|
305
|
+
configMap[SHOP_LOYALTY_REQUIRED_SALES_CONFIG_KEY],
|
|
306
|
+
),
|
|
307
|
+
loyaltyGiftProductId: normalizeShopEntityId(
|
|
308
|
+
configMap[SHOP_LOYALTY_GIFT_PRODUCT_ID_CONFIG_KEY],
|
|
309
|
+
),
|
|
310
|
+
};
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
export const saveAndUpdateConfigValue = ({
|
|
314
|
+
configKey,
|
|
315
|
+
nextValue,
|
|
316
|
+
saveConfig,
|
|
317
|
+
setValue,
|
|
318
|
+
}) => {
|
|
319
|
+
setValue(nextValue);
|
|
320
|
+
return saveConfig(configKey, nextValue);
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
export const toggleAndSaveBooleanConfig = ({
|
|
324
|
+
configKey,
|
|
325
|
+
currentValue,
|
|
326
|
+
saveConfig,
|
|
327
|
+
setValue,
|
|
328
|
+
}) => {
|
|
329
|
+
const nextValue = !Boolean(currentValue);
|
|
330
|
+
setValue(nextValue);
|
|
331
|
+
return saveConfig(configKey, nextValue ? '1' : '0');
|
|
332
|
+
};
|
|
@@ -3,19 +3,153 @@ import {
|
|
|
3
3
|
extractCollectionItems,
|
|
4
4
|
toEntityIri,
|
|
5
5
|
} from '@controleonline/ui-common/src/react/utils/commercialDocumentOrders';
|
|
6
|
-
import {normalizeShopEntityId} from '@controleonline/ui-common/src/react/utils/shopConfig';
|
|
6
|
+
import {normalizeShopEntityId} from '@controleonline/ui-common/src/react/utils/shopConfig';
|
|
7
7
|
|
|
8
8
|
export const SHOP_FRANCHISE_LINK_TYPE = 'franchisee';
|
|
9
9
|
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
|
+
});
|
|
28
|
+
|
|
29
|
+
const normalizeCategoryCandidate = value => {
|
|
30
|
+
const normalizedId = normalizeShopEntityId(value);
|
|
31
|
+
|
|
32
|
+
if (normalizedId) {
|
|
33
|
+
return normalizedId;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
37
|
+
return String(value || '').trim();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return '';
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const extractAddressCategoryIds = address => {
|
|
44
|
+
const candidates = [
|
|
45
|
+
address?.categories,
|
|
46
|
+
address?.category,
|
|
47
|
+
address?.addressCategories,
|
|
48
|
+
address?.address_categories,
|
|
49
|
+
address?.categoryAddresses,
|
|
50
|
+
address?.category_addresses,
|
|
51
|
+
];
|
|
52
|
+
const result = new Set();
|
|
53
|
+
|
|
54
|
+
const collect = value => {
|
|
55
|
+
if (value === null || value === undefined || value === '') {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (Array.isArray(value)) {
|
|
60
|
+
value.forEach(collect);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (typeof value === 'object') {
|
|
65
|
+
[
|
|
66
|
+
value.category,
|
|
67
|
+
value.category_id,
|
|
68
|
+
value.categoryId,
|
|
69
|
+
value.id,
|
|
70
|
+
value['@id'],
|
|
71
|
+
].forEach(collect);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
String(value)
|
|
76
|
+
.split(/\r?\n|,/)
|
|
77
|
+
.map(normalizeCategoryCandidate)
|
|
78
|
+
.filter(Boolean)
|
|
79
|
+
.forEach(id => result.add(id));
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
candidates.forEach(collect);
|
|
83
|
+
|
|
84
|
+
return Array.from(result);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const addressMatchesFranchiseCategoryIds = (
|
|
88
|
+
address,
|
|
89
|
+
categoryIds = [],
|
|
90
|
+
) => {
|
|
91
|
+
const selectedCategoryIds = new Set(
|
|
92
|
+
(Array.isArray(categoryIds) ? categoryIds : [])
|
|
93
|
+
.map(normalizeCategoryCandidate)
|
|
94
|
+
.filter(Boolean),
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
if (selectedCategoryIds.size === 0) {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return extractAddressCategoryIds(address).some(categoryId =>
|
|
102
|
+
selectedCategoryIds.has(categoryId),
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export const filterShopFranchiseDirectory = ({
|
|
107
|
+
directory = [],
|
|
108
|
+
visibleCompanyIds = [],
|
|
109
|
+
addressCategoryIds = [],
|
|
110
|
+
legacyVisibleAddressIds = [],
|
|
111
|
+
} = {}) => {
|
|
112
|
+
const visibleCompanyIdSet = new Set(
|
|
113
|
+
(Array.isArray(visibleCompanyIds) ? visibleCompanyIds : [])
|
|
114
|
+
.map(normalizeShopEntityId)
|
|
115
|
+
.filter(Boolean),
|
|
116
|
+
);
|
|
117
|
+
const legacyVisibleAddressIdSet = new Set(
|
|
118
|
+
(Array.isArray(legacyVisibleAddressIds) ? legacyVisibleAddressIds : [])
|
|
119
|
+
.map(normalizeShopEntityId)
|
|
120
|
+
.filter(Boolean),
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
if (visibleCompanyIdSet.size === 0) {
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return (Array.isArray(directory) ? directory : [])
|
|
128
|
+
.map(company => {
|
|
129
|
+
const companyId = normalizeShopEntityId(company);
|
|
130
|
+
|
|
131
|
+
if (!visibleCompanyIdSet.has(companyId)) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const shopAddresses = (company?.shopAddresses || []).filter(address => {
|
|
136
|
+
if (!addressMatchesFranchiseCategoryIds(address, addressCategoryIds)) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
legacyVisibleAddressIdSet.size === 0 ||
|
|
142
|
+
legacyVisibleAddressIdSet.has(normalizeShopEntityId(address))
|
|
143
|
+
);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
...company,
|
|
148
|
+
shopAddresses,
|
|
149
|
+
};
|
|
150
|
+
})
|
|
151
|
+
.filter(Boolean);
|
|
152
|
+
};
|
|
19
153
|
|
|
20
154
|
export const resolveFranchiseCompanyLabel = company =>
|
|
21
155
|
String(company?.alias || company?.name || '').trim() ||
|
|
@@ -49,14 +183,46 @@ export const fetchShopFranchiseCompanies = async ({
|
|
|
49
183
|
const items = extractCollectionItems(response);
|
|
50
184
|
|
|
51
185
|
return items
|
|
52
|
-
.map(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
186
|
+
.map(normalizeFranchiseDirectoryItem)
|
|
187
|
+
.sort((left, right) =>
|
|
188
|
+
sortByLabel(
|
|
189
|
+
resolveFranchiseCompanyLabel(left),
|
|
190
|
+
resolveFranchiseCompanyLabel(right),
|
|
191
|
+
),
|
|
192
|
+
);
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
export const fetchAllShopFranchiseDirectory = async ({
|
|
196
|
+
companyId,
|
|
197
|
+
publicDirectory = false,
|
|
198
|
+
search = '',
|
|
199
|
+
itemsPerPage = SHOP_FRANCHISE_PAGE_SIZE,
|
|
200
|
+
} = {}) => {
|
|
201
|
+
const normalizedItemsPerPage = normalizeItemsPerPage(itemsPerPage);
|
|
202
|
+
const items = [];
|
|
203
|
+
let page = 1;
|
|
204
|
+
|
|
205
|
+
while (true) {
|
|
206
|
+
const pageItems = await fetchShopFranchiseCompanies({
|
|
207
|
+
companyId,
|
|
208
|
+
publicDirectory,
|
|
209
|
+
search,
|
|
210
|
+
page,
|
|
211
|
+
itemsPerPage: normalizedItemsPerPage,
|
|
212
|
+
});
|
|
213
|
+
const normalizedPageItems = Array.isArray(pageItems) ? pageItems : [];
|
|
214
|
+
|
|
215
|
+
items.push(...normalizedPageItems);
|
|
216
|
+
|
|
217
|
+
if (normalizedPageItems.length < normalizedItemsPerPage) {
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
page += 1;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return items
|
|
225
|
+
.map(normalizeFranchiseDirectoryItem)
|
|
60
226
|
.sort((left, right) =>
|
|
61
227
|
sortByLabel(
|
|
62
228
|
resolveFranchiseCompanyLabel(left),
|
|
@@ -102,13 +268,6 @@ export const fetchShopFranchiseDirectory = async ({
|
|
|
102
268
|
itemsPerPage,
|
|
103
269
|
});
|
|
104
270
|
|
|
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
|
-
}));
|
|
271
|
+
return companies.map(normalizeFranchiseDirectoryItem);
|
|
113
272
|
};
|
|
114
273
|
// 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(
|
|
@@ -116,10 +116,29 @@ const normalizeFormattedValue = value => {
|
|
|
116
116
|
if (value === null || value === undefined) {
|
|
117
117
|
return value;
|
|
118
118
|
}
|
|
119
|
-
|
|
120
|
-
if (
|
|
121
|
-
return value
|
|
122
|
-
|
|
119
|
+
|
|
120
|
+
if (Array.isArray(value)) {
|
|
121
|
+
return value
|
|
122
|
+
.map(item => normalizeFormattedValue(item))
|
|
123
|
+
.filter(item => normalizeText(item))
|
|
124
|
+
.join(', ');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
128
|
+
return (
|
|
129
|
+
value?.label ??
|
|
130
|
+
value?.value ??
|
|
131
|
+
value?.name ??
|
|
132
|
+
value?.alias ??
|
|
133
|
+
value?.icon ??
|
|
134
|
+
value?.fileName ??
|
|
135
|
+
value?.filename ??
|
|
136
|
+
value?.originalName ??
|
|
137
|
+
value?.id ??
|
|
138
|
+
value?.['@id'] ??
|
|
139
|
+
''
|
|
140
|
+
);
|
|
141
|
+
}
|
|
123
142
|
|
|
124
143
|
return value;
|
|
125
144
|
};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import md5 from 'md5';
|
|
2
|
+
|
|
3
|
+
const normalizeText = value => String(value || '').replace(/\s+/g, ' ').trim();
|
|
4
|
+
|
|
5
|
+
const extractNumericId = value => {
|
|
6
|
+
const normalized = normalizeText(value);
|
|
7
|
+
if (!normalized) {
|
|
8
|
+
return '';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (/^\d+$/.test(normalized)) {
|
|
12
|
+
return normalized;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const match = normalized.match(/\/(\d+)(?:\/)?$/);
|
|
16
|
+
return match ? match[1] : '';
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const getAvatarDisplayName = user =>
|
|
20
|
+
normalizeText(
|
|
21
|
+
user?.name ||
|
|
22
|
+
user?.people?.name ||
|
|
23
|
+
user?.person?.name ||
|
|
24
|
+
user?.realname ||
|
|
25
|
+
user?.username,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
export const resolveUserAvatarUrl = (user, resolvePersistedAvatar) => {
|
|
29
|
+
return (
|
|
30
|
+
typeof resolvePersistedAvatar === 'function'
|
|
31
|
+
? normalizeText(resolvePersistedAvatar(user?.avatar))
|
|
32
|
+
: ''
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const resolveUserPeopleIri = (user, session = {}) => {
|
|
37
|
+
const candidates = [
|
|
38
|
+
session?.people,
|
|
39
|
+
session?.person,
|
|
40
|
+
session?.peopleId,
|
|
41
|
+
session?.people_id,
|
|
42
|
+
user?.people?.['@id'],
|
|
43
|
+
user?.people?.id,
|
|
44
|
+
user?.people,
|
|
45
|
+
user?.person?.['@id'],
|
|
46
|
+
user?.person?.id,
|
|
47
|
+
user?.person,
|
|
48
|
+
user?.peopleId,
|
|
49
|
+
user?.people_id,
|
|
50
|
+
user?.person_id,
|
|
51
|
+
user?.['@id'],
|
|
52
|
+
user?.id,
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
for (const candidate of candidates) {
|
|
56
|
+
const normalized = normalizeText(candidate);
|
|
57
|
+
if (!normalized) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (normalized.includes('/people/')) {
|
|
62
|
+
return normalized;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const id = extractNumericId(normalized);
|
|
66
|
+
if (id) {
|
|
67
|
+
return `/people/${id}`;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return '';
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const getUserInitials = ({name, email} = {}) => {
|
|
75
|
+
const words = normalizeText(name).split(' ').filter(Boolean);
|
|
76
|
+
|
|
77
|
+
if (words.length >= 2) {
|
|
78
|
+
return `${words[0][0]}${words[words.length - 1][0]}`.toUpperCase();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (words.length === 1) {
|
|
82
|
+
return words[0][0].toUpperCase();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const normalizedEmail = normalizeText(email);
|
|
86
|
+
return normalizedEmail ? normalizedEmail[0].toUpperCase() : '?';
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const getGravatarUrl = (email, size = 200) => {
|
|
90
|
+
const normalizedEmail = normalizeText(email).toLowerCase();
|
|
91
|
+
if (!normalizedEmail) {
|
|
92
|
+
return '';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return `https://www.gravatar.com/avatar/${md5(normalizedEmail)}?s=${size}&d=404`;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export default {
|
|
99
|
+
getAvatarDisplayName,
|
|
100
|
+
getGravatarUrl,
|
|
101
|
+
getUserInitials,
|
|
102
|
+
resolveUserAvatarUrl,
|
|
103
|
+
resolveUserPeopleIri,
|
|
104
|
+
};
|
|
@@ -8,11 +8,20 @@ export default {
|
|
|
8
8
|
item: {},
|
|
9
9
|
items: [],
|
|
10
10
|
filters: {},
|
|
11
|
-
resourceEndpoint: "categories",
|
|
12
|
-
isLoading: false,
|
|
13
|
-
error: "",
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
resourceEndpoint: "categories",
|
|
12
|
+
isLoading: false,
|
|
13
|
+
error: "",
|
|
14
|
+
configs: {
|
|
15
|
+
import: {
|
|
16
|
+
enabled: true,
|
|
17
|
+
importType: "product",
|
|
18
|
+
labelKey: ["categories", "button", "importCsv"],
|
|
19
|
+
titleKey: ["categories", "title", "productImport"],
|
|
20
|
+
searchPlaceholderKey: ["categories", "input", "importSearch"],
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
totalItems: 0,messages:[], message:{},
|
|
16
25
|
|
|
17
26
|
summary: {},
|
|
18
27
|
filters: {},
|
|
@@ -29,17 +38,34 @@ export default {
|
|
|
29
38
|
return "#" + value;
|
|
30
39
|
},
|
|
31
40
|
},
|
|
32
|
-
{
|
|
33
|
-
externalFilter: false,
|
|
34
|
-
sortable: true,
|
|
35
|
-
name: "name",
|
|
41
|
+
{
|
|
42
|
+
externalFilter: false,
|
|
43
|
+
sortable: true,
|
|
44
|
+
name: "name",
|
|
36
45
|
align: "left",
|
|
37
46
|
label: "name",
|
|
38
47
|
sum: false,
|
|
39
48
|
format: function (value) {
|
|
40
49
|
return value;
|
|
41
|
-
},
|
|
42
|
-
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
sortable: true,
|
|
54
|
+
editable: true,
|
|
55
|
+
inputType: "number",
|
|
56
|
+
name: "sortOrder",
|
|
57
|
+
align: "right",
|
|
58
|
+
label: "sortOrder",
|
|
59
|
+
defaultSort: "ASC",
|
|
60
|
+
format: function (value) {
|
|
61
|
+
return value ?? "";
|
|
62
|
+
},
|
|
63
|
+
saveFormat: function (value) {
|
|
64
|
+
return value === "" || value === null || value === undefined
|
|
65
|
+
? null
|
|
66
|
+
: Number(value);
|
|
67
|
+
},
|
|
68
|
+
},
|
|
43
69
|
{
|
|
44
70
|
sortable: true,
|
|
45
71
|
name: "color",
|
|
@@ -60,15 +86,17 @@ export default {
|
|
|
60
86
|
return value;
|
|
61
87
|
},
|
|
62
88
|
},
|
|
63
|
-
{
|
|
64
|
-
sortable: true,
|
|
65
|
-
name: "categoryFiles",
|
|
66
|
-
align: "left",
|
|
67
|
-
label: "categoryFiles",
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
89
|
+
{
|
|
90
|
+
sortable: true,
|
|
91
|
+
name: "categoryFiles",
|
|
92
|
+
align: "left",
|
|
93
|
+
label: "categoryFiles",
|
|
94
|
+
inputType: "files",
|
|
95
|
+
fileType: "image",
|
|
96
|
+
format: function (value) {
|
|
97
|
+
return value;
|
|
98
|
+
},
|
|
99
|
+
},
|
|
72
100
|
{
|
|
73
101
|
externalFilter: false,
|
|
74
102
|
sortable: true,
|