@controleonline/ui-common 1.2.79 → 1.2.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +8 -0
- package/package.json +9 -3
- package/src/api/fetch.js +7 -7
- package/src/react/components/AddImportModal.js +6 -2
- package/src/react/components/BackgroundRuntimeBridge.js +201 -215
- package/src/react/components/ConfirmModal.js +44 -9
- package/src/react/components/ConfirmModal.styles.js +55 -41
- package/src/react/components/CopyDeviceConfigModal.js +193 -0
- package/src/react/components/CopyDeviceConfigModal.styles.js +123 -0
- package/src/react/components/DefaultProvider.native.js +22 -0
- package/src/react/components/DefaultProvider.web.js +25 -1
- package/src/react/components/EntityLogBranch.js +482 -0
- package/src/react/components/EntityLogCards.js +369 -0
- package/src/react/components/EntityLogContent.js +113 -794
- package/src/react/components/LinkedOrderProductsTab.js +3 -3
- package/src/react/components/PrintService.js +130 -409
- package/src/react/components/RemoteCheckoutService.js +2 -2
- package/src/react/components/RuntimeBottomNavigationBar.js +141 -146
- package/src/react/components/RuntimeFooterMarqueeText.js +137 -0
- package/src/react/components/RuntimeInfoFooter.js +12 -15
- package/src/react/components/SystemErrorToast.js +49 -29
- package/src/react/components/SystemErrorToast.styles.js +43 -38
- package/src/react/components/UserAvatar.js +120 -28
- package/src/react/config/deviceConfigBootstrap.js +330 -304
- package/src/react/hooks/usePrintSpoolEffects.js +161 -0
- package/src/react/pages/DeviceDetailPage.js +6 -2882
- package/src/react/pages/Devices/detail/DeviceDetailAlertsCommandsSection.js +233 -0
- package/src/react/pages/Devices/detail/DeviceDetailHeader.js +138 -0
- package/src/react/pages/Devices/detail/DeviceDetailMovementSections.js +167 -0
- package/src/react/pages/Devices/detail/DeviceDetailOrdersPrintSection.js +216 -0
- package/src/react/pages/Devices/detail/DeviceDetailPaymentSection.js +40 -0
- package/src/react/pages/Devices/detail/DeviceDetailPdvConfigSection.js +390 -0
- package/src/react/pages/Devices/detail/DeviceDetailRenderers.js +135 -0
- package/src/react/pages/Devices/detail/DeviceDetailScreen.js +493 -0
- package/src/react/pages/Devices/detail/OptionButtonChip.js +65 -0
- package/src/react/pages/Devices/detail/deviceDetailConstants.js +36 -0
- package/src/react/pages/Devices/detail/deviceDetailHelpers.js +70 -0
- package/src/react/pages/Devices/detail/useDeviceDetailActions.js +483 -0
- package/src/react/pages/Devices/detail/useDeviceDetailCopyConfig.js +87 -0
- package/src/react/pages/Devices/detail/useDeviceDetailLoaders.js +327 -0
- package/src/react/pages/Devices/detail/useDeviceDetailSaves.js +429 -0
- package/src/react/pages/Devices/detail/useDeviceDetailStateA.js +484 -0
- package/src/react/pages/Devices/detail/useDeviceDetailStateB.js +71 -0
- package/src/react/pages/Devices/deviceTypes/index.js +2 -0
- package/src/react/pages/Devices/deviceTypes/pdv.js +11 -0
- package/src/react/pages/Imports.js +3 -2
- package/src/react/pages/IntegrationConfigFields.js +126 -0
- package/src/react/pages/IntegrationConfigPage.js +122 -591
- package/src/react/pages/IntegrationConfigPage.utils.js +95 -0
- package/src/react/print/usePrintButtonController.js +9 -1
- package/src/react/services/Getnet/Checkout.js +81 -0
- package/src/react/services/Getnet/Getnet.js +77 -0
- package/src/react/services/paymentGatewayExecution.js +20 -0
- package/src/react/utils/bottomNavigationToolbar.js +161 -0
- package/src/react/utils/commercialDocumentOrders.js +18 -6
- package/src/react/utils/copyDeviceConfigs.js +198 -0
- package/src/react/utils/fileUrl.js +43 -0
- package/src/react/utils/importStatus.js +19 -10
- package/src/react/utils/logSettings.js +7 -7
- package/src/react/utils/maintenanceSettings.js +16 -0
- package/src/react/utils/passwordPolicy.js +73 -0
- package/src/react/utils/paymentDevices.js +6 -0
- package/src/react/utils/printManagedPrinter.js +45 -0
- package/src/react/utils/printRouting.js +63 -0
- package/src/react/utils/printSpoolUtils.js +119 -0
- package/src/react/utils/printerDevices.js +368 -368
- package/src/react/utils/runtimeFooter.js +6 -1
- package/src/react/utils/shopFranchises.js +186 -65
- package/src/react/utils/systemErrorMessage.js +71 -67
- package/src/store/device_config/customActions.js +119 -30
- package/src/tests/browser/manager/bottom-navigation-role-toolbar.spec.js +353 -0
- package/src/tests/browser/manager/device-detail-alias-save.spec.js +345 -0
- package/src/tests/browser/manager/device-detail-copy-config.spec.js +365 -0
- package/src/tests/browser/manager/runtime-footer-marquee.spec.js +262 -0
- package/src/tests/browser/manager/theme-confirm-toast.spec.js +236 -0
- package/src/tests/react/components/RuntimeFooterMarqueeText.test.js +171 -0
- package/src/tests/react/components/UserAvatar.test.js +6 -2
- package/src/tests/react/components/themeAwareModals.test.mjs +60 -0
- package/src/tests/react/config/deviceConfigBootstrap.test.js +104 -66
- package/src/tests/react/pages/deviceDetailDelete.test.js +78 -0
- package/src/tests/react/pages/receitaFederalIntegrationContract.test.mjs +48 -0
- package/src/tests/react/utils/bottomNavigationToolbar.test.js +222 -0
- package/src/tests/react/utils/copyDeviceConfigs.test.mjs +127 -0
- package/src/tests/react/utils/fileUrl.test.js +38 -0
- package/src/tests/react/utils/importStatus.test.js +27 -10
- package/src/tests/react/utils/passwordPolicy.test.js +27 -0
- package/src/tests/react/utils/printRouting.test.mjs +86 -0
- package/src/tests/react/utils/printSpoolUtils.test.mjs +52 -0
- package/src/tests/react/utils/runtimeFooter.test.js +10 -8
- package/src/tests/react/utils/shopFranchises.test.js +121 -115
- package/src/tests/react/utils/systemErrorMessage.test.js +32 -59
|
@@ -1,43 +1,57 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {StyleSheet} from 'react-native';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
3
|
+
/**
|
|
4
|
+
* Theme-aware styles for ConfirmModal.
|
|
5
|
+
* Colors must come from themeStore.getters.colors (canonical tokens only).
|
|
6
|
+
*/
|
|
7
|
+
const createStyles = palette =>
|
|
8
|
+
StyleSheet.create({
|
|
9
|
+
overlay: {
|
|
10
|
+
flex: 1,
|
|
11
|
+
justifyContent: 'center',
|
|
12
|
+
alignItems: 'center',
|
|
13
|
+
backgroundColor: palette.modalOverlay,
|
|
14
|
+
},
|
|
15
|
+
card: {
|
|
16
|
+
backgroundColor: palette.modalBackground,
|
|
17
|
+
padding: 20,
|
|
18
|
+
borderRadius: 10,
|
|
19
|
+
width: '80%',
|
|
20
|
+
borderWidth: StyleSheet.hairlineWidth,
|
|
21
|
+
borderColor: palette.modalBorder,
|
|
22
|
+
},
|
|
23
|
+
title: {
|
|
24
|
+
fontSize: 18,
|
|
25
|
+
fontWeight: 'bold',
|
|
26
|
+
marginBottom: 10,
|
|
27
|
+
color: palette.modalHeaderText,
|
|
28
|
+
},
|
|
29
|
+
message: {
|
|
30
|
+
fontSize: 14,
|
|
31
|
+
marginBottom: 20,
|
|
32
|
+
color: palette.modalText,
|
|
33
|
+
},
|
|
34
|
+
actions: {
|
|
35
|
+
flexDirection: 'row',
|
|
36
|
+
justifyContent: 'flex-end',
|
|
37
|
+
gap: 10,
|
|
38
|
+
},
|
|
39
|
+
cancelButton: {
|
|
40
|
+
padding: 10,
|
|
41
|
+
},
|
|
42
|
+
cancelButtonText: {
|
|
43
|
+
color: palette.buttonTextSecondary,
|
|
44
|
+
},
|
|
45
|
+
confirmButton: {
|
|
46
|
+
padding: 10,
|
|
47
|
+
backgroundColor: palette.buttonBackground,
|
|
48
|
+
borderRadius: 5,
|
|
49
|
+
borderWidth: StyleSheet.hairlineWidth,
|
|
50
|
+
borderColor: palette.buttonBorder,
|
|
51
|
+
},
|
|
52
|
+
confirmButtonText: {
|
|
53
|
+
color: palette.buttonText,
|
|
54
|
+
},
|
|
55
|
+
});
|
|
42
56
|
|
|
43
|
-
export default
|
|
57
|
+
export default createStyles;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import React, {useMemo, useState} from 'react';
|
|
2
|
+
import {
|
|
3
|
+
ActivityIndicator,
|
|
4
|
+
Modal,
|
|
5
|
+
ScrollView,
|
|
6
|
+
Text,
|
|
7
|
+
TouchableOpacity,
|
|
8
|
+
View,
|
|
9
|
+
} from 'react-native';
|
|
10
|
+
import Icon from 'react-native-vector-icons/Feather';
|
|
11
|
+
import {
|
|
12
|
+
buildSourceDeviceOptions,
|
|
13
|
+
listCopyableConfigKeys,
|
|
14
|
+
} from '@controleonline/ui-common/src/react/utils/copyDeviceConfigs';
|
|
15
|
+
import styles from './CopyDeviceConfigModal.styles';
|
|
16
|
+
|
|
17
|
+
const tt = (type, key) => global.t?.t('configs', type, key);
|
|
18
|
+
|
|
19
|
+
export default function CopyDeviceConfigModal({
|
|
20
|
+
visible,
|
|
21
|
+
onClose,
|
|
22
|
+
onConfirm,
|
|
23
|
+
companyDeviceConfigs = [],
|
|
24
|
+
companyId,
|
|
25
|
+
destinationDeviceString,
|
|
26
|
+
destinationAlias,
|
|
27
|
+
loading = false,
|
|
28
|
+
confirming = false,
|
|
29
|
+
}) {
|
|
30
|
+
const [selectedDeviceString, setSelectedDeviceString] = useState(null);
|
|
31
|
+
|
|
32
|
+
const options = useMemo(
|
|
33
|
+
() =>
|
|
34
|
+
buildSourceDeviceOptions({
|
|
35
|
+
companyDeviceConfigs,
|
|
36
|
+
companyId,
|
|
37
|
+
destinationDeviceString,
|
|
38
|
+
}),
|
|
39
|
+
[companyDeviceConfigs, companyId, destinationDeviceString],
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const selected = useMemo(
|
|
43
|
+
() => options.find(o => o.deviceString === selectedDeviceString) || null,
|
|
44
|
+
[options, selectedDeviceString],
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const selectedKeys = useMemo(() => {
|
|
48
|
+
if (!selected) {
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
const keys = new Set();
|
|
52
|
+
selected.configs.forEach(row => {
|
|
53
|
+
listCopyableConfigKeys(row?.configs).forEach(k => keys.add(k));
|
|
54
|
+
});
|
|
55
|
+
return Array.from(keys).sort();
|
|
56
|
+
}, [selected]);
|
|
57
|
+
|
|
58
|
+
const selectedTypes = useMemo(() => {
|
|
59
|
+
if (!selected) {
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
return Array.from(
|
|
63
|
+
new Set(
|
|
64
|
+
selected.configs
|
|
65
|
+
.map(row => String(row?.type || '').trim().toUpperCase())
|
|
66
|
+
.filter(Boolean),
|
|
67
|
+
),
|
|
68
|
+
).sort();
|
|
69
|
+
}, [selected]);
|
|
70
|
+
|
|
71
|
+
const handleClose = () => {
|
|
72
|
+
if (confirming) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
setSelectedDeviceString(null);
|
|
76
|
+
onClose?.();
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const handleConfirm = () => {
|
|
80
|
+
if (!selected || confirming) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
onConfirm?.(selected);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<Modal visible={visible} transparent animationType="fade" onRequestClose={handleClose}>
|
|
88
|
+
<View style={styles.overlay}>
|
|
89
|
+
<View style={styles.card} testID="copy-device-config-modal">
|
|
90
|
+
<View style={styles.header}>
|
|
91
|
+
<Text style={styles.title}>
|
|
92
|
+
{tt('device_action', 'copyConfigTitle') || 'Copiar configurações'}
|
|
93
|
+
</Text>
|
|
94
|
+
<TouchableOpacity
|
|
95
|
+
onPress={handleClose}
|
|
96
|
+
disabled={confirming}
|
|
97
|
+
accessibilityLabel="Fechar">
|
|
98
|
+
<Icon name="x" size={20} color="#64748B" />
|
|
99
|
+
</TouchableOpacity>
|
|
100
|
+
</View>
|
|
101
|
+
|
|
102
|
+
<Text style={styles.message} testID="copy-device-config-hint">
|
|
103
|
+
{tt('device_action', 'copyConfigHint') ||
|
|
104
|
+
`Escolha o device origem. As configurações serão aplicadas em "${
|
|
105
|
+
destinationAlias || destinationDeviceString || 'destino'
|
|
106
|
+
}" (identidade do destino não muda).`}
|
|
107
|
+
</Text>
|
|
108
|
+
|
|
109
|
+
{loading ? (
|
|
110
|
+
<ActivityIndicator style={styles.loader} color="#0EA5E9" />
|
|
111
|
+
) : options.length === 0 ? (
|
|
112
|
+
<Text style={styles.empty}>
|
|
113
|
+
{tt('device_action', 'copyConfigEmpty') ||
|
|
114
|
+
'Nenhum outro device na empresa para copiar.'}
|
|
115
|
+
</Text>
|
|
116
|
+
) : (
|
|
117
|
+
<ScrollView style={styles.list} keyboardShouldPersistTaps="handled">
|
|
118
|
+
{options.map(option => {
|
|
119
|
+
const isSelected = option.deviceString === selectedDeviceString;
|
|
120
|
+
return (
|
|
121
|
+
<TouchableOpacity
|
|
122
|
+
key={option.deviceString}
|
|
123
|
+
style={[styles.option, isSelected && styles.optionSelected]}
|
|
124
|
+
onPress={() => setSelectedDeviceString(option.deviceString)}
|
|
125
|
+
disabled={confirming}
|
|
126
|
+
activeOpacity={0.8}
|
|
127
|
+
testID={`copy-device-config-option-${option.deviceString}`}>
|
|
128
|
+
<View style={styles.optionTextBlock}>
|
|
129
|
+
<Text style={styles.optionAlias} numberOfLines={1}>
|
|
130
|
+
{option.alias}
|
|
131
|
+
</Text>
|
|
132
|
+
<Text style={styles.optionMeta} numberOfLines={1}>
|
|
133
|
+
{option.deviceString}
|
|
134
|
+
</Text>
|
|
135
|
+
</View>
|
|
136
|
+
{isSelected ? (
|
|
137
|
+
<Icon name="check-circle" size={18} color="#0EA5E9" />
|
|
138
|
+
) : (
|
|
139
|
+
<Icon name="circle" size={18} color="#CBD5E1" />
|
|
140
|
+
)}
|
|
141
|
+
</TouchableOpacity>
|
|
142
|
+
);
|
|
143
|
+
})}
|
|
144
|
+
</ScrollView>
|
|
145
|
+
)}
|
|
146
|
+
|
|
147
|
+
{selected ? (
|
|
148
|
+
<View style={styles.preview} testID="copy-device-config-preview">
|
|
149
|
+
<Text style={styles.previewTitle}>
|
|
150
|
+
{tt('device_action', 'copyConfigPreview') ||
|
|
151
|
+
'Será sobrescrito no destino:'}
|
|
152
|
+
</Text>
|
|
153
|
+
<Text style={styles.previewLine}>
|
|
154
|
+
Tipos: {selectedTypes.join(', ') || '—'}
|
|
155
|
+
</Text>
|
|
156
|
+
<Text style={styles.previewLine} numberOfLines={4}>
|
|
157
|
+
Chaves: {selectedKeys.length ? selectedKeys.join(', ') : '(vazio)'}
|
|
158
|
+
</Text>
|
|
159
|
+
</View>
|
|
160
|
+
) : null}
|
|
161
|
+
|
|
162
|
+
<View style={styles.actions}>
|
|
163
|
+
<TouchableOpacity
|
|
164
|
+
onPress={handleClose}
|
|
165
|
+
style={styles.cancelButton}
|
|
166
|
+
disabled={confirming}>
|
|
167
|
+
<Text style={styles.cancelText}>
|
|
168
|
+
{tt('device_action', 'cancel') || 'Cancelar'}
|
|
169
|
+
</Text>
|
|
170
|
+
</TouchableOpacity>
|
|
171
|
+
<TouchableOpacity
|
|
172
|
+
onPress={handleConfirm}
|
|
173
|
+
style={[
|
|
174
|
+
styles.confirmButton,
|
|
175
|
+
(!selected || confirming) && styles.confirmDisabled,
|
|
176
|
+
]}
|
|
177
|
+
disabled={!selected || confirming}
|
|
178
|
+
testID="copy-device-config-confirm">
|
|
179
|
+
{confirming ? (
|
|
180
|
+
<ActivityIndicator color="#fff" size="small" />
|
|
181
|
+
) : (
|
|
182
|
+
<Text style={styles.confirmText}>
|
|
183
|
+
{tt('device_action', 'copyConfigConfirm') ||
|
|
184
|
+
'Copiar e sobrescrever'}
|
|
185
|
+
</Text>
|
|
186
|
+
)}
|
|
187
|
+
</TouchableOpacity>
|
|
188
|
+
</View>
|
|
189
|
+
</View>
|
|
190
|
+
</View>
|
|
191
|
+
</Modal>
|
|
192
|
+
);
|
|
193
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import {StyleSheet} from 'react-native';
|
|
2
|
+
|
|
3
|
+
export default StyleSheet.create({
|
|
4
|
+
overlay: {
|
|
5
|
+
flex: 1,
|
|
6
|
+
backgroundColor: 'rgba(15, 23, 42, 0.45)',
|
|
7
|
+
justifyContent: 'center',
|
|
8
|
+
padding: 20,
|
|
9
|
+
},
|
|
10
|
+
card: {
|
|
11
|
+
backgroundColor: '#fff',
|
|
12
|
+
borderRadius: 12,
|
|
13
|
+
maxHeight: '90%',
|
|
14
|
+
padding: 16,
|
|
15
|
+
},
|
|
16
|
+
header: {
|
|
17
|
+
flexDirection: 'row',
|
|
18
|
+
alignItems: 'center',
|
|
19
|
+
justifyContent: 'space-between',
|
|
20
|
+
marginBottom: 8,
|
|
21
|
+
},
|
|
22
|
+
title: {
|
|
23
|
+
fontSize: 17,
|
|
24
|
+
fontWeight: '600',
|
|
25
|
+
color: '#0F172A',
|
|
26
|
+
flex: 1,
|
|
27
|
+
marginRight: 8,
|
|
28
|
+
},
|
|
29
|
+
message: {
|
|
30
|
+
fontSize: 13,
|
|
31
|
+
color: '#475569',
|
|
32
|
+
marginBottom: 12,
|
|
33
|
+
lineHeight: 18,
|
|
34
|
+
},
|
|
35
|
+
loader: {
|
|
36
|
+
marginVertical: 24,
|
|
37
|
+
},
|
|
38
|
+
empty: {
|
|
39
|
+
fontSize: 13,
|
|
40
|
+
color: '#94A3B8',
|
|
41
|
+
textAlign: 'center',
|
|
42
|
+
marginVertical: 16,
|
|
43
|
+
},
|
|
44
|
+
list: {
|
|
45
|
+
maxHeight: 220,
|
|
46
|
+
marginBottom: 8,
|
|
47
|
+
},
|
|
48
|
+
option: {
|
|
49
|
+
flexDirection: 'row',
|
|
50
|
+
alignItems: 'center',
|
|
51
|
+
paddingVertical: 10,
|
|
52
|
+
paddingHorizontal: 10,
|
|
53
|
+
borderRadius: 8,
|
|
54
|
+
borderWidth: 1,
|
|
55
|
+
borderColor: '#E2E8F0',
|
|
56
|
+
marginBottom: 8,
|
|
57
|
+
},
|
|
58
|
+
optionSelected: {
|
|
59
|
+
borderColor: '#0EA5E9',
|
|
60
|
+
backgroundColor: '#F0F9FF',
|
|
61
|
+
},
|
|
62
|
+
optionTextBlock: {
|
|
63
|
+
flex: 1,
|
|
64
|
+
marginRight: 8,
|
|
65
|
+
},
|
|
66
|
+
optionAlias: {
|
|
67
|
+
fontSize: 14,
|
|
68
|
+
fontWeight: '600',
|
|
69
|
+
color: '#0F172A',
|
|
70
|
+
},
|
|
71
|
+
optionMeta: {
|
|
72
|
+
fontSize: 11,
|
|
73
|
+
color: '#94A3B8',
|
|
74
|
+
marginTop: 2,
|
|
75
|
+
},
|
|
76
|
+
preview: {
|
|
77
|
+
backgroundColor: '#F8FAFC',
|
|
78
|
+
borderRadius: 8,
|
|
79
|
+
padding: 10,
|
|
80
|
+
marginBottom: 12,
|
|
81
|
+
},
|
|
82
|
+
previewTitle: {
|
|
83
|
+
fontSize: 12,
|
|
84
|
+
fontWeight: '600',
|
|
85
|
+
color: '#334155',
|
|
86
|
+
marginBottom: 4,
|
|
87
|
+
},
|
|
88
|
+
previewLine: {
|
|
89
|
+
fontSize: 11,
|
|
90
|
+
color: '#64748B',
|
|
91
|
+
lineHeight: 16,
|
|
92
|
+
},
|
|
93
|
+
actions: {
|
|
94
|
+
flexDirection: 'row',
|
|
95
|
+
justifyContent: 'flex-end',
|
|
96
|
+
gap: 8,
|
|
97
|
+
},
|
|
98
|
+
cancelButton: {
|
|
99
|
+
paddingVertical: 10,
|
|
100
|
+
paddingHorizontal: 14,
|
|
101
|
+
borderRadius: 8,
|
|
102
|
+
},
|
|
103
|
+
cancelText: {
|
|
104
|
+
color: '#64748B',
|
|
105
|
+
fontSize: 14,
|
|
106
|
+
},
|
|
107
|
+
confirmButton: {
|
|
108
|
+
backgroundColor: '#0EA5E9',
|
|
109
|
+
paddingVertical: 10,
|
|
110
|
+
paddingHorizontal: 14,
|
|
111
|
+
borderRadius: 8,
|
|
112
|
+
minWidth: 140,
|
|
113
|
+
alignItems: 'center',
|
|
114
|
+
},
|
|
115
|
+
confirmDisabled: {
|
|
116
|
+
opacity: 0.5,
|
|
117
|
+
},
|
|
118
|
+
confirmText: {
|
|
119
|
+
color: '#fff',
|
|
120
|
+
fontSize: 14,
|
|
121
|
+
fontWeight: '600',
|
|
122
|
+
},
|
|
123
|
+
});
|
|
@@ -103,6 +103,20 @@ const resolveDeviceConfigPeopleIri = ({appType, currentCompany, user}) => {
|
|
|
103
103
|
|
|
104
104
|
return '';
|
|
105
105
|
};
|
|
106
|
+
const isTenantAdministrativeAuthority = company => {
|
|
107
|
+
const userFlags = company?.user || {};
|
|
108
|
+
return !!(
|
|
109
|
+
userFlags.owner_enabled ||
|
|
110
|
+
userFlags.director_enabled ||
|
|
111
|
+
userFlags.manager_enabled ||
|
|
112
|
+
userFlags.admin_enabled ||
|
|
113
|
+
company?.owner_enabled ||
|
|
114
|
+
company?.director_enabled ||
|
|
115
|
+
company?.manager_enabled
|
|
116
|
+
);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
|
|
106
120
|
|
|
107
121
|
export const DefaultProvider = ({
|
|
108
122
|
children,
|
|
@@ -607,6 +621,13 @@ export const DefaultProvider = ({
|
|
|
607
621
|
return;
|
|
608
622
|
}
|
|
609
623
|
|
|
624
|
+
// Non-admin users cannot mutate device context/financial policy (API 403).
|
|
625
|
+
// Skip bootstrap write; keep local runtime configs in memory only.
|
|
626
|
+
if (!isTenantAdministrativeAuthority(currentCompany)) {
|
|
627
|
+
setDeviceRuntimeConfigSynced(true);
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
|
|
610
631
|
deviceConfigsActions
|
|
611
632
|
.addDeviceConfigs({
|
|
612
633
|
device: device.id,
|
|
@@ -627,6 +648,7 @@ export const DefaultProvider = ({
|
|
|
627
648
|
deviceConfigFetched,
|
|
628
649
|
deviceConfigPeopleIri,
|
|
629
650
|
deviceRuntimeConfigSynced,
|
|
651
|
+
currentCompany,
|
|
630
652
|
deviceConfigsActions,
|
|
631
653
|
device_config?.configs,
|
|
632
654
|
isLogged,
|
|
@@ -15,6 +15,7 @@ import PrintService from '@controleonline/ui-common/src/react/components/PrintSe
|
|
|
15
15
|
import RemoteCheckoutService from '@controleonline/ui-common/src/react/components/RemoteCheckoutService';
|
|
16
16
|
import ProductCatalogCacheService from '@controleonline/ui-common/src/react/components/ProductCatalogCacheService';
|
|
17
17
|
import RuntimeInfoFooter from '@controleonline/ui-common/src/react/components/RuntimeInfoFooter';
|
|
18
|
+
import {shouldShowRuntimeFooter} from '@controleonline/ui-common/src/react/utils/runtimeFooter';
|
|
18
19
|
import { useStore } from '@store';
|
|
19
20
|
import { api } from '@controleonline/ui-common/src/api';
|
|
20
21
|
import {app_type} from '@appType';
|
|
@@ -100,6 +101,20 @@ const resolveDeviceConfigPeopleIri = ({appType, currentCompany, user}) => {
|
|
|
100
101
|
|
|
101
102
|
return '';
|
|
102
103
|
};
|
|
104
|
+
const isTenantAdministrativeAuthority = company => {
|
|
105
|
+
const userFlags = company?.user || {};
|
|
106
|
+
return !!(
|
|
107
|
+
userFlags.owner_enabled ||
|
|
108
|
+
userFlags.director_enabled ||
|
|
109
|
+
userFlags.manager_enabled ||
|
|
110
|
+
userFlags.admin_enabled ||
|
|
111
|
+
company?.owner_enabled ||
|
|
112
|
+
company?.director_enabled ||
|
|
113
|
+
company?.manager_enabled
|
|
114
|
+
);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
|
|
103
118
|
|
|
104
119
|
const normalizeRuntimeIp = value => String(value || '').trim();
|
|
105
120
|
|
|
@@ -234,6 +249,7 @@ export const DefaultProvider = ({
|
|
|
234
249
|
user,
|
|
235
250
|
});
|
|
236
251
|
const isPublicRouteActive = isPublicRoute(currentRouteName);
|
|
252
|
+
const showRuntimeFooter = shouldShowRuntimeFooter(currentRouteName);
|
|
237
253
|
const currentTranslationConfig = JSON.parse(
|
|
238
254
|
localStorage.getItem('config') || '{}',
|
|
239
255
|
);
|
|
@@ -716,6 +732,13 @@ export const DefaultProvider = ({
|
|
|
716
732
|
return;
|
|
717
733
|
}
|
|
718
734
|
|
|
735
|
+
// Non-admin users cannot mutate device context/financial policy (API 403).
|
|
736
|
+
// Skip bootstrap write; keep local runtime configs in memory only.
|
|
737
|
+
if (!isTenantAdministrativeAuthority(currentCompany)) {
|
|
738
|
+
setDeviceRuntimeConfigSynced(true);
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
741
|
+
|
|
719
742
|
deviceConfigsActions
|
|
720
743
|
.addDeviceConfigs({
|
|
721
744
|
device: device.id,
|
|
@@ -735,6 +758,7 @@ export const DefaultProvider = ({
|
|
|
735
758
|
deviceConfigFetched,
|
|
736
759
|
deviceConfigPeopleIri,
|
|
737
760
|
deviceRuntimeConfigSynced,
|
|
761
|
+
currentCompany,
|
|
738
762
|
deviceConfigsActions,
|
|
739
763
|
device_config?.configs,
|
|
740
764
|
isLogged,
|
|
@@ -959,7 +983,7 @@ export const DefaultProvider = ({
|
|
|
959
983
|
},
|
|
960
984
|
]}>
|
|
961
985
|
<View style={[providerStyles.content, runtimeUiScaleStyle]}>{children}</View>
|
|
962
|
-
{!isShopClientApp && bottomNavigationCount === 0 && (
|
|
986
|
+
{!isShopClientApp && showRuntimeFooter && bottomNavigationCount === 0 && (
|
|
963
987
|
<RuntimeInfoFooter
|
|
964
988
|
appVersion={appVersion}
|
|
965
989
|
defaultCompany={defaultCompany}
|