@controleonline/ui-common 1.2.80 → 1.2.81

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 +40 -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 +493 -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 +484 -0
  43. package/src/react/pages/Devices/detail/useDeviceDetailStateB.js +71 -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
@@ -0,0 +1,429 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+ import { useNavigation, useRoute } from '@react-navigation/native';
3
+ import { useStore } from '@store';
4
+ import { useMessage } from '@controleonline/ui-common/src/react/components/MessageService';
5
+ import { resolveThemePalette } from '@controleonline/../../src/styles/branding';
6
+ import { colors } from '@controleonline/../../src/styles/colors';
7
+ import packageJson from '@package';
8
+ import {
9
+ canDisplayChangePrinter, DEVICE_ANDROID_KIOSK_ENABLED_CONFIG_KEY, DEVICE_ANDROID_LAUNCHER_ENABLED_CONFIG_KEY,
10
+ DISPLAY_AUTO_PRINT_PRODUCT_CONFIG_KEY, DISPLAY_ALLOW_PRINTER_CHANGE_CONFIG_KEY, DEVICE_ALERT_SOUND_ENABLED_KEY,
11
+ DEVICE_ALERT_SOUND_URL_KEY, DEVICE_ORDER_VISIBILITY_COMPANY, DEVICE_ORDER_VISIBILITY_DEVICE, DEVICE_ORDER_VISIBILITY_KEY,
12
+ DEVICE_RUNTIME_DEBUG_INFO_ENABLED_KEY, isPosAutoPrintEnabled, isPosCashRegisterOpen, isTruthyValue, parseConfigsObject,
13
+ POS_AUTO_PRINT_ENABLED_CONFIG_KEY, POS_CASH_MANAGEMENT_MODE_CASH_REGISTER, POS_CASH_MANAGEMENT_MODE_CONFIG_KEY,
14
+ POS_CASH_MANAGEMENT_MODE_DAILY, POS_CHECK_ORDER_MANAGEMENT_MODE_CONFIG_KEY, POS_CHECK_ORDER_MANAGEMENT_MODE_EXISTING_ONLY,
15
+ POS_CHECK_ORDER_MANAGEMENT_MODE_MANAGE, POS_CHECK_ORDER_TYPE_CONFIG_KEY, POS_CHECK_ORDER_TYPE_NONE, POS_CHECK_ORDER_TYPE_TAB,
16
+ POS_CHECK_ORDER_TYPE_TABLE, POS_CHECK_ORDER_TYPE_STAMP, POS_DELIVERY_ENABLED_CONFIG_KEY, POS_OPERATION_MODE_COUNTER,
17
+ POS_OPERATION_MODE_CONFIG_KEY, POS_OPERATION_MODE_OPTIONS, POS_PRODUCT_SHOWCASE_CONFIG_KEY, POS_PRINT_MODE_FORM,
18
+ POS_PRINT_MODE_ORDER, getPosOperationModeOption, isAndroidKioskEnabled, isAndroidLauncherEnabled, isPosDeliveryEnabled,
19
+ resolvePosCheckOrderManagementMode, resolvePosCheckOrderType, resolvePosCheckOrderTypeForShop, resolveDeviceOrderVisibility,
20
+ resolvePosCashManagementMode, resolvePosOperationMode, resolvePosPrintMode,
21
+ } from '@controleonline/ui-common/src/react/config/deviceConfigBootstrap';
22
+ import {
23
+ filterDeviceConfigsByCompany, getCompanyPaymentDeviceOptions, getPaymentGatewayFromConfigs, getPaymentGatewayLabel,
24
+ isPaymentCapableDeviceConfig, isPdvPrinterEnabled, normalizeDeviceId, normalizeEntityId, PAYMENT_TYPE_IDS_CONFIG_KEY,
25
+ PAYMENT_GATEWAY_CIELO, PDV_PRINTER_ENABLED_CONFIG_KEY, ORDER_PAYMENT_DEVICE_CONFIG_KEY, POS_GATEWAY_CONFIG_KEY,
26
+ } from '@controleonline/ui-common/src/react/utils/paymentDevices';
27
+ import { normalizeBooleanConfig, SHOP_LOYALTY_COUPONS_ENABLED_CONFIG_KEY } from '@controleonline/ui-common/src/react/utils/shopConfig';
28
+ import { getPrinterOptionValue, getDeviceTypeLabel, getPrinterLabel, getPrinterOptions } from '@controleonline/ui-common/src/react/utils/printerDevices';
29
+ import { hex, DISPLAY_DEVICE_TYPE, PDV_DEVICE_TYPE, DISPLAY_DEVICE_LINK_CONFIG_KEY, DISPLAY_DEVICE_PRINTER_CONFIG_KEY,
30
+ PDV_TAB_OPERATION, PDV_TAB_ORDERS, PDV_TAB_DEVICE, PDV_TAB_PAYMENT_TYPES, PDV_TAB_MOVEMENT, PDV_DETAIL_TABS, tt,
31
+ } from './deviceDetailConstants';
32
+ import { paymentIcon, formatApiError, getDisplayLabel, getProductShowcaseLabel, getIsOpen, confirm } from './deviceDetailHelpers';
33
+ import { api } from '@controleonline/ui-common/src/api';
34
+ import { buildDeviceAliasStoreUpdates } from '@controleonline/ui-common/src/react/utils/deviceAliasSync';
35
+ import { createDeviceDetailRenderers } from './DeviceDetailRenderers';
36
+ import { Alert, Platform } from 'react-native';
37
+
38
+
39
+ export default function useDeviceDetailSaves(deps) {
40
+ const {
41
+ navigation, deviceId, deviceConfigStore, messageApi, websocketActions, runtimeCompanyConfigs, showSystemError, loyaltyCouponsEnabled, currentDevice, currentDeviceConfig, deviceString, deviceType,
42
+ normalizedInitialConfigs, initialAlias, isDisplayDevice, isPdvDevice, actionsRef, stampAutoDisableSignatureRef, brandColors, products, setProducts, productShowcases, setProductShowcases, companyDeviceConfigs,
43
+ setCompanyDeviceConfigs, inflowData, setInflowData, configs, setConfigs, loadingConfigData, setLoadingConfigData, loadingCompanyDeviceConfigs, setLoadingCompanyDeviceConfigs, loadingMovementData, setLoadingMovementData, actionLoading,
44
+ setActionLoading, activePdvTab, setActivePdvTab, savingPaymentTarget, setSavingPaymentTarget, savingPdvSettings, setSavingPdvSettings, savingPaymentTypes, setSavingPaymentTypes, savingPosOperationMode, setSavingPosOperationMode, savingProductShowcase,
45
+ setSavingProductShowcase, savingLauncherMode, setSavingLauncherMode, savingAlertSound, setSavingAlertSound, savingOrderVisibility, setSavingOrderVisibility, savingDeviceDeliverySettings, setSavingDeviceDeliverySettings, savingRuntimeDebugInfo, setSavingRuntimeDebugInfo, sendingCatalogRefresh,
46
+ setSendingCatalogRefresh, loadingProductShowcases, setLoadingProductShowcases, search, setSearch, devicePaymentTarget, setDevicePaymentTarget, pdvGateway, setPdvGateway, pdvPrinterEnabled, setPdvPrinterEnabled, posOperationMode,
47
+ setPosOperationMode, productShowcaseId, setProductShowcaseId, androidKioskEnabled, setAndroidKioskEnabled, androidLauncherEnabled, setAndroidLauncherEnabled, counterAutoPrintEnabled, setCounterAutoPrintEnabled, counterPrintMode, setCounterPrintMode, counterCashManagementMode,
48
+ setCounterCashManagementMode, checkOrderType, setCheckOrderType, checkOrderManagementMode, setCheckOrderManagementMode, deviceOrderVisibility, setDeviceOrderVisibility, deviceDeliveryEnabled, setDeviceDeliveryEnabled, deviceAlertSoundEnabled, setDeviceAlertSoundEnabled, deviceAlertSoundUrl,
49
+ setDeviceAlertSoundUrl, deviceRuntimeDebugInfoEnabled, setDeviceRuntimeDebugInfoEnabled, linkedDisplayId, setLinkedDisplayId, displayPrinterId, setDisplayPrinterId, displayAllowPrinterChange, setDisplayAllowPrinterChange, displayAutoPrintProductEnabled, setDisplayAutoPrintProductEnabled, savingDisplayPrintingConfig,
50
+ setSavingDisplayPrintingConfig, hasLoadedCurrentConfig, setHasLoadedCurrentConfig, hasLoadedCompanyConfigs, setHasLoadedCompanyConfigs, hasLoadedMovementData, setHasLoadedMovementData, hasLoadedCurrentConfigRef, hasLoadedCompanyConfigsRef, hasLoadedMovementDataRef, hasInitializedPdvTabRef, alias,
51
+ setAlias, editingAlias, setEditingAlias, aliasInput, setAliasInput, savingAlias, setSavingAlias, removingDevice, setRemovingDevice, aliasInputRef, skipAliasSyncFromStoreRef, isOpen,
52
+ hasLocalPaymentGateway, paymentDeviceOptions, displayOptions, printerOptions, selectedPosOperationModeOption, pickerMode, packageVersion, appVersion, runtimeDeviceId, runtimeDeviceType, isEditingRuntimeDevice, resolveDeviceContext,
53
+ loadMovementData, refreshCurrentConfig, loadCompanyConfigs, loadProductShowcases, ensureActiveTabData, ensureActiveTabDataRef, handleToggle, startEditAlias, cancelEditAlias, saveAlias, confirmRemoveDevice, saveDevicePaymentTarget,
54
+ savePdvSettings, saveProductShowcaseConfig, savePaymentTypeConfigs, savePosOperationMode,
55
+ } = deps;
56
+ const saveLauncherMode = useCallback(async (override = {}) => {
57
+ const nextAndroidLauncherEnabled =
58
+ override.androidLauncherEnabled ?? androidLauncherEnabled;
59
+
60
+ if (
61
+ !isPdvDevice ||
62
+ !currentCompany?.id ||
63
+ !deviceString ||
64
+ savingLauncherMode
65
+ ) {
66
+ return;
67
+ }
68
+
69
+ setSavingLauncherMode(true);
70
+ try {
71
+ await actionsRef.current.deviceConfigActions.addDeviceConfigs({
72
+ device: deviceString,
73
+ configs: JSON.stringify({
74
+ [DEVICE_ANDROID_LAUNCHER_ENABLED_CONFIG_KEY]: nextAndroidLauncherEnabled
75
+ ? '1'
76
+ : '0',
77
+ 'config-version': appVersion,
78
+ }),
79
+ people: '/people/' + currentCompany.id,
80
+ type: deviceType,
81
+ });
82
+ await refreshCurrentConfig();
83
+ } catch (error) {
84
+ showSystemError(
85
+ error,
86
+ 'Nao foi possivel salvar o launcher do device.',
87
+ );
88
+ } finally {
89
+ setSavingLauncherMode(false);
90
+ }
91
+ }, [
92
+ androidLauncherEnabled,
93
+ appVersion,
94
+ currentCompany?.id,
95
+ deviceString,
96
+ deviceType,
97
+ isPdvDevice,
98
+ refreshCurrentConfig,
99
+ savingLauncherMode,
100
+ showSystemError,
101
+ ]);
102
+
103
+ const saveDeviceAlertSoundConfig = useCallback(async (override = {}) => {
104
+ const nextDeviceAlertSoundEnabled =
105
+ override.deviceAlertSoundEnabled ?? deviceAlertSoundEnabled;
106
+ const nextDeviceAlertSoundUrl =
107
+ override.deviceAlertSoundUrl ?? deviceAlertSoundUrl;
108
+
109
+ if (!currentCompany?.id || !deviceString || savingAlertSound) {
110
+ return;
111
+ }
112
+
113
+ setSavingAlertSound(true);
114
+ try {
115
+ await actionsRef.current.deviceConfigActions.addDeviceConfigs({
116
+ device: deviceString,
117
+ configs: JSON.stringify({
118
+ [DEVICE_ALERT_SOUND_ENABLED_KEY]: nextDeviceAlertSoundEnabled ? '1' : '0',
119
+ [DEVICE_ALERT_SOUND_URL_KEY]: String(nextDeviceAlertSoundUrl || '').trim(),
120
+ }),
121
+ people: '/people/' + currentCompany.id,
122
+ type: deviceType,
123
+ });
124
+ await refreshCurrentConfig();
125
+ } catch (error) {
126
+ showSystemError(
127
+ error,
128
+ 'Nao foi possivel salvar o som de alerta do device.',
129
+ );
130
+ } finally {
131
+ setSavingAlertSound(false);
132
+ }
133
+ }, [
134
+ currentCompany?.id,
135
+ deviceAlertSoundEnabled,
136
+ deviceAlertSoundUrl,
137
+ deviceString,
138
+ deviceType,
139
+ refreshCurrentConfig,
140
+ savingAlertSound,
141
+ showSystemError,
142
+ ]);
143
+
144
+ const saveDeviceOrderVisibility = useCallback(async (override = {}) => {
145
+ const nextDeviceOrderVisibility =
146
+ override.deviceOrderVisibility ?? deviceOrderVisibility;
147
+
148
+ if (!currentCompany?.id || !deviceString || savingOrderVisibility) {
149
+ return;
150
+ }
151
+
152
+ setSavingOrderVisibility(true);
153
+ try {
154
+ await actionsRef.current.deviceConfigActions.addDeviceConfigs({
155
+ device: deviceString,
156
+ configs: JSON.stringify({
157
+ [DEVICE_ORDER_VISIBILITY_KEY]: nextDeviceOrderVisibility || DEVICE_ORDER_VISIBILITY_DEVICE,
158
+ }),
159
+ people: '/people/' + currentCompany.id,
160
+ type: deviceType,
161
+ });
162
+ await refreshCurrentConfig();
163
+ } catch (error) {
164
+ showSystemError(
165
+ error,
166
+ 'Nao foi possivel salvar a visibilidade dos pedidos.',
167
+ );
168
+ } finally {
169
+ setSavingOrderVisibility(false);
170
+ }
171
+ }, [
172
+ currentCompany?.id,
173
+ deviceOrderVisibility,
174
+ deviceString,
175
+ deviceType,
176
+ refreshCurrentConfig,
177
+ savingOrderVisibility,
178
+ showSystemError,
179
+ ]);
180
+
181
+ const saveDeviceDeliverySettings = useCallback(async (override = {}) => {
182
+ const nextDeviceDeliveryEnabled =
183
+ override.deviceDeliveryEnabled ?? deviceDeliveryEnabled;
184
+
185
+ if (
186
+ !currentCompany?.id ||
187
+ !deviceString ||
188
+ savingDeviceDeliverySettings
189
+ ) {
190
+ return;
191
+ }
192
+
193
+ setSavingDeviceDeliverySettings(true);
194
+ try {
195
+ await actionsRef.current.deviceConfigActions.addDeviceConfigs({
196
+ device: deviceString,
197
+ configs: JSON.stringify({
198
+ [POS_DELIVERY_ENABLED_CONFIG_KEY]: nextDeviceDeliveryEnabled ? '1' : '0',
199
+ }),
200
+ people: '/people/' + currentCompany.id,
201
+ type: deviceType,
202
+ });
203
+ await refreshCurrentConfig();
204
+ } catch (error) {
205
+ showSystemError(
206
+ error,
207
+ 'Nao foi possivel salvar a configuracao de entregas.',
208
+ );
209
+ } finally {
210
+ setSavingDeviceDeliverySettings(false);
211
+ }
212
+ }, [
213
+ currentCompany?.id,
214
+ deviceDeliveryEnabled,
215
+ deviceString,
216
+ deviceType,
217
+ refreshCurrentConfig,
218
+ savingDeviceDeliverySettings,
219
+ showSystemError,
220
+ ]);
221
+
222
+ const saveDeviceRuntimeDebugInfo = useCallback(async (override = {}) => {
223
+ const nextDeviceRuntimeDebugInfoEnabled =
224
+ override.deviceRuntimeDebugInfoEnabled ?? deviceRuntimeDebugInfoEnabled;
225
+
226
+ if (!currentCompany?.id || !deviceString || savingRuntimeDebugInfo) {
227
+ return;
228
+ }
229
+
230
+ setSavingRuntimeDebugInfo(true);
231
+ try {
232
+ await actionsRef.current.deviceConfigActions.addDeviceConfigs({
233
+ device: deviceString,
234
+ configs: JSON.stringify({
235
+ [DEVICE_RUNTIME_DEBUG_INFO_ENABLED_KEY]:
236
+ nextDeviceRuntimeDebugInfoEnabled ? '1' : '0',
237
+ }),
238
+ people: '/people/' + currentCompany.id,
239
+ type: deviceType,
240
+ });
241
+ await refreshCurrentConfig();
242
+ } catch (error) {
243
+ showSystemError(
244
+ error,
245
+ 'Nao foi possivel salvar a exibicao das informacoes tecnicas.',
246
+ );
247
+ } finally {
248
+ setSavingRuntimeDebugInfo(false);
249
+ }
250
+ }, [
251
+ currentCompany?.id,
252
+ deviceRuntimeDebugInfoEnabled,
253
+ deviceString,
254
+ deviceType,
255
+ refreshCurrentConfig,
256
+ savingRuntimeDebugInfo,
257
+ showSystemError,
258
+ ]);
259
+
260
+ const saveDisplayPrintingConfig = useCallback(async (override = {}) => {
261
+ const nextLinkedDisplayId = override.linkedDisplayId ?? linkedDisplayId;
262
+ const nextDisplayPrinterId = override.displayPrinterId ?? displayPrinterId;
263
+ const nextDisplayAllowPrinterChange =
264
+ override.displayAllowPrinterChange ?? displayAllowPrinterChange;
265
+ const nextDisplayAutoPrintProductEnabled =
266
+ override.displayAutoPrintProductEnabled ?? displayAutoPrintProductEnabled;
267
+
268
+ if (
269
+ !isDisplayDevice ||
270
+ !currentCompany?.id ||
271
+ !deviceString ||
272
+ savingDisplayPrintingConfig
273
+ ) {
274
+ return;
275
+ }
276
+
277
+ const normalizedDisplayId = String(nextLinkedDisplayId || '').trim();
278
+ const normalizedPrinterId = normalizeDeviceId(nextDisplayPrinterId);
279
+
280
+ if (
281
+ nextDisplayAutoPrintProductEnabled &&
282
+ (!normalizedDisplayId || !normalizedPrinterId)
283
+ ) {
284
+ return;
285
+ }
286
+
287
+ setSavingDisplayPrintingConfig(true);
288
+ try {
289
+ await actionsRef.current.deviceConfigActions.addDeviceConfigs({
290
+ device: deviceString,
291
+ configs: JSON.stringify({
292
+ [DISPLAY_DEVICE_LINK_CONFIG_KEY]: normalizedDisplayId,
293
+ [DISPLAY_DEVICE_PRINTER_CONFIG_KEY]: normalizedPrinterId,
294
+ [DISPLAY_ALLOW_PRINTER_CHANGE_CONFIG_KEY]:
295
+ nextDisplayAllowPrinterChange ? '1' : '0',
296
+ [DISPLAY_AUTO_PRINT_PRODUCT_CONFIG_KEY]:
297
+ nextDisplayAutoPrintProductEnabled ? '1' : '0',
298
+ }),
299
+ people: '/people/' + currentCompany.id,
300
+ type: deviceType,
301
+ });
302
+ await refreshCurrentConfig();
303
+ } catch (error) {
304
+ showSystemError(
305
+ error,
306
+ 'Nao foi possivel salvar a configuracao de impressao.',
307
+ );
308
+ } finally {
309
+ setSavingDisplayPrintingConfig(false);
310
+ }
311
+ }, [
312
+ currentCompany?.id,
313
+ deviceString,
314
+ deviceType,
315
+ displayAllowPrinterChange,
316
+ displayAutoPrintProductEnabled,
317
+ displayPrinterId,
318
+ isDisplayDevice,
319
+ linkedDisplayId,
320
+ refreshCurrentConfig,
321
+ savingDisplayPrintingConfig,
322
+ showSystemError,
323
+ ]);
324
+
325
+ const sendCatalogRefreshCommand = useCallback(() => {
326
+ if (!currentCompany?.id || !deviceString || sendingCatalogRefresh) {
327
+ return;
328
+ }
329
+
330
+ confirm('Deseja limpar o cache de produtos deste device?', async () => {
331
+ setSendingCatalogRefresh(true);
332
+ try {
333
+ await websocketActions.send({
334
+ destination: deviceString,
335
+ store: 'categories',
336
+ command: 'clear-product-cache',
337
+ companyId: currentCompany.id,
338
+ });
339
+ } catch (error) {
340
+ showSystemError(
341
+ error,
342
+ 'Nao foi possivel enviar o comando para limpar o cache de produtos.',
343
+ );
344
+ } finally {
345
+ setSendingCatalogRefresh(false);
346
+ }
347
+ });
348
+ }, [currentCompany?.id, deviceString, sendingCatalogRefresh, showSystemError, websocketActions]);
349
+
350
+ // Totais derivados
351
+ const productTotal = useMemo(
352
+ () => products.reduce((s, p) => s + Number(p.order_product_total || 0), 0),
353
+ [products],
354
+ );
355
+
356
+ const inflowTotal = inflowData?.total ?? productTotal;
357
+
358
+ const wallets = useMemo(() => {
359
+ if (!inflowData?.wallet) return [];
360
+ return Object.values(inflowData.wallet).map(w => ({
361
+ wallet: w.wallet,
362
+ total: w.total || 0,
363
+ payments: Object.values(w.payment || {}).filter(pt => (pt.inflow || 0) > 0),
364
+ }));
365
+ }, [inflowData]);
366
+
367
+ const filteredProducts = useMemo(() => {
368
+ const term = search.trim().toLowerCase();
369
+ if (!term) return products;
370
+ return products.filter(p =>
371
+ String(p.product_name || '').toLowerCase().includes(term) ||
372
+ String(p.product_sku || '').toLowerCase().includes(term),
373
+ );
374
+ }, [products, search]);
375
+
376
+ const accent = isPdvDevice
377
+ ? (isOpen ? hex.success : hex.danger)
378
+ : hex.info;
379
+ const showPdvOperationTab =
380
+ isPdvDevice && activePdvTab === PDV_TAB_OPERATION;
381
+ const showPdvOrdersTab = isPdvDevice && activePdvTab === PDV_TAB_ORDERS;
382
+ const showPdvDeviceTab = isPdvDevice && activePdvTab === PDV_TAB_DEVICE;
383
+ const showPdvPaymentTypesTab =
384
+ isPdvDevice && activePdvTab === PDV_TAB_PAYMENT_TYPES;
385
+ const showPdvMovementTab =
386
+ isPdvDevice && activePdvTab === PDV_TAB_MOVEMENT;
387
+ const loadingActiveTabData = isPdvDevice && (
388
+ (showPdvMovementTab && loadingMovementData) ||
389
+ (!showPdvMovementTab && loadingConfigData) ||
390
+ (showPdvOrdersTab && loadingCompanyDeviceConfigs)
391
+ );
392
+ const shouldShowOrderVisibility =
393
+ !isDisplayDevice && (!isPdvDevice || showPdvOrdersTab);
394
+ const shouldShowRemotePayment =
395
+ shouldShowOrderVisibility &&
396
+ (!hasLocalPaymentGateway || pdvGateway !== PAYMENT_GATEWAY_CIELO);
397
+ const shouldShowDeviceBehavior = !isPdvDevice || showPdvDeviceTab;
398
+ const shouldShowRemoteCommands =
399
+ !isDisplayDevice && (!isPdvDevice || showPdvDeviceTab);
400
+
401
+ const { renderProduct, renderHelpButton, renderSwitchRow, renderOptionButtons } =
402
+ createDeviceDetailRenderers({ themeColors, palette: brandColors });
403
+
404
+
405
+ return {
406
+ saveLauncherMode,
407
+ saveDeviceAlertSoundConfig,
408
+ saveDeviceOrderVisibility,
409
+ saveDeviceDeliverySettings,
410
+ saveDeviceRuntimeDebugInfo,
411
+ saveDisplayPrintingConfig,
412
+ sendCatalogRefreshCommand,
413
+ productTotal,
414
+ inflowTotal,
415
+ wallets,
416
+ filteredProducts,
417
+ accent,
418
+ showPdvOperationTab,
419
+ showPdvOrdersTab,
420
+ showPdvDeviceTab,
421
+ showPdvPaymentTypesTab,
422
+ showPdvMovementTab,
423
+ loadingActiveTabData,
424
+ shouldShowOrderVisibility,
425
+ shouldShowRemotePayment,
426
+ shouldShowDeviceBehavior,
427
+ shouldShowRemoteCommands,
428
+ };
429
+ }