@controleonline/ui-common 1.2.71 → 1.2.76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/actions/workers/manager/action.yml +147 -0
- package/.github/actions/workers/qa/action.yml +44 -0
- package/.github/actions/workers/security/action.yml +44 -0
- package/.github/actions/workers/technical-documenter/action.yml +51 -0
- package/.github/workflows/manager-worker.yml +168 -0
- package/.github/workflows/publish-npm.yml +45 -0
- package/.gitmodules +3 -0
- package/AGENTS.md +6 -0
- package/README.md +14 -0
- package/package.json +3 -2
- package/src/api/fetch.js +1 -1
- package/src/api/index.js +92 -22
- package/src/react/components/AddImportModal.js +94 -110
- package/src/react/components/BottomNavigationBar.config.js +211 -231
- package/src/react/components/CategoryForm.js +52 -35
- package/src/react/components/DefaultProvider.native.js +131 -95
- package/src/react/components/DefaultProvider.web.js +148 -74
- package/src/react/components/NetworkPrinterPreviewModal.js +249 -0
- package/src/react/components/NetworkPrinterPreviewModal.styles.js +159 -0
- package/src/react/components/RuntimeInfoFooter.js +164 -104
- package/src/react/components/RuntimeInfoFooter.styles.js +3 -0
- package/src/react/components/UnifiedPaymentBar.js +7 -4
- package/src/react/components/UserAvatar.js +160 -0
- package/src/react/components/integrations/IntegrationHero/index.js +48 -0
- package/src/react/components/integrations/IntegrationHero/styles.js +57 -0
- package/src/react/components/integrations/IntegrationTabs/index.js +89 -0
- package/src/react/components/integrations/IntegrationTabs/styles.js +44 -0
- package/src/react/config/deviceConfigBootstrap.js +5 -3
- package/src/react/pages/Connections.js +229 -0
- package/src/react/pages/Connections.styles.js +222 -0
- package/src/react/pages/DeviceDetailPage.js +2865 -0
- package/src/react/pages/DeviceDetailPage.styles.js +308 -0
- package/src/react/pages/Devices/currentDevice.js +194 -0
- package/src/react/pages/Devices/deviceTypes/DeviceGroupCard.js +257 -0
- package/src/react/pages/Devices/deviceTypes/all.js +23 -0
- package/src/react/pages/Devices/deviceTypes/device.js +25 -0
- package/src/react/pages/Devices/deviceTypes/deviceListHelpers.js +178 -0
- package/src/react/pages/Devices/deviceTypes/display.js +26 -0
- package/src/react/pages/Devices/deviceTypes/index.js +145 -0
- package/src/react/pages/Devices/deviceTypes/ipCamera.js +35 -0
- package/src/react/pages/Devices/deviceTypes/pdv.js +88 -0
- package/src/react/pages/Devices/deviceTypes/printer.js +37 -0
- package/src/react/pages/Devices/deviceTypes/shared.js +453 -0
- package/src/react/pages/Devices/deviceTypes/useDeviceNetworkConnectivity.js +145 -0
- package/src/react/pages/Devices.js +183 -0
- package/src/react/pages/Devices.styles.js +353 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99CatalogTab.js +219 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99OverviewTab.js +134 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99PreviewModal.js +173 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99ProductCard.js +1 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99QuickWalletModal.js +181 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99SettingsTab.js +306 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99StoreTab.js +417 -0
- package/src/react/pages/Food99IntegrationPage/index.js +1530 -0
- package/src/react/pages/Food99IntegrationPage/styles.js +792 -0
- package/src/react/pages/Food99IntegrationPage/utils.js +155 -0
- package/src/react/pages/Food99IntegrationPage.js +1 -0
- package/src/react/pages/Food99IntegrationPage.styles.js +1 -0
- package/src/react/pages/GenericLogPage.js +42 -167
- package/src/react/pages/IFoodIntegrationPage/components/IFoodCatalogTab.js +8 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodOperationsTab.js +420 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodOverviewTab.js +118 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodPreviewModal.js +103 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodProductCard.js +1 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodStoreTab.js +150 -0
- package/src/react/pages/IFoodIntegrationPage/index.js +1298 -0
- package/src/react/pages/IFoodIntegrationPage/styles.js +764 -0
- package/src/react/pages/IFoodIntegrationPage/utils.js +91 -0
- package/src/react/pages/IFoodIntegrationPage.js +1 -0
- package/src/react/pages/IFoodIntegrationPage.styles.js +1 -0
- package/src/react/pages/Imports.js +214 -166
- package/src/react/pages/IntegrationConfigPage.js +744 -0
- package/src/react/pages/IntegrationConfigPage.styles.js +269 -0
- package/src/react/pages/Integrations.js +299 -0
- package/src/react/pages/Integrations.styles.js +130 -0
- package/src/react/pages/ManagerOrderNotificationsPage.js +642 -0
- package/src/react/pages/MarketplaceIntegrationPage/components/MarketplaceProductCard.js +205 -0
- package/src/react/pages/MarketplaceIntegrationPage/components/RemoteMarketplaceMenuTab.js +335 -0
- package/src/react/pages/MarketplaceIntegrationPage/index.js +60 -0
- package/src/react/pages/MarketplaceIntegrationPage/utils.js +137 -0
- package/src/react/pages/MercadoLivreIntegrationPage.js +538 -0
- package/src/react/pages/PrinterDeviceDetailPage.js +1916 -0
- package/src/react/pages/PrinterDeviceDetailPage.styles.js +223 -0
- package/src/react/pages/PrinterDeviceFormPage.js +521 -0
- package/src/react/pages/PrinterDeviceFormPage.styles.js +159 -0
- package/src/react/pages/WhatsAppConnectionPage.js +459 -0
- package/src/react/pages/WhatsAppConnectionPage.styles.js +284 -0
- package/src/react/pages/integrationsCatalog.js +399 -0
- package/src/react/services/Cielo/Cielo.js +193 -193
- package/src/react/utils/categoryContexts.js +46 -0
- package/src/react/utils/entityDisplay.js +222 -217
- package/src/react/utils/fileUrl.js +39 -20
- package/src/react/utils/integrationPage.js +16 -0
- package/src/react/utils/runtimeFooter.js +40 -22
- package/src/react/utils/runtimeLanguage.js +50 -9
- package/src/react/utils/runtimeMenu.js +191 -131
- package/src/react/utils/runtimeZoom.js +43 -0
- package/src/react/utils/shopConfig.js +27 -15
- package/src/react/utils/shopFranchises.js +126 -1
- package/src/react/utils/storeColumns.js +23 -4
- package/src/react/utils/userAvatar.js +104 -0
- package/src/store/categories/index.js +48 -20
- package/src/store/device_config/index.js +62 -21
- package/src/store/entity_log/index.js +22 -1
- package/src/store/imports/customActions.js +51 -0
- package/src/store/imports/index.js +89 -88
- package/src/store/status/index.js +11 -11
- package/src/store/themes/index.js +22 -0
- package/src/store/timezones/index.js +3 -1
- package/src/tests/browser/manager/connections.spec.js +143 -0
- package/src/tests/browser/manager/devices-current.spec.js +343 -0
- package/src/tests/browser/manager/mercado-livre-integration.spec.js +268 -0
- package/src/tests/react/api/deviceHeaders.test.js +114 -0
- package/src/tests/react/components/AddImportModal.test.js +166 -0
- package/src/tests/react/components/BottomNavigationBar.config.test.js +20 -0
- package/src/tests/react/components/UserAvatar.test.js +52 -0
- package/src/tests/react/pages/DevicePickerStyles.test.js +47 -0
- package/src/tests/react/pages/Devices/deviceListHelpers.test.js +39 -0
- package/src/tests/react/pages/DevicesCurrentDevice.test.js +198 -0
- package/src/tests/react/pages/connectionsHelpers.test.js +34 -0
- package/src/tests/react/pages/mercadoLivreIntegrationPageContract.test.mjs +16 -0
- package/src/tests/react/services/Cielo.test.js +190 -190
- package/src/tests/react/store/categoriesOrdering.test.js +26 -0
- package/src/tests/react/utils/appDomain.test.js +62 -0
- package/src/tests/react/utils/entityDisplay.test.js +2 -2
- package/src/tests/react/utils/fileUrl.test.js +3 -3
- package/src/tests/react/utils/formatter.test.mjs +33 -0
- package/src/tests/react/utils/runtimeFooter.test.js +29 -4
- package/src/tests/react/utils/runtimeLanguage.test.js +79 -9
- package/src/tests/react/utils/runtimeMenu.test.js +198 -134
- package/src/tests/react/utils/runtimeZoom.test.js +38 -0
- package/src/tests/react/utils/shopConfig.test.js +10 -9
- package/src/tests/react/utils/shopFranchises.test.js +43 -0
- package/src/tests/react/utils/translate.discovery.test.mjs +170 -0
- package/src/tests/react/utils/translate.test.helpers.mjs +152 -0
- package/src/tests/react/utils/translate.test.mjs +141 -349
- package/src/tests/react/utils/userAvatar.test.js +63 -0
- package/src/utils/appDomain.js +15 -4
- package/src/utils/formatter.js +104 -16
- package/src/utils/integrationConfigs.js +80 -80
- package/src/utils/translate.js +222 -438
- package/src/utils/translateDiscovery.js +96 -0
- package/src/utils/translateNormalize.js +33 -0
- package/src/utils/translatePending.js +92 -0
- package/src/utils/translateStorage.js +142 -0
- package/.github/agents/developer.agent.md +0 -30
- package/.github/agents/devops.agent.md +0 -30
- package/.github/agents/qa.agent.md +0 -30
- package/.github/agents/security.agent.md +0 -30
- package/.github/workflows/npmjs.yml +0 -35
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
ActivityIndicator,
|
|
4
|
+
Text,
|
|
5
|
+
TextInput,
|
|
6
|
+
TouchableOpacity,
|
|
7
|
+
View,
|
|
8
|
+
} from 'react-native';
|
|
9
|
+
import Icon from 'react-native-vector-icons/Feather';
|
|
10
|
+
import { colors } from '@controleonline/../../src/styles/colors';
|
|
11
|
+
|
|
12
|
+
import {withOpacity} from '@controleonline/../../src/styles/branding';
|
|
13
|
+
import CompactFilterSelector from '@controleonline/ui-default/src/react/components/filters/CompactFilterSelector';
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
normalizeMarketplaceCatalogProduct,
|
|
17
|
+
normalizeMarketplaceCatalogTabProps,
|
|
18
|
+
} from '../../MarketplaceIntegrationPage/utils';
|
|
19
|
+
import MarketplaceProductCard from '../../MarketplaceIntegrationPage/components/MarketplaceProductCard';
|
|
20
|
+
import styles from '../styles';
|
|
21
|
+
import {
|
|
22
|
+
filterTabs,
|
|
23
|
+
MINIMUM_REQUIRED_ITEMS as DEFAULT_MINIMUM_REQUIRED_ITEMS,
|
|
24
|
+
} from '../utils';
|
|
25
|
+
|
|
26
|
+
const resolveButtonPalette = (palette, accentColor) => {
|
|
27
|
+
const primaryBackground =
|
|
28
|
+
palette.buttonBackground || accentColor || palette.primary;
|
|
29
|
+
const primaryBorder = palette.buttonBorder || primaryBackground;
|
|
30
|
+
const primaryText = palette.buttonText || palette.white;
|
|
31
|
+
const primaryIcon = palette.buttonIcon || primaryText;
|
|
32
|
+
const disabledBackground =
|
|
33
|
+
palette.buttonDisabledBackground || palette.border;
|
|
34
|
+
const disabledBorder = palette.buttonBorderSecondary || palette.border;
|
|
35
|
+
const disabledText = palette.buttonDisabledText || palette.textSecondary;
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
primaryBackground,
|
|
39
|
+
primaryBorder,
|
|
40
|
+
primaryText,
|
|
41
|
+
primaryIcon,
|
|
42
|
+
disabledBackground,
|
|
43
|
+
disabledBorder,
|
|
44
|
+
disabledText,
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// Aba separada para seleção e publicação do catálogo 99Food.
|
|
49
|
+
export default function Food99CatalogTab(props) {
|
|
50
|
+
const {
|
|
51
|
+
shadowStyle,
|
|
52
|
+
accentColor,
|
|
53
|
+
providerKey,
|
|
54
|
+
selectionSummaryTone,
|
|
55
|
+
search,
|
|
56
|
+
setSearch,
|
|
57
|
+
filterKey,
|
|
58
|
+
setFilterKey,
|
|
59
|
+
tabCounts,
|
|
60
|
+
productsResponse,
|
|
61
|
+
selectedEligibleProducts,
|
|
62
|
+
previewLoading,
|
|
63
|
+
onPreview,
|
|
64
|
+
filteredProducts,
|
|
65
|
+
selectedProductSet,
|
|
66
|
+
onToggleProduct,
|
|
67
|
+
onMarkCardPressHandled,
|
|
68
|
+
minimumRequiredItems,
|
|
69
|
+
palette = colors,
|
|
70
|
+
} = normalizeMarketplaceCatalogTabProps(props, {
|
|
71
|
+
providerKey: props?.providerKey || '99food',
|
|
72
|
+
defaultMinimumRequiredItems: DEFAULT_MINIMUM_REQUIRED_ITEMS,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const normalizedProducts = React.useMemo(
|
|
76
|
+
() =>
|
|
77
|
+
filteredProducts.map(product =>
|
|
78
|
+
normalizeMarketplaceCatalogProduct(product, providerKey),
|
|
79
|
+
),
|
|
80
|
+
[filteredProducts, providerKey],
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const filterOptions = filterTabs.map(tab => ({
|
|
84
|
+
key: tab.key,
|
|
85
|
+
label: `${tab.label} (${tabCounts[tab.key] || 0})`,
|
|
86
|
+
}));
|
|
87
|
+
const selectedFilterLabel =
|
|
88
|
+
filterOptions.find(option => option.key === filterKey)?.label ||
|
|
89
|
+
filterOptions[0]?.label ||
|
|
90
|
+
'Todos';
|
|
91
|
+
const buttonPalette = resolveButtonPalette(palette, accentColor);
|
|
92
|
+
const previewDisabled =
|
|
93
|
+
previewLoading || selectedEligibleProducts.length < minimumRequiredItems;
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<View style={[styles.panel, shadowStyle]}>
|
|
97
|
+
<View style={styles.panelHeader}>
|
|
98
|
+
<View>
|
|
99
|
+
<Text style={styles.panelTitle}>Selecao de produtos</Text>
|
|
100
|
+
<Text style={styles.panelSubtitle}>
|
|
101
|
+
Escolha pelo menos {minimumRequiredItems} produtos elegiveis para o
|
|
102
|
+
catalogo.
|
|
103
|
+
</Text>
|
|
104
|
+
</View>
|
|
105
|
+
<View
|
|
106
|
+
style={[
|
|
107
|
+
styles.selectionBadge,
|
|
108
|
+
{backgroundColor: withOpacity(selectionSummaryTone, 0.12)},
|
|
109
|
+
]}>
|
|
110
|
+
<Text
|
|
111
|
+
style={[styles.selectionBadgeText, {color: selectionSummaryTone}]}>
|
|
112
|
+
{selectedEligibleProducts.length}/{minimumRequiredItems}
|
|
113
|
+
</Text>
|
|
114
|
+
</View>
|
|
115
|
+
</View>
|
|
116
|
+
|
|
117
|
+
<View style={styles.searchBox}>
|
|
118
|
+
<Icon name="search" size={16} color={palette.textSecondary} />
|
|
119
|
+
<TextInput
|
|
120
|
+
value={search}
|
|
121
|
+
onChangeText={setSearch}
|
|
122
|
+
placeholder="Buscar produto, categoria ou codigo"
|
|
123
|
+
placeholderTextColor={palette.textSecondary}
|
|
124
|
+
style={styles.searchInput}
|
|
125
|
+
/>
|
|
126
|
+
</View>
|
|
127
|
+
|
|
128
|
+
<CompactFilterSelector
|
|
129
|
+
icon="filter"
|
|
130
|
+
label={selectedFilterLabel}
|
|
131
|
+
title="Produtos do catalogo"
|
|
132
|
+
accentColor={accentColor}
|
|
133
|
+
active={filterKey !== filterTabs[0]?.key}
|
|
134
|
+
options={filterOptions}
|
|
135
|
+
selectedKey={filterKey}
|
|
136
|
+
onSelect={optionKey => {
|
|
137
|
+
setFilterKey(optionKey);
|
|
138
|
+
return true;
|
|
139
|
+
}}
|
|
140
|
+
/>
|
|
141
|
+
|
|
142
|
+
<View style={styles.selectionSummaryRow}>
|
|
143
|
+
<Text style={styles.selectionSummaryText}>
|
|
144
|
+
{productsResponse?.eligible_product_count || 0} produtos aptos no
|
|
145
|
+
cadastro atual
|
|
146
|
+
</Text>
|
|
147
|
+
<TouchableOpacity
|
|
148
|
+
style={[
|
|
149
|
+
styles.previewButton,
|
|
150
|
+
{
|
|
151
|
+
borderWidth: 1,
|
|
152
|
+
borderColor: previewDisabled
|
|
153
|
+
? buttonPalette.disabledBorder
|
|
154
|
+
: buttonPalette.primaryBorder,
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
backgroundColor:
|
|
158
|
+
previewDisabled
|
|
159
|
+
? buttonPalette.disabledBackground
|
|
160
|
+
: buttonPalette.primaryBackground,
|
|
161
|
+
},
|
|
162
|
+
]}
|
|
163
|
+
onPress={onPreview}
|
|
164
|
+
disabled={previewDisabled}>
|
|
165
|
+
{previewLoading ? (
|
|
166
|
+
<ActivityIndicator
|
|
167
|
+
size="small"
|
|
168
|
+
color={buttonPalette.disabledText}
|
|
169
|
+
/>
|
|
170
|
+
) : (
|
|
171
|
+
<>
|
|
172
|
+
<Icon
|
|
173
|
+
name="eye"
|
|
174
|
+
size={15}
|
|
175
|
+
color={
|
|
176
|
+
previewDisabled
|
|
177
|
+
? buttonPalette.disabledText
|
|
178
|
+
: buttonPalette.primaryIcon
|
|
179
|
+
}
|
|
180
|
+
/>
|
|
181
|
+
<Text
|
|
182
|
+
style={[
|
|
183
|
+
styles.previewButtonText,
|
|
184
|
+
{
|
|
185
|
+
color: previewDisabled
|
|
186
|
+
? buttonPalette.disabledText
|
|
187
|
+
: buttonPalette.primaryText,
|
|
188
|
+
},
|
|
189
|
+
]}>
|
|
190
|
+
Pre-visualizar menu
|
|
191
|
+
</Text>
|
|
192
|
+
</>
|
|
193
|
+
)}
|
|
194
|
+
</TouchableOpacity>
|
|
195
|
+
</View>
|
|
196
|
+
|
|
197
|
+
{normalizedProducts.length > 0 ? (
|
|
198
|
+
<View style={styles.productsList}>
|
|
199
|
+
{normalizedProducts.map(product => (
|
|
200
|
+
<MarketplaceProductCard
|
|
201
|
+
key={product.id}
|
|
202
|
+
product={product}
|
|
203
|
+
accentColor={accentColor}
|
|
204
|
+
selected={selectedProductSet.has(String(product.id))}
|
|
205
|
+
onPress={onToggleProduct}
|
|
206
|
+
onMarkCardPressHandled={onMarkCardPressHandled}
|
|
207
|
+
/>
|
|
208
|
+
))}
|
|
209
|
+
</View>
|
|
210
|
+
) : (
|
|
211
|
+
<View style={styles.emptyProducts}>
|
|
212
|
+
<Text style={styles.emptyProductsText}>
|
|
213
|
+
Nenhum produto encontrado para este filtro.
|
|
214
|
+
</Text>
|
|
215
|
+
</View>
|
|
216
|
+
)}
|
|
217
|
+
</View>
|
|
218
|
+
);
|
|
219
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Text, View } from 'react-native';
|
|
3
|
+
import Icon from 'react-native-vector-icons/Feather';
|
|
4
|
+
import { colors } from '@controleonline/../../src/styles/colors';
|
|
5
|
+
|
|
6
|
+
import { withOpacity } from '@controleonline/../../src/styles/branding';
|
|
7
|
+
|
|
8
|
+
import styles from '../styles';
|
|
9
|
+
|
|
10
|
+
// Aba inicial com leitura rápida da integração 99Food.
|
|
11
|
+
export default function Food99OverviewTab({
|
|
12
|
+
shadowStyle,
|
|
13
|
+
connected,
|
|
14
|
+
needsReconnect,
|
|
15
|
+
summaryCards,
|
|
16
|
+
lastMenuPublishState,
|
|
17
|
+
publicationTone,
|
|
18
|
+
publishStateLabel,
|
|
19
|
+
lastMenuTaskMessage,
|
|
20
|
+
lastErrorMessage,
|
|
21
|
+
palette = colors,
|
|
22
|
+
}) {
|
|
23
|
+
const reconnectRequired = Boolean(needsReconnect);
|
|
24
|
+
const pillBackgroundColor = reconnectRequired
|
|
25
|
+
? withOpacity(palette.warning, 0.24)
|
|
26
|
+
: connected
|
|
27
|
+
? withOpacity(palette.success, 0.18)
|
|
28
|
+
: withOpacity(palette.warning, 0.24);
|
|
29
|
+
const pillTextColor = reconnectRequired
|
|
30
|
+
? palette.warning
|
|
31
|
+
: connected
|
|
32
|
+
? palette.success
|
|
33
|
+
: palette.warning;
|
|
34
|
+
const pillLabel = reconnectRequired
|
|
35
|
+
? 'Reconexão necessária'
|
|
36
|
+
: connected
|
|
37
|
+
? '99Food conectado'
|
|
38
|
+
: 'Integração pendente';
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<>
|
|
42
|
+
<View style={styles.companyRow}>
|
|
43
|
+
<View
|
|
44
|
+
style={[
|
|
45
|
+
styles.statusPill,
|
|
46
|
+
{ backgroundColor: pillBackgroundColor },
|
|
47
|
+
]}>
|
|
48
|
+
<Text
|
|
49
|
+
style={[
|
|
50
|
+
styles.statusPillText,
|
|
51
|
+
{ color: pillTextColor },
|
|
52
|
+
]}>
|
|
53
|
+
{pillLabel}
|
|
54
|
+
</Text>
|
|
55
|
+
</View>
|
|
56
|
+
</View>
|
|
57
|
+
|
|
58
|
+
<View style={styles.summaryGrid}>
|
|
59
|
+
{summaryCards.map(card => (
|
|
60
|
+
<View key={card.key} style={[styles.summaryCard, shadowStyle]}>
|
|
61
|
+
<View
|
|
62
|
+
style={[
|
|
63
|
+
styles.summaryIcon,
|
|
64
|
+
{ backgroundColor: palette.cardIconBackground || palette.iconBackground },
|
|
65
|
+
]}
|
|
66
|
+
>
|
|
67
|
+
<Icon
|
|
68
|
+
name={card.icon}
|
|
69
|
+
size={18}
|
|
70
|
+
color={palette.cardIconColor || palette.iconColor || palette.text}
|
|
71
|
+
/>
|
|
72
|
+
</View>
|
|
73
|
+
<Text style={styles.summaryValue}>{card.value}</Text>
|
|
74
|
+
<Text style={styles.summaryLabel}>{card.label}</Text>
|
|
75
|
+
</View>
|
|
76
|
+
))}
|
|
77
|
+
</View>
|
|
78
|
+
|
|
79
|
+
<View style={[styles.panel, shadowStyle]}>
|
|
80
|
+
<View style={styles.panelHeader}>
|
|
81
|
+
<View>
|
|
82
|
+
<Text style={styles.panelTitle}>Leitura rapida</Text>
|
|
83
|
+
<Text style={styles.panelSubtitle}>
|
|
84
|
+
Use as abas seguintes para trabalhar conexao, configuracoes e catalogo separadamente.
|
|
85
|
+
</Text>
|
|
86
|
+
</View>
|
|
87
|
+
</View>
|
|
88
|
+
|
|
89
|
+
{!!lastMenuPublishState && (
|
|
90
|
+
<View style={[styles.infoBanner, { backgroundColor: withOpacity(publicationTone, 0.12) }]}>
|
|
91
|
+
<Icon
|
|
92
|
+
name={
|
|
93
|
+
lastMenuPublishState === 'failed'
|
|
94
|
+
? 'alert-triangle'
|
|
95
|
+
: lastMenuPublishState === 'published'
|
|
96
|
+
? 'check-circle'
|
|
97
|
+
: 'clock'
|
|
98
|
+
}
|
|
99
|
+
size={14}
|
|
100
|
+
color={publicationTone}
|
|
101
|
+
/>
|
|
102
|
+
<Text style={[styles.infoBannerText, { color: publicationTone }]}>
|
|
103
|
+
{publishStateLabel}
|
|
104
|
+
{lastMenuTaskMessage ? ` • ${lastMenuTaskMessage}` : ''}
|
|
105
|
+
</Text>
|
|
106
|
+
</View>
|
|
107
|
+
)}
|
|
108
|
+
|
|
109
|
+
{!!lastErrorMessage && lastMenuPublishState !== 'failed' && (
|
|
110
|
+
<View style={styles.errorBanner}>
|
|
111
|
+
<Icon name="alert-circle" size={14} color={palette.error} />
|
|
112
|
+
<Text style={styles.errorBannerText}>{lastErrorMessage}</Text>
|
|
113
|
+
</View>
|
|
114
|
+
)}
|
|
115
|
+
|
|
116
|
+
{reconnectRequired && !lastMenuPublishState && !lastErrorMessage ? (
|
|
117
|
+
<View style={[styles.infoBanner, { backgroundColor: withOpacity(palette.warning, 0.24) }]}>
|
|
118
|
+
<Icon name="alert-triangle" size={14} color={palette.warning} />
|
|
119
|
+
<Text style={[styles.infoBannerText, { color: palette.warning }]}>
|
|
120
|
+
A loja está vinculada localmente, mas a conexão remota caiu. Use a aba Loja para reconectar e retomar os webhooks.
|
|
121
|
+
</Text>
|
|
122
|
+
</View>
|
|
123
|
+
) : !lastMenuPublishState && !lastErrorMessage ? (
|
|
124
|
+
<View style={[styles.infoBanner, { backgroundColor: withOpacity(palette.info, 0.12) }]}>
|
|
125
|
+
<Icon name="info" size={14} color={palette.info} />
|
|
126
|
+
<Text style={[styles.infoBannerText, { color: palette.info }]}>
|
|
127
|
+
A aba de loja concentra status remoto e ações de conexão. A aba de cardápio cuida somente dos produtos.
|
|
128
|
+
</Text>
|
|
129
|
+
</View>
|
|
130
|
+
) : null}
|
|
131
|
+
</View>
|
|
132
|
+
</>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ActivityIndicator, ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
|
3
|
+
import Icon from 'react-native-vector-icons/Feather';
|
|
4
|
+
import { colors } from '@controleonline/../../src/styles/colors';
|
|
5
|
+
|
|
6
|
+
import AnimatedModal from '@controleonline/ui-common/src/react/components/AnimatedModal';
|
|
7
|
+
|
|
8
|
+
import styles from '../styles';
|
|
9
|
+
import { countCollection } from '@controleonline/ui-common/src/react/utils/integrationPage';
|
|
10
|
+
|
|
11
|
+
const resolveButtonPalette = (palette, accentColor) => {
|
|
12
|
+
const primaryBackground =
|
|
13
|
+
palette.buttonBackground || accentColor || palette.primary;
|
|
14
|
+
const primaryBorder = palette.buttonBorder || primaryBackground;
|
|
15
|
+
const primaryText = palette.buttonText || palette.white;
|
|
16
|
+
const primaryIcon = palette.buttonIcon || primaryText;
|
|
17
|
+
const secondaryBackground =
|
|
18
|
+
palette.buttonBackgroundSecondary || palette.white;
|
|
19
|
+
const secondaryBorder = palette.buttonBorderSecondary || palette.border;
|
|
20
|
+
const secondaryText = palette.buttonTextSecondary || palette.textSecondary;
|
|
21
|
+
const secondaryIcon = palette.buttonIconSecondary || secondaryText;
|
|
22
|
+
const disabledBackground =
|
|
23
|
+
palette.buttonDisabledBackground || secondaryBorder;
|
|
24
|
+
const disabledBorder = palette.buttonBorderSecondary || secondaryBorder;
|
|
25
|
+
const disabledText = palette.buttonDisabledText || secondaryText;
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
primaryBackground,
|
|
29
|
+
primaryBorder,
|
|
30
|
+
primaryText,
|
|
31
|
+
primaryIcon,
|
|
32
|
+
secondaryBackground,
|
|
33
|
+
secondaryBorder,
|
|
34
|
+
secondaryText,
|
|
35
|
+
secondaryIcon,
|
|
36
|
+
disabledBackground,
|
|
37
|
+
disabledBorder,
|
|
38
|
+
disabledText,
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Modal de pré-visualização do menu antes do envio à 99Food.
|
|
43
|
+
export default function Food99PreviewModal({
|
|
44
|
+
visible,
|
|
45
|
+
previewData,
|
|
46
|
+
selectedEligibleProducts,
|
|
47
|
+
uploading,
|
|
48
|
+
accentColor,
|
|
49
|
+
palette = colors,
|
|
50
|
+
onClose,
|
|
51
|
+
onUpload,
|
|
52
|
+
}) {
|
|
53
|
+
const buttonPalette = resolveButtonPalette(palette, accentColor);
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<AnimatedModal visible={visible} onRequestClose={onClose}>
|
|
57
|
+
<View style={styles.modalShell}>
|
|
58
|
+
<View style={styles.modalCard}>
|
|
59
|
+
<View style={styles.modalHeader}>
|
|
60
|
+
<View>
|
|
61
|
+
<Text style={styles.modalTitle}>Pre-visualizacao do menu</Text>
|
|
62
|
+
<Text style={styles.modalSubtitle}>
|
|
63
|
+
{previewData?.eligible_product_count || selectedEligibleProducts.length} produtos prontos para upload
|
|
64
|
+
</Text>
|
|
65
|
+
</View>
|
|
66
|
+
<TouchableOpacity onPress={onClose} style={styles.modalCloseButton}>
|
|
67
|
+
<Icon name="x" size={18} color={palette.textSecondary} />
|
|
68
|
+
</TouchableOpacity>
|
|
69
|
+
</View>
|
|
70
|
+
|
|
71
|
+
<ScrollView showsVerticalScrollIndicator={false} contentContainerStyle={styles.modalContent}>
|
|
72
|
+
<View style={styles.modalSummaryGrid}>
|
|
73
|
+
<View style={styles.modalSummaryCard}>
|
|
74
|
+
<Text style={styles.modalSummaryValue}>{countCollection(previewData?.payload?.menus)}</Text>
|
|
75
|
+
<Text style={styles.modalSummaryLabel}>Menus</Text>
|
|
76
|
+
</View>
|
|
77
|
+
<View style={styles.modalSummaryCard}>
|
|
78
|
+
<Text style={styles.modalSummaryValue}>{countCollection(previewData?.payload?.categories)}</Text>
|
|
79
|
+
<Text style={styles.modalSummaryLabel}>Categorias</Text>
|
|
80
|
+
</View>
|
|
81
|
+
<View style={styles.modalSummaryCard}>
|
|
82
|
+
<Text style={styles.modalSummaryValue}>{countCollection(previewData?.payload?.items)}</Text>
|
|
83
|
+
<Text style={styles.modalSummaryLabel}>Itens</Text>
|
|
84
|
+
</View>
|
|
85
|
+
</View>
|
|
86
|
+
|
|
87
|
+
<View style={styles.previewSection}>
|
|
88
|
+
<Text style={styles.previewSectionTitle}>Categorias</Text>
|
|
89
|
+
{(previewData?.payload?.categories || []).map(category => (
|
|
90
|
+
<View key={category.app_category_id} style={styles.previewLine}>
|
|
91
|
+
<Text style={styles.previewLineTitle}>{category.category_name}</Text>
|
|
92
|
+
<Text style={styles.previewLineMeta}>
|
|
93
|
+
{countCollection(category.app_item_ids)} item(ns)
|
|
94
|
+
</Text>
|
|
95
|
+
</View>
|
|
96
|
+
))}
|
|
97
|
+
</View>
|
|
98
|
+
|
|
99
|
+
<View style={styles.previewSection}>
|
|
100
|
+
<Text style={styles.previewSectionTitle}>Itens selecionados</Text>
|
|
101
|
+
{selectedEligibleProducts.map(product => (
|
|
102
|
+
<View key={product.id} style={styles.previewLine}>
|
|
103
|
+
<Text style={styles.previewLineTitle}>{product.name}</Text>
|
|
104
|
+
<Text style={styles.previewLineMeta}>
|
|
105
|
+
{product.category?.name || 'Sem categoria'} • R$ {Number(product.price || 0).toFixed(2)}
|
|
106
|
+
</Text>
|
|
107
|
+
</View>
|
|
108
|
+
))}
|
|
109
|
+
</View>
|
|
110
|
+
</ScrollView>
|
|
111
|
+
|
|
112
|
+
<View style={styles.modalActions}>
|
|
113
|
+
<TouchableOpacity
|
|
114
|
+
style={[
|
|
115
|
+
styles.secondaryButton,
|
|
116
|
+
{
|
|
117
|
+
borderColor: buttonPalette.secondaryBorder,
|
|
118
|
+
backgroundColor: buttonPalette.secondaryBackground,
|
|
119
|
+
},
|
|
120
|
+
]}
|
|
121
|
+
onPress={onClose}>
|
|
122
|
+
<Text
|
|
123
|
+
style={[
|
|
124
|
+
styles.secondaryButtonText,
|
|
125
|
+
{ color: buttonPalette.secondaryText },
|
|
126
|
+
]}>
|
|
127
|
+
Fechar
|
|
128
|
+
</Text>
|
|
129
|
+
</TouchableOpacity>
|
|
130
|
+
<TouchableOpacity
|
|
131
|
+
style={[
|
|
132
|
+
styles.primaryButton,
|
|
133
|
+
styles.modalPrimaryButton,
|
|
134
|
+
{
|
|
135
|
+
borderWidth: 1,
|
|
136
|
+
borderColor: uploading
|
|
137
|
+
? buttonPalette.disabledBorder
|
|
138
|
+
: buttonPalette.primaryBorder,
|
|
139
|
+
backgroundColor: uploading
|
|
140
|
+
? buttonPalette.disabledBackground
|
|
141
|
+
: buttonPalette.primaryBackground,
|
|
142
|
+
},
|
|
143
|
+
]}
|
|
144
|
+
onPress={onUpload}
|
|
145
|
+
disabled={uploading}>
|
|
146
|
+
{uploading ? (
|
|
147
|
+
<ActivityIndicator
|
|
148
|
+
size="small"
|
|
149
|
+
color={buttonPalette.disabledText}
|
|
150
|
+
/>
|
|
151
|
+
) : (
|
|
152
|
+
<>
|
|
153
|
+
<Icon
|
|
154
|
+
name="upload-cloud"
|
|
155
|
+
size={16}
|
|
156
|
+
color={buttonPalette.primaryIcon}
|
|
157
|
+
/>
|
|
158
|
+
<Text
|
|
159
|
+
style={[
|
|
160
|
+
styles.primaryButtonText,
|
|
161
|
+
{ color: buttonPalette.primaryText },
|
|
162
|
+
]}>
|
|
163
|
+
Publicar menu
|
|
164
|
+
</Text>
|
|
165
|
+
</>
|
|
166
|
+
)}
|
|
167
|
+
</TouchableOpacity>
|
|
168
|
+
</View>
|
|
169
|
+
</View>
|
|
170
|
+
</View>
|
|
171
|
+
</AnimatedModal>
|
|
172
|
+
);
|
|
173
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {default} from '../../MarketplaceIntegrationPage/components/MarketplaceProductCard';
|