@controleonline/ui-common 1.2.80 → 1.2.82

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 (90) hide show
  1. package/AGENTS.md +8 -0
  2. package/package.json +9 -3
  3. package/src/api/fetch.js +7 -7
  4. package/src/react/components/AddImportModal.js +6 -2
  5. package/src/react/components/BackgroundRuntimeBridge.js +201 -215
  6. package/src/react/components/ConfirmModal.js +44 -9
  7. package/src/react/components/ConfirmModal.styles.js +55 -41
  8. package/src/react/components/CopyDeviceConfigModal.js +193 -0
  9. package/src/react/components/CopyDeviceConfigModal.styles.js +123 -0
  10. package/src/react/components/DefaultProvider.native.js +22 -0
  11. package/src/react/components/DefaultProvider.web.js +25 -1
  12. package/src/react/components/EntityLogBranch.js +482 -0
  13. package/src/react/components/EntityLogCards.js +369 -0
  14. package/src/react/components/EntityLogContent.js +113 -794
  15. package/src/react/components/LinkedOrderProductsTab.js +3 -3
  16. package/src/react/components/PrintService.js +130 -409
  17. package/src/react/components/RemoteCheckoutService.js +2 -2
  18. package/src/react/components/RuntimeBottomNavigationBar.js +141 -146
  19. package/src/react/components/RuntimeFooterMarqueeText.js +137 -0
  20. package/src/react/components/RuntimeInfoFooter.js +12 -15
  21. package/src/react/components/SystemErrorToast.js +49 -29
  22. package/src/react/components/SystemErrorToast.styles.js +43 -38
  23. package/src/react/components/UserAvatar.js +120 -28
  24. package/src/react/config/deviceConfigBootstrap.js +330 -304
  25. package/src/react/hooks/usePrintSpoolEffects.js +161 -0
  26. package/src/react/pages/DeviceDetailPage.js +6 -2882
  27. package/src/react/pages/Devices/detail/DeviceDetailAlertsCommandsSection.js +233 -0
  28. package/src/react/pages/Devices/detail/DeviceDetailHeader.js +138 -0
  29. package/src/react/pages/Devices/detail/DeviceDetailMovementSections.js +167 -0
  30. package/src/react/pages/Devices/detail/DeviceDetailOrdersPrintSection.js +216 -0
  31. package/src/react/pages/Devices/detail/DeviceDetailPaymentSection.js +44 -0
  32. package/src/react/pages/Devices/detail/DeviceDetailPdvConfigSection.js +390 -0
  33. package/src/react/pages/Devices/detail/DeviceDetailRenderers.js +135 -0
  34. package/src/react/pages/Devices/detail/DeviceDetailScreen.js +495 -0
  35. package/src/react/pages/Devices/detail/OptionButtonChip.js +65 -0
  36. package/src/react/pages/Devices/detail/deviceDetailConstants.js +36 -0
  37. package/src/react/pages/Devices/detail/deviceDetailHelpers.js +70 -0
  38. package/src/react/pages/Devices/detail/useDeviceDetailActions.js +483 -0
  39. package/src/react/pages/Devices/detail/useDeviceDetailCopyConfig.js +87 -0
  40. package/src/react/pages/Devices/detail/useDeviceDetailLoaders.js +327 -0
  41. package/src/react/pages/Devices/detail/useDeviceDetailSaves.js +429 -0
  42. package/src/react/pages/Devices/detail/useDeviceDetailStateA.js +489 -0
  43. package/src/react/pages/Devices/detail/useDeviceDetailStateB.js +98 -0
  44. package/src/react/pages/Devices/deviceTypes/index.js +2 -0
  45. package/src/react/pages/Devices/deviceTypes/pdv.js +11 -0
  46. package/src/react/pages/Imports.js +3 -2
  47. package/src/react/pages/IntegrationConfigFields.js +126 -0
  48. package/src/react/pages/IntegrationConfigPage.js +122 -591
  49. package/src/react/pages/IntegrationConfigPage.utils.js +95 -0
  50. package/src/react/print/usePrintButtonController.js +9 -1
  51. package/src/react/services/Getnet/Checkout.js +81 -0
  52. package/src/react/services/Getnet/Getnet.js +77 -0
  53. package/src/react/services/paymentGatewayExecution.js +20 -0
  54. package/src/react/utils/bottomNavigationToolbar.js +161 -0
  55. package/src/react/utils/commercialDocumentOrders.js +18 -6
  56. package/src/react/utils/copyDeviceConfigs.js +198 -0
  57. package/src/react/utils/fileUrl.js +43 -0
  58. package/src/react/utils/importStatus.js +19 -10
  59. package/src/react/utils/logSettings.js +7 -7
  60. package/src/react/utils/maintenanceSettings.js +16 -0
  61. package/src/react/utils/paymentDevices.js +6 -0
  62. package/src/react/utils/printManagedPrinter.js +45 -0
  63. package/src/react/utils/printRouting.js +63 -0
  64. package/src/react/utils/printSpoolUtils.js +119 -0
  65. package/src/react/utils/printerDevices.js +368 -368
  66. package/src/react/utils/runtimeFooter.js +10 -19
  67. package/src/react/utils/shopFranchises.js +186 -65
  68. package/src/react/utils/systemErrorMessage.js +71 -67
  69. package/src/store/device_config/customActions.js +119 -30
  70. package/src/tests/browser/manager/bottom-navigation-role-toolbar.spec.js +353 -0
  71. package/src/tests/browser/manager/device-detail-alias-save.spec.js +345 -0
  72. package/src/tests/browser/manager/device-detail-copy-config.spec.js +365 -0
  73. package/src/tests/browser/manager/runtime-footer-marquee.spec.js +262 -0
  74. package/src/tests/browser/manager/theme-confirm-toast.spec.js +236 -0
  75. package/src/tests/react/components/RuntimeFooterMarqueeText.test.js +171 -0
  76. package/src/tests/react/components/UserAvatar.test.js +6 -2
  77. package/src/tests/react/components/themeAwareModals.test.mjs +60 -0
  78. package/src/tests/react/config/deviceConfigBootstrap.test.js +104 -66
  79. package/src/tests/react/pages/deviceDetailDelete.test.js +78 -0
  80. package/src/tests/react/pages/receitaFederalIntegrationContract.test.mjs +48 -0
  81. package/src/tests/react/utils/bottomNavigationToolbar.test.js +222 -0
  82. package/src/tests/react/utils/copyDeviceConfigs.test.mjs +127 -0
  83. package/src/tests/react/utils/fileUrl.test.js +38 -0
  84. package/src/tests/react/utils/importStatus.test.js +26 -9
  85. package/src/tests/react/utils/passwordPolicy.test.js +27 -0
  86. package/src/tests/react/utils/printRouting.test.mjs +86 -0
  87. package/src/tests/react/utils/printSpoolUtils.test.mjs +52 -0
  88. package/src/tests/react/utils/runtimeFooter.test.js +7 -0
  89. package/src/tests/react/utils/shopFranchises.test.js +121 -115
  90. package/src/tests/react/utils/systemErrorMessage.test.js +32 -59
package/AGENTS.md CHANGED
@@ -20,6 +20,14 @@
20
20
 
21
21
  Cópia versionada no Git: `docs/technical/Technical-Documenter-Workflow.md`
22
22
 
23
+
24
+ ### Device Detail (Manager)
25
+
26
+ | Página | O que documenta |
27
+ | --- | --- |
28
+ | [Device Detail — sync do alias na UI](https://github.com/ControleOnline/ui-common/wiki/Device-Detail-Alias-UI-Sync) | Alias salvo coerente no header/stores sem refresh (#382) |
29
+ | [Device Detail — exclusão de device](https://github.com/ControleOnline/ui-common/wiki/Device-Detail-Exclusao) | Botão lixeira, confirmação web/nativo, DELETE e retorno à listagem (#383) |
30
+
23
31
  ### Visão deste módulo
24
32
 
25
33
  `ui-common` é o módulo compartilhado de runtime, API e utilitários de UI usado pelas visões `MANAGER`, `ADMIN`, `CRM`, `POS`, `PPC`, `SHOP`, `DELIVERY` e `SERVICE`. A automação documentada aqui é de governança do repositório e não altera comportamento funcional dessas visões.
package/package.json CHANGED
@@ -1,17 +1,23 @@
1
1
  {
2
2
  "name": "@controleonline/ui-common",
3
- "version": "1.2.80",
3
+ "version": "1.2.82",
4
4
  "author": "ControleOnline",
5
5
  "description": "ControleOnline Common Quasar UI Component",
6
6
  "license": "MIT",
7
7
  "main": "src/react/index.js",
8
8
  "scripts": {
9
- "test": "npm run test:imports-status && npm run test:runtime-language && npm run test:runtime-footer && npm run test:invoice-presentation",
9
+ "test": "npm run test:receita-federal && npm run test:imports-status && npm run test:runtime-language && npm run test:runtime-footer && npm run test:runtime-footer-marquee && npm run test:invoice-presentation && npm run test:system-error-message && npm run test:bottom-navigation-toolbar && npm run test:copy-device-configs && npm run test:print-routing",
10
+ "test:receita-federal": "node --test src/tests/react/pages/receitaFederalIntegrationContract.test.mjs",
10
11
  "test:imports-status": "mkdir -p node_modules/@controleonline && ln -sfn ../.. node_modules/@controleonline/ui-common && node --test src/tests/react/utils/importStatus.test.js",
11
12
  "test:runtime-language": "node --test src/tests/react/utils/runtimeLanguage.test.js",
12
13
  "test:runtime-footer": "node --test src/tests/react/utils/runtimeFooter.test.js",
13
14
  "test:invoice-presentation": "node --test src/tests/react/utils/invoicePresentation.test.mjs",
14
- "test:coverage": "c8 --reporter=clover --report-dir coverage npm test"
15
+ "test:system-error-message": "mkdir -p node_modules/@controleonline && ln -sfn ../.. node_modules/@controleonline/ui-common && node --test src/tests/react/utils/systemErrorMessage.test.js",
16
+ "test:coverage": "c8 --reporter=clover --report-dir coverage npm test",
17
+ "test:bottom-navigation-toolbar": "node --test src/tests/react/utils/bottomNavigationToolbar.test.js",
18
+ "test:copy-device-configs": "node --test src/tests/react/utils/copyDeviceConfigs.test.mjs",
19
+ "test:print-routing": "node --test src/tests/react/utils/printRouting.test.mjs src/tests/react/utils/printSpoolUtils.test.mjs",
20
+ "test:runtime-footer-marquee": "node --test src/tests/react/components/RuntimeFooterMarqueeText.test.js"
15
21
  },
16
22
  "devDependencies": {
17
23
  "c8": "^10.1.3"
package/src/api/fetch.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import {env as APP_ENV} from '@env';
2
- import resolveSystemErrorMessage from '@controleonline/ui-common/src/react/utils/systemErrorMessage';
2
+ import {resolveSystemErrorMessage} from '@controleonline/ui-common/src/react/utils/systemErrorMessage';
3
3
  import {resolveApiEntryPoint} from '@controleonline/ui-common/src/utils/apiEntryPoint';
4
4
 
5
5
  const buildHttpError = (response, body) => {
@@ -36,12 +36,12 @@ export default function (resourceEndpoint, options = {}) {
36
36
  const apiEntryPoint = resolveApiEntryPoint(APP_ENV.API_ENTRYPOINT);
37
37
  const entryPoint =
38
38
  apiEntryPoint + (apiEntryPoint.endsWith("/") ? "" : "/");
39
-
40
- if (!resourceEndpoint || !entryPoint) return;
41
-
42
- // if (resourceEndpoint == "/people/companies/my")
43
- //console.log(entryPoint, resourceEndpoint, options);
44
-
39
+
40
+ if (!resourceEndpoint || !entryPoint) return;
41
+
42
+ // if (resourceEndpoint == "/people/companies/my")
43
+ //console.log(entryPoint, resourceEndpoint, options);
44
+
45
45
  //console.log(entryPoint, resourceEndpoint);
46
46
 
47
47
  return fetch(new URL(resourceEndpoint, entryPoint), options).then(async response => {
@@ -12,6 +12,7 @@ import { useStore } from '@store';
12
12
  import AnimatedModal from './AnimatedModal';
13
13
  import { useMessage } from '@controleonline/ui-common/src/react/components/MessageService';
14
14
  import DefaultUpload from '@controleonline/ui-default/src/react/components/upload/DefaultUpload';
15
+ import { resolveSystemErrorMessage } from '@controleonline/ui-common/src/react/utils/systemErrorMessage';
15
16
  import styles from './AddImportModal.styles';
16
17
 
17
18
  const AddImportModal = ({ visible, onClose, onSuccess, context = {} }) => {
@@ -53,8 +54,11 @@ const AddImportModal = ({ visible, onClose, onSuccess, context = {} }) => {
53
54
  if (onSuccess) onSuccess();
54
55
  handleClose();
55
56
  return file;
56
- } catch {
57
- throw new Error(importErrorLabel);
57
+ } catch (error) {
58
+ const importFeedback =
59
+ resolveSystemErrorMessage(error) || importErrorLabel;
60
+ showError(importFeedback);
61
+ throw new Error(importFeedback);
58
62
  }
59
63
  };
60
64
 
@@ -1,220 +1,206 @@
1
- import React, {useEffect, useMemo, useRef} from 'react';
2
- import {NativeModules} from 'react-native';
1
+ import React, {useEffect, useMemo, useRef} from 'react';
2
+ import {NativeModules} from 'react-native';
3
3
  import {app_type} from '@appType';
4
4
  import { env as APP_ENV } from '@env';
5
- import {useStore} from '@store';
6
- import DeviceInfo from 'react-native-device-info';
5
+ import {useStore} from '@store';
6
+ import DeviceInfo from 'react-native-device-info';
7
7
  import {resolveAppDomain} from '@controleonline/ui-common/src/utils/appDomain';
8
8
  import {resolveApiEntryPoint} from '@controleonline/ui-common/src/utils/apiEntryPoint';
9
- import {isWebRuntimeDevice} from '@controleonline/ui-common/src/react/utils/deviceRuntime';
10
- import {normalizeDeviceId} from '@controleonline/ui-common/src/react/utils/paymentDevices';
11
- import {
12
- DEVICE_ALERT_SOUND_ENABLED_KEY,
13
- DEVICE_ALERT_SOUND_URL_KEY,
14
- DEVICE_RUNTIME_DEBUG_INFO_ENABLED_KEY,
15
- isTruthyValue,
16
- parseConfigsObject,
17
- } from '@controleonline/ui-common/src/react/config/deviceConfigBootstrap';
18
- import {
19
- isManagerAppType,
20
- resolveManagerOrderNotificationPreferences,
21
- } from '@controleonline/ui-common/src/react/utils/managerOrderNotifications';
22
- import {syncBackgroundRuntimeRegistration} from '@controleonline/ui-common/src/react/utils/backgroundRuntimeRegistration';
23
- import {
24
- DEFAULT_NETWORK_PRINTER_PORT,
25
- DISPLAY_DEVICE_TYPE,
26
- NETWORK_PRINTER_PORT_CONFIG_KEY,
27
- PDV_DEVICE_TYPE,
28
- getManagedPrinterDevices,
29
- getPrinterHost,
30
- normalizeDeviceType,
31
- normalizePrinterPort,
32
- } from '@controleonline/ui-common/src/react/utils/printerDevices';
33
-
34
- const backgroundRuntimeModule = NativeModules?.BackgroundRuntime;
35
-
36
- const safeTrim = value => String(value || '').trim();
37
- const readSessionToken = () => {
38
- try {
39
- const session = JSON.parse(localStorage.getItem('session') || '{}');
40
- return safeTrim(session?.token || session?.api_key);
41
- } catch {
42
- return '';
43
- }
44
- };
45
-
46
- const BackgroundRuntimeBridge = () => {
47
- const authStore = useStore('auth');
48
- const peopleStore = useStore('people');
49
- const deviceStore = useStore('device');
50
- const deviceConfigStore = useStore('device_config');
51
-
52
- const {isLogged, user} = authStore.getters;
53
- const {currentCompany} = peopleStore.getters;
54
- const {item: runtimeDevice} = deviceStore.getters;
55
- const {
56
- item: runtimeDeviceConfig,
57
- items: companyDeviceConfigs = [],
58
- } = deviceConfigStore.getters;
59
-
60
- const lastRegistrationIdRef = useRef('');
61
- const lastRegistrationPayloadRef = useRef('');
62
-
63
- const bundleId = safeTrim(DeviceInfo.getBundleId());
64
- const runtimeAppKey =
65
- bundleId || safeTrim(app_type).toUpperCase() || 'app';
66
- const runtimeDeviceId = normalizeDeviceId(runtimeDevice?.id);
67
- const runtimeDeviceType = normalizeDeviceType(
68
- runtimeDeviceConfig?.type ||
69
- runtimeDeviceConfig?.device?.type ||
70
- runtimeDevice?.type,
71
- );
72
- const currentCompanyId = safeTrim(currentCompany?.id);
73
- const sessionToken = readSessionToken();
74
- const isManagerRuntime = isManagerAppType(app_type);
75
- const managerOrderNotificationPreferences =
76
- resolveManagerOrderNotificationPreferences(user);
77
- const userAlertSoundUrl = safeTrim(
78
- managerOrderNotificationPreferences.soundUrl,
79
- );
80
- const userAlertSoundEnabled =
81
- isManagerRuntime &&
82
- managerOrderNotificationPreferences.pushEnabled &&
83
- managerOrderNotificationPreferences.soundEnabled;
84
- const runtimeDeviceConfigs = parseConfigsObject(runtimeDeviceConfig?.configs);
85
- const deviceAlertSoundEnabled = isTruthyValue(
86
- runtimeDeviceConfigs?.[DEVICE_ALERT_SOUND_ENABLED_KEY],
87
- );
88
- const deviceAlertSoundUrl = safeTrim(
89
- runtimeDeviceConfigs?.[DEVICE_ALERT_SOUND_URL_KEY],
90
- );
91
- const runtimeDebugInfoEnabled = isTruthyValue(
92
- runtimeDeviceConfigs?.[DEVICE_RUNTIME_DEBUG_INFO_ENABLED_KEY],
93
- );
94
- const alertSoundEnabled = userAlertSoundEnabled || deviceAlertSoundEnabled;
95
- const alertSoundUrl = userAlertSoundEnabled
96
- ? userAlertSoundUrl
97
- : deviceAlertSoundUrl;
98
-
99
- const managedPrinters = useMemo(
100
- () =>
101
- getManagedPrinterDevices({
102
- deviceConfigs: companyDeviceConfigs,
103
- companyId: currentCompanyId,
104
- managerDeviceId: runtimeDeviceId,
105
- })
106
- .map(printer => {
107
- const host = safeTrim(getPrinterHost(printer));
108
- const port = normalizePrinterPort(
109
- printer?.configs?.[NETWORK_PRINTER_PORT_CONFIG_KEY] ||
110
- DEFAULT_NETWORK_PRINTER_PORT,
111
- );
112
- const deviceId = normalizeDeviceId(printer?.device);
113
-
114
- if (!host || !deviceId) {
115
- return null;
116
- }
117
-
118
- return {
119
- deviceId,
120
- host,
121
- port,
122
- };
123
- })
124
- .filter(Boolean),
125
- [companyDeviceConfigs, currentCompanyId, runtimeDeviceId],
126
- );
127
-
128
- const spoolDeviceIds = useMemo(() => {
129
- if (!runtimeDeviceId || isWebRuntimeDevice(runtimeDevice)) {
130
- return [];
131
- }
132
-
133
- if (runtimeDeviceType === PDV_DEVICE_TYPE) {
134
- return Array.from(
135
- new Set([
136
- runtimeDeviceId,
137
- ...managedPrinters.map(printer => normalizeDeviceId(printer?.deviceId)),
138
- ].filter(Boolean)),
139
- );
140
- }
141
-
142
- if (runtimeDeviceType === DISPLAY_DEVICE_TYPE) {
143
- return Array.from(
144
- new Set(
145
- managedPrinters
146
- .map(printer => normalizeDeviceId(printer?.deviceId))
147
- .filter(Boolean),
148
- ),
149
- );
150
- }
151
-
152
- return [];
153
- }, [managedPrinters, runtimeDevice, runtimeDeviceId, runtimeDeviceType]);
154
-
155
- const registration = useMemo(() => {
156
- if (!isLogged || !sessionToken || !runtimeDeviceId || !currentCompanyId) {
157
- return null;
158
- }
159
-
160
- return {
161
- registrationId: `${runtimeAppKey}::${runtimeDeviceId}::${currentCompanyId}`,
162
- packageName: runtimeAppKey,
163
- companyAlias: safeTrim(currentCompany?.alias || currentCompany?.name),
164
- companyId: currentCompanyId,
165
- appDomain: safeTrim(resolveAppDomain(APP_ENV.DOMAIN)),
166
- appType: safeTrim(app_type).toUpperCase(),
167
- backgroundEnabled: true,
168
- deviceId: runtimeDeviceId,
169
- deviceType: runtimeDeviceType,
170
- notificationEnabled: !isManagerRuntime,
171
- alertSoundEnabled,
172
- alertSoundUrl,
173
- deviceAlertSoundEnabled,
174
- deviceAlertSoundUrl,
175
- userAlertSoundEnabled,
176
- userAlertSoundUrl,
177
- runtimeDebugInfoEnabled,
178
- printEnabled: spoolDeviceIds.length > 0 && managedPrinters.length > 0,
179
- managedPrinters,
180
- socketUrl: safeTrim(APP_ENV.SOCKET),
181
- spoolDeviceIds,
182
- token: sessionToken,
9
+ import {isWebRuntimeDevice} from '@controleonline/ui-common/src/react/utils/deviceRuntime';
10
+ import {normalizeDeviceId} from '@controleonline/ui-common/src/react/utils/paymentDevices';
11
+ import {
12
+ DEVICE_ALERT_SOUND_ENABLED_KEY,
13
+ DEVICE_ALERT_SOUND_URL_KEY,
14
+ DEVICE_RUNTIME_DEBUG_INFO_ENABLED_KEY,
15
+ isTruthyValue,
16
+ parseConfigsObject,
17
+ } from '@controleonline/ui-common/src/react/config/deviceConfigBootstrap';
18
+ import {
19
+ isManagerAppType,
20
+ resolveManagerOrderNotificationPreferences,
21
+ } from '@controleonline/ui-common/src/react/utils/managerOrderNotifications';
22
+ import {syncBackgroundRuntimeRegistration} from '@controleonline/ui-common/src/react/utils/backgroundRuntimeRegistration';
23
+ import {
24
+ DEFAULT_NETWORK_PRINTER_PORT,
25
+ DISPLAY_DEVICE_TYPE,
26
+ NETWORK_PRINTER_PORT_CONFIG_KEY,
27
+ PDV_DEVICE_TYPE,
28
+ getManagedPrinterDevices,
29
+ getPrinterHost,
30
+ normalizeDeviceType,
31
+ normalizePrinterPort,
32
+ } from '@controleonline/ui-common/src/react/utils/printerDevices';
33
+ import {resolveSpoolDeviceIdsForRuntime} from '@controleonline/ui-common/src/react/utils/printRouting';
34
+
35
+ const backgroundRuntimeModule = NativeModules?.BackgroundRuntime;
36
+
37
+ const safeTrim = value => String(value || '').trim();
38
+ const readSessionToken = () => {
39
+ try {
40
+ const session = JSON.parse(localStorage.getItem('session') || '{}');
41
+ return safeTrim(session?.token || session?.api_key);
42
+ } catch {
43
+ return '';
44
+ }
45
+ };
46
+
47
+ const BackgroundRuntimeBridge = () => {
48
+ const authStore = useStore('auth');
49
+ const peopleStore = useStore('people');
50
+ const deviceStore = useStore('device');
51
+ const deviceConfigStore = useStore('device_config');
52
+
53
+ const {isLogged, user} = authStore.getters;
54
+ const {currentCompany} = peopleStore.getters;
55
+ const {item: runtimeDevice} = deviceStore.getters;
56
+ const {
57
+ item: runtimeDeviceConfig,
58
+ items: companyDeviceConfigs = [],
59
+ } = deviceConfigStore.getters;
60
+
61
+ const lastRegistrationIdRef = useRef('');
62
+ const lastRegistrationPayloadRef = useRef('');
63
+
64
+ const bundleId = safeTrim(DeviceInfo.getBundleId());
65
+ const runtimeAppKey =
66
+ bundleId || safeTrim(app_type).toUpperCase() || 'app';
67
+ const runtimeDeviceId = normalizeDeviceId(runtimeDevice?.id);
68
+ const runtimeDeviceType = normalizeDeviceType(
69
+ runtimeDeviceConfig?.type ||
70
+ runtimeDeviceConfig?.device?.type ||
71
+ runtimeDevice?.type,
72
+ );
73
+ const currentCompanyId = safeTrim(currentCompany?.id);
74
+ const sessionToken = readSessionToken();
75
+ const isManagerRuntime = isManagerAppType(app_type);
76
+ const managerOrderNotificationPreferences =
77
+ resolveManagerOrderNotificationPreferences(user);
78
+ const userAlertSoundUrl = safeTrim(
79
+ managerOrderNotificationPreferences.soundUrl,
80
+ );
81
+ const userAlertSoundEnabled =
82
+ isManagerRuntime &&
83
+ managerOrderNotificationPreferences.pushEnabled &&
84
+ managerOrderNotificationPreferences.soundEnabled;
85
+ const runtimeDeviceConfigs = parseConfigsObject(runtimeDeviceConfig?.configs);
86
+ const deviceAlertSoundEnabled = isTruthyValue(
87
+ runtimeDeviceConfigs?.[DEVICE_ALERT_SOUND_ENABLED_KEY],
88
+ );
89
+ const deviceAlertSoundUrl = safeTrim(
90
+ runtimeDeviceConfigs?.[DEVICE_ALERT_SOUND_URL_KEY],
91
+ );
92
+ const runtimeDebugInfoEnabled = isTruthyValue(
93
+ runtimeDeviceConfigs?.[DEVICE_RUNTIME_DEBUG_INFO_ENABLED_KEY],
94
+ );
95
+ const alertSoundEnabled = userAlertSoundEnabled || deviceAlertSoundEnabled;
96
+ const alertSoundUrl = userAlertSoundEnabled
97
+ ? userAlertSoundUrl
98
+ : deviceAlertSoundUrl;
99
+
100
+ const managedPrinters = useMemo(
101
+ () =>
102
+ getManagedPrinterDevices({
103
+ deviceConfigs: companyDeviceConfigs,
104
+ companyId: currentCompanyId,
105
+ managerDeviceId: runtimeDeviceId,
106
+ })
107
+ .map(printer => {
108
+ const host = safeTrim(getPrinterHost(printer));
109
+ const port = normalizePrinterPort(
110
+ printer?.configs?.[NETWORK_PRINTER_PORT_CONFIG_KEY] ||
111
+ DEFAULT_NETWORK_PRINTER_PORT,
112
+ );
113
+ const deviceId = normalizeDeviceId(printer?.device);
114
+
115
+ if (!host || !deviceId) {
116
+ return null;
117
+ }
118
+
119
+ return {
120
+ deviceId,
121
+ host,
122
+ port,
123
+ };
124
+ })
125
+ .filter(Boolean),
126
+ [companyDeviceConfigs, currentCompanyId, runtimeDeviceId],
127
+ );
128
+
129
+ const spoolDeviceIds = useMemo(
130
+ () =>
131
+ resolveSpoolDeviceIdsForRuntime({
132
+ runtimeDeviceId,
133
+ runtimeDeviceType,
134
+ isWebRuntime: isWebRuntimeDevice(runtimeDevice),
135
+ managedPrinters,
136
+ includeLocalDevice: true,
137
+ }),
138
+ [managedPrinters, runtimeDevice, runtimeDeviceId, runtimeDeviceType],
139
+ );
140
+
141
+ const registration = useMemo(() => {
142
+ if (!isLogged || !sessionToken || !runtimeDeviceId || !currentCompanyId) {
143
+ return null;
144
+ }
145
+
146
+ return {
147
+ registrationId: `${runtimeAppKey}::${runtimeDeviceId}::${currentCompanyId}`,
148
+ packageName: runtimeAppKey,
149
+ companyAlias: safeTrim(currentCompany?.alias || currentCompany?.name),
150
+ companyId: currentCompanyId,
151
+ appDomain: safeTrim(resolveAppDomain(APP_ENV.DOMAIN)),
152
+ appType: safeTrim(app_type).toUpperCase(),
153
+ backgroundEnabled: true,
154
+ deviceId: runtimeDeviceId,
155
+ deviceType: runtimeDeviceType,
156
+ notificationEnabled: !isManagerRuntime,
157
+ alertSoundEnabled,
158
+ alertSoundUrl,
159
+ deviceAlertSoundEnabled,
160
+ deviceAlertSoundUrl,
161
+ userAlertSoundEnabled,
162
+ userAlertSoundUrl,
163
+ runtimeDebugInfoEnabled,
164
+ printEnabled: spoolDeviceIds.length > 0 && managedPrinters.length > 0,
165
+ managedPrinters,
166
+ socketUrl: safeTrim(APP_ENV.SOCKET),
167
+ spoolDeviceIds,
168
+ token: sessionToken,
183
169
  apiBaseUrl: safeTrim(resolveApiEntryPoint(APP_ENV.API_ENTRYPOINT)),
184
- };
185
- }, [
186
- currentCompany?.alias,
187
- currentCompany?.name,
188
- currentCompanyId,
189
- alertSoundEnabled,
190
- alertSoundUrl,
191
- deviceAlertSoundEnabled,
192
- deviceAlertSoundUrl,
193
- runtimeAppKey,
194
- isLogged,
195
- isManagerRuntime,
196
- managedPrinters,
197
- runtimeDeviceId,
198
- runtimeDeviceType,
199
- sessionToken,
200
- spoolDeviceIds,
201
- userAlertSoundEnabled,
202
- userAlertSoundUrl,
203
- runtimeDebugInfoEnabled,
204
- ]);
205
-
206
- useEffect(() => {
207
- syncBackgroundRuntimeRegistration({
208
- backgroundRuntimeModule,
209
- registration,
210
- lastRegistrationIdRef,
211
- lastRegistrationPayloadRef,
212
- });
213
- // Keep the registration alive after this component unmounts.
214
- // Explicit logout/device changes are handled by the branches above.
215
- }, [registration]);
216
-
217
- return null;
218
- };
219
-
220
- export default BackgroundRuntimeBridge;
170
+ };
171
+ }, [
172
+ currentCompany?.alias,
173
+ currentCompany?.name,
174
+ currentCompanyId,
175
+ alertSoundEnabled,
176
+ alertSoundUrl,
177
+ deviceAlertSoundEnabled,
178
+ deviceAlertSoundUrl,
179
+ runtimeAppKey,
180
+ isLogged,
181
+ isManagerRuntime,
182
+ managedPrinters,
183
+ runtimeDeviceId,
184
+ runtimeDeviceType,
185
+ sessionToken,
186
+ spoolDeviceIds,
187
+ userAlertSoundEnabled,
188
+ userAlertSoundUrl,
189
+ runtimeDebugInfoEnabled,
190
+ ]);
191
+
192
+ useEffect(() => {
193
+ syncBackgroundRuntimeRegistration({
194
+ backgroundRuntimeModule,
195
+ registration,
196
+ lastRegistrationIdRef,
197
+ lastRegistrationPayloadRef,
198
+ });
199
+ // Keep the registration alive after this component unmounts.
200
+ // Explicit logout/device changes are handled by the branches above.
201
+ }, [registration]);
202
+
203
+ return null;
204
+ };
205
+
206
+ export default BackgroundRuntimeBridge;
@@ -1,8 +1,39 @@
1
- import React from 'react';
2
- import { Modal, View, Text, TouchableOpacity } from 'react-native';
3
- import styles from './ConfirmModal.styles';
1
+ import React, {useMemo} from 'react';
2
+ import {Modal, View, Text, TouchableOpacity} from 'react-native';
3
+ import {useStore} from '@store';
4
+ import createStyles from './ConfirmModal.styles';
5
+
6
+ export const ConfirmModal = ({visible, title, message, onConfirm, onCancel}) => {
7
+ const themeStore = useStore('theme');
8
+ const themeColors = themeStore?.getters?.colors || {};
9
+
10
+ const palette = useMemo(
11
+ () => ({
12
+ modalOverlay: themeColors.modalOverlay,
13
+ modalBackground: themeColors.modalBackground,
14
+ modalBorder: themeColors.modalBorder,
15
+ modalHeaderText: themeColors.modalHeaderText,
16
+ modalText: themeColors.modalText,
17
+ buttonBackground: themeColors.buttonBackground,
18
+ buttonBorder: themeColors.buttonBorder,
19
+ buttonText: themeColors.buttonText,
20
+ buttonTextSecondary: themeColors.buttonTextSecondary,
21
+ }),
22
+ [
23
+ themeColors.modalOverlay,
24
+ themeColors.modalBackground,
25
+ themeColors.modalBorder,
26
+ themeColors.modalHeaderText,
27
+ themeColors.modalText,
28
+ themeColors.buttonBackground,
29
+ themeColors.buttonBorder,
30
+ themeColors.buttonText,
31
+ themeColors.buttonTextSecondary,
32
+ ],
33
+ );
34
+
35
+ const styles = useMemo(() => createStyles(palette), [palette]);
4
36
 
5
- export const ConfirmModal = ({ visible, title, message, onConfirm, onCancel }) => {
6
37
  return (
7
38
  <Modal visible={visible} transparent animationType="fade">
8
39
  <View style={styles.overlay}>
@@ -11,14 +42,18 @@ export const ConfirmModal = ({ visible, title, message, onConfirm, onCancel }) =
11
42
  <Text style={styles.message}>{message}</Text>
12
43
  <View style={styles.actions}>
13
44
  <TouchableOpacity onPress={onCancel} style={styles.cancelButton}>
14
- <Text>{global.t?.t('confirmModal', 'button', 'cancel')}</Text>
45
+ <Text style={styles.cancelButtonText}>
46
+ {global.t?.t('confirmModal', 'button', 'cancel')}
47
+ </Text>
15
48
  </TouchableOpacity>
16
49
  <TouchableOpacity onPress={onConfirm} style={styles.confirmButton}>
17
- <Text style={styles.confirmButtonText}>{global.t?.t('confirmModal', 'button', 'confirm')}</Text>
50
+ <Text style={styles.confirmButtonText}>
51
+ {global.t?.t('confirmModal', 'button', 'confirm')}
52
+ </Text>
18
53
  </TouchableOpacity>
19
54
  </View>
20
55
  </View>
21
- </View>
22
- </Modal>
23
- );
56
+ </View>
57
+ </Modal>
58
+ );
24
59
  };