@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.
Files changed (188) hide show
  1. package/.github/actions/workers/manager/action.yml +147 -0
  2. package/.github/actions/workers/qa/action.yml +44 -0
  3. package/.github/actions/workers/security/action.yml +44 -0
  4. package/.github/actions/workers/technical-documenter/action.yml +51 -0
  5. package/.github/workflows/manager-worker.yml +168 -0
  6. package/.github/workflows/publish-npm.yml +45 -0
  7. package/.gitmodules +3 -0
  8. package/AGENTS.md +6 -0
  9. package/README.md +14 -0
  10. package/package.json +32 -28
  11. package/src/api/fetch.js +1 -1
  12. package/src/api/index.js +328 -58
  13. package/src/react/components/AddImportModal.js +95 -111
  14. package/src/react/components/AnimatedModal.js +171 -0
  15. package/src/react/components/AnimatedModal.styles.js +21 -0
  16. package/src/react/components/AppTypeSwitcher.js +164 -0
  17. package/src/react/components/AppTypeSwitcher.styles.js +109 -0
  18. package/src/react/components/BackgroundRuntimeBridge.js +5 -4
  19. package/src/react/components/BottomNavigationBar.config.js +211 -231
  20. package/src/react/components/BottomNavigationBar.js +86 -31
  21. package/src/react/components/BottomNavigationBar.styles.js +118 -110
  22. package/src/react/components/CategoryForm.js +52 -35
  23. package/src/react/components/DefaultProvider.native.js +194 -156
  24. package/src/react/components/DefaultProvider.web.js +188 -112
  25. package/src/react/components/DeliveryPushBridge.native.js +2 -2
  26. package/src/react/components/DeviceAlertSoundService.js +3 -3
  27. package/src/react/components/KioskModeBridge.js +2 -2
  28. package/src/react/components/LauncherModeBridge.js +2 -2
  29. package/src/react/components/ManagerPushBridge.native.js +2 -2
  30. package/src/react/components/NetworkPrinterPreviewModal.js +249 -0
  31. package/src/react/components/NetworkPrinterPreviewModal.styles.js +159 -0
  32. package/src/react/components/RemoteCheckoutService.js +28 -20
  33. package/src/react/components/RuntimeBottomNavigationBar.js +146 -119
  34. package/src/react/components/RuntimeInfoFooter.js +137 -45
  35. package/src/react/components/RuntimeInfoFooter.styles.js +3 -0
  36. package/src/react/components/StateStore.js +258 -0
  37. package/src/react/components/UnifiedPaymentBar.js +7 -4
  38. package/src/react/components/UserAvatar.js +160 -0
  39. package/src/react/components/WebsocketListener.native.js +11 -11
  40. package/src/react/components/integrations/IntegrationHero/index.js +48 -0
  41. package/src/react/components/integrations/IntegrationHero/styles.js +57 -0
  42. package/src/react/components/integrations/IntegrationTabs/index.js +89 -0
  43. package/src/react/components/integrations/IntegrationTabs/styles.js +44 -0
  44. package/src/react/config/deviceConfigBootstrap.js +71 -30
  45. package/src/react/css/orders.js +72 -0
  46. package/src/react/pages/Connections.js +229 -0
  47. package/src/react/pages/Connections.styles.js +222 -0
  48. package/src/react/pages/DeviceDetailPage.js +2814 -0
  49. package/src/react/pages/DeviceDetailPage.styles.js +308 -0
  50. package/src/react/pages/Devices/currentDevice.js +194 -0
  51. package/src/react/pages/Devices/deviceTypes/DeviceGroupCard.js +257 -0
  52. package/src/react/pages/Devices/deviceTypes/all.js +23 -0
  53. package/src/react/pages/Devices/deviceTypes/device.js +25 -0
  54. package/src/react/pages/Devices/deviceTypes/deviceListHelpers.js +178 -0
  55. package/src/react/pages/Devices/deviceTypes/display.js +26 -0
  56. package/src/react/pages/Devices/deviceTypes/index.js +145 -0
  57. package/src/react/pages/Devices/deviceTypes/ipCamera.js +35 -0
  58. package/src/react/pages/Devices/deviceTypes/pdv.js +88 -0
  59. package/src/react/pages/Devices/deviceTypes/printer.js +37 -0
  60. package/src/react/pages/Devices/deviceTypes/shared.js +453 -0
  61. package/src/react/pages/Devices/deviceTypes/useDeviceNetworkConnectivity.js +145 -0
  62. package/src/react/pages/Devices.js +183 -0
  63. package/src/react/pages/Devices.styles.js +353 -0
  64. package/src/react/pages/Food99IntegrationPage/components/Food99CatalogTab.js +219 -0
  65. package/src/react/pages/Food99IntegrationPage/components/Food99OverviewTab.js +134 -0
  66. package/src/react/pages/Food99IntegrationPage/components/Food99PreviewModal.js +173 -0
  67. package/src/react/pages/Food99IntegrationPage/components/Food99ProductCard.js +1 -0
  68. package/src/react/pages/Food99IntegrationPage/components/Food99QuickWalletModal.js +181 -0
  69. package/src/react/pages/Food99IntegrationPage/components/Food99SettingsTab.js +306 -0
  70. package/src/react/pages/Food99IntegrationPage/components/Food99StoreTab.js +417 -0
  71. package/src/react/pages/Food99IntegrationPage/index.js +1530 -0
  72. package/src/react/pages/Food99IntegrationPage/styles.js +792 -0
  73. package/src/react/pages/Food99IntegrationPage/utils.js +155 -0
  74. package/src/react/pages/Food99IntegrationPage.js +1 -0
  75. package/src/react/pages/Food99IntegrationPage.styles.js +1 -0
  76. package/src/react/pages/GenericLogPage.js +42 -167
  77. package/src/react/pages/IFoodIntegrationPage/components/IFoodCatalogTab.js +8 -0
  78. package/src/react/pages/IFoodIntegrationPage/components/IFoodOperationsTab.js +420 -0
  79. package/src/react/pages/IFoodIntegrationPage/components/IFoodOverviewTab.js +118 -0
  80. package/src/react/pages/IFoodIntegrationPage/components/IFoodPreviewModal.js +103 -0
  81. package/src/react/pages/IFoodIntegrationPage/components/IFoodProductCard.js +1 -0
  82. package/src/react/pages/IFoodIntegrationPage/components/IFoodStoreTab.js +150 -0
  83. package/src/react/pages/IFoodIntegrationPage/index.js +1298 -0
  84. package/src/react/pages/IFoodIntegrationPage/styles.js +764 -0
  85. package/src/react/pages/IFoodIntegrationPage/utils.js +91 -0
  86. package/src/react/pages/IFoodIntegrationPage.js +1 -0
  87. package/src/react/pages/IFoodIntegrationPage.styles.js +1 -0
  88. package/src/react/pages/Imports.js +214 -166
  89. package/src/react/pages/IntegrationConfigPage.js +744 -0
  90. package/src/react/pages/IntegrationConfigPage.styles.js +269 -0
  91. package/src/react/pages/Integrations.js +299 -0
  92. package/src/react/pages/Integrations.styles.js +130 -0
  93. package/src/react/pages/ManagerOrderNotificationsPage.js +642 -0
  94. package/src/react/pages/MarketplaceIntegrationPage/components/MarketplaceProductCard.js +205 -0
  95. package/src/react/pages/MarketplaceIntegrationPage/components/RemoteMarketplaceMenuTab.js +335 -0
  96. package/src/react/pages/MarketplaceIntegrationPage/index.js +60 -0
  97. package/src/react/pages/MarketplaceIntegrationPage/utils.js +137 -0
  98. package/src/react/pages/MercadoLivreIntegrationPage.js +538 -0
  99. package/src/react/pages/PrinterDeviceDetailPage.js +1916 -0
  100. package/src/react/pages/PrinterDeviceDetailPage.styles.js +223 -0
  101. package/src/react/pages/PrinterDeviceFormPage.js +521 -0
  102. package/src/react/pages/PrinterDeviceFormPage.styles.js +159 -0
  103. package/src/react/pages/SettingsPage/PaymentTypesByWalletTab.js +484 -454
  104. package/src/react/pages/SettingsPage/index.js +1266 -1167
  105. package/src/react/pages/WhatsAppConnectionPage.js +459 -0
  106. package/src/react/pages/WhatsAppConnectionPage.styles.js +284 -0
  107. package/src/react/pages/integrationsCatalog.js +399 -0
  108. package/src/react/print/providers/local.js +1 -1
  109. package/src/react/router/publicRoutes.js +25 -0
  110. package/src/react/services/Cielo/Checkout.js +39 -0
  111. package/src/react/services/Cielo/Cielo.js +193 -0
  112. package/src/react/services/Cielo/Print.js +7 -0
  113. package/src/react/services/InfinitePay/Checkout.js +33 -0
  114. package/src/react/services/InfinitePay/InfinitePay.js +24 -0
  115. package/src/react/{utils → services}/paymentGatewayExecution.js +91 -91
  116. package/src/react/styles/global.js +115 -0
  117. package/src/react/utils/categoryContexts.js +46 -0
  118. package/src/react/utils/entityDisplay.js +222 -217
  119. package/src/react/utils/fileUrl.js +201 -16
  120. package/src/react/utils/integrationPage.js +16 -0
  121. package/src/react/utils/menuNavigation.js +31 -0
  122. package/src/react/utils/orderIdentity.js +277 -0
  123. package/src/react/utils/remotePayment.js +115 -61
  124. package/src/react/utils/runtimeFooter.js +40 -22
  125. package/src/react/utils/runtimeLanguage.js +50 -9
  126. package/src/react/utils/runtimeMenu.js +190 -98
  127. package/src/react/utils/runtimeZoom.js +43 -0
  128. package/src/react/utils/shopConfig.js +72 -34
  129. package/src/react/utils/shopFranchises.js +182 -23
  130. package/src/react/utils/socketRuntimePipeline.js +14 -14
  131. package/src/react/utils/storeColumns.js +23 -4
  132. package/src/react/utils/userAvatar.js +104 -0
  133. package/src/store/categories/index.js +48 -20
  134. package/src/store/configs/index.js +2 -2
  135. package/src/store/device_config/index.js +62 -21
  136. package/src/store/entity_log/index.js +22 -1
  137. package/src/store/imports/customActions.js +51 -0
  138. package/src/store/imports/index.js +89 -88
  139. package/src/store/status/index.js +11 -11
  140. package/src/store/themes/index.js +22 -0
  141. package/src/store/timezones/index.js +3 -1
  142. package/src/tests/browser/manager/connections.spec.js +143 -0
  143. package/src/tests/browser/manager/devices-current.spec.js +343 -0
  144. package/src/tests/browser/manager/mercado-livre-integration.spec.js +268 -0
  145. package/src/tests/react/api/deviceHeaders.test.js +114 -0
  146. package/src/tests/react/api/loadSmokeIndex.test.js +75 -0
  147. package/src/tests/react/components/AddImportModal.test.js +166 -0
  148. package/src/tests/react/components/BottomNavigationBar.config.test.js +20 -0
  149. package/src/tests/react/components/UserAvatar.test.js +52 -0
  150. package/src/tests/react/config/deviceConfigBootstrap.test.js +47 -0
  151. package/src/tests/react/pages/DevicePickerStyles.test.js +47 -0
  152. package/src/tests/react/pages/Devices/deviceListHelpers.test.js +39 -0
  153. package/src/tests/react/pages/DevicesCurrentDevice.test.js +198 -0
  154. package/src/tests/react/pages/connectionsHelpers.test.js +34 -0
  155. package/src/tests/react/pages/mercadoLivreIntegrationPageContract.test.mjs +16 -0
  156. package/src/tests/react/print/localPrintProvider.test.js +1 -1
  157. package/src/tests/react/services/Cielo.test.js +190 -0
  158. package/src/tests/react/store/categoriesOrdering.test.js +26 -0
  159. package/src/tests/react/utils/appDomain.test.js +62 -0
  160. package/src/tests/react/utils/entityDisplay.test.js +2 -2
  161. package/src/tests/react/utils/fileUrl.test.js +62 -0
  162. package/src/tests/react/utils/formatter.test.mjs +33 -0
  163. package/src/tests/react/utils/importStatus.test.js +2 -2
  164. package/src/tests/react/utils/orderIdentity.test.js +139 -0
  165. package/src/tests/react/utils/remotePayment.test.js +62 -0
  166. package/src/tests/react/utils/runtimeFooter.test.js +32 -9
  167. package/src/tests/react/utils/runtimeLanguage.test.js +80 -10
  168. package/src/tests/react/utils/runtimeMenu.test.js +195 -111
  169. package/src/tests/react/utils/runtimeZoom.test.js +38 -0
  170. package/src/tests/react/utils/shopConfig.test.js +75 -0
  171. package/src/tests/react/utils/shopFranchises.test.js +122 -12
  172. package/src/tests/react/utils/translate.discovery.test.mjs +170 -0
  173. package/src/tests/react/utils/translate.test.helpers.mjs +152 -0
  174. package/src/tests/react/utils/translate.test.mjs +252 -396
  175. package/src/tests/react/utils/userAvatar.test.js +63 -0
  176. package/src/utils/appDomain.js +15 -4
  177. package/src/utils/formatter.js +122 -16
  178. package/src/utils/integrationConfigs.js +1 -0
  179. package/src/utils/translate.js +277 -398
  180. package/src/utils/translateDiscovery.js +96 -0
  181. package/src/utils/translateNormalize.js +33 -0
  182. package/src/utils/translatePending.js +92 -0
  183. package/src/utils/translateStorage.js +142 -0
  184. package/.github/agents/developer.agent.md +0 -30
  185. package/.github/agents/devops.agent.md +0 -30
  186. package/.github/agents/qa.agent.md +0 -30
  187. package/.github/agents/security.agent.md +0 -30
  188. package/.github/workflows/npmjs.yml +0 -35
@@ -0,0 +1,63 @@
1
+ import {
2
+ getAvatarDisplayName,
3
+ getGravatarUrl,
4
+ getUserInitials,
5
+ resolveUserAvatarUrl,
6
+ resolveUserPeopleIri,
7
+ } from '../../../react/utils/userAvatar';
8
+
9
+ describe('userAvatar', () => {
10
+ it('uses the first and last names for two initials', () => {
11
+ expect(getUserInitials({name: 'Alexandre AleMac Cunha'})).toBe('AC');
12
+ });
13
+
14
+ it('uses one initial for a single name', () => {
15
+ expect(getUserInitials({name: 'Alexandre'})).toBe('A');
16
+ });
17
+
18
+ it('falls back to the email initial when the name is unavailable', () => {
19
+ expect(getUserInitials({email: 'claudio@example.com'})).toBe('C');
20
+ });
21
+
22
+ it('asks Gravatar for a real image without an identicon fallback', () => {
23
+ expect(getGravatarUrl(' MyEmailAddress@example.com ', 120)).toBe(
24
+ 'https://www.gravatar.com/avatar/0bc83cb571cd1c50ba6f3e8a78ef1346?s=120&d=404',
25
+ );
26
+ });
27
+
28
+ it('does not call Gravatar without an email', () => {
29
+ expect(getGravatarUrl('')).toBe('');
30
+ });
31
+
32
+ it('uses the complete person name and never the functional alias', () => {
33
+ const user = {name: 'Claudio Medeiros', realname: 'Claudio Owner', alias: 'owner'};
34
+
35
+ expect(getAvatarDisplayName(user)).toBe('Claudio Medeiros');
36
+ expect(getUserInitials({name: getAvatarDisplayName(user)})).toBe('CM');
37
+ });
38
+
39
+ it('resolves the person from the same stored session shape used by Profile', () => {
40
+ expect(
41
+ resolveUserPeopleIri({id: 131}, {people: '/people/14'}),
42
+ ).toBe('/people/14');
43
+ });
44
+
45
+ it('resolves only the canonical persisted avatar', () => {
46
+ const user = {avatar: {id: 42}};
47
+
48
+ expect(
49
+ resolveUserAvatarUrl(user, avatar =>
50
+ avatar?.id ? `https://api.example/files/${avatar.id}/download` : '',
51
+ ),
52
+ ).toBe('https://api.example/files/42/download');
53
+ });
54
+
55
+ it('does not treat avatarUrl as an avatar source', () => {
56
+ expect(
57
+ resolveUserAvatarUrl(
58
+ {avatarUrl: 'https://legacy.example/avatar.png'},
59
+ () => '',
60
+ ),
61
+ ).toBe('');
62
+ });
63
+ });
@@ -1,4 +1,9 @@
1
- const toRawString = value => String(value || '').trim();
1
+ const INVALID_DOMAIN_VALUES = new Set(['undefined', 'null', 'false']);
2
+
3
+ const toRawString = value => {
4
+ const raw = String(value || '').trim();
5
+ return INVALID_DOMAIN_VALUES.has(raw.toLowerCase()) ? '' : raw;
6
+ };
2
7
 
3
8
  const tryParseHost = value => {
4
9
  const raw = toRawString(value);
@@ -23,10 +28,16 @@ export const resolveRuntimeHost = () => {
23
28
  return toRawString(location?.host || '');
24
29
  };
25
30
 
31
+ /**
32
+ * App-Domain header value.
33
+ * Browser (web multi-tenant): always prefer window.location.host so custom
34
+ * domains (e.g. erpjaguncos.com.br) resolve the correct tenant.
35
+ * Native / no location: fall back to configured DOMAIN from env.
36
+ */
26
37
  export const resolveAppDomain = configuredDomain => {
27
- const configuredHost = tryParseHost(configuredDomain);
28
- if (configuredHost) return configuredHost;
29
- return tryParseHost(resolveRuntimeHost());
38
+ const runtimeHost = tryParseHost(resolveRuntimeHost());
39
+ if (runtimeHost) return runtimeHost;
40
+ return tryParseHost(configuredDomain);
30
41
  };
31
42
 
32
43
  export const resolveCompanyDomain = (company, fallbackDomain = '') => {
@@ -1,10 +1,62 @@
1
- export default class Formatter {
1
+ /* global Intl */
2
+
3
+ const MOJIBAKE_REPLACEMENTS = [
4
+ ['À', 'À'],
5
+ ['\u00C3\u0081', 'Á'],
6
+ ['Â', 'Â'],
7
+ ['Ã', 'Ã'],
8
+ ['É', 'É'],
9
+ ['Ê', 'Ê'],
10
+ ['Ó', 'Ó'],
11
+ ['Ô', 'Ô'],
12
+ ['Õ', 'Õ'],
13
+ ['Ú', 'Ú'],
14
+ ['á', 'á'],
15
+ ['à', 'à'],
16
+ ['Ã\u00A0', 'à'],
17
+ ['â', 'â'],
18
+ ['ã', 'ã'],
19
+ ['é', 'é'],
20
+ ['ê', 'ê'],
21
+ ['í', 'í'],
22
+ ['ó', 'ó'],
23
+ ['ô', 'ô'],
24
+ ['õ', 'õ'],
25
+ ['ú', 'ú'],
26
+ ['Ç', 'Ç'],
27
+ ['ç', 'ç'],
28
+ ['º', 'º'],
29
+ ['ª', 'ª'],
30
+ ['·', '·'],
31
+ ['→', '→'],
32
+ ['–', '–'],
33
+ ['—', '—'],
34
+ ['‘', "'"],
35
+ ['’', "'"],
36
+ ['“', '"'],
37
+ ['\u00E2\u20AC\u009D', '"'],
38
+ ['Â', ''],
39
+ ];
40
+
41
+ export default class Formatter {
2
42
 
3
43
  /* ================= UTIL ================= */
4
44
 
5
- static onlyNumbers(value) {
6
- return String(value || '').replace(/\D/g, '');
7
- }
45
+ static onlyNumbers(value) {
46
+ return String(value || '').replace(/\D/g, '');
47
+ }
48
+
49
+ static repairMojibake(value) {
50
+ let text = String(value || '');
51
+
52
+ for (let pass = 0; pass < 2; pass += 1) {
53
+ MOJIBAKE_REPLACEMENTS.forEach(([broken, fixed]) => {
54
+ text = text.split(broken).join(fixed);
55
+ });
56
+ }
57
+
58
+ return text;
59
+ }
8
60
 
9
61
  /* ================= DOCUMENTOS ================= */
10
62
 
@@ -310,6 +362,24 @@ export default class Formatter {
310
362
  return `${Formatter.formatDecimal(value, locale, maximumFractionDigits)}%`;
311
363
  }
312
364
 
365
+ static formatCount(value, singular, plural = `${singular}s`) {
366
+ return `${value} ${value === 1 ? singular : plural}`;
367
+ }
368
+
369
+ static formatDateTime(value) {
370
+ if (!value) return 'sem data';
371
+
372
+ const date = new Date(value);
373
+
374
+ if (isNaN(date.getTime()))
375
+ return value;
376
+
377
+ return new Intl.DateTimeFormat('pt-BR', {
378
+ dateStyle: 'medium',
379
+ timeStyle: 'short',
380
+ }).format(date);
381
+ }
382
+
313
383
  static formatSignedInteger(value, locale = 'pt-BR') {
314
384
 
315
385
  const numericValue = Number(value || 0);
@@ -384,14 +454,18 @@ export default class Formatter {
384
454
  return `${year}-${month}-${day}`;
385
455
  }
386
456
 
387
- static formatDateYmdTodmY(value, withTime = false) {
388
-
389
- if (!value) return '';
390
-
391
- const date = new Date(value);
392
-
393
- if (isNaN(date.getTime()))
394
- return value;
457
+ static formatDateYmdTodmY(value, withTime = false) {
458
+
459
+ if (!value) return '';
460
+
461
+ const isoOffsetParts = Formatter.parseIsoDateWithNumericOffset(value);
462
+ if (isoOffsetParts)
463
+ return Formatter.formatDatePartsToBR(isoOffsetParts, withTime);
464
+
465
+ const date = new Date(value);
466
+
467
+ if (isNaN(date.getTime()))
468
+ return value;
395
469
 
396
470
  const clientTimeZoneOffset = new Date().getTimezoneOffset();
397
471
 
@@ -412,8 +486,40 @@ export default class Formatter {
412
486
  options.minute = '2-digit';
413
487
  options.second = '2-digit';
414
488
  }
415
-
416
- return date.toLocaleString('pt-BR', options);
417
- }
418
-
489
+
490
+ return date.toLocaleString('pt-BR', options);
491
+ }
492
+
493
+ static parseIsoDateWithNumericOffset(value) {
494
+
495
+ if (typeof value !== 'string')
496
+ return null;
497
+
498
+ const matches = value.match(
499
+ /^(\d{4})-(\d{2})-(\d{2})[T\s](\d{2}):(\d{2})(?::(\d{2})(?:\.\d+)?)?[+-]\d{2}:?\d{2}$/
500
+ );
501
+
502
+ if (!matches)
503
+ return null;
504
+
505
+ return {
506
+ year: matches[1],
507
+ month: matches[2],
508
+ day: matches[3],
509
+ hour: matches[4],
510
+ minute: matches[5],
511
+ second: matches[6] || '00',
512
+ };
513
+ }
514
+
515
+ static formatDatePartsToBR(parts, withTime = false) {
516
+
517
+ const date = `${parts.day}/${parts.month}/${parts.year}`;
518
+
519
+ if (!withTime)
520
+ return date;
521
+
522
+ return `${date}, ${parts.hour}:${parts.minute}:${parts.second}`;
523
+ }
524
+
419
525
  }
@@ -6,6 +6,7 @@ export const DEFAULT_CIELO_CONFIG = {
6
6
  ACCESS_TOKEN: '',
7
7
  CLIENT_ID: '',
8
8
  EMAIL: '',
9
+ MERCHANT_CODE: '',
9
10
  };
10
11
 
11
12
  export const DEFAULT_NEW_RELIC_CONFIG = {