@controleonline/ui-common 1.2.71 → 1.2.76
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.
- package/.github/actions/workers/manager/action.yml +147 -0
- package/.github/actions/workers/qa/action.yml +44 -0
- package/.github/actions/workers/security/action.yml +44 -0
- package/.github/actions/workers/technical-documenter/action.yml +51 -0
- package/.github/workflows/manager-worker.yml +168 -0
- package/.github/workflows/publish-npm.yml +45 -0
- package/.gitmodules +3 -0
- package/AGENTS.md +6 -0
- package/README.md +14 -0
- package/package.json +3 -2
- package/src/api/fetch.js +1 -1
- package/src/api/index.js +92 -22
- package/src/react/components/AddImportModal.js +94 -110
- package/src/react/components/BottomNavigationBar.config.js +211 -231
- package/src/react/components/CategoryForm.js +52 -35
- package/src/react/components/DefaultProvider.native.js +131 -95
- package/src/react/components/DefaultProvider.web.js +148 -74
- package/src/react/components/NetworkPrinterPreviewModal.js +249 -0
- package/src/react/components/NetworkPrinterPreviewModal.styles.js +159 -0
- package/src/react/components/RuntimeInfoFooter.js +164 -104
- package/src/react/components/RuntimeInfoFooter.styles.js +3 -0
- package/src/react/components/UnifiedPaymentBar.js +7 -4
- package/src/react/components/UserAvatar.js +160 -0
- package/src/react/components/integrations/IntegrationHero/index.js +48 -0
- package/src/react/components/integrations/IntegrationHero/styles.js +57 -0
- package/src/react/components/integrations/IntegrationTabs/index.js +89 -0
- package/src/react/components/integrations/IntegrationTabs/styles.js +44 -0
- package/src/react/config/deviceConfigBootstrap.js +5 -3
- package/src/react/pages/Connections.js +229 -0
- package/src/react/pages/Connections.styles.js +222 -0
- package/src/react/pages/DeviceDetailPage.js +2865 -0
- package/src/react/pages/DeviceDetailPage.styles.js +308 -0
- package/src/react/pages/Devices/currentDevice.js +194 -0
- package/src/react/pages/Devices/deviceTypes/DeviceGroupCard.js +257 -0
- package/src/react/pages/Devices/deviceTypes/all.js +23 -0
- package/src/react/pages/Devices/deviceTypes/device.js +25 -0
- package/src/react/pages/Devices/deviceTypes/deviceListHelpers.js +178 -0
- package/src/react/pages/Devices/deviceTypes/display.js +26 -0
- package/src/react/pages/Devices/deviceTypes/index.js +145 -0
- package/src/react/pages/Devices/deviceTypes/ipCamera.js +35 -0
- package/src/react/pages/Devices/deviceTypes/pdv.js +88 -0
- package/src/react/pages/Devices/deviceTypes/printer.js +37 -0
- package/src/react/pages/Devices/deviceTypes/shared.js +453 -0
- package/src/react/pages/Devices/deviceTypes/useDeviceNetworkConnectivity.js +145 -0
- package/src/react/pages/Devices.js +183 -0
- package/src/react/pages/Devices.styles.js +353 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99CatalogTab.js +219 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99OverviewTab.js +134 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99PreviewModal.js +173 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99ProductCard.js +1 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99QuickWalletModal.js +181 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99SettingsTab.js +306 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99StoreTab.js +417 -0
- package/src/react/pages/Food99IntegrationPage/index.js +1530 -0
- package/src/react/pages/Food99IntegrationPage/styles.js +792 -0
- package/src/react/pages/Food99IntegrationPage/utils.js +155 -0
- package/src/react/pages/Food99IntegrationPage.js +1 -0
- package/src/react/pages/Food99IntegrationPage.styles.js +1 -0
- package/src/react/pages/GenericLogPage.js +42 -167
- package/src/react/pages/IFoodIntegrationPage/components/IFoodCatalogTab.js +8 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodOperationsTab.js +420 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodOverviewTab.js +118 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodPreviewModal.js +103 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodProductCard.js +1 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodStoreTab.js +150 -0
- package/src/react/pages/IFoodIntegrationPage/index.js +1298 -0
- package/src/react/pages/IFoodIntegrationPage/styles.js +764 -0
- package/src/react/pages/IFoodIntegrationPage/utils.js +91 -0
- package/src/react/pages/IFoodIntegrationPage.js +1 -0
- package/src/react/pages/IFoodIntegrationPage.styles.js +1 -0
- package/src/react/pages/Imports.js +214 -166
- package/src/react/pages/IntegrationConfigPage.js +744 -0
- package/src/react/pages/IntegrationConfigPage.styles.js +269 -0
- package/src/react/pages/Integrations.js +299 -0
- package/src/react/pages/Integrations.styles.js +130 -0
- package/src/react/pages/ManagerOrderNotificationsPage.js +642 -0
- package/src/react/pages/MarketplaceIntegrationPage/components/MarketplaceProductCard.js +205 -0
- package/src/react/pages/MarketplaceIntegrationPage/components/RemoteMarketplaceMenuTab.js +335 -0
- package/src/react/pages/MarketplaceIntegrationPage/index.js +60 -0
- package/src/react/pages/MarketplaceIntegrationPage/utils.js +137 -0
- package/src/react/pages/MercadoLivreIntegrationPage.js +538 -0
- package/src/react/pages/PrinterDeviceDetailPage.js +1916 -0
- package/src/react/pages/PrinterDeviceDetailPage.styles.js +223 -0
- package/src/react/pages/PrinterDeviceFormPage.js +521 -0
- package/src/react/pages/PrinterDeviceFormPage.styles.js +159 -0
- package/src/react/pages/WhatsAppConnectionPage.js +459 -0
- package/src/react/pages/WhatsAppConnectionPage.styles.js +284 -0
- package/src/react/pages/integrationsCatalog.js +399 -0
- package/src/react/services/Cielo/Cielo.js +193 -193
- package/src/react/utils/categoryContexts.js +46 -0
- package/src/react/utils/entityDisplay.js +222 -217
- package/src/react/utils/fileUrl.js +39 -20
- package/src/react/utils/integrationPage.js +16 -0
- package/src/react/utils/runtimeFooter.js +40 -22
- package/src/react/utils/runtimeLanguage.js +50 -9
- package/src/react/utils/runtimeMenu.js +191 -131
- package/src/react/utils/runtimeZoom.js +43 -0
- package/src/react/utils/shopConfig.js +27 -15
- package/src/react/utils/shopFranchises.js +126 -1
- package/src/react/utils/storeColumns.js +23 -4
- package/src/react/utils/userAvatar.js +104 -0
- package/src/store/categories/index.js +48 -20
- package/src/store/device_config/index.js +62 -21
- package/src/store/entity_log/index.js +22 -1
- package/src/store/imports/customActions.js +51 -0
- package/src/store/imports/index.js +89 -88
- package/src/store/status/index.js +11 -11
- package/src/store/themes/index.js +22 -0
- package/src/store/timezones/index.js +3 -1
- package/src/tests/browser/manager/connections.spec.js +143 -0
- package/src/tests/browser/manager/devices-current.spec.js +343 -0
- package/src/tests/browser/manager/mercado-livre-integration.spec.js +268 -0
- package/src/tests/react/api/deviceHeaders.test.js +114 -0
- package/src/tests/react/components/AddImportModal.test.js +166 -0
- package/src/tests/react/components/BottomNavigationBar.config.test.js +20 -0
- package/src/tests/react/components/UserAvatar.test.js +52 -0
- package/src/tests/react/pages/DevicePickerStyles.test.js +47 -0
- package/src/tests/react/pages/Devices/deviceListHelpers.test.js +39 -0
- package/src/tests/react/pages/DevicesCurrentDevice.test.js +198 -0
- package/src/tests/react/pages/connectionsHelpers.test.js +34 -0
- package/src/tests/react/pages/mercadoLivreIntegrationPageContract.test.mjs +16 -0
- package/src/tests/react/services/Cielo.test.js +190 -190
- package/src/tests/react/store/categoriesOrdering.test.js +26 -0
- package/src/tests/react/utils/appDomain.test.js +62 -0
- package/src/tests/react/utils/entityDisplay.test.js +2 -2
- package/src/tests/react/utils/fileUrl.test.js +3 -3
- package/src/tests/react/utils/formatter.test.mjs +33 -0
- package/src/tests/react/utils/runtimeFooter.test.js +29 -4
- package/src/tests/react/utils/runtimeLanguage.test.js +79 -9
- package/src/tests/react/utils/runtimeMenu.test.js +198 -134
- package/src/tests/react/utils/runtimeZoom.test.js +38 -0
- package/src/tests/react/utils/shopConfig.test.js +10 -9
- package/src/tests/react/utils/shopFranchises.test.js +43 -0
- package/src/tests/react/utils/translate.discovery.test.mjs +170 -0
- package/src/tests/react/utils/translate.test.helpers.mjs +152 -0
- package/src/tests/react/utils/translate.test.mjs +141 -349
- package/src/tests/react/utils/userAvatar.test.js +63 -0
- package/src/utils/appDomain.js +15 -4
- package/src/utils/formatter.js +104 -16
- package/src/utils/integrationConfigs.js +80 -80
- package/src/utils/translate.js +222 -438
- package/src/utils/translateDiscovery.js +96 -0
- package/src/utils/translateNormalize.js +33 -0
- package/src/utils/translatePending.js +92 -0
- package/src/utils/translateStorage.js +142 -0
- package/.github/agents/developer.agent.md +0 -30
- package/.github/agents/devops.agent.md +0 -30
- package/.github/agents/qa.agent.md +0 -30
- package/.github/agents/security.agent.md +0 -30
- 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;
|