@controleonline/ui-common 1.2.87 → 1.2.89
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/workflows/integration-source-gate.yml +68 -0
- package/.github/workflows/manager-worker.yml +7 -156
- package/.github/workflows/publish-npm.yml +73 -27
- package/.github/workflows/pull-request-checks.yml +7 -5
- package/docs/technical/Device-Detail-Alias-UI-Sync.md +141 -0
- package/package.json +13 -8
- package/src/api/localDB.js +86 -131
- package/src/react/components/BottomNavigationBar.js +178 -174
- package/src/react/components/BottomNavigationBar.styles.js +139 -118
- package/src/react/components/DefaultProvider.native.js +427 -421
- package/src/react/components/DefaultProvider.web.js +131 -125
- package/src/react/components/RemoteCheckoutService.js +3 -3
- package/src/react/components/RuntimeFooterMarqueeText.js +88 -36
- package/src/react/components/RuntimeInfoFooter.js +76 -43
- package/src/react/components/RuntimeInfoFooter.styles.js +22 -14
- package/src/react/config/deviceConfigBootstrap.js +71 -233
- package/src/react/config/deviceConfigValues.js +238 -0
- package/src/react/pages/Devices/detail/DeviceChargePermissionSection.js +32 -0
- package/src/react/pages/Devices/detail/DeviceDetailAlertsCommandsSection.js +4 -22
- package/src/react/pages/Devices/detail/DeviceDetailMovementSections.js +6 -2
- package/src/react/pages/Devices/detail/DeviceDetailOrdersPrintSection.js +4 -0
- package/src/react/pages/Devices/detail/DeviceDetailPdvConfigSection.js +7 -0
- package/src/react/pages/Devices/detail/DeviceDetailScreen.js +24 -335
- package/src/react/pages/Devices/detail/createDeviceDetailContext.js +20 -0
- package/src/react/pages/Devices/detail/deviceDetailHelpers.js +2 -11
- package/src/react/pages/Devices/detail/useDeviceDetailActions.js +11 -36
- package/src/react/pages/Devices/detail/useDeviceDetailLoaders.js +129 -37
- package/src/react/pages/Devices/detail/useDeviceDetailSaves.js +11 -38
- package/src/react/pages/Devices/detail/useDeviceDetailStateA.js +9 -28
- package/src/react/pages/IntegrationConfigFields.js +1 -0
- package/src/react/pages/IntegrationConfigPage.js +101 -45
- package/src/react/pages/IntegrationConfigPage.utils.js +21 -13
- package/src/react/pages/fetchPeopleConfigs.js +21 -0
- package/src/react/pages/integrationsCatalog.js +15 -110
- package/src/react/services/Cielo/Cielo.js +9 -9
- package/src/react/services/Getnet/Getnet.web.js +25 -0
- package/src/react/utils/companyAuthority.js +36 -0
- package/src/react/utils/confirmAction.js +12 -0
- package/src/react/utils/fileUrl.js +14 -5
- package/src/react/utils/paymentDevices.js +375 -270
- package/src/react/utils/printerDevices.js +2 -2
- package/src/react/utils/runtimeFooter.js +178 -224
- package/src/react/utils/runtimeFooterText.js +160 -0
- package/src/react/utils/runtimeLanguage.js +5 -5
- package/src/react/utils/runtimeZoom.js +29 -5
- package/src/react/utils/shopFranchises.js +167 -12
- package/src/react/utils/storeColumns.js +235 -217
- package/src/react/utils/systemErrorMessage.js +2 -1
- package/src/store/integration/index.js +43 -0
- package/src/tests/browser/manager/device-detail-apply-config-defined.spec.js +31 -0
- package/src/tests/browser/manager/device-detail-composition.spec.js +295 -0
- package/src/tests/browser/manager/device-detail-copy-config.spec.js +11 -1
- package/src/tests/browser/manager/device-detail-pdv-current-company.spec.js +273 -0
- package/src/tests/browser/manager/runtime-footer-rotation.spec.js +397 -0
- package/src/tests/react/components/DefaultProviderAuthority.test.js +28 -0
- package/src/tests/react/components/RuntimeFooterMarqueeText.build.test.js +29 -0
- package/src/tests/react/config/deviceConfigBootstrap.test.js +24 -1
- package/src/tests/react/pages/DeviceChargePermissionSection.test.js +42 -0
- package/src/tests/react/pages/applyCurrentDeviceConfig.test.js +85 -0
- package/src/tests/react/pages/deviceDetailComposition.test.js +65 -0
- package/src/tests/react/pages/deviceDetailHookDependencies.test.mjs +31 -0
- package/src/tests/react/pages/deviceDetailLoaderDependencies.test.mjs +28 -0
- package/src/tests/react/pages/receitaFederalIntegrationContract.test.mjs +27 -6
- package/src/tests/react/services/Cielo.test.js +2 -2
- package/src/tests/react/utils/companyAuthority.test.js +53 -0
- package/src/tests/react/utils/formatter.test.mjs +6 -0
- package/src/tests/react/utils/paymentDevices.test.js +72 -0
- package/src/tests/react/utils/runtimeFooter.test.js +35 -0
- package/src/tests/react/utils/runtimeFooterText.test.js +88 -0
- package/src/tests/react/utils/runtimeLanguage.test.js +4 -4
- package/src/tests/react/utils/runtimeZoom.test.js +20 -0
- package/src/tests/react/utils/shopFranchises.test.js +32 -13
- package/src/tests/react/utils/translate.test.mjs +6 -6
- package/src/utils/formatter.js +7 -3
- package/src/utils/translate.js +16 -16
- package/src/utils/translatePending.js +6 -6
- package/src/utils/translateStorage.js +2 -2
|
@@ -1,44 +1,16 @@
|
|
|
1
|
-
import { useCallback, useEffect,
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
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';
|
|
1
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
import { useFocusEffect } from '@react-navigation/native';
|
|
3
|
+
|
|
4
|
+
import { canDisplayChangePrinter, DISPLAY_AUTO_PRINT_PRODUCT_CONFIG_KEY, DEVICE_ALERT_SOUND_ENABLED_KEY, DEVICE_ALERT_SOUND_URL_KEY, DEVICE_ORDER_VISIBILITY_DEVICE, DEVICE_RUNTIME_DEBUG_INFO_ENABLED_KEY, isPosAutoPrintEnabled, isTruthyValue, parseConfigsObject, POS_PRODUCT_SHOWCASE_CONFIG_KEY, isAndroidKioskEnabled, isAndroidLauncherEnabled, isPosDeliveryEnabled, resolvePosCheckOrderManagementMode, resolvePosCheckOrderTypeForShop, resolveDeviceOrderVisibility, resolvePosCashManagementMode, resolvePosOperationMode, resolvePosPrintMode } from '@controleonline/ui-common/src/react/config/deviceConfigBootstrap';
|
|
5
|
+
import { filterDeviceConfigsByCompany, getPaymentGatewayFromConfigs, isPdvPrinterEnabled, normalizeDeviceId, normalizeEntityId, ORDER_PAYMENT_DEVICE_CONFIG_KEY } from '@controleonline/ui-common/src/react/utils/paymentDevices';
|
|
37
6
|
|
|
7
|
+
import { DISPLAY_DEVICE_LINK_CONFIG_KEY, DISPLAY_DEVICE_PRINTER_CONFIG_KEY, PDV_TAB_OPERATION, PDV_TAB_ORDERS, PDV_TAB_MOVEMENT } from './deviceDetailConstants';
|
|
8
|
+
|
|
9
|
+
import { api } from '@controleonline/ui-common/src/api';
|
|
38
10
|
|
|
39
11
|
export default function useDeviceDetailLoaders(deps) {
|
|
40
12
|
const {
|
|
41
|
-
navigation, deviceId, deviceConfigStore, messageApi, websocketActions, runtimeCompanyConfigs, showSystemError, loyaltyCouponsEnabled, currentDevice, currentDeviceConfig, deviceString, deviceType,
|
|
13
|
+
navigation, deviceId, deviceConfigStore, messageApi, websocketActions, runtimeCompanyConfigs, showSystemError, loyaltyCouponsEnabled, currentCompany, currentDevice, currentDeviceConfig, deviceString, deviceType,
|
|
42
14
|
normalizedInitialConfigs, initialAlias, isDisplayDevice, isPdvDevice, actionsRef, stampAutoDisableSignatureRef, brandColors, products, setProducts, productShowcases, setProductShowcases, companyDeviceConfigs,
|
|
43
15
|
setCompanyDeviceConfigs, inflowData, setInflowData, configs, setConfigs, loadingConfigData, setLoadingConfigData, loadingCompanyDeviceConfigs, setLoadingCompanyDeviceConfigs, loadingMovementData, setLoadingMovementData, actionLoading,
|
|
44
16
|
setActionLoading, activePdvTab, setActivePdvTab, savingPaymentTarget, setSavingPaymentTarget, savingPdvSettings, setSavingPdvSettings, savingPaymentTypes, setSavingPaymentTypes, savingPosOperationMode, setSavingPosOperationMode, savingProductShowcase,
|
|
@@ -50,7 +22,126 @@ export default function useDeviceDetailLoaders(deps) {
|
|
|
50
22
|
setSavingDisplayPrintingConfig, hasLoadedCurrentConfig, setHasLoadedCurrentConfig, hasLoadedCompanyConfigs, setHasLoadedCompanyConfigs, hasLoadedMovementData, setHasLoadedMovementData, hasLoadedCurrentConfigRef, hasLoadedCompanyConfigsRef, hasLoadedMovementDataRef, hasInitializedPdvTabRef, alias,
|
|
51
23
|
setAlias, editingAlias, setEditingAlias, aliasInput, setAliasInput, savingAlias, setSavingAlias, removingDevice, setRemovingDevice, aliasInputRef, skipAliasSyncFromStoreRef, isOpen,
|
|
52
24
|
hasLocalPaymentGateway, paymentDeviceOptions, displayOptions, printerOptions, selectedPosOperationModeOption, pickerMode, packageVersion, appVersion, runtimeDeviceId, runtimeDeviceType, isEditingRuntimeDevice, resolveDeviceContext,
|
|
25
|
+
displayStore, printerStore,
|
|
53
26
|
} = deps;
|
|
27
|
+
const applyCurrentDeviceConfig = useCallback((scopedItems, context = {}) => {
|
|
28
|
+
const currentDeviceString = String(
|
|
29
|
+
context.deviceString || deviceString || '',
|
|
30
|
+
).trim();
|
|
31
|
+
const currentDeviceType = String(
|
|
32
|
+
context.deviceType || deviceType || '',
|
|
33
|
+
)
|
|
34
|
+
.trim()
|
|
35
|
+
.toUpperCase();
|
|
36
|
+
const currentDeviceConfigId = normalizeEntityId(
|
|
37
|
+
context.deviceId || deviceId,
|
|
38
|
+
);
|
|
39
|
+
const dc = (scopedItems || []).find(d => {
|
|
40
|
+
const currentConfigType = String(d?.type || d?.device?.type || '')
|
|
41
|
+
.trim()
|
|
42
|
+
.toUpperCase();
|
|
43
|
+
const nextDeviceId = normalizeEntityId(
|
|
44
|
+
d?.device?.id ||
|
|
45
|
+
d?.device?.['@id'] ||
|
|
46
|
+
d?.deviceId ||
|
|
47
|
+
d?.device?.deviceId,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
if (currentDeviceConfigId && nextDeviceId === currentDeviceConfigId) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
d?.device?.device === currentDeviceString &&
|
|
56
|
+
currentConfigType === currentDeviceType
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (dc) {
|
|
61
|
+
const nextConfigs = parseConfigsObject(dc.configs);
|
|
62
|
+
actionsRef.current.deviceConfigActions.setItem({
|
|
63
|
+
...dc,
|
|
64
|
+
configs: nextConfigs,
|
|
65
|
+
});
|
|
66
|
+
setConfigs(nextConfigs);
|
|
67
|
+
setDevicePaymentTarget(
|
|
68
|
+
normalizeDeviceId(nextConfigs[ORDER_PAYMENT_DEVICE_CONFIG_KEY]),
|
|
69
|
+
);
|
|
70
|
+
setPdvGateway(getPaymentGatewayFromConfigs(nextConfigs));
|
|
71
|
+
setPdvPrinterEnabled(isPdvPrinterEnabled(nextConfigs));
|
|
72
|
+
setPosOperationMode(resolvePosOperationMode(nextConfigs));
|
|
73
|
+
setProductShowcaseId(
|
|
74
|
+
normalizeEntityId(nextConfigs[POS_PRODUCT_SHOWCASE_CONFIG_KEY]),
|
|
75
|
+
);
|
|
76
|
+
setAndroidKioskEnabled(isAndroidKioskEnabled(nextConfigs));
|
|
77
|
+
setAndroidLauncherEnabled(isAndroidLauncherEnabled(nextConfigs));
|
|
78
|
+
setCounterAutoPrintEnabled(isPosAutoPrintEnabled(nextConfigs));
|
|
79
|
+
setCounterPrintMode(resolvePosPrintMode(nextConfigs));
|
|
80
|
+
setCounterCashManagementMode(resolvePosCashManagementMode(nextConfigs));
|
|
81
|
+
setCheckOrderType(
|
|
82
|
+
resolvePosCheckOrderTypeForShop(nextConfigs, runtimeCompanyConfigs),
|
|
83
|
+
);
|
|
84
|
+
setCheckOrderManagementMode(
|
|
85
|
+
resolvePosCheckOrderManagementMode(nextConfigs),
|
|
86
|
+
);
|
|
87
|
+
setDeviceOrderVisibility(
|
|
88
|
+
resolveDeviceOrderVisibility(nextConfigs),
|
|
89
|
+
);
|
|
90
|
+
setDeviceDeliveryEnabled(
|
|
91
|
+
isPosDeliveryEnabled(nextConfigs),
|
|
92
|
+
);
|
|
93
|
+
setDeviceAlertSoundEnabled(
|
|
94
|
+
isTruthyValue(nextConfigs[DEVICE_ALERT_SOUND_ENABLED_KEY]),
|
|
95
|
+
);
|
|
96
|
+
setDeviceAlertSoundUrl(
|
|
97
|
+
String(nextConfigs[DEVICE_ALERT_SOUND_URL_KEY] || ''),
|
|
98
|
+
);
|
|
99
|
+
setDeviceRuntimeDebugInfoEnabled(
|
|
100
|
+
isTruthyValue(nextConfigs[DEVICE_RUNTIME_DEBUG_INFO_ENABLED_KEY]),
|
|
101
|
+
);
|
|
102
|
+
setLinkedDisplayId(
|
|
103
|
+
normalizeEntityId(nextConfigs[DISPLAY_DEVICE_LINK_CONFIG_KEY]),
|
|
104
|
+
);
|
|
105
|
+
setDisplayPrinterId(
|
|
106
|
+
normalizeDeviceId(nextConfigs[DISPLAY_DEVICE_PRINTER_CONFIG_KEY]),
|
|
107
|
+
);
|
|
108
|
+
setDisplayAllowPrinterChange(
|
|
109
|
+
canDisplayChangePrinter(nextConfigs),
|
|
110
|
+
);
|
|
111
|
+
setDisplayAutoPrintProductEnabled(
|
|
112
|
+
isTruthyValue(nextConfigs[DISPLAY_AUTO_PRINT_PRODUCT_CONFIG_KEY]),
|
|
113
|
+
);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
actionsRef.current.deviceConfigActions.setItem({});
|
|
118
|
+
|
|
119
|
+
setConfigs({});
|
|
120
|
+
setDevicePaymentTarget('');
|
|
121
|
+
setPdvGateway('');
|
|
122
|
+
setPdvPrinterEnabled(true);
|
|
123
|
+
setPosOperationMode(resolvePosOperationMode({}));
|
|
124
|
+
setProductShowcaseId('');
|
|
125
|
+
setAndroidKioskEnabled(false);
|
|
126
|
+
setAndroidLauncherEnabled(false);
|
|
127
|
+
setCounterAutoPrintEnabled(isPosAutoPrintEnabled({}));
|
|
128
|
+
setCounterPrintMode(resolvePosPrintMode({}));
|
|
129
|
+
setCounterCashManagementMode(resolvePosCashManagementMode({}));
|
|
130
|
+
setCheckOrderType(
|
|
131
|
+
resolvePosCheckOrderTypeForShop({}, runtimeCompanyConfigs),
|
|
132
|
+
);
|
|
133
|
+
setCheckOrderManagementMode(resolvePosCheckOrderManagementMode({}));
|
|
134
|
+
setDeviceOrderVisibility(DEVICE_ORDER_VISIBILITY_DEVICE);
|
|
135
|
+
setDeviceDeliveryEnabled(isPosDeliveryEnabled({}));
|
|
136
|
+
setDeviceAlertSoundEnabled(false);
|
|
137
|
+
setDeviceAlertSoundUrl('');
|
|
138
|
+
setDeviceRuntimeDebugInfoEnabled(false);
|
|
139
|
+
setLinkedDisplayId('');
|
|
140
|
+
setDisplayPrinterId('');
|
|
141
|
+
setDisplayAllowPrinterChange(false);
|
|
142
|
+
setDisplayAutoPrintProductEnabled(false);
|
|
143
|
+
}, [deviceId, deviceString, deviceType, runtimeCompanyConfigs]);
|
|
144
|
+
|
|
54
145
|
const loadMovementData = useCallback(async () => {
|
|
55
146
|
if (!isPdvDevice) {
|
|
56
147
|
setProducts([]);
|
|
@@ -317,6 +408,7 @@ export default function useDeviceDetailLoaders(deps) {
|
|
|
317
408
|
);
|
|
318
409
|
|
|
319
410
|
return {
|
|
411
|
+
applyCurrentDeviceConfig,
|
|
320
412
|
loadMovementData,
|
|
321
413
|
refreshCurrentConfig,
|
|
322
414
|
loadCompanyConfigs,
|
|
@@ -1,44 +1,17 @@
|
|
|
1
|
-
import { useCallback,
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
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';
|
|
1
|
+
import { useCallback, useMemo } from 'react';
|
|
2
|
+
|
|
3
|
+
import { DEVICE_ANDROID_LAUNCHER_ENABLED_CONFIG_KEY, DISPLAY_AUTO_PRINT_PRODUCT_CONFIG_KEY, DISPLAY_ALLOW_PRINTER_CHANGE_CONFIG_KEY, DEVICE_ALERT_SOUND_ENABLED_KEY, DEVICE_ALERT_SOUND_URL_KEY, DEVICE_ORDER_VISIBILITY_DEVICE, DEVICE_ORDER_VISIBILITY_KEY, DEVICE_RUNTIME_DEBUG_INFO_ENABLED_KEY, POS_DELIVERY_ENABLED_CONFIG_KEY } from '@controleonline/ui-common/src/react/config/deviceConfigBootstrap';
|
|
4
|
+
import { normalizeDeviceId, PAYMENT_GATEWAY_CIELO } from '@controleonline/ui-common/src/react/utils/paymentDevices';
|
|
37
5
|
|
|
6
|
+
import { hex, DISPLAY_DEVICE_LINK_CONFIG_KEY, DISPLAY_DEVICE_PRINTER_CONFIG_KEY, PDV_TAB_OPERATION, PDV_TAB_ORDERS, PDV_TAB_DEVICE, PDV_TAB_PAYMENT_TYPES, PDV_TAB_MOVEMENT } from './deviceDetailConstants';
|
|
7
|
+
import { confirm } from './deviceDetailHelpers';
|
|
8
|
+
|
|
9
|
+
import { createDeviceDetailRenderers } from './DeviceDetailRenderers';
|
|
38
10
|
|
|
39
11
|
export default function useDeviceDetailSaves(deps) {
|
|
40
12
|
const {
|
|
41
|
-
|
|
13
|
+
themeColors,
|
|
14
|
+
navigation, deviceId, deviceConfigStore, messageApi, websocketActions, runtimeCompanyConfigs, showSystemError, loyaltyCouponsEnabled, currentCompany, currentDevice, currentDeviceConfig, deviceString, deviceType,
|
|
42
15
|
normalizedInitialConfigs, initialAlias, isDisplayDevice, isPdvDevice, actionsRef, stampAutoDisableSignatureRef, brandColors, products, setProducts, productShowcases, setProductShowcases, companyDeviceConfigs,
|
|
43
16
|
setCompanyDeviceConfigs, inflowData, setInflowData, configs, setConfigs, loadingConfigData, setLoadingConfigData, loadingCompanyDeviceConfigs, setLoadingCompanyDeviceConfigs, loadingMovementData, setLoadingMovementData, actionLoading,
|
|
44
17
|
setActionLoading, activePdvTab, setActivePdvTab, savingPaymentTarget, setSavingPaymentTarget, savingPdvSettings, setSavingPdvSettings, savingPaymentTypes, setSavingPaymentTypes, savingPosOperationMode, setSavingPosOperationMode, savingProductShowcase,
|
|
@@ -401,8 +374,8 @@ export default function useDeviceDetailSaves(deps) {
|
|
|
401
374
|
const { renderProduct, renderHelpButton, renderSwitchRow, renderOptionButtons } =
|
|
402
375
|
createDeviceDetailRenderers({ themeColors, palette: brandColors });
|
|
403
376
|
|
|
404
|
-
|
|
405
377
|
return {
|
|
378
|
+
renderProduct, renderHelpButton, renderSwitchRow, renderOptionButtons,
|
|
406
379
|
saveLauncherMode,
|
|
407
380
|
saveDeviceAlertSoundConfig,
|
|
408
381
|
saveDeviceOrderVisibility,
|
|
@@ -5,36 +5,14 @@ import { useMessage } from '@controleonline/ui-common/src/react/components/Messa
|
|
|
5
5
|
import { resolveThemePalette } from '@controleonline/../../src/styles/branding';
|
|
6
6
|
import { colors } from '@controleonline/../../src/styles/colors';
|
|
7
7
|
import packageJson from '@package';
|
|
8
|
-
import {
|
|
9
|
-
|
|
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';
|
|
8
|
+
import { canDisplayChangePrinter, DISPLAY_AUTO_PRINT_PRODUCT_CONFIG_KEY, DEVICE_ALERT_SOUND_ENABLED_KEY, DEVICE_ALERT_SOUND_URL_KEY, DEVICE_RUNTIME_DEBUG_INFO_ENABLED_KEY, isPosAutoPrintEnabled, isTruthyValue, parseConfigsObject, POS_PRODUCT_SHOWCASE_CONFIG_KEY, getPosOperationModeOption, isAndroidKioskEnabled, isAndroidLauncherEnabled, isPosDeliveryEnabled, resolvePosCheckOrderManagementMode, resolvePosCheckOrderTypeForShop, resolveDeviceOrderVisibility, resolvePosCashManagementMode, resolvePosOperationMode, resolvePosPrintMode } from '@controleonline/ui-common/src/react/config/deviceConfigBootstrap';
|
|
9
|
+
import { filterDeviceConfigsByCompany, getCompanyPaymentDeviceOptions, getPaymentGatewayFromConfigs, isPaymentCapableDeviceConfig, isPdvPrinterEnabled, normalizeDeviceId, normalizeEntityId, ORDER_PAYMENT_DEVICE_CONFIG_KEY } from '@controleonline/ui-common/src/react/utils/paymentDevices';
|
|
27
10
|
import { normalizeBooleanConfig, SHOP_LOYALTY_COUPONS_ENABLED_CONFIG_KEY } from '@controleonline/ui-common/src/react/utils/shopConfig';
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
|
|
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';
|
|
11
|
+
import { getPrinterOptions } from '@controleonline/ui-common/src/react/utils/printerDevices';
|
|
12
|
+
import { DISPLAY_DEVICE_TYPE, PDV_DEVICE_TYPE, DISPLAY_DEVICE_LINK_CONFIG_KEY, DISPLAY_DEVICE_PRINTER_CONFIG_KEY, PDV_TAB_OPERATION } from './deviceDetailConstants';
|
|
13
|
+
import { formatApiError, getIsOpen } from './deviceDetailHelpers';
|
|
37
14
|
|
|
15
|
+
import { Platform } from 'react-native';
|
|
38
16
|
|
|
39
17
|
export default function useDeviceDetailStateA() {
|
|
40
18
|
const route = useRoute();
|
|
@@ -485,5 +463,8 @@ export default function useDeviceDetailStateA() {
|
|
|
485
463
|
runtimeDeviceId,
|
|
486
464
|
runtimeDeviceType,
|
|
487
465
|
currentCompany,
|
|
466
|
+
runtimeDevice, runtimeDeviceConfig, themeColors,
|
|
467
|
+
displayStore,
|
|
468
|
+
printerStore,
|
|
488
469
|
};
|
|
489
470
|
}
|
|
@@ -23,6 +23,7 @@ const FileField = ({ field, value, editable, providerId, updateField }) => (
|
|
|
23
23
|
acceptedTypes={field.accept || '.pfx,.p12,application/x-pkcs12'}
|
|
24
24
|
fileType=""
|
|
25
25
|
fileTypeLabel="certificado"
|
|
26
|
+
knownFileIds={[extractFileId(value)].filter(Boolean)}
|
|
26
27
|
title={field.label}
|
|
27
28
|
triggerLabel="Gerenciar certificado"
|
|
28
29
|
managerTitle="Gerenciador de arquivos"
|
|
@@ -9,19 +9,20 @@ import useToastMessage from '@controleonline/ui-crm/src/react/hooks/useToastMess
|
|
|
9
9
|
import { useStore } from '@store';
|
|
10
10
|
import { colors } from '@controleonline/../../src/styles/colors';
|
|
11
11
|
import { resolveThemePalette, withOpacity } from '@controleonline/../../src/styles/branding';
|
|
12
|
-
import { getIntegrationConfig, getIntegrationByKey
|
|
12
|
+
import { getIntegrationConfig, getIntegrationByKey } from './integrationsCatalog';
|
|
13
|
+
import { fetchPeopleConfigs } from './fetchPeopleConfigs';
|
|
13
14
|
import IntegrationConfigFields from './IntegrationConfigFields';
|
|
14
15
|
import {
|
|
15
16
|
ROUTE_PROVIDER_MAP,
|
|
16
|
-
buildFieldValues,
|
|
17
17
|
extractAuthorizationUrl,
|
|
18
18
|
formatApiError,
|
|
19
19
|
formatUberOAuthError,
|
|
20
20
|
getConfigFields,
|
|
21
21
|
isConnectedValue,
|
|
22
|
+
isMethodNotAllowed,
|
|
23
|
+
mergeTabValues,
|
|
22
24
|
normalizeTextValue,
|
|
23
25
|
openAuthorizationUrl,
|
|
24
|
-
resolveFallbackConfigs,
|
|
25
26
|
resolveProviderId,
|
|
26
27
|
routeNameToPath,
|
|
27
28
|
toConfigRequestValue,
|
|
@@ -44,13 +45,13 @@ const CenterState = ({ icon, iconColor, title, text, backgroundColor, spinnerCol
|
|
|
44
45
|
</SafeAreaView>
|
|
45
46
|
);
|
|
46
47
|
|
|
47
|
-
export default function IntegrationConfigPage({ route, embedded = false }) {
|
|
48
|
+
export default function IntegrationConfigPage({ route, embedded = false, fiscalTab = '', onlyFiscalTab = false }) {
|
|
48
49
|
const peopleStore = useStore('people');
|
|
49
50
|
const themeStore = useStore('theme');
|
|
50
51
|
const configsStore = useStore('configs');
|
|
51
52
|
const { currentCompany } = peopleStore.getters;
|
|
52
53
|
const { colors: themeColors } = themeStore.getters;
|
|
53
|
-
const configActions = configsStore.actions;
|
|
54
|
+
const configActions = configsStore.actions || {};
|
|
54
55
|
const { isSaving } = configsStore.getters;
|
|
55
56
|
const { showError, showSuccess } = useToastMessage();
|
|
56
57
|
const oauthNoticeRef = useRef('');
|
|
@@ -62,7 +63,8 @@ export default function IntegrationConfigPage({ route, embedded = false }) {
|
|
|
62
63
|
const providerConfig = useMemo(() => getIntegrationConfig(providerKey), [providerKey]);
|
|
63
64
|
const configFields = useMemo(() => getConfigFields(providerConfig), [providerConfig]);
|
|
64
65
|
const fiscalTabs = providerConfig?.tabs || [];
|
|
65
|
-
const
|
|
66
|
+
const requestedFiscalTab = fiscalTab || route?.params?.fiscalTab || '';
|
|
67
|
+
const [activeFiscalTab, setActiveFiscalTab] = useState(() => requestedFiscalTab || fiscalTabs[0]?.key || 'general');
|
|
66
68
|
const activeTabDef = useMemo(
|
|
67
69
|
() => fiscalTabs.find(tab => tab.key === activeFiscalTab) || fiscalTabs[0] || null,
|
|
68
70
|
[activeFiscalTab, fiscalTabs],
|
|
@@ -71,10 +73,13 @@ export default function IntegrationConfigPage({ route, embedded = false }) {
|
|
|
71
73
|
() => (activeTabDef?.fields?.length ? activeTabDef.fields : configFields),
|
|
72
74
|
[activeTabDef, configFields],
|
|
73
75
|
);
|
|
74
|
-
|
|
75
76
|
useEffect(() => {
|
|
77
|
+
if (requestedFiscalTab && fiscalTabs.some(tab => tab.key === requestedFiscalTab)) {
|
|
78
|
+
if (activeFiscalTab !== requestedFiscalTab) setActiveFiscalTab(requestedFiscalTab);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
76
81
|
if (fiscalTabs.length && !fiscalTabs.some(tab => tab.key === activeFiscalTab)) setActiveFiscalTab(fiscalTabs[0].key);
|
|
77
|
-
}, [activeFiscalTab, fiscalTabs]);
|
|
82
|
+
}, [activeFiscalTab, fiscalTabs, requestedFiscalTab]);
|
|
78
83
|
|
|
79
84
|
const returnPath = useMemo(() => {
|
|
80
85
|
const routePath = normalizeTextValue(route?.params?.return_path || route?.params?.returnPath || '');
|
|
@@ -88,28 +93,30 @@ export default function IntegrationConfigPage({ route, embedded = false }) {
|
|
|
88
93
|
[themeColors, currentCompany?.id],
|
|
89
94
|
);
|
|
90
95
|
const [loading, setLoading] = useState(true);
|
|
96
|
+
const [tabLoading, setTabLoading] = useState(false);
|
|
91
97
|
const [refreshing, setRefreshing] = useState(false);
|
|
92
98
|
const [authLoading, setAuthLoading] = useState(false);
|
|
93
99
|
const [configValues, setConfigValues] = useState({});
|
|
94
100
|
const [integrationSummary, setIntegrationSummary] = useState(null);
|
|
95
101
|
|
|
96
|
-
// Company details can edit a company that is not the globally selected one.
|
|
97
|
-
// The embedded route id is authoritative for all fiscal reads and writes.
|
|
98
102
|
const providerId = useMemo(
|
|
99
|
-
() => resolveProviderId({ route, currentCompany }),
|
|
100
|
-
[route?.params?.companyId, currentCompany?.id],
|
|
103
|
+
() => resolveProviderId({ route, currentCompany, embedded }),
|
|
104
|
+
[embedded, route?.params?.companyId, route?.params?.clientId, currentCompany?.id],
|
|
101
105
|
);
|
|
102
106
|
const providerIri = useMemo(() => (providerId ? `/people/${providerId}` : ''), [providerId]);
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
107
|
+
const allConfigFields = useMemo(() => getConfigFields(providerConfig), [providerConfig]);
|
|
108
|
+
const allFieldKeys = useMemo(
|
|
109
|
+
() => allConfigFields.map(field => field.key).filter(Boolean),
|
|
110
|
+
[allConfigFields],
|
|
106
111
|
);
|
|
112
|
+
const allFieldKeysSig = useMemo(() => allFieldKeys.join('|'), [allFieldKeys]);
|
|
113
|
+
// Pure config providers (e.g. receita-federal) do not use marketplace/integrations.
|
|
114
|
+
const needsMarketplaceIntegration = Boolean(providerConfig?.oauthConnect);
|
|
107
115
|
|
|
108
|
-
|
|
109
|
-
setConfigValues(
|
|
110
|
-
}, [
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
setConfigValues({});
|
|
118
|
+
}, [providerIri]);
|
|
111
119
|
|
|
112
|
-
useEffect(() => syncConfigValues(fallbackConfigs), [fallbackConfigs, syncConfigValues]);
|
|
113
120
|
useEffect(() => {
|
|
114
121
|
const oauthStatus = normalizeTextValue(route?.params?.oauth_status).toLowerCase();
|
|
115
122
|
const oauthError = normalizeTextValue(route?.params?.oauth_error);
|
|
@@ -128,26 +135,49 @@ export default function IntegrationConfigPage({ route, embedded = false }) {
|
|
|
128
135
|
}
|
|
129
136
|
if (showLoading) setLoading(true);
|
|
130
137
|
try {
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
138
|
+
const keys = allFieldKeys.length
|
|
139
|
+
? allFieldKeys
|
|
140
|
+
: visibleFields.map(field => field.key).filter(Boolean);
|
|
141
|
+
|
|
142
|
+
if (keys.length) {
|
|
143
|
+
const configItems = await fetchPeopleConfigs({ peopleIri: providerIri, configKeys: keys });
|
|
144
|
+
const mergeFields = allConfigFields.length ? allConfigFields : visibleFields;
|
|
145
|
+
setConfigValues(current => mergeTabValues(mergeFields, configItems, current));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (needsMarketplaceIntegration) {
|
|
149
|
+
try {
|
|
150
|
+
const integrationResponse = await api.fetch('/marketplace/integrations', {
|
|
151
|
+
params: { provider_id: providerId },
|
|
152
|
+
});
|
|
153
|
+
setIntegrationSummary(getIntegrationByKey(integrationResponse, providerConfig.key));
|
|
154
|
+
} catch (integrationError) {
|
|
155
|
+
// OAuth / marketplace providers still surface the error; pure config never hits this branch.
|
|
156
|
+
showError(formatApiError(integrationError));
|
|
157
|
+
setIntegrationSummary(null);
|
|
158
|
+
}
|
|
139
159
|
} else {
|
|
140
|
-
setIntegrationSummary(
|
|
160
|
+
setIntegrationSummary(null);
|
|
141
161
|
}
|
|
142
162
|
} catch (error) {
|
|
143
163
|
showError(formatApiError(error));
|
|
144
|
-
syncConfigValues(fallbackConfigs);
|
|
145
164
|
setIntegrationSummary(null);
|
|
146
165
|
} finally {
|
|
147
|
-
|
|
166
|
+
setLoading(false);
|
|
167
|
+
setTabLoading(false);
|
|
148
168
|
}
|
|
149
|
-
}, [
|
|
169
|
+
}, [
|
|
170
|
+
allConfigFields,
|
|
171
|
+
allFieldKeys,
|
|
172
|
+
allFieldKeysSig,
|
|
173
|
+
needsMarketplaceIntegration,
|
|
174
|
+
providerConfig,
|
|
175
|
+
providerIri,
|
|
176
|
+
providerId,
|
|
177
|
+
showError,
|
|
178
|
+
]);
|
|
150
179
|
|
|
180
|
+
// Reload only when the company/provider identity or full key set changes — not on fiscal sub-tab switch.
|
|
151
181
|
useFocusEffect(useCallback(() => { loadPageData(); }, [loadPageData]));
|
|
152
182
|
const onRefresh = useCallback(async () => {
|
|
153
183
|
setRefreshing(true);
|
|
@@ -157,6 +187,29 @@ export default function IntegrationConfigPage({ route, embedded = false }) {
|
|
|
157
187
|
setConfigValues(current => ({ ...current, [fieldKey]: value }));
|
|
158
188
|
}, []);
|
|
159
189
|
|
|
190
|
+
const persistConfigs = useCallback(async payload => {
|
|
191
|
+
if (typeof configActions.addManyConfigs === 'function') {
|
|
192
|
+
try {
|
|
193
|
+
return await configActions.addManyConfigs(payload);
|
|
194
|
+
} catch (error) {
|
|
195
|
+
if (!isMethodNotAllowed(error)) throw error;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (typeof configActions.addConfigs !== 'function') {
|
|
199
|
+
throw new Error('Nao foi possivel salvar: acao de configs indisponivel.');
|
|
200
|
+
}
|
|
201
|
+
for (const item of payload.configs) {
|
|
202
|
+
await configActions.addConfigs({
|
|
203
|
+
configKey: item.configKey,
|
|
204
|
+
configValue: item.configValue,
|
|
205
|
+
people: payload.people,
|
|
206
|
+
module: payload.module,
|
|
207
|
+
visibility: payload.visibility,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
return true;
|
|
211
|
+
}, [configActions]);
|
|
212
|
+
|
|
160
213
|
const handleOAuthConnect = useCallback(async () => {
|
|
161
214
|
if (!providerIri || !providerConfig?.oauthConnect) {
|
|
162
215
|
showError('Nao foi possivel identificar a integracao selecionada.');
|
|
@@ -181,29 +234,32 @@ export default function IntegrationConfigPage({ route, embedded = false }) {
|
|
|
181
234
|
? isConnectedValue(integrationSummary.connected)
|
|
182
235
|
: requiredKeys.length > 0 && requiredKeys.every(key => normalizeTextValue(configValues[key]) !== '');
|
|
183
236
|
const statusTone = connected ? '#16A34A' : '#e67e22';
|
|
184
|
-
const editable = Boolean(providerIri && providerConfig && !
|
|
185
|
-
const actionLoading = providerConfig?.oauthConnect ? authLoading : isSaving;
|
|
186
|
-
const actionDisabled = providerConfig?.oauthConnect ? authLoading || loading : !editable;
|
|
237
|
+
const editable = Boolean(providerIri && providerConfig && !providerConfig.oauthConnect);
|
|
238
|
+
const actionLoading = providerConfig?.oauthConnect ? authLoading : Boolean(isSaving || tabLoading);
|
|
239
|
+
const actionDisabled = providerConfig?.oauthConnect ? authLoading || loading : !editable || actionLoading;
|
|
240
|
+
const saveLabel = fiscalTabs.length
|
|
241
|
+
? `Salvar ${activeTabDef?.label || 'aba'}`
|
|
242
|
+
: providerConfig?.saveLabel;
|
|
187
243
|
|
|
188
244
|
const saveIntegration = useCallback(async () => {
|
|
189
245
|
if (!providerIri || !providerConfig || providerConfig.oauthConnect) {
|
|
190
246
|
showError('Nao foi possivel identificar a integracao selecionada.');
|
|
191
247
|
return;
|
|
192
248
|
}
|
|
193
|
-
const configs =
|
|
249
|
+
const configs = visibleFields.map(field => ({
|
|
194
250
|
configKey: field.key,
|
|
195
251
|
configValue: toConfigRequestValue(normalizeTextValue(configValues[field.key])),
|
|
196
252
|
}));
|
|
197
253
|
try {
|
|
198
|
-
await
|
|
199
|
-
showSuccess(`${providerConfig.label} salvo com sucesso.`);
|
|
254
|
+
await persistConfigs({ configs, people: providerIri, module: 4, visibility: 'public' });
|
|
255
|
+
showSuccess(`${activeTabDef?.label || providerConfig.label} salvo com sucesso.`);
|
|
200
256
|
await loadPageData({ showLoading: false });
|
|
201
257
|
} catch (error) { showError(error?.message || 'Nao foi possivel salvar a integracao.'); }
|
|
202
|
-
}, [
|
|
258
|
+
}, [activeTabDef, configValues, loadPageData, persistConfigs, providerConfig, providerIri, showError, showSuccess, visibleFields]);
|
|
203
259
|
|
|
204
260
|
if (!providerConfig) return <CenterState icon="alert-triangle" iconColor="#e67e22" title="Integracao indisponivel" text="A tela solicitada nao possui configuracao cadastrada." />;
|
|
205
|
-
if (!providerId) return <CenterState icon="building" iconColor="#94A3B8" title="
|
|
206
|
-
if (loading) return <CenterState backgroundColor={brandColors.background} spinnerColor={providerConfig.accent} title="Carregando integracao" text="Buscando as credenciais
|
|
261
|
+
if (!providerId) return <CenterState icon="building" iconColor="#94A3B8" title="Empresa nao identificada" text="Abra a ficha da empresa para gravar as configuracoes fiscais nela." />;
|
|
262
|
+
if (loading) return <CenterState backgroundColor={brandColors.background} spinnerColor={providerConfig.accent} title="Carregando integracao" text="Buscando as credenciais desta aba." />;
|
|
207
263
|
|
|
208
264
|
return (
|
|
209
265
|
<SafeAreaView style={[styles.container, { backgroundColor: brandColors.background }]} edges={['bottom']}>
|
|
@@ -227,7 +283,7 @@ export default function IntegrationConfigPage({ route, embedded = false }) {
|
|
|
227
283
|
<Text style={styles.sectionTitle}>Status</Text>
|
|
228
284
|
<Text style={styles.sectionSubtitle}>{providerConfig.oauthConnect
|
|
229
285
|
? 'A integracao fica conectada quando o login do Uber termina e o store e salvo automaticamente.'
|
|
230
|
-
: 'A integracao so aparece como conectada quando todos os campos obrigatorios foram salvos
|
|
286
|
+
: 'A integracao so aparece como conectada quando todos os campos obrigatorios foram salvos nesta empresa.'}</Text>
|
|
231
287
|
</View>
|
|
232
288
|
<View style={[styles.statusBadge, { backgroundColor: withOpacity(statusTone, 0.12) }]}>
|
|
233
289
|
<Text style={[styles.statusBadgeText, { color: statusTone }]}>{connected ? 'Conectado' : 'Pendente'}</Text>
|
|
@@ -240,7 +296,7 @@ export default function IntegrationConfigPage({ route, embedded = false }) {
|
|
|
240
296
|
<Text style={styles.cardTitle}>{providerConfig.oauthConnect ? 'Conexao' : fiscalTabs.length ? activeTabDef?.label || 'Configuracoes' : 'Credenciais'}</Text>
|
|
241
297
|
{!embedded ? <Text style={styles.cardSubtitle}>{providerConfig.oauthConnect
|
|
242
298
|
? 'Use o login oficial do Uber. A store sera localizada e gravada automaticamente na empresa ativa.'
|
|
243
|
-
: '
|
|
299
|
+
: 'Troca de aba e local; as configuracoes sao carregadas uma vez e cada aba grava so as chaves dela.'}</Text> : null}
|
|
244
300
|
|
|
245
301
|
{providerConfig.oauthConnect ? (
|
|
246
302
|
<View style={styles.fieldList}><View style={styles.fieldGroup}>
|
|
@@ -249,7 +305,7 @@ export default function IntegrationConfigPage({ route, embedded = false }) {
|
|
|
249
305
|
</View></View>
|
|
250
306
|
) : (
|
|
251
307
|
<View style={styles.fieldList}>
|
|
252
|
-
{fiscalTabs.length ? <View style={styles.subTabRow}>{fiscalTabs.map(tab => {
|
|
308
|
+
{fiscalTabs.length && !onlyFiscalTab ? <View style={styles.subTabRow}>{fiscalTabs.map(tab => {
|
|
253
309
|
const selected = tab.key === (activeTabDef?.key || activeFiscalTab);
|
|
254
310
|
return <TouchableOpacity key={tab.key} style={[styles.subTabButton, selected && styles.subTabButtonActive]}
|
|
255
311
|
activeOpacity={0.85} onPress={() => setActiveFiscalTab(tab.key)}>
|
|
@@ -257,6 +313,7 @@ export default function IntegrationConfigPage({ route, embedded = false }) {
|
|
|
257
313
|
</TouchableOpacity>;
|
|
258
314
|
})}</View> : null}
|
|
259
315
|
{activeTabDef?.description ? <Text style={styles.tabDescription}>{activeTabDef.description}</Text> : null}
|
|
316
|
+
{tabLoading ? <ActivityIndicator color={providerConfig.accent} /> : null}
|
|
260
317
|
<IntegrationConfigFields fields={visibleFields} configValues={configValues} editable={editable}
|
|
261
318
|
embedded={embedded} providerId={providerId} updateField={updateField} />
|
|
262
319
|
</View>
|
|
@@ -265,11 +322,10 @@ export default function IntegrationConfigPage({ route, embedded = false }) {
|
|
|
265
322
|
<TouchableOpacity style={[styles.saveButton, { backgroundColor: providerConfig.accent }, actionDisabled && styles.saveButtonDisabled]}
|
|
266
323
|
disabled={actionDisabled} activeOpacity={0.9} onPress={providerConfig.oauthConnect ? handleOAuthConnect : saveIntegration}>
|
|
267
324
|
{actionLoading ? <ActivityIndicator color="#FFFFFF" /> : <Icon name={providerConfig.oauthConnect ? 'log-in' : 'save'} size={16} color="#FFFFFF" />}
|
|
268
|
-
<Text style={styles.saveButtonText}>{providerConfig.oauthConnect ? providerConfig.connectLabel || 'Conectar' :
|
|
325
|
+
<Text style={styles.saveButtonText}>{providerConfig.oauthConnect ? providerConfig.connectLabel || 'Conectar' : saveLabel}</Text>
|
|
269
326
|
</TouchableOpacity>
|
|
270
327
|
</View>
|
|
271
328
|
</ScrollView>
|
|
272
329
|
</SafeAreaView>
|
|
273
330
|
);
|
|
274
331
|
}
|
|
275
|
-
// TODO(store-first): quando este arquivo for mexido, mover a leitura para stores, remover api.fetch e evitar repassar dados em objetos quando o store ja resolver isso.
|