@controleonline/ui-common 1.2.70

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 (203) hide show
  1. package/.github/agents/developer.agent.md +30 -0
  2. package/.github/agents/devops.agent.md +30 -0
  3. package/.github/agents/qa.agent.md +30 -0
  4. package/.github/agents/security.agent.md +30 -0
  5. package/.github/workflows/npmjs.yml +35 -0
  6. package/.github/workflows/pull-request-checks.yml +19 -0
  7. package/.scrutinizer.yml +24 -0
  8. package/FUNDING.yml +1 -0
  9. package/package.json +28 -0
  10. package/src/api/fetch.js +74 -0
  11. package/src/api/index.js +155 -0
  12. package/src/api/localDB.js +131 -0
  13. package/src/api/queue.js +66 -0
  14. package/src/react/assets/tap.mp3 +0 -0
  15. package/src/react/components/AddImportModal.js +157 -0
  16. package/src/react/components/AddImportModal.styles.js +81 -0
  17. package/src/react/components/BackgroundRuntimeBridge.js +219 -0
  18. package/src/react/components/BottomNavigationBar.config.js +238 -0
  19. package/src/react/components/BottomNavigationBar.js +120 -0
  20. package/src/react/components/BottomNavigationBar.styles.js +110 -0
  21. package/src/react/components/CategoryForm.js +572 -0
  22. package/src/react/components/CategoryForm.styles.js +334 -0
  23. package/src/react/components/ConfirmModal.js +24 -0
  24. package/src/react/components/ConfirmModal.styles.js +43 -0
  25. package/src/react/components/ContextHelpButton.js +69 -0
  26. package/src/react/components/ContextHelpButton.styles.js +62 -0
  27. package/src/react/components/DefaultProvider.native.js +848 -0
  28. package/src/react/components/DefaultProvider.styles.js +21 -0
  29. package/src/react/components/DefaultProvider.web.js +909 -0
  30. package/src/react/components/DeliveryPushBridge.native.js +314 -0
  31. package/src/react/components/DeliveryPushBridge.web.js +5 -0
  32. package/src/react/components/DeviceAlertSoundService.js +499 -0
  33. package/src/react/components/EntityLogContent.js +909 -0
  34. package/src/react/components/EntityLogContent.styles.js +400 -0
  35. package/src/react/components/EventBus.js +12 -0
  36. package/src/react/components/KioskModeBridge.js +65 -0
  37. package/src/react/components/LauncherModeBridge.js +47 -0
  38. package/src/react/components/LinkedOrderProductsTab.js +388 -0
  39. package/src/react/components/LinkedOrderProductsTab.styles.js +180 -0
  40. package/src/react/components/ManagerPushBridge.native.js +345 -0
  41. package/src/react/components/MessageService.js +314 -0
  42. package/src/react/components/Paywall/Google.js +89 -0
  43. package/src/react/components/PrintService.js +778 -0
  44. package/src/react/components/ProductCatalogCacheService.js +45 -0
  45. package/src/react/components/RemoteCheckoutService.js +292 -0
  46. package/src/react/components/RuntimeBottomNavigationBar.js +151 -0
  47. package/src/react/components/RuntimeInfoFooter.js +214 -0
  48. package/src/react/components/RuntimeInfoFooter.styles.js +56 -0
  49. package/src/react/components/SystemErrorToast.js +29 -0
  50. package/src/react/components/SystemErrorToast.styles.js +38 -0
  51. package/src/react/components/TouchFeedbackProvider.js +65 -0
  52. package/src/react/components/UnifiedPaymentBar.js +155 -0
  53. package/src/react/components/UnifiedPaymentBar.styles.js +174 -0
  54. package/src/react/components/WebsocketListener.native.js +487 -0
  55. package/src/react/components/WebsocketListener.web.js +102 -0
  56. package/src/react/components/inputs/IdInput.js +49 -0
  57. package/src/react/components/inputs/IdInput.styles.js +26 -0
  58. package/src/react/components/inputs/InvoiceDueDateFilterInput.js +74 -0
  59. package/src/react/components/inputs/InvoiceDueDateFilterInput.styles.js +34 -0
  60. package/src/react/components/inputs/InvoiceDueDateRangeFilterInput.js +115 -0
  61. package/src/react/components/inputs/InvoiceDueDateRangeFilterInput.styles.js +39 -0
  62. package/src/react/components/lists/CategoriesList.js +56 -0
  63. package/src/react/components/lists/PaymentTypeList.js +55 -0
  64. package/src/react/components/lists/ReceiverList.js +56 -0
  65. package/src/react/components/lists/SelectList.styles.js +18 -0
  66. package/src/react/components/lists/StatusList.js +55 -0
  67. package/src/react/components/lists/WalletList.js +54 -0
  68. package/src/react/components/radio/Spotify.js +144 -0
  69. package/src/react/components/radio/Spotify.styles.js +32 -0
  70. package/src/react/components/radio/YouTube.js +82 -0
  71. package/src/react/components/radio/YouTube.styles.js +16 -0
  72. package/src/react/components/toastConfig.js +16 -0
  73. package/src/react/config/deviceConfigBootstrap.js +571 -0
  74. package/src/react/index.js +4 -0
  75. package/src/react/localStorage.js +30 -0
  76. package/src/react/pages/EntityLogPage.js +124 -0
  77. package/src/react/pages/EntityLogPage.styles.js +17 -0
  78. package/src/react/pages/GenericLogPage.js +760 -0
  79. package/src/react/pages/GenericLogPage.styles.js +401 -0
  80. package/src/react/pages/Imports.js +361 -0
  81. package/src/react/pages/Imports.styles.js +223 -0
  82. package/src/react/pages/SettingsPage/PaymentTypesByWalletTab.js +462 -0
  83. package/src/react/pages/SettingsPage/index.js +1171 -0
  84. package/src/react/pages/SettingsPage/index.styles.js +122 -0
  85. package/src/react/print/jobs.js +147 -0
  86. package/src/react/print/providers/local.js +53 -0
  87. package/src/react/print/providers/remote.js +81 -0
  88. package/src/react/print/selection.js +296 -0
  89. package/src/react/print/usePrintButtonController.js +474 -0
  90. package/src/react/router/routes.js +42 -0
  91. package/src/react/services/NetworkPrinterService.native.js +391 -0
  92. package/src/react/services/NetworkPrinterService.web.js +15 -0
  93. package/src/react/stores/index.js +128 -0
  94. package/src/react/stores/storeErrorBridge.js +36 -0
  95. package/src/react/utils/backgroundRuntimeRegistration.js +69 -0
  96. package/src/react/utils/cashPayment.js +87 -0
  97. package/src/react/utils/commercialDocumentOrders.js +269 -0
  98. package/src/react/utils/dateRangeFilter.js +264 -0
  99. package/src/react/utils/deviceRuntime.js +193 -0
  100. package/src/react/utils/entityDisplay.js +231 -0
  101. package/src/react/utils/entityLog.js +649 -0
  102. package/src/react/utils/fileUrl.js +102 -0
  103. package/src/react/utils/frontendDebugLog.js +45 -0
  104. package/src/react/utils/googleMapsConfig.js +49 -0
  105. package/src/react/utils/importStatus.js +100 -0
  106. package/src/react/utils/invoiceDueDateMessages.js +14 -0
  107. package/src/react/utils/invoicePresentation.js +46 -0
  108. package/src/react/utils/logSettings.js +143 -0
  109. package/src/react/utils/maintenanceSettings.js +53 -0
  110. package/src/react/utils/managerOrderNotifications.js +523 -0
  111. package/src/react/utils/mapNavigation.js +76 -0
  112. package/src/react/utils/menuCatalogConfig.js +8 -0
  113. package/src/react/utils/menuCatalogDownload.js +157 -0
  114. package/src/react/utils/networkCameraDevices.js +175 -0
  115. package/src/react/utils/networkDeviceProfiles.js +135 -0
  116. package/src/react/utils/normalizedCatalogDownload.js +157 -0
  117. package/src/react/utils/notificationNavigation.js +94 -0
  118. package/src/react/utils/notificationSound.js +42 -0
  119. package/src/react/utils/paymentDevices.js +397 -0
  120. package/src/react/utils/paymentGatewayExecution.js +91 -0
  121. package/src/react/utils/paymentOptions.js +88 -0
  122. package/src/react/utils/peopleDisplay.js +39 -0
  123. package/src/react/utils/printerDevices.js +465 -0
  124. package/src/react/utils/remotePayment.js +61 -0
  125. package/src/react/utils/runtimeFooter.js +475 -0
  126. package/src/react/utils/runtimeLanguage.js +50 -0
  127. package/src/react/utils/runtimeMenu.js +224 -0
  128. package/src/react/utils/screenMetrics.js +30 -0
  129. package/src/react/utils/shopConfig.js +294 -0
  130. package/src/react/utils/shopFranchises.js +114 -0
  131. package/src/react/utils/socketRuntimePipeline.js +454 -0
  132. package/src/react/utils/spoolAckTracker.js +77 -0
  133. package/src/react/utils/storeColumns.js +427 -0
  134. package/src/react/utils/systemErrorChannel.js +109 -0
  135. package/src/react/utils/systemErrorMessage.js +67 -0
  136. package/src/react/utils/toastPresentation.js +53 -0
  137. package/src/react/utils/websocketSharedRuntime.js +826 -0
  138. package/src/store/acl/getters.js +4 -0
  139. package/src/store/acl/index.js +19 -0
  140. package/src/store/acl/mutation_types.js +4 -0
  141. package/src/store/acl/mutations.js +17 -0
  142. package/src/store/address/city.js +22 -0
  143. package/src/store/categories/category_file/index.js +25 -0
  144. package/src/store/categories/index.js +93 -0
  145. package/src/store/configs/customActions.js +131 -0
  146. package/src/store/configs/index.js +25 -0
  147. package/src/store/connections/customActions.js +26 -0
  148. package/src/store/connections/index.js +124 -0
  149. package/src/store/device/index.js +22 -0
  150. package/src/store/device_config/customActions.js +190 -0
  151. package/src/store/device_config/index.js +28 -0
  152. package/src/store/entity_log/customActions.js +63 -0
  153. package/src/store/entity_log/index.js +25 -0
  154. package/src/store/extra/data.js +85 -0
  155. package/src/store/extra/fields.js +88 -0
  156. package/src/store/file/actions.js +27 -0
  157. package/src/store/file/index.js +24 -0
  158. package/src/store/imports/index.js +88 -0
  159. package/src/store/print/customActions.js +251 -0
  160. package/src/store/print/index.js +28 -0
  161. package/src/store/printer/customActions.js +54 -0
  162. package/src/store/printer/index.js +26 -0
  163. package/src/store/runtime_debug/customActions.js +71 -0
  164. package/src/store/runtime_debug/index.js +30 -0
  165. package/src/store/status/index.js +65 -0
  166. package/src/store/timezones/index.js +43 -0
  167. package/src/store/websocket/customActions.js +24 -0
  168. package/src/store/websocket/index.js +28 -0
  169. package/src/tests/react/components/LauncherModeBridge.test.js +93 -0
  170. package/src/tests/react/config/deviceConfigBootstrap.test.js +337 -0
  171. package/src/tests/react/print/localPrintProvider.test.js +45 -0
  172. package/src/tests/react/utils/backgroundRuntimeRegistration.test.js +123 -0
  173. package/src/tests/react/utils/cashPayment.test.js +41 -0
  174. package/src/tests/react/utils/dateRangeFilter.test.mjs +29 -0
  175. package/src/tests/react/utils/entityDisplay.test.js +18 -0
  176. package/src/tests/react/utils/googleMapsConfig.test.js +32 -0
  177. package/src/tests/react/utils/importStatus.test.js +85 -0
  178. package/src/tests/react/utils/invoicePresentation.test.mjs +40 -0
  179. package/src/tests/react/utils/managerOrderNotifications.test.js +127 -0
  180. package/src/tests/react/utils/mapNavigation.test.js +58 -0
  181. package/src/tests/react/utils/notificationNavigation.test.js +39 -0
  182. package/src/tests/react/utils/notificationSound.test.js +27 -0
  183. package/src/tests/react/utils/paymentDevices.test.js +88 -0
  184. package/src/tests/react/utils/runtimeFooter.test.js +429 -0
  185. package/src/tests/react/utils/runtimeLanguage.test.js +80 -0
  186. package/src/tests/react/utils/runtimeMenu.test.js +174 -0
  187. package/src/tests/react/utils/shopFranchises.test.js +82 -0
  188. package/src/tests/react/utils/socketRuntimePipeline.test.js +124 -0
  189. package/src/tests/react/utils/spoolAckTracker.test.js +40 -0
  190. package/src/tests/react/utils/storeErrorBridge.test.js +66 -0
  191. package/src/tests/react/utils/systemErrorChannel.test.js +58 -0
  192. package/src/tests/react/utils/systemErrorMessage.test.js +59 -0
  193. package/src/tests/react/utils/toastPresentation.test.js +75 -0
  194. package/src/tests/react/utils/translate.test.mjs +396 -0
  195. package/src/tests/react/utils/websocketSharedRuntime.test.js +245 -0
  196. package/src/utils/apiEntryPoint.js +31 -0
  197. package/src/utils/appDomain.js +50 -0
  198. package/src/utils/config.js +14 -0
  199. package/src/utils/formatter.js +419 -0
  200. package/src/utils/integrationConfigs.js +79 -0
  201. package/src/utils/methods.js +23 -0
  202. package/src/utils/oauth.js +42 -0
  203. package/src/utils/translate.js +620 -0
@@ -0,0 +1,909 @@
1
+ import React, {
2
+ createContext,
3
+ useCallback,
4
+ useContext,
5
+ useEffect,
6
+ useMemo,
7
+ useRef,
8
+ useState,
9
+ } from 'react';
10
+ import { View } from 'react-native';
11
+ import Translate from '@controleonline/ui-common/src/utils/translate';
12
+ import { WebsocketListener } from '@controleonline/ui-common/src/react/components/WebsocketListener';
13
+ import DeviceAlertSoundService from '@controleonline/ui-common/src/react/components/DeviceAlertSoundService';
14
+ import PrintService from '@controleonline/ui-common/src/react/components/PrintService';
15
+ import RemoteCheckoutService from '@controleonline/ui-common/src/react/components/RemoteCheckoutService';
16
+ import ProductCatalogCacheService from '@controleonline/ui-common/src/react/components/ProductCatalogCacheService';
17
+ import RuntimeInfoFooter from '@controleonline/ui-common/src/react/components/RuntimeInfoFooter';
18
+ import { useStore } from '@store';
19
+ import { api } from '@controleonline/ui-common/src/api';
20
+ import { env as APP_ENV } from '@env';
21
+ import { isPublicRoute } from '@controleonline/ui-login/src/react/router/publicRoutes';
22
+ const { resolveConfiguredLanguage } = require('../utils/runtimeLanguage');
23
+ import {
24
+ applyPaletteToRuntimeColors,
25
+ applyThemeCssVariables,
26
+ resolveThemePalette,
27
+ } from '@controleonline/../../src/styles/branding';
28
+ import { resolveAppDomain } from '@controleonline/ui-common/src/utils/appDomain';
29
+ import { colors as runtimeColors } from '@controleonline/../../src/styles/colors';
30
+ import {
31
+ buildProviderManagedDeviceConfigs,
32
+ parseConfigsObject,
33
+ } from '@controleonline/ui-common/src/react/config/deviceConfigBootstrap';
34
+ import {
35
+ buildDeviceRegistrationPayload,
36
+ buildLocalRuntimeDevice,
37
+ getOrCreateWebDeviceInstanceId,
38
+ hasDeviceRecordChanges,
39
+ resolveOperationalDeviceType,
40
+ } from '@controleonline/ui-common/src/react/utils/deviceRuntime';
41
+ import {
42
+ filterWalletPaymentTypesByAllowedIds,
43
+ resolveDevicePaymentTypeIds,
44
+ } from '@controleonline/ui-common/src/react/utils/paymentDevices';
45
+ import {normalizeRuntimeMenuResponse} from '@controleonline/ui-common/src/react/utils/runtimeMenu';
46
+ import stores from '@stores';
47
+ import packageJson from '@package';
48
+ import providerStyles from './DefaultProvider.styles';
49
+ const ThemeContext = createContext();
50
+
51
+ const parseThemeCss = cssText => {
52
+ const parsedColors = {};
53
+ const matches = String(cssText || '').match(/--([\w-]+)\s*:\s*([^;}{]+)\s*;/g) || [];
54
+
55
+ matches.forEach(match => {
56
+ const clean = match.trim().replace(/^--/, '').replace(/;$/, '');
57
+ const splitIndex = clean.indexOf(':');
58
+ if (splitIndex <= 0) return;
59
+
60
+ const key = clean.slice(0, splitIndex).trim();
61
+ const value = clean.slice(splitIndex + 1).trim();
62
+ if (!key || !value) return;
63
+ parsedColors[key] = value;
64
+ });
65
+
66
+ return parsedColors;
67
+ };
68
+
69
+ const normalizeDeviceId = value =>
70
+ String(value?.device || value?.id || value || '').trim();
71
+
72
+ const normalizeEntityId = value =>
73
+ String(value?.id || value || '')
74
+ .replace(/\D/g, '')
75
+ .trim();
76
+
77
+ const resolveDeviceConfigPeopleIri = ({appType, currentCompany, user}) => {
78
+ const normalizedAppType = String(appType || '').trim().toUpperCase();
79
+ const currentPeopleId = normalizeEntityId(
80
+ user?.people ?? user?.peopleId ?? user?.person ?? user?.personId ?? '',
81
+ );
82
+ const currentCompanyId = normalizeEntityId(currentCompany?.id);
83
+
84
+ if (normalizedAppType === 'DELIVERY' && currentPeopleId) {
85
+ return `/people/${currentPeopleId}`;
86
+ }
87
+
88
+ if (currentCompanyId) {
89
+ return `/people/${currentCompanyId}`;
90
+ }
91
+
92
+ return '';
93
+ };
94
+
95
+ const normalizeRuntimeIp = value => String(value || '').trim();
96
+
97
+ const getRuntimeIpFromResponse = response =>
98
+ normalizeRuntimeIp(response?.member?.[0]?.ip || response?.ip);
99
+
100
+ const getRuntimeIpFromDeviceInfo = deviceInfo =>
101
+ normalizeRuntimeIp(
102
+ deviceInfo?.externalIp ||
103
+ deviceInfo?.metadata?.network?.publicIp ||
104
+ deviceInfo?.metadata?.browser?.publicIp,
105
+ );
106
+
107
+ const selectRuntimeDeviceConfig = ({
108
+ items = [],
109
+ deviceId,
110
+ companyId,
111
+ runtimeDeviceType,
112
+ }) => {
113
+ const normalizedDeviceId = normalizeDeviceId(deviceId);
114
+ const normalizedCompanyId = normalizeEntityId(companyId);
115
+ const normalizedType = String(runtimeDeviceType || '')
116
+ .trim()
117
+ .toUpperCase();
118
+
119
+ return (Array.isArray(items) ? items : [])
120
+ .filter(item => {
121
+ const itemDeviceId = normalizeDeviceId(item?.device);
122
+ const itemCompanyId = normalizeEntityId(item?.people);
123
+ const itemType = String(item?.type || item?.device?.type || '')
124
+ .trim()
125
+ .toUpperCase();
126
+
127
+ if (normalizedDeviceId && itemDeviceId !== normalizedDeviceId) {
128
+ return false;
129
+ }
130
+
131
+ if (normalizedCompanyId && itemCompanyId !== normalizedCompanyId) {
132
+ return false;
133
+ }
134
+
135
+ if (normalizedType && itemType && itemType !== normalizedType) {
136
+ return false;
137
+ }
138
+
139
+ return true;
140
+ })
141
+ .sort((left, right) => Number(right?.id || 0) - Number(left?.id || 0))[0] || null;
142
+ };
143
+
144
+ export const DefaultProvider = ({ children, onBootstrapReady }) => {
145
+ const appType = String(APP_ENV.APP_TYPE || '').toUpperCase();
146
+ const isShopClientApp = appType === 'SHOP';
147
+ const themeStore = useStore('theme');
148
+ const getters = themeStore.getters;
149
+ const actions = themeStore.actions;
150
+
151
+ const authStore = useStore('auth');
152
+ const authGetters = authStore.getters;
153
+
154
+ const peopleStore = useStore('people');
155
+ const peopleGetters = peopleStore.getters;
156
+ const peopleActions = peopleStore.actions;
157
+
158
+ const deviceStore = useStore('device');
159
+ const deviceActions = deviceStore.actions;
160
+
161
+ const device_configStore = useStore('device_config');
162
+ const deviceConfigsGetters = device_configStore.getters;
163
+ const deviceConfigsActions = device_configStore.actions;
164
+
165
+ const configsStore = useStore('configs');
166
+ const configActions = configsStore.actions;
167
+ const configsGetters = configsStore.getters;
168
+
169
+ const printerStore = useStore('printer');
170
+ const printerActions = printerStore.actions;
171
+
172
+ const walletPaymentTypeStore = useStore('walletPaymentType');
173
+ const paymentTypeActions = walletPaymentTypeStore.actions;
174
+
175
+ const translateStore = useStore('translate');
176
+ const translateActions = translateStore.actions;
177
+
178
+ const { items: companyConfigs } = configsGetters;
179
+ const { colors, menus } = getters;
180
+ const { currentCompany, defaultCompany, companies } = peopleGetters;
181
+ const { item: device_config } = deviceConfigsGetters;
182
+ const { isLogged, user } = authGetters;
183
+ const hasCurrentCompany =
184
+ !!currentCompany && Object.entries(currentCompany).length > 0;
185
+
186
+ const [translateReady, setTranslateReady] = useState(true);
187
+ const [deviceConfigFetched, setDeviceConfigFetched] = useState(false);
188
+ const [mainConfigsDiscovered, setMainConfigsDiscovered] = useState(false);
189
+ const [deviceRuntimeConfigSynced, setDeviceRuntimeConfigSynced] =
190
+ useState(false);
191
+ const [currentRouteName, setCurrentRouteName] = useState('');
192
+ const [, setTranslateVersion] = useState(0);
193
+ const [baseThemeColors, setBaseThemeColors] = useState({});
194
+ const [bottomNavigationCount, setBottomNavigationCount] = useState(0);
195
+ const translateBootstrapKeyRef = useRef('');
196
+ const lastDeviceConfigPeopleIriRef = useRef('');
197
+ const [device, setDevice] = useState(
198
+ JSON.parse(localStorage.getItem('device') || '{}'),
199
+ );
200
+ const [webRuntimeIp, setWebRuntimeIp] = useState(() =>
201
+ getRuntimeIpFromDeviceInfo(
202
+ JSON.parse(localStorage.getItem('device') || '{}'),
203
+ ),
204
+ );
205
+ const packageVersion = packageJson?.version || packageJson?.default?.version;
206
+ const appVersion = packageVersion || device?.appVersion;
207
+ const runtimeDeviceType = resolveOperationalDeviceType({
208
+ appType: APP_ENV.APP_TYPE,
209
+ deviceInfo: device || {},
210
+ });
211
+ const deviceConfigPeopleIri = resolveDeviceConfigPeopleIri({
212
+ appType,
213
+ currentCompany,
214
+ user,
215
+ });
216
+ const isPublicRouteActive = isPublicRoute(currentRouteName);
217
+
218
+ const registerBottomNavigation = useCallback(() => {
219
+ setBottomNavigationCount(current => current + 1);
220
+
221
+ let released = false;
222
+
223
+ return () => {
224
+ if (released) {
225
+ return;
226
+ }
227
+
228
+ released = true;
229
+ setBottomNavigationCount(current => Math.max(0, current - 1));
230
+ };
231
+ }, []);
232
+
233
+ const themeContextValue = useMemo(
234
+ () => ({
235
+ colors,
236
+ menus,
237
+ runtimeFooter: isShopClientApp
238
+ ? null
239
+ : {
240
+ appVersion,
241
+ colors,
242
+ defaultCompany,
243
+ device,
244
+ },
245
+ bottomChrome: {
246
+ hasBottomNavigation: bottomNavigationCount > 0,
247
+ registerBottomNavigation,
248
+ },
249
+ }),
250
+ [
251
+ appVersion,
252
+ bottomNavigationCount,
253
+ colors,
254
+ defaultCompany,
255
+ device,
256
+ isShopClientApp,
257
+ menus,
258
+ registerBottomNavigation,
259
+ ],
260
+ );
261
+
262
+ useEffect(() => {
263
+ global.refreshTranslationsUI = () => {
264
+ setTranslateVersion(version => version + 1);
265
+ };
266
+
267
+ return () => {
268
+ if (global.refreshTranslationsUI) {
269
+ delete global.refreshTranslationsUI;
270
+ }
271
+ };
272
+ }, []);
273
+
274
+ useEffect(() => {
275
+ global.setRuntimeRouteName = routeName => {
276
+ const normalizedRouteName = String(routeName || '').trim();
277
+
278
+ setCurrentRouteName(previousRouteName =>
279
+ previousRouteName === normalizedRouteName
280
+ ? previousRouteName
281
+ : normalizedRouteName,
282
+ );
283
+ };
284
+
285
+ return () => {
286
+ if (global.setRuntimeRouteName) {
287
+ delete global.setRuntimeRouteName;
288
+ }
289
+ };
290
+ }, []);
291
+
292
+ useEffect(() => {
293
+ if (isLogged && !isPublicRouteActive) {
294
+ return;
295
+ }
296
+
297
+ setTranslateReady(true);
298
+ translateBootstrapKeyRef.current = '';
299
+ translateActions.setMessages({});
300
+ translateActions.setPendingMessages?.({});
301
+
302
+ if (global.t) {
303
+ delete global.t;
304
+ }
305
+ }, [isLogged, isPublicRouteActive]);
306
+
307
+ useEffect(() => {
308
+ if (
309
+ !deviceConfigPeopleIri ||
310
+ lastDeviceConfigPeopleIriRef.current === deviceConfigPeopleIri
311
+ ) {
312
+ return;
313
+ }
314
+
315
+ lastDeviceConfigPeopleIriRef.current = deviceConfigPeopleIri;
316
+ setDeviceConfigFetched(false);
317
+ setDeviceRuntimeConfigSynced(false);
318
+ deviceConfigsActions.setItem({});
319
+ }, [deviceConfigPeopleIri, deviceConfigsActions]);
320
+
321
+ useEffect(() => {
322
+ if (!isLogged) {
323
+ return;
324
+ }
325
+
326
+ let cancelled = false;
327
+
328
+ api
329
+ .fetch('runtime/ip', {
330
+ method: 'GET',
331
+ })
332
+ .then(response => {
333
+ const nextRuntimeIp = getRuntimeIpFromResponse(response);
334
+ if (!nextRuntimeIp || cancelled) {
335
+ return;
336
+ }
337
+
338
+ setWebRuntimeIp(currentIp =>
339
+ currentIp === nextRuntimeIp ? currentIp : nextRuntimeIp,
340
+ );
341
+ })
342
+ .catch(() => {});
343
+
344
+ return () => {
345
+ cancelled = true;
346
+ };
347
+ }, [isLogged, user?.id]);
348
+
349
+ const buildWebDevice = () => {
350
+ const webDeviceId = getOrCreateWebDeviceInstanceId();
351
+ if (!webDeviceId) {
352
+ return null;
353
+ }
354
+
355
+ const nextAppName =
356
+ packageJson?.displayName ||
357
+ packageJson?.default?.displayName ||
358
+ packageJson?.name ||
359
+ packageJson?.default?.name ||
360
+ 'Web App';
361
+
362
+ return buildLocalRuntimeDevice({
363
+ appType: APP_ENV.APP_TYPE,
364
+ deviceInfo: {
365
+ id: webDeviceId,
366
+ appName: nextAppName,
367
+ deviceType: 'web',
368
+ systemName: 'web',
369
+ systemVersion: 'web',
370
+ manufacturer: 'web',
371
+ model: 'browser',
372
+ batteryLevel: 'unknow',
373
+ isEmulator: false,
374
+ appVersion: packageVersion || '1.0.0',
375
+ buildNumber: packageVersion || '1.0.0',
376
+ externalIp: webRuntimeIp || null,
377
+ },
378
+ });
379
+ };
380
+
381
+ useEffect(() => {
382
+ if (!isLogged && !isShopClientApp && (!device || !device.id)) {
383
+ return;
384
+ }
385
+
386
+ const nextDevice = buildWebDevice();
387
+ if (!nextDevice) {
388
+ if (device && device.id) {
389
+ deviceActions.setItem(device);
390
+ }
391
+ return;
392
+ }
393
+
394
+ const shouldRefreshDevice =
395
+ !device?.id ||
396
+ device.id !== nextDevice.id ||
397
+ device.appVersion !== nextDevice.appVersion ||
398
+ device.appName !== nextDevice.appName ||
399
+ device.type !== nextDevice.type ||
400
+ JSON.stringify(device.metadata || {}) !==
401
+ JSON.stringify(nextDevice.metadata || {});
402
+
403
+ if (shouldRefreshDevice) {
404
+ setDevice(nextDevice);
405
+ localStorage.setItem('device', JSON.stringify(nextDevice));
406
+ deviceActions.setItem(nextDevice);
407
+ localStorage.removeItem('master-device');
408
+ return;
409
+ }
410
+
411
+ deviceActions.setItem(device);
412
+ }, [device, deviceActions, isLogged, isShopClientApp, packageVersion, user?.id, webRuntimeIp]);
413
+
414
+ useEffect(() => {
415
+ if (isShopClientApp || device?.id) {
416
+ peopleActions.defaultCompany().catch(() => {});
417
+ }
418
+ }, [device?.id, isShopClientApp, peopleActions]);
419
+
420
+ useEffect(() => {
421
+ if (!isLogged || !device?.id) {
422
+ return;
423
+ }
424
+
425
+ let cancelled = false;
426
+
427
+ const syncDeviceRegistration = async () => {
428
+ const items = await deviceActions.getItems({
429
+ device: device.id,
430
+ });
431
+
432
+ if (cancelled) {
433
+ return;
434
+ }
435
+
436
+ const existingDevice =
437
+ Array.isArray(items) && items.length > 0 ? items[0] : null;
438
+ const nextDevice = buildDeviceRegistrationPayload({
439
+ deviceInfo: device,
440
+ appType: APP_ENV.APP_TYPE,
441
+ existingDevice,
442
+ });
443
+
444
+ if (!hasDeviceRecordChanges({existingDevice, nextDevice})) {
445
+ const nextLocalDevice = {
446
+ ...device,
447
+ entityId: existingDevice?.id || device?.entityId || null,
448
+ entityIri:
449
+ existingDevice?.['@id'] ||
450
+ device?.entityIri ||
451
+ (existingDevice?.id ? `/devices/${existingDevice.id}` : null),
452
+ alias: existingDevice?.alias || nextDevice.alias,
453
+ type: device?.type || runtimeDeviceType,
454
+ metadata: existingDevice?.metadata || nextDevice.metadata,
455
+ };
456
+
457
+ if (JSON.stringify(nextLocalDevice) !== JSON.stringify(device)) {
458
+ setDevice(nextLocalDevice);
459
+ localStorage.setItem('device', JSON.stringify(nextLocalDevice));
460
+ deviceActions.setItem(nextLocalDevice);
461
+ }
462
+ return;
463
+ }
464
+
465
+ const savedDevice = await deviceActions.save(nextDevice);
466
+ if (cancelled || !savedDevice) {
467
+ return;
468
+ }
469
+
470
+ const nextLocalDevice = {
471
+ ...device,
472
+ entityId: savedDevice?.id || device?.entityId || null,
473
+ entityIri:
474
+ savedDevice?.['@id'] ||
475
+ device?.entityIri ||
476
+ (savedDevice?.id ? `/devices/${savedDevice.id}` : null),
477
+ alias: savedDevice.alias || nextDevice.alias,
478
+ type: device?.type || runtimeDeviceType,
479
+ metadata: savedDevice.metadata || nextDevice.metadata,
480
+ };
481
+
482
+ if (JSON.stringify(nextLocalDevice) !== JSON.stringify(device)) {
483
+ setDevice(nextLocalDevice);
484
+ localStorage.setItem('device', JSON.stringify(nextLocalDevice));
485
+ deviceActions.setItem(nextLocalDevice);
486
+ }
487
+ };
488
+
489
+ syncDeviceRegistration().catch(() => {});
490
+
491
+ return () => {
492
+ cancelled = true;
493
+ };
494
+ }, [
495
+ device?.appVersion,
496
+ device?.batteryLevel,
497
+ device?.buildNumber,
498
+ device?.deviceType,
499
+ device?.externalIp,
500
+ device?.id,
501
+ device?.manufacturer,
502
+ device?.model,
503
+ device?.systemVersion,
504
+ isLogged,
505
+ runtimeDeviceType,
506
+ ]);
507
+
508
+ useEffect(() => {
509
+ if (isShopClientApp || !isLogged || !currentCompany?.id) {
510
+ return;
511
+ }
512
+
513
+ printerActions
514
+ .ensureCompanyPrintersLoaded({people: currentCompany.id})
515
+ .catch(() => {});
516
+ }, [currentCompany?.id, isLogged, isShopClientApp, printerActions]);
517
+
518
+ useEffect(() => {
519
+ const paymentConfigSource = isShopClientApp
520
+ ? Object.keys(companyConfigs || {}).length > 0
521
+ ? companyConfigs
522
+ : currentCompany?.configs
523
+ : device_config?.configs;
524
+
525
+ if (!currentCompany?.id || !paymentConfigSource) {
526
+ paymentTypeActions.setItems([]);
527
+ return;
528
+ }
529
+
530
+ let isMounted = true;
531
+
532
+ api
533
+ .fetch('wallet_payment_types', {
534
+ params: {
535
+ people: `/people/${currentCompany.id}`,
536
+ },
537
+ })
538
+ .then(response => {
539
+ if (!isMounted) {
540
+ return;
541
+ }
542
+
543
+ const walletPaymentTypes = Array.isArray(response?.member)
544
+ ? response.member
545
+ : Array.isArray(response?.['hydra:member'])
546
+ ? response['hydra:member']
547
+ : Array.isArray(response)
548
+ ? response
549
+ : [];
550
+ const allowedPaymentTypeIds = resolveDevicePaymentTypeIds(
551
+ paymentConfigSource,
552
+ walletPaymentTypes,
553
+ );
554
+
555
+ paymentTypeActions.setItems(
556
+ filterWalletPaymentTypesByAllowedIds(
557
+ walletPaymentTypes,
558
+ allowedPaymentTypeIds,
559
+ ),
560
+ );
561
+ })
562
+ .catch(() => {
563
+ if (isMounted) {
564
+ paymentTypeActions.setItems([]);
565
+ }
566
+ });
567
+
568
+ return () => {
569
+ isMounted = false;
570
+ };
571
+ }, [
572
+ companyConfigs,
573
+ currentCompany?.configs,
574
+ currentCompany?.id,
575
+ device_config?.configs,
576
+ isShopClientApp,
577
+ paymentTypeActions,
578
+ ]);
579
+
580
+ useEffect(() => {
581
+ if (!device?.id || !isLogged || !deviceConfigPeopleIri) {
582
+ return;
583
+ }
584
+
585
+ setDeviceConfigFetched(false);
586
+ setDeviceRuntimeConfigSynced(false);
587
+ deviceConfigsActions.setItem({});
588
+
589
+ deviceConfigsActions
590
+ .getItems({
591
+ 'device.device': device.id,
592
+ people: deviceConfigPeopleIri,
593
+ type: runtimeDeviceType,
594
+ })
595
+ .then(data => {
596
+ const selectedConfig = selectRuntimeDeviceConfig({
597
+ items: data,
598
+ deviceId: device.id,
599
+ companyId: deviceConfigPeopleIri,
600
+ runtimeDeviceType,
601
+ });
602
+
603
+ if (selectedConfig) {
604
+ const nextItem = {
605
+ ...selectedConfig,
606
+ configs: parseConfigsObject(selectedConfig?.configs),
607
+ };
608
+ deviceConfigsActions.setItem(nextItem);
609
+ return;
610
+ }
611
+
612
+ deviceConfigsActions.setItem({});
613
+ })
614
+ .catch(() => {})
615
+ .finally(() => {
616
+ setDeviceConfigFetched(true);
617
+ });
618
+ }, [
619
+ device?.id,
620
+ deviceConfigPeopleIri,
621
+ deviceConfigsActions,
622
+ isLogged,
623
+ runtimeDeviceType,
624
+ ]);
625
+
626
+ useEffect(() => {
627
+ if (
628
+ !deviceConfigFetched ||
629
+ !isLogged ||
630
+ !deviceConfigPeopleIri ||
631
+ !device?.id ||
632
+ deviceRuntimeConfigSynced
633
+ ) {
634
+ return;
635
+ }
636
+
637
+ const {nextConfigs, needsUpdate} = buildProviderManagedDeviceConfigs({
638
+ configs: device_config?.configs,
639
+ appVersion,
640
+ deviceInfo: device,
641
+ });
642
+
643
+ if (!needsUpdate) {
644
+ setDeviceRuntimeConfigSynced(true);
645
+ return;
646
+ }
647
+
648
+ deviceConfigsActions
649
+ .addDeviceConfigs({
650
+ device: device.id,
651
+ configs: JSON.stringify(nextConfigs),
652
+ people: deviceConfigPeopleIri,
653
+ type: runtimeDeviceType,
654
+ })
655
+ .catch(() => { })
656
+ .finally(() => {
657
+ setDeviceRuntimeConfigSynced(true);
658
+ });
659
+ }, [
660
+ appVersion,
661
+ device?.id,
662
+ device?.manufacturer,
663
+ device?.isEmulator,
664
+ deviceConfigFetched,
665
+ deviceConfigPeopleIri,
666
+ deviceRuntimeConfigSynced,
667
+ deviceConfigsActions,
668
+ device_config?.configs,
669
+ isLogged,
670
+ runtimeDeviceType,
671
+ ]);
672
+
673
+ useEffect(() => {
674
+ if (!isLogged || !currentCompany?.id || !device?.id) {
675
+ return;
676
+ }
677
+
678
+ setMainConfigsDiscovered(false);
679
+ }, [isLogged, currentCompany?.id, device?.id]);
680
+
681
+ useEffect(() => {
682
+ if (
683
+ !isLogged ||
684
+ !currentCompany?.id ||
685
+ !device?.id ||
686
+ mainConfigsDiscovered
687
+ ) {
688
+ return;
689
+ }
690
+
691
+ configActions
692
+ .discoveryMainConfigs({
693
+ people: '/people/' + currentCompany.id,
694
+ })
695
+ .catch(() => { })
696
+ .finally(() => {
697
+ setMainConfigsDiscovered(true);
698
+ });
699
+ }, [configActions, currentCompany?.id, device?.id, isLogged, mainConfigsDiscovered]);
700
+
701
+ useEffect(() => {
702
+ if (
703
+ isLogged &&
704
+ currentCompany &&
705
+ Object.entries(currentCompany).length > 0 &&
706
+ !mainConfigsDiscovered
707
+ ) {
708
+ configActions.setItems(currentCompany.configs);
709
+ }
710
+ }, [currentCompany, isLogged, mainConfigsDiscovered]);
711
+
712
+ useEffect(() => {
713
+ if (
714
+ !currentRouteName ||
715
+ isPublicRouteActive
716
+ ) {
717
+ return;
718
+ }
719
+
720
+ if (
721
+ !isLogged ||
722
+ Object.entries(currentCompany).length === 0 ||
723
+ !deviceConfigFetched
724
+ ) {
725
+ return;
726
+ }
727
+
728
+ const currentConfig = JSON.parse(localStorage.getItem('config') || '{}');
729
+ const sessionData = JSON.parse(localStorage.getItem('session') || '{}');
730
+ const currentCompanyId = normalizeEntityId(currentCompany?.id);
731
+ const defaultCompanyId = normalizeEntityId(defaultCompany?.id);
732
+ const configuredLanguage = resolveConfiguredLanguage({
733
+ currentCompany,
734
+ defaultCompany,
735
+ currentConfig,
736
+ sessionData,
737
+ });
738
+ const nextTranslateBootstrapKey = [
739
+ configuredLanguage,
740
+ currentCompanyId,
741
+ defaultCompanyId,
742
+ ].join('::');
743
+
744
+ if (translateBootstrapKeyRef.current === nextTranslateBootstrapKey) {
745
+ if (global.t) {
746
+ global.t.companies = companies;
747
+ global.t.currentCompany = currentCompany;
748
+ global.t.defaultCompany = defaultCompany;
749
+ }
750
+
751
+ return;
752
+ }
753
+
754
+ if (currentConfig.language !== configuredLanguage) {
755
+ const nextConfig = { ...currentConfig, language: configuredLanguage };
756
+ localStorage.setItem(
757
+ 'config',
758
+ JSON.stringify(nextConfig),
759
+ );
760
+ }
761
+
762
+ translateBootstrapKeyRef.current = nextTranslateBootstrapKey;
763
+ global.t = new Translate(
764
+ companies,
765
+ defaultCompany,
766
+ currentCompany,
767
+ Object.keys(stores),
768
+ translateStore,
769
+ );
770
+ setTranslateReady(true);
771
+ global.refreshTranslationsUI?.();
772
+ global.t.discoveryAll().catch(() => {});
773
+ }, [
774
+ companies,
775
+ currentCompany,
776
+ currentRouteName,
777
+ defaultCompany,
778
+ deviceConfigFetched,
779
+ isLogged,
780
+ isPublicRouteActive,
781
+ translateActions,
782
+ ]);
783
+
784
+ useEffect(() => {
785
+ if (!isLogged || translateReady || !hasCurrentCompany) {
786
+ onBootstrapReady?.();
787
+ }
788
+ }, [isLogged, translateReady, hasCurrentCompany, onBootstrapReady]);
789
+
790
+ useEffect(() => {
791
+ if (device && device.id && isLogged) {
792
+ peopleActions.myCompanies();
793
+ }
794
+ }, [isLogged, device?.id]);
795
+
796
+ useEffect(() => {
797
+ const fetchColors = async () => {
798
+ const appDomain = resolveAppDomain(APP_ENV.DOMAIN);
799
+ const params = appDomain ? { 'app-domain': appDomain } : undefined;
800
+
801
+ try {
802
+ const cssText = await api.fetch('themes-colors.css', {
803
+ responseType: 'text',
804
+ params,
805
+ });
806
+ const parsedColors = parseThemeCss(cssText);
807
+ setBaseThemeColors(parsedColors);
808
+ actions.setColors(parsedColors);
809
+ } catch {
810
+ setBaseThemeColors({});
811
+ }
812
+ };
813
+
814
+ fetchColors();
815
+ }, [actions, currentCompany?.id, defaultCompany?.id, device?.id]);
816
+
817
+ useEffect(() => {
818
+ if (!isLogged || !currentCompany?.id || !appType) {
819
+ actions.setMenus([]);
820
+ return;
821
+ }
822
+
823
+ let cancelled = false;
824
+
825
+ api
826
+ .fetch('menus-people', {
827
+ params: {
828
+ myCompany: currentCompany.id,
829
+ appType,
830
+ menuType: 'home',
831
+ },
832
+ })
833
+ .then(result => {
834
+ if (!cancelled) {
835
+ actions.setMenus(normalizeRuntimeMenuResponse(result, {appType}));
836
+ }
837
+ })
838
+ .catch(() => {
839
+ if (!cancelled) {
840
+ actions.setMenus(normalizeRuntimeMenuResponse(null, {appType}));
841
+ }
842
+ });
843
+
844
+ return () => {
845
+ cancelled = true;
846
+ };
847
+ }, [actions, appType, currentCompany?.id, isLogged]);
848
+
849
+ useEffect(() => {
850
+ const companyThemeColors = isShopClientApp
851
+ ? defaultCompany?.theme?.colors || {}
852
+ : currentCompany?.theme?.colors || defaultCompany?.theme?.colors || {};
853
+ const mergedThemeColors = {
854
+ ...(baseThemeColors || {}),
855
+ ...(companyThemeColors || {}),
856
+ };
857
+
858
+ const palette = resolveThemePalette(mergedThemeColors, runtimeColors);
859
+ applyPaletteToRuntimeColors(palette, runtimeColors);
860
+ applyThemeCssVariables({
861
+ themeColors: mergedThemeColors,
862
+ palette,
863
+ });
864
+
865
+ actions.setColors(mergedThemeColors);
866
+ }, [
867
+ actions,
868
+ baseThemeColors,
869
+ currentCompany?.id,
870
+ currentCompany?.theme?.colors,
871
+ defaultCompany?.id,
872
+ defaultCompany?.theme?.colors,
873
+ isShopClientApp,
874
+ ]);
875
+
876
+ return (
877
+ <ThemeContext.Provider value={themeContextValue}>
878
+ <View
879
+ style={[
880
+ providerStyles.shell,
881
+ {
882
+ backgroundColor: colors?.background || runtimeColors.background,
883
+ },
884
+ ]}>
885
+ <View style={providerStyles.content}>{children}</View>
886
+ {!isShopClientApp && bottomNavigationCount === 0 && (
887
+ <RuntimeInfoFooter
888
+ appVersion={appVersion}
889
+ defaultCompany={defaultCompany}
890
+ device={device}
891
+ colors={colors}
892
+ />
893
+ )}
894
+ </View>
895
+ {!isShopClientApp && device?.id && isLogged && (
896
+ <>
897
+ <WebsocketListener />
898
+ <DeviceAlertSoundService />
899
+ <ProductCatalogCacheService />
900
+ <RemoteCheckoutService />
901
+ <PrintService />
902
+ </>
903
+ )}
904
+ </ThemeContext.Provider>
905
+ );
906
+ };
907
+
908
+ export const useTheme = () => useContext(ThemeContext);
909
+ // 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.