@controleonline/ui-common 1.2.71 → 1.2.75
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +100 -36
- 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 +2814 -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,89 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { colors } from '@controleonline/../../src/styles/colors';
|
|
5
|
+
|
|
6
|
+
import createStyles from './styles';
|
|
7
|
+
|
|
8
|
+
// Abas horizontais simples para reduzir densidade visual das páginas.
|
|
9
|
+
export default function IntegrationTabs({ tabs, activeKey, onChange, accentColor, palette = colors }) {
|
|
10
|
+
const styles = createStyles(palette);
|
|
11
|
+
const resolvedPrimaryBackground =
|
|
12
|
+
palette.buttonBackground ||
|
|
13
|
+
accentColor ||
|
|
14
|
+
palette.primary;
|
|
15
|
+
const resolvedPrimaryBorder =
|
|
16
|
+
palette.buttonBorder ||
|
|
17
|
+
resolvedPrimaryBackground;
|
|
18
|
+
const resolvedPrimaryText =
|
|
19
|
+
palette.buttonText ||
|
|
20
|
+
palette.white;
|
|
21
|
+
const resolvedSecondaryBackground =
|
|
22
|
+
palette.buttonBackgroundSecondary ||
|
|
23
|
+
palette.white;
|
|
24
|
+
const resolvedSecondaryBorder =
|
|
25
|
+
palette.buttonBorderSecondary ||
|
|
26
|
+
palette.border;
|
|
27
|
+
const resolvedSecondaryText =
|
|
28
|
+
palette.buttonTextSecondary ||
|
|
29
|
+
palette.textSecondary;
|
|
30
|
+
const resolvedSecondaryIcon =
|
|
31
|
+
palette.buttonIconSecondary ||
|
|
32
|
+
resolvedSecondaryText;
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<ScrollView
|
|
36
|
+
horizontal
|
|
37
|
+
showsHorizontalScrollIndicator={false}
|
|
38
|
+
contentContainerStyle={styles.scrollContent}>
|
|
39
|
+
{tabs.map(tab => {
|
|
40
|
+
const active = tab.key === activeKey;
|
|
41
|
+
const tabColors = active
|
|
42
|
+
? {
|
|
43
|
+
backgroundColor: resolvedPrimaryBackground,
|
|
44
|
+
borderColor: resolvedPrimaryBorder,
|
|
45
|
+
textColor: resolvedPrimaryText,
|
|
46
|
+
badgeBackground: palette.buttonPressedBackground || resolvedPrimaryBorder,
|
|
47
|
+
badgeText: resolvedPrimaryText,
|
|
48
|
+
}
|
|
49
|
+
: {
|
|
50
|
+
backgroundColor: resolvedSecondaryBackground,
|
|
51
|
+
borderColor: resolvedSecondaryBorder,
|
|
52
|
+
textColor: resolvedSecondaryText,
|
|
53
|
+
badgeBackground: palette.badgeBackground || resolvedSecondaryBackground,
|
|
54
|
+
badgeText: resolvedSecondaryIcon,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<TouchableOpacity
|
|
59
|
+
key={tab.key}
|
|
60
|
+
activeOpacity={0.85}
|
|
61
|
+
style={[
|
|
62
|
+
styles.tabButton,
|
|
63
|
+
{
|
|
64
|
+
backgroundColor: tabColors.backgroundColor,
|
|
65
|
+
borderColor: tabColors.borderColor,
|
|
66
|
+
},
|
|
67
|
+
]}
|
|
68
|
+
onPress={() => onChange(tab.key)}>
|
|
69
|
+
<Text style={[styles.tabLabel, { color: tabColors.textColor }]}>
|
|
70
|
+
{tab.label}
|
|
71
|
+
</Text>
|
|
72
|
+
|
|
73
|
+
{tab.badge !== undefined && tab.badge !== null && tab.badge !== '' && (
|
|
74
|
+
<View
|
|
75
|
+
style={[
|
|
76
|
+
styles.tabBadge,
|
|
77
|
+
{ backgroundColor: tabColors.badgeBackground },
|
|
78
|
+
]}>
|
|
79
|
+
<Text style={[styles.tabBadgeText, { color: tabColors.badgeText }]}>
|
|
80
|
+
{tab.badge}
|
|
81
|
+
</Text>
|
|
82
|
+
</View>
|
|
83
|
+
)}
|
|
84
|
+
</TouchableOpacity>
|
|
85
|
+
);
|
|
86
|
+
})}
|
|
87
|
+
</ScrollView>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import {colors} from '@controleonline/../../src/styles/colors';
|
|
3
|
+
|
|
4
|
+
const createStyles = (palette = colors) =>
|
|
5
|
+
StyleSheet.create({
|
|
6
|
+
scrollContent: {
|
|
7
|
+
gap: 8,
|
|
8
|
+
paddingBottom: 4,
|
|
9
|
+
},
|
|
10
|
+
tabButton: {
|
|
11
|
+
minHeight: 40,
|
|
12
|
+
borderRadius: 999,
|
|
13
|
+
borderWidth: 1,
|
|
14
|
+
borderColor: palette.buttonBorderSecondary || palette.border,
|
|
15
|
+
backgroundColor: palette.buttonBackgroundSecondary || palette.white,
|
|
16
|
+
paddingHorizontal: 14,
|
|
17
|
+
paddingVertical: 8,
|
|
18
|
+
flexDirection: 'row',
|
|
19
|
+
alignItems: 'center',
|
|
20
|
+
justifyContent: 'center',
|
|
21
|
+
gap: 8,
|
|
22
|
+
},
|
|
23
|
+
tabLabel: {
|
|
24
|
+
fontSize: 12,
|
|
25
|
+
fontWeight: '700',
|
|
26
|
+
color: palette.buttonTextSecondary || palette.textSecondary,
|
|
27
|
+
},
|
|
28
|
+
tabBadge: {
|
|
29
|
+
minWidth: 22,
|
|
30
|
+
height: 22,
|
|
31
|
+
borderRadius: 999,
|
|
32
|
+
backgroundColor: palette.badgeBackground || palette.border,
|
|
33
|
+
alignItems: 'center',
|
|
34
|
+
justifyContent: 'center',
|
|
35
|
+
paddingHorizontal: 6,
|
|
36
|
+
},
|
|
37
|
+
tabBadgeText: {
|
|
38
|
+
fontSize: 11,
|
|
39
|
+
fontWeight: '800',
|
|
40
|
+
color: palette.buttonIconSecondary || palette.textSecondary,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
export default createStyles;
|
|
@@ -27,6 +27,7 @@ export const DISPLAY_SIZE_MIN = 1;
|
|
|
27
27
|
export const DISPLAY_SIZE_MAX = 10;
|
|
28
28
|
export const DISPLAY_SIZE_DEFAULT = 5;
|
|
29
29
|
export const POS_OPERATION_MODE_CONFIG_KEY = 'pos-operation-mode';
|
|
30
|
+
export const POS_PRODUCT_SHOWCASE_CONFIG_KEY = 'pos-product-showcase-id';
|
|
30
31
|
export const DEVICE_ANDROID_KIOSK_ENABLED_CONFIG_KEY =
|
|
31
32
|
'android-kiosk-enabled';
|
|
32
33
|
export const DEVICE_ANDROID_LAUNCHER_ENABLED_CONFIG_KEY =
|
|
@@ -105,9 +106,10 @@ export const DEFAULT_DEVICE_CONFIGS = {
|
|
|
105
106
|
[POS_CHECK_ORDER_MANAGEMENT_MODE_CONFIG_KEY]:
|
|
106
107
|
POS_CHECK_ORDER_MANAGEMENT_MODE_MANAGE,
|
|
107
108
|
[POS_OPERATION_MODE_CONFIG_KEY]: POS_OPERATION_MODE_DEFAULT,
|
|
108
|
-
[
|
|
109
|
-
[
|
|
110
|
-
|
|
109
|
+
[POS_PRODUCT_SHOWCASE_CONFIG_KEY]: '',
|
|
110
|
+
[POS_AUTO_PRINT_ENABLED_CONFIG_KEY]: '0',
|
|
111
|
+
[POS_CASH_MANAGEMENT_MODE_CONFIG_KEY]: POS_CASH_MANAGEMENT_MODE_DEFAULT,
|
|
112
|
+
};
|
|
111
113
|
|
|
112
114
|
export const isTruthyValue = value =>
|
|
113
115
|
value === true || value === '1' || value === 1 || value === 'true';
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import React, { useCallback, useMemo } from 'react';
|
|
2
|
+
import { Platform, Text, TouchableOpacity, View } from 'react-native';
|
|
3
|
+
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
4
|
+
import { useFocusEffect, useNavigation } from '@react-navigation/native';
|
|
5
|
+
import Icon from 'react-native-vector-icons/Feather';
|
|
6
|
+
|
|
7
|
+
import { useStore } from '@store';
|
|
8
|
+
import { colors } from '@controleonline/../../src/styles/colors';
|
|
9
|
+
import { createStyles } from './Connections.styles';
|
|
10
|
+
import {
|
|
11
|
+
resolveThemePalette,
|
|
12
|
+
withOpacity,
|
|
13
|
+
} from '@controleonline/../../src/styles/branding';
|
|
14
|
+
import DefaultTable from '@controleonline/ui-default/src/react/components/table/DefaultTable';
|
|
15
|
+
|
|
16
|
+
const tt = (type, key) => global.t?.t('configs', type, key);
|
|
17
|
+
|
|
18
|
+
const resolveShadowStyle = textColor =>
|
|
19
|
+
Platform.select({
|
|
20
|
+
ios: {
|
|
21
|
+
shadowColor: textColor,
|
|
22
|
+
shadowOffset: { width: 0, height: 8 },
|
|
23
|
+
shadowOpacity: 0.08,
|
|
24
|
+
shadowRadius: 16,
|
|
25
|
+
},
|
|
26
|
+
android: { elevation: 3 },
|
|
27
|
+
web: { boxShadow: `0 10px 24px ${withOpacity(textColor, 0.08)}` },
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const formatPhoneLabel = phone => {
|
|
31
|
+
if (!phone) return tt('connections_label', 'notProvided') || 'Nao informado';
|
|
32
|
+
if (typeof phone === 'string') return phone;
|
|
33
|
+
const ddd = String(phone?.ddd || '').trim();
|
|
34
|
+
const digits = String(phone?.phone || '').replace(/\D/g, '');
|
|
35
|
+
if (!ddd && !digits) return tt('connections_label', 'notProvided') || 'Nao informado';
|
|
36
|
+
if (!digits) return `(${ddd})`;
|
|
37
|
+
const lastFour = digits.slice(-4);
|
|
38
|
+
const firstPart = digits.slice(0, -4);
|
|
39
|
+
if (!firstPart) return ddd ? `(${ddd}) ${lastFour}` : lastFour;
|
|
40
|
+
return ddd ? `(${ddd}) ${firstPart}-${lastFour}` : `${firstPart}-${lastFour}`;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const formatStatusLabel = status => {
|
|
44
|
+
if (!status) return tt('connections_status', 'unknown') || '—';
|
|
45
|
+
if (typeof status === 'string') return status;
|
|
46
|
+
return status?.status || status?.name || '—';
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export default function Connections() {
|
|
50
|
+
const navigation = useNavigation();
|
|
51
|
+
const peopleStore = useStore('people');
|
|
52
|
+
const themeStore = useStore('theme');
|
|
53
|
+
const connectionsStore = useStore('connections');
|
|
54
|
+
|
|
55
|
+
const { currentCompany } = peopleStore.getters || {};
|
|
56
|
+
const { colors: themeColors } = themeStore.getters || {};
|
|
57
|
+
const items = connectionsStore.getters?.items;
|
|
58
|
+
const totalItems = connectionsStore.getters?.totalItems;
|
|
59
|
+
|
|
60
|
+
const brandColors = useMemo(
|
|
61
|
+
() =>
|
|
62
|
+
resolveThemePalette(
|
|
63
|
+
{ ...themeColors, ...(currentCompany?.theme?.colors || {}) },
|
|
64
|
+
colors,
|
|
65
|
+
),
|
|
66
|
+
[themeColors, currentCompany?.id],
|
|
67
|
+
);
|
|
68
|
+
const styles = useMemo(() => createStyles(brandColors), [brandColors]);
|
|
69
|
+
const shadowStyle = useMemo(
|
|
70
|
+
() => resolveShadowStyle(brandColors.text),
|
|
71
|
+
[brandColors.text],
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const providerId = currentCompany?.id;
|
|
75
|
+
const peopleIri = useMemo(
|
|
76
|
+
() => (providerId ? `/people/${String(providerId).replace(/\D/g, '')}` : ''),
|
|
77
|
+
[providerId],
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const requestParams = useMemo(
|
|
81
|
+
() => (peopleIri ? { people: peopleIri } : {}),
|
|
82
|
+
[peopleIri],
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
const connectionCount = useMemo(() => {
|
|
86
|
+
if (typeof totalItems === 'number' && totalItems > 0) return totalItems;
|
|
87
|
+
return Array.isArray(items) ? items.length : 0;
|
|
88
|
+
}, [items, totalItems]);
|
|
89
|
+
|
|
90
|
+
useFocusEffect(
|
|
91
|
+
useCallback(() => {
|
|
92
|
+
if (!peopleIri || typeof connectionsStore.actions?.getItems !== 'function') {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
connectionsStore.actions.getItems({ people: peopleIri });
|
|
96
|
+
}, [peopleIri]),
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const openWhatsAppChannel = useCallback(() => {
|
|
100
|
+
navigation.navigate('WhatsAppConnectionPage');
|
|
101
|
+
}, [navigation]);
|
|
102
|
+
|
|
103
|
+
const renderConnectionCard = useCallback(
|
|
104
|
+
({ item }) => {
|
|
105
|
+
if (!item) return null;
|
|
106
|
+
return (
|
|
107
|
+
<View>
|
|
108
|
+
<Text style={styles.previewName}>
|
|
109
|
+
{item.name || tt('connections_label', 'unnamed') || 'Sem nome'}
|
|
110
|
+
</Text>
|
|
111
|
+
<Text style={styles.previewPhone}>{formatPhoneLabel(item.phone)}</Text>
|
|
112
|
+
<Text style={styles.previewStatus}>{formatStatusLabel(item.status)}</Text>
|
|
113
|
+
</View>
|
|
114
|
+
);
|
|
115
|
+
},
|
|
116
|
+
[styles.previewName, styles.previewPhone, styles.previewStatus],
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
if (!providerId) {
|
|
120
|
+
return (
|
|
121
|
+
<SafeAreaView style={styles.container} edges={['bottom']}>
|
|
122
|
+
<View style={styles.centerState}>
|
|
123
|
+
<Icon name="building" size={32} color={brandColors.textSecondary} />
|
|
124
|
+
<Text style={styles.centerStateTitle}>
|
|
125
|
+
{tt('connections_title', 'selectCompany') || 'Selecione uma empresa'}
|
|
126
|
+
</Text>
|
|
127
|
+
<Text style={styles.centerStateText}>
|
|
128
|
+
{tt('connections_text', 'selectCompany') ||
|
|
129
|
+
'As conexoes disponiveis dependem da empresa ativa.'}
|
|
130
|
+
</Text>
|
|
131
|
+
</View>
|
|
132
|
+
</SafeAreaView>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<SafeAreaView
|
|
138
|
+
style={[styles.container, { backgroundColor: brandColors.background }]}
|
|
139
|
+
edges={['bottom']}>
|
|
140
|
+
<View style={[styles.heroCard, shadowStyle, { backgroundColor: brandColors.primary }]}>
|
|
141
|
+
<View style={styles.heroCopy}>
|
|
142
|
+
<Text style={styles.heroEyebrow}>
|
|
143
|
+
{tt('connections_eyebrow', 'communication') || 'COMUNICACAO'}
|
|
144
|
+
</Text>
|
|
145
|
+
<Text style={styles.heroTitle}>
|
|
146
|
+
{tt('connections_title', 'connections') || 'Conexoes'}
|
|
147
|
+
</Text>
|
|
148
|
+
<Text style={styles.heroText}>
|
|
149
|
+
{tt('connections_text', 'hero') ||
|
|
150
|
+
'Gerencie os canais de comunicacao conectados com a sua operacao.'}
|
|
151
|
+
</Text>
|
|
152
|
+
</View>
|
|
153
|
+
<View style={styles.heroBadge}>
|
|
154
|
+
<Icon name="radio" size={22} color={brandColors.primary} />
|
|
155
|
+
</View>
|
|
156
|
+
</View>
|
|
157
|
+
|
|
158
|
+
<View style={styles.companyRow}>
|
|
159
|
+
<View style={styles.companyBadge}>
|
|
160
|
+
<Text style={styles.companyBadgeText}>
|
|
161
|
+
{`${connectionCount} ${tt('connections_label', 'connections') || 'conexoes'}`}
|
|
162
|
+
</Text>
|
|
163
|
+
</View>
|
|
164
|
+
</View>
|
|
165
|
+
|
|
166
|
+
<TouchableOpacity
|
|
167
|
+
activeOpacity={0.92}
|
|
168
|
+
onPress={openWhatsAppChannel}
|
|
169
|
+
style={[styles.channelCard, shadowStyle]}>
|
|
170
|
+
<View style={styles.channelTopRow}>
|
|
171
|
+
<View
|
|
172
|
+
style={[
|
|
173
|
+
styles.channelIconWrap,
|
|
174
|
+
{ backgroundColor: withOpacity(brandColors.success, 0.12) },
|
|
175
|
+
]}>
|
|
176
|
+
<Icon name="message-circle" size={20} color={brandColors.success} />
|
|
177
|
+
</View>
|
|
178
|
+
<View style={styles.channelStatusPill}>
|
|
179
|
+
<Text style={styles.channelStatusText}>
|
|
180
|
+
{connectionCount > 0
|
|
181
|
+
? `${connectionCount} ${tt('connections_status', 'configured') || 'configurada(s)'}`
|
|
182
|
+
: tt('connections_status', 'readyToConfigure') || 'Pronta para configurar'}
|
|
183
|
+
</Text>
|
|
184
|
+
</View>
|
|
185
|
+
</View>
|
|
186
|
+
<Text style={styles.channelTitle}>
|
|
187
|
+
{tt('connections_label', 'whatsApp') || 'WhatsApp'}
|
|
188
|
+
</Text>
|
|
189
|
+
<Text style={styles.channelDescription}>
|
|
190
|
+
{tt('connections_text', 'whatsApp') ||
|
|
191
|
+
'Conecte numeros, acompanhe status e gere o QR Code de autenticacao.'}
|
|
192
|
+
</Text>
|
|
193
|
+
<View style={styles.actionRow}>
|
|
194
|
+
<Text style={styles.actionText}>
|
|
195
|
+
{tt('connections_button', 'openChannel') || 'Abrir canal'}
|
|
196
|
+
</Text>
|
|
197
|
+
<Icon name="arrow-right" size={18} color={brandColors.primary} />
|
|
198
|
+
</View>
|
|
199
|
+
</TouchableOpacity>
|
|
200
|
+
|
|
201
|
+
<View style={{ flex: 1, marginTop: 12 }}>
|
|
202
|
+
<DefaultTable
|
|
203
|
+
storeName="connections"
|
|
204
|
+
requestParams={requestParams}
|
|
205
|
+
initialViewMode="cards"
|
|
206
|
+
forceCardsOnCompact
|
|
207
|
+
showToolbar
|
|
208
|
+
showRowActions={false}
|
|
209
|
+
showColumnFiltersButton
|
|
210
|
+
onRowPress={openWhatsAppChannel}
|
|
211
|
+
renderCard={renderConnectionCard}
|
|
212
|
+
searchProps={{
|
|
213
|
+
compact: true,
|
|
214
|
+
placeholder:
|
|
215
|
+
tt('connections_label', 'search') || 'Buscar conexao, telefone ou status',
|
|
216
|
+
searchKey: 'search',
|
|
217
|
+
storeName: 'connections',
|
|
218
|
+
}}
|
|
219
|
+
totalItemsLabel="connections"
|
|
220
|
+
visibleColumnsPreferenceKey="connections"
|
|
221
|
+
accentColor={brandColors.primary}
|
|
222
|
+
onAdd={openWhatsAppChannel}
|
|
223
|
+
add
|
|
224
|
+
addLabel={tt('connections_button', 'openChannel') || 'Abrir canal'}
|
|
225
|
+
/>
|
|
226
|
+
</View>
|
|
227
|
+
</SafeAreaView>
|
|
228
|
+
);
|
|
229
|
+
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import { colors } from '@controleonline/../../src/styles/colors';
|
|
3
|
+
import { withOpacity } from '@controleonline/../../src/styles/branding';
|
|
4
|
+
|
|
5
|
+
export const createStyles = (palette = colors) =>
|
|
6
|
+
StyleSheet.create({
|
|
7
|
+
container: {
|
|
8
|
+
flex: 1,
|
|
9
|
+
backgroundColor: palette.background,
|
|
10
|
+
},
|
|
11
|
+
scroll: {
|
|
12
|
+
paddingHorizontal: 16,
|
|
13
|
+
paddingTop: 16,
|
|
14
|
+
paddingBottom: 32,
|
|
15
|
+
},
|
|
16
|
+
centerState: {
|
|
17
|
+
flex: 1,
|
|
18
|
+
justifyContent: 'center',
|
|
19
|
+
alignItems: 'center',
|
|
20
|
+
paddingHorizontal: 28,
|
|
21
|
+
},
|
|
22
|
+
centerStateTitle: {
|
|
23
|
+
marginTop: 16,
|
|
24
|
+
fontSize: 18,
|
|
25
|
+
fontWeight: '700',
|
|
26
|
+
color: palette.text,
|
|
27
|
+
textAlign: 'center',
|
|
28
|
+
},
|
|
29
|
+
centerStateText: {
|
|
30
|
+
marginTop: 8,
|
|
31
|
+
fontSize: 14,
|
|
32
|
+
lineHeight: 21,
|
|
33
|
+
color: palette.textSecondary,
|
|
34
|
+
textAlign: 'center',
|
|
35
|
+
},
|
|
36
|
+
heroCard: {
|
|
37
|
+
borderRadius: 28,
|
|
38
|
+
paddingHorizontal: 22,
|
|
39
|
+
paddingVertical: 24,
|
|
40
|
+
marginBottom: 18,
|
|
41
|
+
flexDirection: 'row',
|
|
42
|
+
alignItems: 'flex-start',
|
|
43
|
+
justifyContent: 'space-between',
|
|
44
|
+
},
|
|
45
|
+
heroCopy: {
|
|
46
|
+
flex: 1,
|
|
47
|
+
paddingRight: 16,
|
|
48
|
+
},
|
|
49
|
+
heroEyebrow: {
|
|
50
|
+
fontSize: 13,
|
|
51
|
+
fontWeight: '800',
|
|
52
|
+
letterSpacing: 1.4,
|
|
53
|
+
color: withOpacity(palette.white, 0.82),
|
|
54
|
+
marginBottom: 10,
|
|
55
|
+
},
|
|
56
|
+
heroTitle: {
|
|
57
|
+
fontSize: 22,
|
|
58
|
+
fontWeight: '800',
|
|
59
|
+
color: palette.white,
|
|
60
|
+
marginBottom: 8,
|
|
61
|
+
},
|
|
62
|
+
heroText: {
|
|
63
|
+
fontSize: 14,
|
|
64
|
+
lineHeight: 21,
|
|
65
|
+
color: withOpacity(palette.white, 0.88),
|
|
66
|
+
},
|
|
67
|
+
heroBadge: {
|
|
68
|
+
width: 54,
|
|
69
|
+
height: 54,
|
|
70
|
+
borderRadius: 18,
|
|
71
|
+
backgroundColor: palette.white,
|
|
72
|
+
alignItems: 'center',
|
|
73
|
+
justifyContent: 'center',
|
|
74
|
+
},
|
|
75
|
+
companyRow: {
|
|
76
|
+
flexDirection: 'row',
|
|
77
|
+
alignItems: 'flex-start',
|
|
78
|
+
justifyContent: 'space-between',
|
|
79
|
+
marginBottom: 18,
|
|
80
|
+
gap: 12,
|
|
81
|
+
},
|
|
82
|
+
sectionTitle: {
|
|
83
|
+
fontSize: 13,
|
|
84
|
+
fontWeight: '700',
|
|
85
|
+
color: palette.textSecondary,
|
|
86
|
+
marginBottom: 4,
|
|
87
|
+
},
|
|
88
|
+
companyName: {
|
|
89
|
+
fontSize: 21,
|
|
90
|
+
fontWeight: '800',
|
|
91
|
+
color: palette.text,
|
|
92
|
+
},
|
|
93
|
+
companyBadge: {
|
|
94
|
+
borderRadius: 999,
|
|
95
|
+
paddingHorizontal: 12,
|
|
96
|
+
paddingVertical: 8,
|
|
97
|
+
backgroundColor: withOpacity(palette.info, 0.12),
|
|
98
|
+
},
|
|
99
|
+
companyBadgeText: {
|
|
100
|
+
fontSize: 13,
|
|
101
|
+
fontWeight: '700',
|
|
102
|
+
color: palette.info,
|
|
103
|
+
},
|
|
104
|
+
channelCard: {
|
|
105
|
+
borderRadius: 28,
|
|
106
|
+
backgroundColor: palette.white,
|
|
107
|
+
padding: 18,
|
|
108
|
+
},
|
|
109
|
+
channelTopRow: {
|
|
110
|
+
flexDirection: 'row',
|
|
111
|
+
alignItems: 'center',
|
|
112
|
+
justifyContent: 'space-between',
|
|
113
|
+
marginBottom: 16,
|
|
114
|
+
gap: 12,
|
|
115
|
+
},
|
|
116
|
+
channelIconWrap: {
|
|
117
|
+
width: 56,
|
|
118
|
+
height: 56,
|
|
119
|
+
borderRadius: 18,
|
|
120
|
+
alignItems: 'center',
|
|
121
|
+
justifyContent: 'center',
|
|
122
|
+
},
|
|
123
|
+
channelStatusPill: {
|
|
124
|
+
borderRadius: 999,
|
|
125
|
+
backgroundColor: palette.background,
|
|
126
|
+
paddingHorizontal: 12,
|
|
127
|
+
paddingVertical: 8,
|
|
128
|
+
},
|
|
129
|
+
channelStatusText: {
|
|
130
|
+
fontSize: 13,
|
|
131
|
+
fontWeight: '700',
|
|
132
|
+
color: palette.textSecondary,
|
|
133
|
+
},
|
|
134
|
+
channelTitle: {
|
|
135
|
+
fontSize: 28,
|
|
136
|
+
fontWeight: '800',
|
|
137
|
+
color: palette.text,
|
|
138
|
+
marginBottom: 8,
|
|
139
|
+
},
|
|
140
|
+
channelDescription: {
|
|
141
|
+
fontSize: 14,
|
|
142
|
+
lineHeight: 21,
|
|
143
|
+
color: palette.textSecondary,
|
|
144
|
+
marginBottom: 18,
|
|
145
|
+
},
|
|
146
|
+
metaRow: {
|
|
147
|
+
flexDirection: 'row',
|
|
148
|
+
gap: 12,
|
|
149
|
+
marginBottom: 16,
|
|
150
|
+
},
|
|
151
|
+
metaItem: {
|
|
152
|
+
flex: 1,
|
|
153
|
+
borderRadius: 18,
|
|
154
|
+
backgroundColor: palette.background,
|
|
155
|
+
paddingHorizontal: 14,
|
|
156
|
+
paddingVertical: 14,
|
|
157
|
+
},
|
|
158
|
+
metaLabel: {
|
|
159
|
+
fontSize: 12,
|
|
160
|
+
fontWeight: '700',
|
|
161
|
+
color: palette.textSecondary,
|
|
162
|
+
marginBottom: 6,
|
|
163
|
+
},
|
|
164
|
+
metaValue: {
|
|
165
|
+
fontSize: 18,
|
|
166
|
+
fontWeight: '800',
|
|
167
|
+
color: palette.text,
|
|
168
|
+
},
|
|
169
|
+
previewList: {
|
|
170
|
+
gap: 12,
|
|
171
|
+
},
|
|
172
|
+
previewRow: {
|
|
173
|
+
flexDirection: 'row',
|
|
174
|
+
alignItems: 'center',
|
|
175
|
+
justifyContent: 'space-between',
|
|
176
|
+
borderRadius: 18,
|
|
177
|
+
backgroundColor: palette.background,
|
|
178
|
+
paddingHorizontal: 14,
|
|
179
|
+
paddingVertical: 14,
|
|
180
|
+
gap: 12,
|
|
181
|
+
},
|
|
182
|
+
previewName: {
|
|
183
|
+
fontSize: 15,
|
|
184
|
+
fontWeight: '700',
|
|
185
|
+
color: palette.text,
|
|
186
|
+
marginBottom: 4,
|
|
187
|
+
},
|
|
188
|
+
previewPhone: {
|
|
189
|
+
fontSize: 13,
|
|
190
|
+
color: palette.textSecondary,
|
|
191
|
+
},
|
|
192
|
+
previewStatus: {
|
|
193
|
+
fontSize: 13,
|
|
194
|
+
fontWeight: '700',
|
|
195
|
+
color: palette.info,
|
|
196
|
+
},
|
|
197
|
+
emptyInline: {
|
|
198
|
+
borderRadius: 18,
|
|
199
|
+
backgroundColor: palette.background,
|
|
200
|
+
paddingHorizontal: 14,
|
|
201
|
+
paddingVertical: 16,
|
|
202
|
+
},
|
|
203
|
+
emptyInlineText: {
|
|
204
|
+
fontSize: 14,
|
|
205
|
+
lineHeight: 21,
|
|
206
|
+
color: palette.textSecondary,
|
|
207
|
+
},
|
|
208
|
+
actionRow: {
|
|
209
|
+
marginTop: 18,
|
|
210
|
+
flexDirection: 'row',
|
|
211
|
+
alignItems: 'center',
|
|
212
|
+
justifyContent: 'space-between',
|
|
213
|
+
},
|
|
214
|
+
actionText: {
|
|
215
|
+
fontSize: 15,
|
|
216
|
+
fontWeight: '800',
|
|
217
|
+
color: palette.text,
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
const styles = createStyles(colors);
|
|
222
|
+
export default styles;
|