@controleonline/ui-common 1.2.70 → 1.2.75

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/.github/actions/workers/manager/action.yml +147 -0
  2. package/.github/actions/workers/qa/action.yml +44 -0
  3. package/.github/actions/workers/security/action.yml +44 -0
  4. package/.github/actions/workers/technical-documenter/action.yml +51 -0
  5. package/.github/workflows/manager-worker.yml +168 -0
  6. package/.github/workflows/publish-npm.yml +45 -0
  7. package/.gitmodules +3 -0
  8. package/AGENTS.md +6 -0
  9. package/README.md +14 -0
  10. package/package.json +32 -28
  11. package/src/api/fetch.js +1 -1
  12. package/src/api/index.js +328 -58
  13. package/src/react/components/AddImportModal.js +95 -111
  14. package/src/react/components/AnimatedModal.js +171 -0
  15. package/src/react/components/AnimatedModal.styles.js +21 -0
  16. package/src/react/components/AppTypeSwitcher.js +164 -0
  17. package/src/react/components/AppTypeSwitcher.styles.js +109 -0
  18. package/src/react/components/BackgroundRuntimeBridge.js +5 -4
  19. package/src/react/components/BottomNavigationBar.config.js +211 -231
  20. package/src/react/components/BottomNavigationBar.js +86 -31
  21. package/src/react/components/BottomNavigationBar.styles.js +118 -110
  22. package/src/react/components/CategoryForm.js +52 -35
  23. package/src/react/components/DefaultProvider.native.js +194 -156
  24. package/src/react/components/DefaultProvider.web.js +188 -112
  25. package/src/react/components/DeliveryPushBridge.native.js +2 -2
  26. package/src/react/components/DeviceAlertSoundService.js +3 -3
  27. package/src/react/components/KioskModeBridge.js +2 -2
  28. package/src/react/components/LauncherModeBridge.js +2 -2
  29. package/src/react/components/ManagerPushBridge.native.js +2 -2
  30. package/src/react/components/NetworkPrinterPreviewModal.js +249 -0
  31. package/src/react/components/NetworkPrinterPreviewModal.styles.js +159 -0
  32. package/src/react/components/RemoteCheckoutService.js +28 -20
  33. package/src/react/components/RuntimeBottomNavigationBar.js +146 -119
  34. package/src/react/components/RuntimeInfoFooter.js +137 -45
  35. package/src/react/components/RuntimeInfoFooter.styles.js +3 -0
  36. package/src/react/components/StateStore.js +258 -0
  37. package/src/react/components/UnifiedPaymentBar.js +7 -4
  38. package/src/react/components/UserAvatar.js +160 -0
  39. package/src/react/components/WebsocketListener.native.js +11 -11
  40. package/src/react/components/integrations/IntegrationHero/index.js +48 -0
  41. package/src/react/components/integrations/IntegrationHero/styles.js +57 -0
  42. package/src/react/components/integrations/IntegrationTabs/index.js +89 -0
  43. package/src/react/components/integrations/IntegrationTabs/styles.js +44 -0
  44. package/src/react/config/deviceConfigBootstrap.js +71 -30
  45. package/src/react/css/orders.js +72 -0
  46. package/src/react/pages/Connections.js +229 -0
  47. package/src/react/pages/Connections.styles.js +222 -0
  48. package/src/react/pages/DeviceDetailPage.js +2814 -0
  49. package/src/react/pages/DeviceDetailPage.styles.js +308 -0
  50. package/src/react/pages/Devices/currentDevice.js +194 -0
  51. package/src/react/pages/Devices/deviceTypes/DeviceGroupCard.js +257 -0
  52. package/src/react/pages/Devices/deviceTypes/all.js +23 -0
  53. package/src/react/pages/Devices/deviceTypes/device.js +25 -0
  54. package/src/react/pages/Devices/deviceTypes/deviceListHelpers.js +178 -0
  55. package/src/react/pages/Devices/deviceTypes/display.js +26 -0
  56. package/src/react/pages/Devices/deviceTypes/index.js +145 -0
  57. package/src/react/pages/Devices/deviceTypes/ipCamera.js +35 -0
  58. package/src/react/pages/Devices/deviceTypes/pdv.js +88 -0
  59. package/src/react/pages/Devices/deviceTypes/printer.js +37 -0
  60. package/src/react/pages/Devices/deviceTypes/shared.js +453 -0
  61. package/src/react/pages/Devices/deviceTypes/useDeviceNetworkConnectivity.js +145 -0
  62. package/src/react/pages/Devices.js +183 -0
  63. package/src/react/pages/Devices.styles.js +353 -0
  64. package/src/react/pages/Food99IntegrationPage/components/Food99CatalogTab.js +219 -0
  65. package/src/react/pages/Food99IntegrationPage/components/Food99OverviewTab.js +134 -0
  66. package/src/react/pages/Food99IntegrationPage/components/Food99PreviewModal.js +173 -0
  67. package/src/react/pages/Food99IntegrationPage/components/Food99ProductCard.js +1 -0
  68. package/src/react/pages/Food99IntegrationPage/components/Food99QuickWalletModal.js +181 -0
  69. package/src/react/pages/Food99IntegrationPage/components/Food99SettingsTab.js +306 -0
  70. package/src/react/pages/Food99IntegrationPage/components/Food99StoreTab.js +417 -0
  71. package/src/react/pages/Food99IntegrationPage/index.js +1530 -0
  72. package/src/react/pages/Food99IntegrationPage/styles.js +792 -0
  73. package/src/react/pages/Food99IntegrationPage/utils.js +155 -0
  74. package/src/react/pages/Food99IntegrationPage.js +1 -0
  75. package/src/react/pages/Food99IntegrationPage.styles.js +1 -0
  76. package/src/react/pages/GenericLogPage.js +42 -167
  77. package/src/react/pages/IFoodIntegrationPage/components/IFoodCatalogTab.js +8 -0
  78. package/src/react/pages/IFoodIntegrationPage/components/IFoodOperationsTab.js +420 -0
  79. package/src/react/pages/IFoodIntegrationPage/components/IFoodOverviewTab.js +118 -0
  80. package/src/react/pages/IFoodIntegrationPage/components/IFoodPreviewModal.js +103 -0
  81. package/src/react/pages/IFoodIntegrationPage/components/IFoodProductCard.js +1 -0
  82. package/src/react/pages/IFoodIntegrationPage/components/IFoodStoreTab.js +150 -0
  83. package/src/react/pages/IFoodIntegrationPage/index.js +1298 -0
  84. package/src/react/pages/IFoodIntegrationPage/styles.js +764 -0
  85. package/src/react/pages/IFoodIntegrationPage/utils.js +91 -0
  86. package/src/react/pages/IFoodIntegrationPage.js +1 -0
  87. package/src/react/pages/IFoodIntegrationPage.styles.js +1 -0
  88. package/src/react/pages/Imports.js +214 -166
  89. package/src/react/pages/IntegrationConfigPage.js +744 -0
  90. package/src/react/pages/IntegrationConfigPage.styles.js +269 -0
  91. package/src/react/pages/Integrations.js +299 -0
  92. package/src/react/pages/Integrations.styles.js +130 -0
  93. package/src/react/pages/ManagerOrderNotificationsPage.js +642 -0
  94. package/src/react/pages/MarketplaceIntegrationPage/components/MarketplaceProductCard.js +205 -0
  95. package/src/react/pages/MarketplaceIntegrationPage/components/RemoteMarketplaceMenuTab.js +335 -0
  96. package/src/react/pages/MarketplaceIntegrationPage/index.js +60 -0
  97. package/src/react/pages/MarketplaceIntegrationPage/utils.js +137 -0
  98. package/src/react/pages/MercadoLivreIntegrationPage.js +538 -0
  99. package/src/react/pages/PrinterDeviceDetailPage.js +1916 -0
  100. package/src/react/pages/PrinterDeviceDetailPage.styles.js +223 -0
  101. package/src/react/pages/PrinterDeviceFormPage.js +521 -0
  102. package/src/react/pages/PrinterDeviceFormPage.styles.js +159 -0
  103. package/src/react/pages/SettingsPage/PaymentTypesByWalletTab.js +484 -454
  104. package/src/react/pages/SettingsPage/index.js +1266 -1167
  105. package/src/react/pages/WhatsAppConnectionPage.js +459 -0
  106. package/src/react/pages/WhatsAppConnectionPage.styles.js +284 -0
  107. package/src/react/pages/integrationsCatalog.js +399 -0
  108. package/src/react/print/providers/local.js +1 -1
  109. package/src/react/router/publicRoutes.js +25 -0
  110. package/src/react/services/Cielo/Checkout.js +39 -0
  111. package/src/react/services/Cielo/Cielo.js +193 -0
  112. package/src/react/services/Cielo/Print.js +7 -0
  113. package/src/react/services/InfinitePay/Checkout.js +33 -0
  114. package/src/react/services/InfinitePay/InfinitePay.js +24 -0
  115. package/src/react/{utils → services}/paymentGatewayExecution.js +91 -91
  116. package/src/react/styles/global.js +115 -0
  117. package/src/react/utils/categoryContexts.js +46 -0
  118. package/src/react/utils/entityDisplay.js +222 -217
  119. package/src/react/utils/fileUrl.js +201 -16
  120. package/src/react/utils/integrationPage.js +16 -0
  121. package/src/react/utils/menuNavigation.js +31 -0
  122. package/src/react/utils/orderIdentity.js +277 -0
  123. package/src/react/utils/remotePayment.js +115 -61
  124. package/src/react/utils/runtimeFooter.js +40 -22
  125. package/src/react/utils/runtimeLanguage.js +50 -9
  126. package/src/react/utils/runtimeMenu.js +190 -98
  127. package/src/react/utils/runtimeZoom.js +43 -0
  128. package/src/react/utils/shopConfig.js +72 -34
  129. package/src/react/utils/shopFranchises.js +182 -23
  130. package/src/react/utils/socketRuntimePipeline.js +14 -14
  131. package/src/react/utils/storeColumns.js +23 -4
  132. package/src/react/utils/userAvatar.js +104 -0
  133. package/src/store/categories/index.js +48 -20
  134. package/src/store/configs/index.js +2 -2
  135. package/src/store/device_config/index.js +62 -21
  136. package/src/store/entity_log/index.js +22 -1
  137. package/src/store/imports/customActions.js +51 -0
  138. package/src/store/imports/index.js +89 -88
  139. package/src/store/status/index.js +11 -11
  140. package/src/store/themes/index.js +22 -0
  141. package/src/store/timezones/index.js +3 -1
  142. package/src/tests/browser/manager/connections.spec.js +143 -0
  143. package/src/tests/browser/manager/devices-current.spec.js +343 -0
  144. package/src/tests/browser/manager/mercado-livre-integration.spec.js +268 -0
  145. package/src/tests/react/api/deviceHeaders.test.js +114 -0
  146. package/src/tests/react/api/loadSmokeIndex.test.js +75 -0
  147. package/src/tests/react/components/AddImportModal.test.js +166 -0
  148. package/src/tests/react/components/BottomNavigationBar.config.test.js +20 -0
  149. package/src/tests/react/components/UserAvatar.test.js +52 -0
  150. package/src/tests/react/config/deviceConfigBootstrap.test.js +47 -0
  151. package/src/tests/react/pages/DevicePickerStyles.test.js +47 -0
  152. package/src/tests/react/pages/Devices/deviceListHelpers.test.js +39 -0
  153. package/src/tests/react/pages/DevicesCurrentDevice.test.js +198 -0
  154. package/src/tests/react/pages/connectionsHelpers.test.js +34 -0
  155. package/src/tests/react/pages/mercadoLivreIntegrationPageContract.test.mjs +16 -0
  156. package/src/tests/react/print/localPrintProvider.test.js +1 -1
  157. package/src/tests/react/services/Cielo.test.js +190 -0
  158. package/src/tests/react/store/categoriesOrdering.test.js +26 -0
  159. package/src/tests/react/utils/appDomain.test.js +62 -0
  160. package/src/tests/react/utils/entityDisplay.test.js +2 -2
  161. package/src/tests/react/utils/fileUrl.test.js +62 -0
  162. package/src/tests/react/utils/formatter.test.mjs +33 -0
  163. package/src/tests/react/utils/importStatus.test.js +2 -2
  164. package/src/tests/react/utils/orderIdentity.test.js +139 -0
  165. package/src/tests/react/utils/remotePayment.test.js +62 -0
  166. package/src/tests/react/utils/runtimeFooter.test.js +32 -9
  167. package/src/tests/react/utils/runtimeLanguage.test.js +80 -10
  168. package/src/tests/react/utils/runtimeMenu.test.js +195 -111
  169. package/src/tests/react/utils/runtimeZoom.test.js +38 -0
  170. package/src/tests/react/utils/shopConfig.test.js +75 -0
  171. package/src/tests/react/utils/shopFranchises.test.js +122 -12
  172. package/src/tests/react/utils/translate.discovery.test.mjs +170 -0
  173. package/src/tests/react/utils/translate.test.helpers.mjs +152 -0
  174. package/src/tests/react/utils/translate.test.mjs +252 -396
  175. package/src/tests/react/utils/userAvatar.test.js +63 -0
  176. package/src/utils/appDomain.js +15 -4
  177. package/src/utils/formatter.js +122 -16
  178. package/src/utils/integrationConfigs.js +1 -0
  179. package/src/utils/translate.js +277 -398
  180. package/src/utils/translateDiscovery.js +96 -0
  181. package/src/utils/translateNormalize.js +33 -0
  182. package/src/utils/translatePending.js +92 -0
  183. package/src/utils/translateStorage.js +142 -0
  184. package/.github/agents/developer.agent.md +0 -30
  185. package/.github/agents/devops.agent.md +0 -30
  186. package/.github/agents/qa.agent.md +0 -30
  187. package/.github/agents/security.agent.md +0 -30
  188. package/.github/workflows/npmjs.yml +0 -35
@@ -0,0 +1,257 @@
1
+ import React from 'react';
2
+ import {Text, TouchableOpacity, View} from 'react-native';
3
+ import Icon from 'react-native-vector-icons/Feather';
4
+ import {PDV_DEVICE_TYPE} from '@controleonline/ui-common/src/react/utils/printerDevices';
5
+ import {
6
+ findDeviceConfigByType,
7
+ isCurrentDeviceGroup,
8
+ } from '../currentDevice';
9
+ import {withOpacity} from '@controleonline/../../src/styles/branding';
10
+ import {
11
+ getDeviceConfigType,
12
+ isManagedNetworkDeviceType,
13
+ normalizeDeviceId,
14
+ getDeviceListIdentifier,
15
+ getDeviceTypeAccent,
16
+ getDeviceBadgeLabel,
17
+ getDeviceIconName,
18
+ getDeviceItemTypeLabel,
19
+ getPrinterConnectivityMeta,
20
+ getPosStatusLabel,
21
+ getPosOperationModeLabel,
22
+ isPdvPrinterEnabled,
23
+ isPosDeviceOpen,
24
+ parseConfigsObject,
25
+ tt,
26
+ } from './deviceListHelpers';
27
+ import styles from '../../Devices.styles';
28
+
29
+ export default function DeviceGroupCard({
30
+ item: deviceGroup,
31
+ brandColors,
32
+ creatingPdv,
33
+ goToDetail,
34
+ handleCreateCurrentPdv,
35
+ networkConnectivityByDevice,
36
+ queryTypes = [],
37
+ runtimeDeviceIdentifier,
38
+ runtimeDeviceType,
39
+ showCurrentPdvSetup,
40
+ }) {
41
+ const isCurrentDevice = isCurrentDeviceGroup({
42
+ deviceGroup,
43
+ runtimeDeviceIdentifier,
44
+ });
45
+ const sessionConfig = isCurrentDevice
46
+ ? findDeviceConfigByType(deviceGroup, runtimeDeviceType)
47
+ : null;
48
+ const filteredTypeConfig =
49
+ queryTypes.length === 1
50
+ ? findDeviceConfigByType(deviceGroup, queryTypes[0])
51
+ : null;
52
+ const primaryConfig =
53
+ sessionConfig ||
54
+ filteredTypeConfig ||
55
+ deviceGroup.deviceConfigs[0] ||
56
+ null;
57
+ const normalizedType = primaryConfig
58
+ ? getDeviceConfigType(primaryConfig)
59
+ : runtimeDeviceType || 'DEVICE';
60
+ const isManagedNetwork =
61
+ primaryConfig && isManagedNetworkDeviceType(normalizedType);
62
+ const isPdv = normalizedType === PDV_DEVICE_TYPE;
63
+ const alias =
64
+ deviceGroup.device?.alias ||
65
+ deviceGroup.device?.device ||
66
+ 'Dispositivo';
67
+ const deviceIdentifier = primaryConfig
68
+ ? getDeviceListIdentifier(primaryConfig)
69
+ : String(deviceGroup.device?.device || runtimeDeviceIdentifier).trim();
70
+ const deviceKey = normalizeDeviceId(
71
+ deviceGroup.device?.device ||
72
+ deviceGroup.device?.id ||
73
+ deviceGroup.key,
74
+ );
75
+ const accent = getDeviceTypeAccent(normalizedType);
76
+ const metaChips = [];
77
+
78
+ if (isPdv && primaryConfig) {
79
+ const posOperationModeLabel = getPosOperationModeLabel(
80
+ primaryConfig?.configs,
81
+ );
82
+
83
+ if (posOperationModeLabel) {
84
+ metaChips.push(posOperationModeLabel);
85
+ }
86
+
87
+ metaChips.push(
88
+ `Impressora ${isPdvPrinterEnabled(primaryConfig) ? 'Sim' : 'Nao'}`,
89
+ );
90
+ metaChips.push(getPosStatusLabel(primaryConfig));
91
+ }
92
+
93
+ if (isManagedNetwork) {
94
+ metaChips.push(
95
+ getPrinterConnectivityMeta(
96
+ networkConnectivityByDevice?.[deviceKey]?.status,
97
+ ).label,
98
+ );
99
+ }
100
+
101
+ return (
102
+ <View
103
+ testID={`device-group-${deviceGroup.key}`}
104
+ accessibilityLabel={
105
+ isCurrentDevice
106
+ ? `${alias}, ${tt('device_label', 'currentDevice') || 'Este dispositivo'}`
107
+ : alias
108
+ }
109
+ style={[
110
+ styles.deviceCard,
111
+ isCurrentDevice && styles.deviceCardCurrent,
112
+ ]}>
113
+ <View style={styles.cardLeft}>
114
+ <View
115
+ style={[
116
+ styles.iconBox,
117
+ {backgroundColor: withOpacity(accent, 0.1)},
118
+ ]}>
119
+ <Icon
120
+ name={getDeviceIconName(normalizedType)}
121
+ size={18}
122
+ color={accent}
123
+ />
124
+ </View>
125
+ <View style={styles.cardTextWrap}>
126
+ {isCurrentDevice ? (
127
+ <View
128
+ testID="current-device-badge"
129
+ style={styles.currentDeviceBadge}>
130
+ <Icon
131
+ name="crosshair"
132
+ size={11}
133
+ color={
134
+ brandColors.badgeSelectedText ||
135
+ brandColors.cardSelectedText ||
136
+ brandColors.primary
137
+ }
138
+ />
139
+ <Text style={styles.currentDeviceBadgeText}>
140
+ {tt('device_label', 'currentDevice') ||
141
+ 'Este dispositivo'}
142
+ </Text>
143
+ </View>
144
+ ) : null}
145
+ <Text style={styles.deviceTitle} numberOfLines={1}>
146
+ {alias}
147
+ </Text>
148
+ <Text style={styles.deviceSub} numberOfLines={1}>
149
+ {deviceIdentifier}
150
+ </Text>
151
+
152
+ <View style={styles.deviceConfigRow}>
153
+ {deviceGroup.deviceConfigs.map(deviceConfig => {
154
+ const configType = getDeviceConfigType(deviceConfig);
155
+ const configAccent = getDeviceTypeAccent(configType);
156
+ const isSessionConfig =
157
+ isCurrentDevice &&
158
+ runtimeDeviceType &&
159
+ configType === runtimeDeviceType;
160
+
161
+ return (
162
+ <TouchableOpacity
163
+ key={String(deviceConfig.id)}
164
+ testID={`device-config-${deviceConfig.id}`}
165
+ dataSet={{
166
+ sessionConfig: isSessionConfig ? 'true' : 'false',
167
+ }}
168
+ accessibilityRole="button"
169
+ accessibilityLabel={`${getDeviceItemTypeLabel(configType)}${
170
+ isSessionConfig ? ', Em uso nesta sessao' : ''
171
+ }`}
172
+ activeOpacity={0.82}
173
+ style={[
174
+ styles.deviceConfigChip,
175
+ {
176
+ backgroundColor: withOpacity(configAccent, 0.1),
177
+ borderColor: withOpacity(configAccent, 0.45),
178
+ },
179
+ isSessionConfig && styles.deviceConfigChipActive,
180
+ ]}
181
+ onPress={() => goToDetail(deviceConfig)}>
182
+ <View
183
+ style={[
184
+ styles.dot,
185
+ {backgroundColor: configAccent},
186
+ ]}
187
+ />
188
+ <Text
189
+ style={[
190
+ styles.deviceConfigChipText,
191
+ {color: configAccent},
192
+ ]}>
193
+ {getDeviceBadgeLabel(configType, deviceConfig)}
194
+ </Text>
195
+ {isSessionConfig ? (
196
+ <Text style={styles.deviceConfigChipActiveText}>
197
+ {tt('device_label', 'inUse') || 'Em uso'}
198
+ </Text>
199
+ ) : null}
200
+ <Icon
201
+ name="chevron-right"
202
+ size={13}
203
+ color={configAccent}
204
+ />
205
+ </TouchableOpacity>
206
+ );
207
+ })}
208
+
209
+ {isCurrentDevice && showCurrentPdvSetup ? (
210
+ <TouchableOpacity
211
+ testID="configure-current-device-pdv"
212
+ accessibilityRole="button"
213
+ accessibilityLabel={
214
+ tt('device_action', 'configureCurrentAsPdv') ||
215
+ 'Configurar este dispositivo como PDV'
216
+ }
217
+ activeOpacity={0.82}
218
+ disabled={creatingPdv}
219
+ style={[
220
+ styles.deviceConfigCreateChip,
221
+ creatingPdv &&
222
+ styles.currentPdvSetupButtonDisabled,
223
+ ]}
224
+ onPress={handleCreateCurrentPdv}>
225
+ <Icon
226
+ name="plus-circle"
227
+ size={15}
228
+ color={brandColors.buttonText || brandColors.white}
229
+ />
230
+ <Text style={styles.deviceConfigCreateChipText}>
231
+ {creatingPdv
232
+ ? tt('device_action', 'configuringPdv') ||
233
+ 'Configurando...'
234
+ : tt('device_action', 'configureAsPdv') ||
235
+ 'Configurar como PDV'}
236
+ </Text>
237
+ </TouchableOpacity>
238
+ ) : null}
239
+ </View>
240
+
241
+ {metaChips.length > 0 ? (
242
+ <View style={styles.deviceMetaRow}>
243
+ {metaChips.map(chipLabel => (
244
+ <View key={chipLabel} style={styles.deviceMetaChip}>
245
+ <Text style={styles.deviceMetaChipText}>
246
+ {chipLabel}
247
+ </Text>
248
+ </View>
249
+ ))}
250
+ </View>
251
+ ) : null}
252
+ </View>
253
+ </View>
254
+ </View>
255
+ );
256
+
257
+ }
@@ -0,0 +1,23 @@
1
+ import {createDeviceTypeTab} from './shared';
2
+
3
+ const emptyState = {
4
+ icon: 'monitor',
5
+ title: 'Nenhum dispositivo encontrado',
6
+ description: 'Cadastre dispositivos para visualizar os equipamentos da empresa.',
7
+ };
8
+
9
+ const allDeviceType = {
10
+ key: 'ALL',
11
+ label: 'Todos',
12
+ icon: 'layers',
13
+ shouldDisplay: () => true,
14
+ getAccent: ({brandColors, hex}) => brandColors?.primary || hex.primary,
15
+ getEmptyState: () => emptyState,
16
+ TabComponent: createDeviceTypeTab({
17
+ label: 'Todos os dispositivos',
18
+ emptyState,
19
+ offerCurrentPdvSetup: true,
20
+ }),
21
+ };
22
+
23
+ export default allDeviceType;
@@ -0,0 +1,25 @@
1
+ import {createDeviceTypeTab} from './shared';
2
+
3
+ const emptyState = {
4
+ icon: 'cpu',
5
+ title: 'Nenhum device encontrado',
6
+ description: 'A empresa ativa ainda nao possui devices cadastrados neste filtro.',
7
+ };
8
+
9
+ const deviceDeviceType = {
10
+ key: 'DEVICE',
11
+ label: 'Devices',
12
+ itemLabel: 'Device',
13
+ icon: 'cpu',
14
+ matches: type => String(type || '').trim().toUpperCase() === 'DEVICE',
15
+ shouldDisplay: () => true,
16
+ getAccent: ({hex}) => hex.warning,
17
+ getEmptyState: () => emptyState,
18
+ TabComponent: createDeviceTypeTab({
19
+ label: 'Devices',
20
+ queryTypes: ['DEVICE'],
21
+ emptyState,
22
+ }),
23
+ };
24
+
25
+ export default deviceDeviceType;
@@ -0,0 +1,178 @@
1
+ import {
2
+ getPosOperationModeOption,
3
+ isPosCashRegisterOpen,
4
+ parseConfigsObject,
5
+ resolvePosOperationMode,
6
+ } from '@controleonline/ui-common/src/react/config/deviceConfigBootstrap';
7
+ import {
8
+ DEFAULT_NETWORK_PRINTER_PORT,
9
+ DISPLAY_DEVICE_TYPE,
10
+ getDeviceConfigType,
11
+ getDeviceTypeLabel,
12
+ getPrinterHost,
13
+ IP_CAMERA_DEVICE_TYPE,
14
+ NETWORK_PRINTER_PORT_CONFIG_KEY,
15
+ PDV_DEVICE_TYPE,
16
+ isManagedNetworkDeviceType,
17
+ isPrinterDeviceType,
18
+ normalizeDeviceType,
19
+ normalizePrinterPort,
20
+ } from '@controleonline/ui-common/src/react/utils/printerDevices';
21
+ import {
22
+ getPaymentGateway,
23
+ getPaymentGatewayLabel,
24
+ isPdvPrinterEnabled,
25
+ normalizeDeviceId,
26
+ normalizeEntityId,
27
+ } from '@controleonline/ui-common/src/react/utils/paymentDevices';
28
+ import {getRuntimeFooterDebugInfo} from '@controleonline/ui-common/src/react/utils/runtimeFooter';
29
+
30
+ export const PAGE_SIZE = 20;
31
+ export const API_PAGE_SIZE = 200;
32
+
33
+ export const tt = (type, key) => global.t?.t('configs', type, key);
34
+
35
+ export const hex = {
36
+ primary: '#0EA5E9',
37
+ success: '#10b981',
38
+ danger: '#c10015',
39
+ warning: '#e67e22',
40
+ };
41
+
42
+ export const mergeDeviceConfigs = (currentItems = [], nextItems = []) => {
43
+ const currentList = Array.isArray(currentItems) ? currentItems : [];
44
+ const nextList = Array.isArray(nextItems) ? nextItems : [];
45
+ const seenIds = new Set(currentList.map(item => String(item?.id || '')));
46
+
47
+ return [
48
+ ...currentList,
49
+ ...nextList.filter(item => {
50
+ const itemId = String(item?.id || '');
51
+ if (!itemId || seenIds.has(itemId)) {
52
+ return false;
53
+ }
54
+ seenIds.add(itemId);
55
+ return true;
56
+ }),
57
+ ];
58
+ };
59
+
60
+ export const isPosDeviceOpen = deviceConfig => {
61
+ const configs = parseConfigsObject(deviceConfig?.configs);
62
+ return isPosCashRegisterOpen(configs);
63
+ };
64
+
65
+ export const getPrinterConnectivityMeta = status => {
66
+ if (status === 'online') {
67
+ return {label: tt('device_status', 'online') || 'Online', tone: 'success'};
68
+ }
69
+ if (status === 'checking') {
70
+ return {label: tt('device_status', 'checking') || 'Verificando...', tone: 'warning'};
71
+ }
72
+ if (status === 'unsupported') {
73
+ return {
74
+ label: tt('device_status', 'unsupported') || 'Sem suporte runtime',
75
+ tone: 'warning',
76
+ };
77
+ }
78
+ return {label: tt('device_status', 'offline') || 'Offline', tone: 'danger'};
79
+ };
80
+
81
+ export const getDeviceIconName = type => {
82
+ const normalizedType = normalizeDeviceType(type);
83
+ if (normalizedType === PDV_DEVICE_TYPE) return 'smartphone';
84
+ if (normalizedType === DISPLAY_DEVICE_TYPE) return 'monitor';
85
+ if (isPrinterDeviceType(normalizedType)) return 'printer';
86
+ if (normalizedType === IP_CAMERA_DEVICE_TYPE) return 'camera';
87
+ return 'cpu';
88
+ };
89
+
90
+ export const getDeviceItemTypeLabel = type => {
91
+ const normalizedType = normalizeDeviceType(type);
92
+ return getDeviceTypeLabel(normalizedType) || normalizedType || 'Device';
93
+ };
94
+
95
+ export const getDeviceBadgeLabel = (type, deviceConfig) => {
96
+ const normalizedType = normalizeDeviceType(type);
97
+ if (normalizedType === PDV_DEVICE_TYPE) {
98
+ const gateway = getPaymentGateway(parseConfigsObject(deviceConfig?.configs));
99
+ return getPaymentGatewayLabel(gateway) || 'PDV';
100
+ }
101
+ return getDeviceItemTypeLabel(normalizedType);
102
+ };
103
+
104
+ export const getDeviceTypeAccent = type => {
105
+ const normalizedType = normalizeDeviceType(type);
106
+ if (normalizedType === PDV_DEVICE_TYPE) return hex.primary;
107
+ if (normalizedType === DISPLAY_DEVICE_TYPE) return hex.success;
108
+ if (isPrinterDeviceType(normalizedType)) return hex.warning;
109
+ if (normalizedType === IP_CAMERA_DEVICE_TYPE) return hex.danger;
110
+ return hex.primary;
111
+ };
112
+
113
+ export const getPosStatusLabel = deviceConfig =>
114
+ isPosDeviceOpen(deviceConfig)
115
+ ? tt('device_status', 'open') || 'Aberto'
116
+ : tt('device_status', 'closed') || 'Fechado';
117
+
118
+ export const getPosOperationModeLabel = configs => {
119
+ const mode = resolvePosOperationMode(configs);
120
+ const option = getPosOperationModeOption(mode);
121
+ return option?.label || mode || '';
122
+ };
123
+
124
+ export const getDeviceDetailRoute = type => {
125
+ const normalizedType = normalizeDeviceType(type);
126
+ if (normalizedType === IP_CAMERA_DEVICE_TYPE) {
127
+ return 'IpCameraDetail';
128
+ }
129
+ if (isPrinterDeviceType(normalizedType)) {
130
+ return 'PrinterDeviceDetail';
131
+ }
132
+ return 'DeviceDetail';
133
+ };
134
+
135
+ export const getDeviceListIdentifier = deviceConfig =>
136
+ getRuntimeFooterDebugInfo({
137
+ device: deviceConfig?.device || {},
138
+ deviceConfig,
139
+ }).runtimeDetail || String(deviceConfig?.device?.device || '').trim();
140
+
141
+ export const buildDeviceListParams = ({
142
+ companyId,
143
+ page,
144
+ pageSize = PAGE_SIZE,
145
+ queryTypes = [],
146
+ }) => {
147
+ const params = {
148
+ people: `/people/${companyId}`,
149
+ page,
150
+ itemsPerPage: pageSize,
151
+ 'order[id]': 'DESC',
152
+ };
153
+
154
+ if (Array.isArray(queryTypes) && queryTypes.length === 1) {
155
+ params.type = queryTypes[0];
156
+ }
157
+
158
+ if (Array.isArray(queryTypes) && queryTypes.length > 1) {
159
+ params.type = queryTypes;
160
+ }
161
+
162
+ return params;
163
+ };
164
+
165
+ export {
166
+ parseConfigsObject,
167
+ getDeviceConfigType,
168
+ isManagedNetworkDeviceType,
169
+ isPrinterDeviceType,
170
+ normalizeDeviceType,
171
+ normalizeDeviceId,
172
+ normalizeEntityId,
173
+ getPrinterHost,
174
+ normalizePrinterPort,
175
+ DEFAULT_NETWORK_PRINTER_PORT,
176
+ NETWORK_PRINTER_PORT_CONFIG_KEY,
177
+ isPdvPrinterEnabled,
178
+ };
@@ -0,0 +1,26 @@
1
+ import {DISPLAY_DEVICE_TYPE, normalizeDeviceType} from '@controleonline/ui-common/src/react/utils/printerDevices';
2
+ import {createDeviceTypeTab} from './shared';
3
+
4
+ const emptyState = {
5
+ icon: 'monitor',
6
+ title: 'Nenhum kds encontrado',
7
+ description: 'A empresa ativa ainda nao possui devices cadastrados neste filtro.',
8
+ };
9
+
10
+ const displayDeviceType = {
11
+ key: DISPLAY_DEVICE_TYPE,
12
+ label: 'KDS',
13
+ itemLabel: 'KDS',
14
+ icon: 'monitor',
15
+ matches: type => normalizeDeviceType(type) === DISPLAY_DEVICE_TYPE,
16
+ shouldDisplay: () => true,
17
+ getAccent: ({brandColors, hex}) => brandColors?.primary || hex.primary,
18
+ getEmptyState: () => emptyState,
19
+ TabComponent: createDeviceTypeTab({
20
+ label: 'KDS',
21
+ queryTypes: [DISPLAY_DEVICE_TYPE],
22
+ emptyState,
23
+ }),
24
+ };
25
+
26
+ export default displayDeviceType;
@@ -0,0 +1,145 @@
1
+ import {getDeviceTypeLabel, normalizeDeviceType} from '@controleonline/ui-common/src/react/utils/printerDevices';
2
+
3
+ import allDeviceType from './all';
4
+ import deviceDeviceType from './device';
5
+ import displayDeviceType from './display';
6
+ import ipCameraDeviceType from './ipCamera';
7
+ import pdvDeviceType, {
8
+ PDV_SUBFILTER_KEYS,
9
+ pdvCieloDeviceType,
10
+ pdvInfinitePayDeviceType,
11
+ } from './pdv';
12
+ import printerDeviceType from './printer';
13
+ import {createDeviceTypeTab} from './shared';
14
+
15
+ const registeredDeviceTypes = [
16
+ allDeviceType,
17
+ pdvDeviceType,
18
+ pdvCieloDeviceType,
19
+ pdvInfinitePayDeviceType,
20
+ displayDeviceType,
21
+ printerDeviceType,
22
+ ipCameraDeviceType,
23
+ deviceDeviceType,
24
+ ];
25
+ const visibleDeviceTypes = registeredDeviceTypes.filter(
26
+ deviceType => !PDV_SUBFILTER_KEYS.includes(deviceType.key),
27
+ );
28
+ const pdvSubfilterDeviceTypes = registeredDeviceTypes.filter(deviceType =>
29
+ PDV_SUBFILTER_KEYS.includes(deviceType.key),
30
+ );
31
+
32
+ const deviceTypesByKey = registeredDeviceTypes.reduce((acc, deviceType) => {
33
+ acc[deviceType.key] = deviceType;
34
+ return acc;
35
+ }, {});
36
+
37
+ const matchedDeviceTypes = [
38
+ pdvDeviceType,
39
+ displayDeviceType,
40
+ printerDeviceType,
41
+ ipCameraDeviceType,
42
+ deviceDeviceType,
43
+ ];
44
+
45
+ export const ALL_DEVICE_FILTER = allDeviceType.key;
46
+ export const PRINTER_DEVICE_FILTER = printerDeviceType.key;
47
+
48
+ const createRuntimeDeviceType = filterKey => {
49
+ const normalizedType = normalizeDeviceType(filterKey);
50
+ const emptyState = {
51
+ icon: 'cpu',
52
+ title: `Nenhum ${getDeviceTypeLabel(normalizedType).toLowerCase()} encontrado`,
53
+ description:
54
+ 'A empresa ativa ainda nao possui devices cadastrados neste filtro.',
55
+ };
56
+
57
+ return {
58
+ key: normalizedType,
59
+ label: getDeviceTypeLabel(normalizedType),
60
+ itemLabel: getDeviceTypeLabel(normalizedType),
61
+ icon: 'cpu',
62
+ shouldDisplay: () => true,
63
+ getAccent: ({hex}) => hex.warning,
64
+ getEmptyState: () => emptyState,
65
+ TabComponent: createDeviceTypeTab({
66
+ label: getDeviceTypeLabel(normalizedType),
67
+ queryTypes: [normalizedType],
68
+ emptyState,
69
+ }),
70
+ };
71
+ };
72
+
73
+ const resolveDeviceTypeDefinition = type => {
74
+ const normalizedType = normalizeDeviceType(type);
75
+
76
+ if (!normalizedType) {
77
+ return deviceDeviceType;
78
+ }
79
+
80
+ return (
81
+ matchedDeviceTypes.find(deviceType => deviceType.matches(normalizedType)) ||
82
+ createRuntimeDeviceType(normalizedType)
83
+ );
84
+ };
85
+
86
+ export const resolveDeviceFilterKey = type =>
87
+ resolveDeviceTypeDefinition(type).key;
88
+
89
+ export const getDeviceFilterDefinition = filterKey =>
90
+ deviceTypesByKey[filterKey] || createRuntimeDeviceType(filterKey);
91
+
92
+ export const hasRegisteredDeviceFilter = filterKey => Boolean(deviceTypesByKey[filterKey]);
93
+
94
+ export const isPdvSubfilter = filterKey => PDV_SUBFILTER_KEYS.includes(filterKey);
95
+
96
+ export const getDeviceFilterIcon = filterKey =>
97
+ getDeviceFilterDefinition(filterKey).icon;
98
+
99
+ export const getDeviceFilterAccent = (filterKey, context = {}) =>
100
+ getDeviceFilterDefinition(filterKey).getAccent(context);
101
+
102
+ export const getDeviceDetailRoute = type =>
103
+ resolveDeviceTypeDefinition(type).detailRouteName || 'DeviceDetail';
104
+
105
+ export const getDeviceCreationAction = filterKey => {
106
+ const deviceType = getDeviceFilterDefinition(filterKey);
107
+
108
+ if (!deviceType.createRouteName) {
109
+ return null;
110
+ }
111
+
112
+ return {
113
+ routeName: deviceType.createRouteName,
114
+ label: deviceType.createActionLabel,
115
+ helperText: deviceType.createHelperText,
116
+ };
117
+ };
118
+
119
+ export const getDeviceItemTypeLabel = type => {
120
+ const normalizedType = normalizeDeviceType(type);
121
+ const deviceType = resolveDeviceTypeDefinition(normalizedType);
122
+
123
+ return deviceType.itemLabel || getDeviceTypeLabel(normalizedType);
124
+ };
125
+
126
+ export const getDeviceFilterOptions = () =>
127
+ visibleDeviceTypes
128
+ .filter(deviceType => deviceType.shouldDisplay())
129
+ .map(deviceType => ({
130
+ key: deviceType.key,
131
+ label: deviceType.label,
132
+ icon: deviceType.icon,
133
+ }));
134
+
135
+ export const getPdvSubfilterOptions = () =>
136
+ pdvSubfilterDeviceTypes
137
+ .filter(deviceType => deviceType.shouldDisplay())
138
+ .map(deviceType => ({
139
+ key: deviceType.key,
140
+ label: deviceType.label,
141
+ icon: deviceType.icon,
142
+ }));
143
+
144
+ export const getDeviceEmptyState = ({activeFilter} = {}) =>
145
+ getDeviceFilterDefinition(activeFilter).getEmptyState();
@@ -0,0 +1,35 @@
1
+ import {getNetworkDeviceProfile} from '@controleonline/ui-common/src/react/utils/networkDeviceProfiles';
2
+ import {
3
+ IP_CAMERA_DEVICE_TYPE,
4
+ normalizeDeviceType,
5
+ } from '@controleonline/ui-common/src/react/utils/printerDevices';
6
+ import {createDeviceTypeTab} from './shared';
7
+
8
+ const ipCameraProfile = getNetworkDeviceProfile(IP_CAMERA_DEVICE_TYPE);
9
+ const emptyState = {
10
+ icon: ipCameraProfile.icon,
11
+ title: ipCameraProfile.emptyTitle,
12
+ description: ipCameraProfile.emptyDescription,
13
+ };
14
+
15
+ const ipCameraDeviceType = {
16
+ key: ipCameraProfile.filterKey,
17
+ label: ipCameraProfile.filterLabel,
18
+ itemLabel: ipCameraProfile.itemLabel,
19
+ icon: ipCameraProfile.icon,
20
+ matches: type => normalizeDeviceType(type) === IP_CAMERA_DEVICE_TYPE,
21
+ shouldDisplay: () => true,
22
+ getAccent: ({brandColors, hex}) => brandColors?.primary || hex.primary,
23
+ getEmptyState: () => emptyState,
24
+ detailRouteName: ipCameraProfile.detailRouteName,
25
+ createRouteName: ipCameraProfile.formRouteName,
26
+ createActionLabel: ipCameraProfile.createActionLabel,
27
+ createHelperText: ipCameraProfile.createHelperText,
28
+ TabComponent: createDeviceTypeTab({
29
+ label: ipCameraProfile.filterLabel,
30
+ queryTypes: [IP_CAMERA_DEVICE_TYPE],
31
+ emptyState,
32
+ }),
33
+ };
34
+
35
+ export default ipCameraDeviceType;