@controleonline/ui-common 1.2.70
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/agents/developer.agent.md +30 -0
- package/.github/agents/devops.agent.md +30 -0
- package/.github/agents/qa.agent.md +30 -0
- package/.github/agents/security.agent.md +30 -0
- package/.github/workflows/npmjs.yml +35 -0
- package/.github/workflows/pull-request-checks.yml +19 -0
- package/.scrutinizer.yml +24 -0
- package/FUNDING.yml +1 -0
- package/package.json +28 -0
- package/src/api/fetch.js +74 -0
- package/src/api/index.js +155 -0
- package/src/api/localDB.js +131 -0
- package/src/api/queue.js +66 -0
- package/src/react/assets/tap.mp3 +0 -0
- package/src/react/components/AddImportModal.js +157 -0
- package/src/react/components/AddImportModal.styles.js +81 -0
- package/src/react/components/BackgroundRuntimeBridge.js +219 -0
- package/src/react/components/BottomNavigationBar.config.js +238 -0
- package/src/react/components/BottomNavigationBar.js +120 -0
- package/src/react/components/BottomNavigationBar.styles.js +110 -0
- package/src/react/components/CategoryForm.js +572 -0
- package/src/react/components/CategoryForm.styles.js +334 -0
- package/src/react/components/ConfirmModal.js +24 -0
- package/src/react/components/ConfirmModal.styles.js +43 -0
- package/src/react/components/ContextHelpButton.js +69 -0
- package/src/react/components/ContextHelpButton.styles.js +62 -0
- package/src/react/components/DefaultProvider.native.js +848 -0
- package/src/react/components/DefaultProvider.styles.js +21 -0
- package/src/react/components/DefaultProvider.web.js +909 -0
- package/src/react/components/DeliveryPushBridge.native.js +314 -0
- package/src/react/components/DeliveryPushBridge.web.js +5 -0
- package/src/react/components/DeviceAlertSoundService.js +499 -0
- package/src/react/components/EntityLogContent.js +909 -0
- package/src/react/components/EntityLogContent.styles.js +400 -0
- package/src/react/components/EventBus.js +12 -0
- package/src/react/components/KioskModeBridge.js +65 -0
- package/src/react/components/LauncherModeBridge.js +47 -0
- package/src/react/components/LinkedOrderProductsTab.js +388 -0
- package/src/react/components/LinkedOrderProductsTab.styles.js +180 -0
- package/src/react/components/ManagerPushBridge.native.js +345 -0
- package/src/react/components/MessageService.js +314 -0
- package/src/react/components/Paywall/Google.js +89 -0
- package/src/react/components/PrintService.js +778 -0
- package/src/react/components/ProductCatalogCacheService.js +45 -0
- package/src/react/components/RemoteCheckoutService.js +292 -0
- package/src/react/components/RuntimeBottomNavigationBar.js +151 -0
- package/src/react/components/RuntimeInfoFooter.js +214 -0
- package/src/react/components/RuntimeInfoFooter.styles.js +56 -0
- package/src/react/components/SystemErrorToast.js +29 -0
- package/src/react/components/SystemErrorToast.styles.js +38 -0
- package/src/react/components/TouchFeedbackProvider.js +65 -0
- package/src/react/components/UnifiedPaymentBar.js +155 -0
- package/src/react/components/UnifiedPaymentBar.styles.js +174 -0
- package/src/react/components/WebsocketListener.native.js +487 -0
- package/src/react/components/WebsocketListener.web.js +102 -0
- package/src/react/components/inputs/IdInput.js +49 -0
- package/src/react/components/inputs/IdInput.styles.js +26 -0
- package/src/react/components/inputs/InvoiceDueDateFilterInput.js +74 -0
- package/src/react/components/inputs/InvoiceDueDateFilterInput.styles.js +34 -0
- package/src/react/components/inputs/InvoiceDueDateRangeFilterInput.js +115 -0
- package/src/react/components/inputs/InvoiceDueDateRangeFilterInput.styles.js +39 -0
- package/src/react/components/lists/CategoriesList.js +56 -0
- package/src/react/components/lists/PaymentTypeList.js +55 -0
- package/src/react/components/lists/ReceiverList.js +56 -0
- package/src/react/components/lists/SelectList.styles.js +18 -0
- package/src/react/components/lists/StatusList.js +55 -0
- package/src/react/components/lists/WalletList.js +54 -0
- package/src/react/components/radio/Spotify.js +144 -0
- package/src/react/components/radio/Spotify.styles.js +32 -0
- package/src/react/components/radio/YouTube.js +82 -0
- package/src/react/components/radio/YouTube.styles.js +16 -0
- package/src/react/components/toastConfig.js +16 -0
- package/src/react/config/deviceConfigBootstrap.js +571 -0
- package/src/react/index.js +4 -0
- package/src/react/localStorage.js +30 -0
- package/src/react/pages/EntityLogPage.js +124 -0
- package/src/react/pages/EntityLogPage.styles.js +17 -0
- package/src/react/pages/GenericLogPage.js +760 -0
- package/src/react/pages/GenericLogPage.styles.js +401 -0
- package/src/react/pages/Imports.js +361 -0
- package/src/react/pages/Imports.styles.js +223 -0
- package/src/react/pages/SettingsPage/PaymentTypesByWalletTab.js +462 -0
- package/src/react/pages/SettingsPage/index.js +1171 -0
- package/src/react/pages/SettingsPage/index.styles.js +122 -0
- package/src/react/print/jobs.js +147 -0
- package/src/react/print/providers/local.js +53 -0
- package/src/react/print/providers/remote.js +81 -0
- package/src/react/print/selection.js +296 -0
- package/src/react/print/usePrintButtonController.js +474 -0
- package/src/react/router/routes.js +42 -0
- package/src/react/services/NetworkPrinterService.native.js +391 -0
- package/src/react/services/NetworkPrinterService.web.js +15 -0
- package/src/react/stores/index.js +128 -0
- package/src/react/stores/storeErrorBridge.js +36 -0
- package/src/react/utils/backgroundRuntimeRegistration.js +69 -0
- package/src/react/utils/cashPayment.js +87 -0
- package/src/react/utils/commercialDocumentOrders.js +269 -0
- package/src/react/utils/dateRangeFilter.js +264 -0
- package/src/react/utils/deviceRuntime.js +193 -0
- package/src/react/utils/entityDisplay.js +231 -0
- package/src/react/utils/entityLog.js +649 -0
- package/src/react/utils/fileUrl.js +102 -0
- package/src/react/utils/frontendDebugLog.js +45 -0
- package/src/react/utils/googleMapsConfig.js +49 -0
- package/src/react/utils/importStatus.js +100 -0
- package/src/react/utils/invoiceDueDateMessages.js +14 -0
- package/src/react/utils/invoicePresentation.js +46 -0
- package/src/react/utils/logSettings.js +143 -0
- package/src/react/utils/maintenanceSettings.js +53 -0
- package/src/react/utils/managerOrderNotifications.js +523 -0
- package/src/react/utils/mapNavigation.js +76 -0
- package/src/react/utils/menuCatalogConfig.js +8 -0
- package/src/react/utils/menuCatalogDownload.js +157 -0
- package/src/react/utils/networkCameraDevices.js +175 -0
- package/src/react/utils/networkDeviceProfiles.js +135 -0
- package/src/react/utils/normalizedCatalogDownload.js +157 -0
- package/src/react/utils/notificationNavigation.js +94 -0
- package/src/react/utils/notificationSound.js +42 -0
- package/src/react/utils/paymentDevices.js +397 -0
- package/src/react/utils/paymentGatewayExecution.js +91 -0
- package/src/react/utils/paymentOptions.js +88 -0
- package/src/react/utils/peopleDisplay.js +39 -0
- package/src/react/utils/printerDevices.js +465 -0
- package/src/react/utils/remotePayment.js +61 -0
- package/src/react/utils/runtimeFooter.js +475 -0
- package/src/react/utils/runtimeLanguage.js +50 -0
- package/src/react/utils/runtimeMenu.js +224 -0
- package/src/react/utils/screenMetrics.js +30 -0
- package/src/react/utils/shopConfig.js +294 -0
- package/src/react/utils/shopFranchises.js +114 -0
- package/src/react/utils/socketRuntimePipeline.js +454 -0
- package/src/react/utils/spoolAckTracker.js +77 -0
- package/src/react/utils/storeColumns.js +427 -0
- package/src/react/utils/systemErrorChannel.js +109 -0
- package/src/react/utils/systemErrorMessage.js +67 -0
- package/src/react/utils/toastPresentation.js +53 -0
- package/src/react/utils/websocketSharedRuntime.js +826 -0
- package/src/store/acl/getters.js +4 -0
- package/src/store/acl/index.js +19 -0
- package/src/store/acl/mutation_types.js +4 -0
- package/src/store/acl/mutations.js +17 -0
- package/src/store/address/city.js +22 -0
- package/src/store/categories/category_file/index.js +25 -0
- package/src/store/categories/index.js +93 -0
- package/src/store/configs/customActions.js +131 -0
- package/src/store/configs/index.js +25 -0
- package/src/store/connections/customActions.js +26 -0
- package/src/store/connections/index.js +124 -0
- package/src/store/device/index.js +22 -0
- package/src/store/device_config/customActions.js +190 -0
- package/src/store/device_config/index.js +28 -0
- package/src/store/entity_log/customActions.js +63 -0
- package/src/store/entity_log/index.js +25 -0
- package/src/store/extra/data.js +85 -0
- package/src/store/extra/fields.js +88 -0
- package/src/store/file/actions.js +27 -0
- package/src/store/file/index.js +24 -0
- package/src/store/imports/index.js +88 -0
- package/src/store/print/customActions.js +251 -0
- package/src/store/print/index.js +28 -0
- package/src/store/printer/customActions.js +54 -0
- package/src/store/printer/index.js +26 -0
- package/src/store/runtime_debug/customActions.js +71 -0
- package/src/store/runtime_debug/index.js +30 -0
- package/src/store/status/index.js +65 -0
- package/src/store/timezones/index.js +43 -0
- package/src/store/websocket/customActions.js +24 -0
- package/src/store/websocket/index.js +28 -0
- package/src/tests/react/components/LauncherModeBridge.test.js +93 -0
- package/src/tests/react/config/deviceConfigBootstrap.test.js +337 -0
- package/src/tests/react/print/localPrintProvider.test.js +45 -0
- package/src/tests/react/utils/backgroundRuntimeRegistration.test.js +123 -0
- package/src/tests/react/utils/cashPayment.test.js +41 -0
- package/src/tests/react/utils/dateRangeFilter.test.mjs +29 -0
- package/src/tests/react/utils/entityDisplay.test.js +18 -0
- package/src/tests/react/utils/googleMapsConfig.test.js +32 -0
- package/src/tests/react/utils/importStatus.test.js +85 -0
- package/src/tests/react/utils/invoicePresentation.test.mjs +40 -0
- package/src/tests/react/utils/managerOrderNotifications.test.js +127 -0
- package/src/tests/react/utils/mapNavigation.test.js +58 -0
- package/src/tests/react/utils/notificationNavigation.test.js +39 -0
- package/src/tests/react/utils/notificationSound.test.js +27 -0
- package/src/tests/react/utils/paymentDevices.test.js +88 -0
- package/src/tests/react/utils/runtimeFooter.test.js +429 -0
- package/src/tests/react/utils/runtimeLanguage.test.js +80 -0
- package/src/tests/react/utils/runtimeMenu.test.js +174 -0
- package/src/tests/react/utils/shopFranchises.test.js +82 -0
- package/src/tests/react/utils/socketRuntimePipeline.test.js +124 -0
- package/src/tests/react/utils/spoolAckTracker.test.js +40 -0
- package/src/tests/react/utils/storeErrorBridge.test.js +66 -0
- package/src/tests/react/utils/systemErrorChannel.test.js +58 -0
- package/src/tests/react/utils/systemErrorMessage.test.js +59 -0
- package/src/tests/react/utils/toastPresentation.test.js +75 -0
- package/src/tests/react/utils/translate.test.mjs +396 -0
- package/src/tests/react/utils/websocketSharedRuntime.test.js +245 -0
- package/src/utils/apiEntryPoint.js +31 -0
- package/src/utils/appDomain.js +50 -0
- package/src/utils/config.js +14 -0
- package/src/utils/formatter.js +419 -0
- package/src/utils/integrationConfigs.js +79 -0
- package/src/utils/methods.js +23 -0
- package/src/utils/oauth.js +42 -0
- package/src/utils/translate.js +620 -0
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
import {Platform} from 'react-native';
|
|
2
|
+
|
|
3
|
+
import Formatter from '@controleonline/ui-common/src/utils/formatter';
|
|
4
|
+
|
|
5
|
+
export const MANAGER_ORDER_NOTIFICATION_PREFERENCES_KEY =
|
|
6
|
+
'managerOrderNotifications';
|
|
7
|
+
export const MANAGER_FINANCIAL_NOTIFICATION_PREFERENCES_KEY =
|
|
8
|
+
'managerFinancialNotifications';
|
|
9
|
+
|
|
10
|
+
export const DEFAULT_MANAGER_ORDER_NOTIFICATION_PREFERENCES = {
|
|
11
|
+
pushEnabled: true,
|
|
12
|
+
soundEnabled: false,
|
|
13
|
+
soundUrl: '',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const DEFAULT_MANAGER_FINANCIAL_NOTIFICATION_PREFERENCES = {
|
|
17
|
+
cashClosePushEnabled: true,
|
|
18
|
+
storeClosePushEnabled: true,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const ANDROID_MANAGER_ORDERS_CHANNEL_ID = 'manager-orders';
|
|
22
|
+
const ANDROID_MANAGER_PUSH_CHANNEL_ID = 'manager-orders-push-caixa-v1';
|
|
23
|
+
let notificationsModulePromise = null;
|
|
24
|
+
let nativeNotificationHandlerConfigured = false;
|
|
25
|
+
let nativeNotificationChannelConfigured = false;
|
|
26
|
+
|
|
27
|
+
const normalizeText = value => String(value || '').trim();
|
|
28
|
+
|
|
29
|
+
const parseNumericValue = value => {
|
|
30
|
+
if (typeof value === 'number') {
|
|
31
|
+
return Number.isFinite(value) ? value : NaN;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const normalizedValue = normalizeText(value);
|
|
35
|
+
if (!normalizedValue) {
|
|
36
|
+
return NaN;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const sanitizedValue = normalizedValue
|
|
40
|
+
.replace(/[^\d,.-]/g, '')
|
|
41
|
+
.replace(/\.(?=\d{3}(?:\D|$))/g, '')
|
|
42
|
+
.replace(',', '.');
|
|
43
|
+
const numericValue = Number(sanitizedValue);
|
|
44
|
+
|
|
45
|
+
return Number.isFinite(numericValue) ? numericValue : NaN;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const isPlainObject = value =>
|
|
49
|
+
!!value && typeof value === 'object' && !Array.isArray(value);
|
|
50
|
+
|
|
51
|
+
const normalizeBoolean = (value, fallback = false) => {
|
|
52
|
+
if (value === undefined || value === null || value === '') {
|
|
53
|
+
return fallback;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
value === true ||
|
|
58
|
+
value === 1 ||
|
|
59
|
+
value === '1' ||
|
|
60
|
+
normalizeText(value).toLowerCase() === 'true'
|
|
61
|
+
);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const getUserLocalPreferences = user =>
|
|
65
|
+
isPlainObject(user?.localPreferences) ? user.localPreferences : {};
|
|
66
|
+
|
|
67
|
+
const extractOrderId = value => {
|
|
68
|
+
if (value === null || value === undefined || value === '') {
|
|
69
|
+
return '';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (typeof value === 'object') {
|
|
73
|
+
return extractOrderId(value?.id || value?.['@id'] || value?.order || value);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const numericId = String(value).replace(/\D+/g, '').trim();
|
|
77
|
+
return numericId || normalizeText(value);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const resolveCustomerName = message =>
|
|
81
|
+
normalizeText(
|
|
82
|
+
message?.notificationCustomerName ||
|
|
83
|
+
message?.customerName ||
|
|
84
|
+
message?.clientName ||
|
|
85
|
+
message?.client?.alias ||
|
|
86
|
+
message?.client?.name,
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const resolvePriceLabel = message => {
|
|
90
|
+
const explicitLabel = normalizeText(
|
|
91
|
+
message?.notificationPriceLabel ||
|
|
92
|
+
message?.priceLabel ||
|
|
93
|
+
message?.orderPriceLabel,
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
if (explicitLabel) {
|
|
97
|
+
return explicitLabel;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const numericPrice = parseNumericValue(
|
|
101
|
+
message?.notificationPrice || message?.orderPrice || message?.price,
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
if (Number.isFinite(numericPrice) && numericPrice > 0) {
|
|
105
|
+
return Formatter.formatMoney(numericPrice);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return '';
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const toPermissionStatus = permissions => {
|
|
112
|
+
if (permissions?.granted === true) {
|
|
113
|
+
return 'granted';
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (permissions?.canAskAgain === false) {
|
|
117
|
+
return 'denied';
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return normalizeText(permissions?.status) || 'default';
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const loadExpoNotifications = async () => {
|
|
124
|
+
if (!notificationsModulePromise) {
|
|
125
|
+
notificationsModulePromise = import('expo-notifications')
|
|
126
|
+
.then(module => module?.default || module)
|
|
127
|
+
.catch(error => {
|
|
128
|
+
notificationsModulePromise = null;
|
|
129
|
+
throw error;
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return notificationsModulePromise;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const getWebNotification = () => globalThis.Notification;
|
|
137
|
+
|
|
138
|
+
const ensureNativeNotificationsReady = async () => {
|
|
139
|
+
const Notifications = await loadExpoNotifications();
|
|
140
|
+
|
|
141
|
+
if (
|
|
142
|
+
!nativeNotificationHandlerConfigured &&
|
|
143
|
+
typeof Notifications?.setNotificationHandler === 'function'
|
|
144
|
+
) {
|
|
145
|
+
Notifications.setNotificationHandler({
|
|
146
|
+
handleNotification: async () => ({
|
|
147
|
+
shouldPlaySound: true,
|
|
148
|
+
shouldSetBadge: false,
|
|
149
|
+
shouldShowBanner: true,
|
|
150
|
+
shouldShowList: true,
|
|
151
|
+
}),
|
|
152
|
+
});
|
|
153
|
+
nativeNotificationHandlerConfigured = true;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (
|
|
157
|
+
Platform.OS === 'android' &&
|
|
158
|
+
!nativeNotificationChannelConfigured &&
|
|
159
|
+
typeof Notifications?.setNotificationChannelAsync === 'function'
|
|
160
|
+
) {
|
|
161
|
+
await Notifications.setNotificationChannelAsync(
|
|
162
|
+
ANDROID_MANAGER_ORDERS_CHANNEL_ID,
|
|
163
|
+
{
|
|
164
|
+
name: 'Pedidos do Gestor',
|
|
165
|
+
importance: Notifications.AndroidImportance?.HIGH ?? 4,
|
|
166
|
+
vibrationPattern: [0, 250, 250, 250],
|
|
167
|
+
lightColor: '#2563EB',
|
|
168
|
+
sound: null,
|
|
169
|
+
showBadge: false,
|
|
170
|
+
},
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
await Notifications.setNotificationChannelAsync(
|
|
174
|
+
ANDROID_MANAGER_PUSH_CHANNEL_ID,
|
|
175
|
+
{
|
|
176
|
+
name: 'Pedidos do Gestor Push',
|
|
177
|
+
importance: Notifications.AndroidImportance?.HIGH ?? 4,
|
|
178
|
+
vibrationPattern: [0, 250, 250, 250],
|
|
179
|
+
lightColor: '#2563EB',
|
|
180
|
+
sound: 'caixa.m4a',
|
|
181
|
+
showBadge: false,
|
|
182
|
+
},
|
|
183
|
+
);
|
|
184
|
+
nativeNotificationChannelConfigured = true;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return Notifications;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
export const isManagerAppType = appType =>
|
|
191
|
+
normalizeText(appType).toUpperCase() === 'MANAGER';
|
|
192
|
+
|
|
193
|
+
export const hasStoredManagerOrderNotificationPreferences = user =>
|
|
194
|
+
isPlainObject(
|
|
195
|
+
getUserLocalPreferences(user)?.[MANAGER_ORDER_NOTIFICATION_PREFERENCES_KEY],
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
export const resolveManagerOrderNotificationPreferences = user => {
|
|
199
|
+
const storedPreferences = hasStoredManagerOrderNotificationPreferences(user)
|
|
200
|
+
? getUserLocalPreferences(user)[MANAGER_ORDER_NOTIFICATION_PREFERENCES_KEY]
|
|
201
|
+
: {};
|
|
202
|
+
|
|
203
|
+
return {
|
|
204
|
+
pushEnabled: normalizeBoolean(
|
|
205
|
+
storedPreferences?.pushEnabled,
|
|
206
|
+
DEFAULT_MANAGER_ORDER_NOTIFICATION_PREFERENCES.pushEnabled,
|
|
207
|
+
),
|
|
208
|
+
soundEnabled: normalizeBoolean(
|
|
209
|
+
storedPreferences?.soundEnabled,
|
|
210
|
+
DEFAULT_MANAGER_ORDER_NOTIFICATION_PREFERENCES.soundEnabled,
|
|
211
|
+
),
|
|
212
|
+
soundUrl: normalizeText(
|
|
213
|
+
storedPreferences?.soundUrl ||
|
|
214
|
+
DEFAULT_MANAGER_ORDER_NOTIFICATION_PREFERENCES.soundUrl,
|
|
215
|
+
),
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
export const applyManagerOrderNotificationPreferences = (user, patch = {}) => {
|
|
220
|
+
const currentPreferences = resolveManagerOrderNotificationPreferences(user);
|
|
221
|
+
const nextPreferences = {
|
|
222
|
+
...currentPreferences,
|
|
223
|
+
...(isPlainObject(patch) ? patch : {}),
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
return {
|
|
227
|
+
...(user || {}),
|
|
228
|
+
localPreferences: {
|
|
229
|
+
...getUserLocalPreferences(user),
|
|
230
|
+
[MANAGER_ORDER_NOTIFICATION_PREFERENCES_KEY]: {
|
|
231
|
+
pushEnabled: normalizeBoolean(nextPreferences.pushEnabled, true),
|
|
232
|
+
soundEnabled: normalizeBoolean(nextPreferences.soundEnabled, false),
|
|
233
|
+
soundUrl: normalizeText(nextPreferences.soundUrl),
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
};
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
export const resolveManagerFinancialNotificationPreferences = user => {
|
|
240
|
+
const storedPreferences = isPlainObject(
|
|
241
|
+
getUserLocalPreferences(user)?.[MANAGER_FINANCIAL_NOTIFICATION_PREFERENCES_KEY],
|
|
242
|
+
)
|
|
243
|
+
? getUserLocalPreferences(user)[MANAGER_FINANCIAL_NOTIFICATION_PREFERENCES_KEY]
|
|
244
|
+
: {};
|
|
245
|
+
|
|
246
|
+
return {
|
|
247
|
+
cashClosePushEnabled: normalizeBoolean(
|
|
248
|
+
storedPreferences?.cashClosePushEnabled,
|
|
249
|
+
DEFAULT_MANAGER_FINANCIAL_NOTIFICATION_PREFERENCES.cashClosePushEnabled,
|
|
250
|
+
),
|
|
251
|
+
storeClosePushEnabled: normalizeBoolean(
|
|
252
|
+
storedPreferences?.storeClosePushEnabled,
|
|
253
|
+
DEFAULT_MANAGER_FINANCIAL_NOTIFICATION_PREFERENCES.storeClosePushEnabled,
|
|
254
|
+
),
|
|
255
|
+
};
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
export const applyManagerFinancialNotificationPreferences = (user, patch = {}) => {
|
|
259
|
+
const currentPreferences = resolveManagerFinancialNotificationPreferences(user);
|
|
260
|
+
const nextPreferences = {
|
|
261
|
+
...currentPreferences,
|
|
262
|
+
...(isPlainObject(patch) ? patch : {}),
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
return {
|
|
266
|
+
...(user || {}),
|
|
267
|
+
localPreferences: {
|
|
268
|
+
...getUserLocalPreferences(user),
|
|
269
|
+
[MANAGER_FINANCIAL_NOTIFICATION_PREFERENCES_KEY]: {
|
|
270
|
+
cashClosePushEnabled: normalizeBoolean(
|
|
271
|
+
nextPreferences.cashClosePushEnabled,
|
|
272
|
+
true,
|
|
273
|
+
),
|
|
274
|
+
storeClosePushEnabled: normalizeBoolean(
|
|
275
|
+
nextPreferences.storeClosePushEnabled,
|
|
276
|
+
true,
|
|
277
|
+
),
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
};
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
export const buildManagerOrderNotificationContent = (
|
|
284
|
+
messages = [],
|
|
285
|
+
currentCompany = null,
|
|
286
|
+
) => {
|
|
287
|
+
const firstMessage = Array.isArray(messages) ? messages[0] || null : null;
|
|
288
|
+
const orderIds = Array.from(
|
|
289
|
+
new Set(
|
|
290
|
+
(Array.isArray(messages) ? messages : [])
|
|
291
|
+
.map(message => extractOrderId(message?.order))
|
|
292
|
+
.filter(Boolean),
|
|
293
|
+
),
|
|
294
|
+
);
|
|
295
|
+
const companyLabel = normalizeText(
|
|
296
|
+
currentCompany?.alias || currentCompany?.name || currentCompany?.company,
|
|
297
|
+
);
|
|
298
|
+
const headerTitle = normalizeText(
|
|
299
|
+
firstMessage?.notificationHeader ||
|
|
300
|
+
firstMessage?.headerTitle ||
|
|
301
|
+
firstMessage?.orderHeader,
|
|
302
|
+
);
|
|
303
|
+
const headerSubtitle = normalizeText(
|
|
304
|
+
firstMessage?.notificationSubheader ||
|
|
305
|
+
firstMessage?.headerSubtitle ||
|
|
306
|
+
firstMessage?.orderSubheader,
|
|
307
|
+
);
|
|
308
|
+
const notificationBody = normalizeText(
|
|
309
|
+
firstMessage?.notificationBody ||
|
|
310
|
+
firstMessage?.body ||
|
|
311
|
+
firstMessage?.message,
|
|
312
|
+
);
|
|
313
|
+
const statusLabel =
|
|
314
|
+
normalizeText(
|
|
315
|
+
firstMessage?.notificationStatusLabel ||
|
|
316
|
+
firstMessage?.statusLabel ||
|
|
317
|
+
firstMessage?.queueStatusLabel,
|
|
318
|
+
) || 'Fila';
|
|
319
|
+
const customerName = resolveCustomerName(firstMessage);
|
|
320
|
+
const priceLabel = resolvePriceLabel(firstMessage);
|
|
321
|
+
|
|
322
|
+
if (orderIds.length > 1) {
|
|
323
|
+
return {
|
|
324
|
+
title: `${orderIds.length} novos pedidos`,
|
|
325
|
+
body: companyLabel
|
|
326
|
+
? `${companyLabel} recebeu ${orderIds.length} novos pedidos. Status: ${statusLabel}.`
|
|
327
|
+
: `${orderIds.length} novos pedidos entraram na ${statusLabel.toLowerCase()}.`,
|
|
328
|
+
orderIds,
|
|
329
|
+
statusLabel,
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const orderLabel = orderIds[0] ? ` #${orderIds[0]}` : '';
|
|
334
|
+
return {
|
|
335
|
+
title: headerTitle || `Novo pedido${orderLabel}`,
|
|
336
|
+
body:
|
|
337
|
+
[headerSubtitle, notificationBody]
|
|
338
|
+
.concat(customerName ? [`Cliente: ${customerName}`] : [])
|
|
339
|
+
.concat(priceLabel ? [`Valor: ${priceLabel}`] : [])
|
|
340
|
+
.concat(companyLabel ? [companyLabel] : [])
|
|
341
|
+
.concat([`Status: ${statusLabel}`])
|
|
342
|
+
.filter(Boolean)
|
|
343
|
+
.join(' | ') || `Novo pedido${orderLabel}`,
|
|
344
|
+
orderIds,
|
|
345
|
+
statusLabel,
|
|
346
|
+
};
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
export const getManagerOrderNotificationPermissionStatus = async () => {
|
|
350
|
+
if (Platform.OS === 'web') {
|
|
351
|
+
const WebNotification = getWebNotification();
|
|
352
|
+
if (typeof WebNotification === 'undefined') {
|
|
353
|
+
return 'unsupported';
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return normalizeText(WebNotification.permission) || 'default';
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
try {
|
|
360
|
+
const Notifications = await ensureNativeNotificationsReady();
|
|
361
|
+
|
|
362
|
+
if (typeof Notifications?.getPermissionsAsync !== 'function') {
|
|
363
|
+
return 'unsupported';
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
return toPermissionStatus(await Notifications.getPermissionsAsync());
|
|
367
|
+
} catch {
|
|
368
|
+
return 'unsupported';
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
export const requestManagerOrderNotificationPermission = async () => {
|
|
373
|
+
if (Platform.OS === 'web') {
|
|
374
|
+
const WebNotification = getWebNotification();
|
|
375
|
+
if (typeof WebNotification === 'undefined') {
|
|
376
|
+
return 'unsupported';
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if (typeof WebNotification.requestPermission !== 'function') {
|
|
380
|
+
return normalizeText(WebNotification.permission) || 'unsupported';
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
try {
|
|
384
|
+
return normalizeText(await WebNotification.requestPermission()) || 'default';
|
|
385
|
+
} catch {
|
|
386
|
+
return 'denied';
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
try {
|
|
391
|
+
const Notifications = await ensureNativeNotificationsReady();
|
|
392
|
+
|
|
393
|
+
if (typeof Notifications?.requestPermissionsAsync !== 'function') {
|
|
394
|
+
return 'unsupported';
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (typeof Notifications?.getPermissionsAsync === 'function') {
|
|
398
|
+
const currentPermissions = await Notifications.getPermissionsAsync();
|
|
399
|
+
if (currentPermissions?.granted === true) {
|
|
400
|
+
return 'granted';
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return toPermissionStatus(await Notifications.requestPermissionsAsync());
|
|
405
|
+
} catch {
|
|
406
|
+
return 'unsupported';
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
export const ensureManagerOrderNotificationPermission = async ({
|
|
411
|
+
getPermissionStatus = getManagerOrderNotificationPermissionStatus,
|
|
412
|
+
requestPermission = requestManagerOrderNotificationPermission,
|
|
413
|
+
} = {}) => {
|
|
414
|
+
const currentPermissionStatus = await getPermissionStatus();
|
|
415
|
+
|
|
416
|
+
if (currentPermissionStatus !== 'default') {
|
|
417
|
+
return currentPermissionStatus;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return requestPermission();
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
export const showManagerOrderNotification = async ({
|
|
424
|
+
messages = [],
|
|
425
|
+
currentCompany = null,
|
|
426
|
+
store = 'orders',
|
|
427
|
+
event = 'order.created',
|
|
428
|
+
tag = '',
|
|
429
|
+
} = {}) => {
|
|
430
|
+
const {title, body, orderIds} = buildManagerOrderNotificationContent(
|
|
431
|
+
messages,
|
|
432
|
+
currentCompany,
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
if (Platform.OS === 'web') {
|
|
436
|
+
const WebNotification = getWebNotification();
|
|
437
|
+
if (
|
|
438
|
+
typeof WebNotification === 'undefined' ||
|
|
439
|
+
normalizeText(WebNotification.permission) !== 'granted'
|
|
440
|
+
) {
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
try {
|
|
445
|
+
const notification = new WebNotification(title, {
|
|
446
|
+
body,
|
|
447
|
+
silent: true,
|
|
448
|
+
tag:
|
|
449
|
+
tag ||
|
|
450
|
+
(orderIds.length > 0
|
|
451
|
+
? `manager-order-${orderIds.join('-')}`
|
|
452
|
+
: 'manager-order'),
|
|
453
|
+
renotify: true,
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
if (notification && typeof notification.close === 'function') {
|
|
457
|
+
setTimeout(() => {
|
|
458
|
+
try {
|
|
459
|
+
notification.close();
|
|
460
|
+
} catch {
|
|
461
|
+
// Ignora browsers que bloqueiam close manual.
|
|
462
|
+
}
|
|
463
|
+
}, 8000);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
return true;
|
|
467
|
+
} catch {
|
|
468
|
+
return false;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
try {
|
|
473
|
+
const Notifications = await ensureNativeNotificationsReady();
|
|
474
|
+
|
|
475
|
+
if (typeof Notifications?.getPermissionsAsync === 'function') {
|
|
476
|
+
const permissions = await Notifications.getPermissionsAsync();
|
|
477
|
+
if (permissions?.granted !== true) {
|
|
478
|
+
return false;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
await Notifications.scheduleNotificationAsync({
|
|
483
|
+
content: {
|
|
484
|
+
title,
|
|
485
|
+
body,
|
|
486
|
+
channelId:
|
|
487
|
+
Platform.OS === 'android'
|
|
488
|
+
? ANDROID_MANAGER_ORDERS_CHANNEL_ID
|
|
489
|
+
: undefined,
|
|
490
|
+
data: {
|
|
491
|
+
store,
|
|
492
|
+
event,
|
|
493
|
+
orderIds,
|
|
494
|
+
company: currentCompany?.id || null,
|
|
495
|
+
},
|
|
496
|
+
},
|
|
497
|
+
trigger: null,
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
return true;
|
|
501
|
+
} catch {
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
export const showManagerFinancialNotification = async ({
|
|
507
|
+
messages = [],
|
|
508
|
+
currentCompany = null,
|
|
509
|
+
store = 'orders',
|
|
510
|
+
event = 'cash.closed',
|
|
511
|
+
tag = '',
|
|
512
|
+
} = {}) =>
|
|
513
|
+
showManagerOrderNotification({
|
|
514
|
+
messages,
|
|
515
|
+
currentCompany,
|
|
516
|
+
store,
|
|
517
|
+
event,
|
|
518
|
+
tag:
|
|
519
|
+
tag ||
|
|
520
|
+
`manager-financial-${normalizeText(event || 'financial')}-${normalizeText(
|
|
521
|
+
currentCompany?.id || 'company',
|
|
522
|
+
)}`,
|
|
523
|
+
});
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
const normalizeText = value => {
|
|
2
|
+
if (value === null || value === undefined) {
|
|
3
|
+
return '';
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
return String(value).trim();
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const normalizeCoordinate = value => {
|
|
10
|
+
const numericValue = Number(value);
|
|
11
|
+
return Number.isFinite(numericValue) ? numericValue : null;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const resolveCoordinates = value => {
|
|
15
|
+
const latitude = normalizeCoordinate(value?.latitude);
|
|
16
|
+
const longitude = normalizeCoordinate(value?.longitude);
|
|
17
|
+
|
|
18
|
+
if (latitude === null || longitude === null) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return {latitude, longitude};
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const buildNavigationMapQuery = parts =>
|
|
26
|
+
(Array.isArray(parts) ? parts : [parts])
|
|
27
|
+
.map(normalizeText)
|
|
28
|
+
.filter(Boolean)
|
|
29
|
+
.join(', ');
|
|
30
|
+
|
|
31
|
+
export const buildGoogleMapsNavigationUrl = ({
|
|
32
|
+
coordinates,
|
|
33
|
+
mapQuery,
|
|
34
|
+
origin,
|
|
35
|
+
}) => {
|
|
36
|
+
const destinationCoordinates = resolveCoordinates(coordinates);
|
|
37
|
+
const normalizedMapQuery = normalizeText(mapQuery);
|
|
38
|
+
|
|
39
|
+
if (destinationCoordinates) {
|
|
40
|
+
const originCoordinates = resolveCoordinates(origin);
|
|
41
|
+
const originParam = originCoordinates
|
|
42
|
+
? `&origin=${encodeURIComponent(
|
|
43
|
+
`${originCoordinates.latitude},${originCoordinates.longitude}`,
|
|
44
|
+
)}`
|
|
45
|
+
: '';
|
|
46
|
+
|
|
47
|
+
return `https://www.google.com/maps/dir/?api=1&destination=${encodeURIComponent(
|
|
48
|
+
`${destinationCoordinates.latitude},${destinationCoordinates.longitude}`,
|
|
49
|
+
)}${originParam}&travelmode=driving`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!normalizedMapQuery) {
|
|
53
|
+
return '';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(
|
|
57
|
+
normalizedMapQuery,
|
|
58
|
+
)}`;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const buildWazeNavigationUrl = ({coordinates, mapQuery}) => {
|
|
62
|
+
const destinationCoordinates = resolveCoordinates(coordinates);
|
|
63
|
+
const normalizedMapQuery = normalizeText(mapQuery);
|
|
64
|
+
|
|
65
|
+
if (destinationCoordinates) {
|
|
66
|
+
return `https://waze.com/ul?ll=${destinationCoordinates.latitude},${destinationCoordinates.longitude}&navigate=yes`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!normalizedMapQuery) {
|
|
70
|
+
return '';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return `https://waze.com/ul?q=${encodeURIComponent(
|
|
74
|
+
normalizedMapQuery,
|
|
75
|
+
)}&navigate=yes`;
|
|
76
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const normalizeId = value => String(value || '').replace(/\D+/g, '').trim();
|
|
2
|
+
|
|
3
|
+
export const MENU_CATALOG_MODEL_CONFIG_KEY = 'menu-catalog-model';
|
|
4
|
+
|
|
5
|
+
export const normalizeModelReference = value => {
|
|
6
|
+
const normalizedId = normalizeId(value);
|
|
7
|
+
return normalizedId ? `/models/${normalizedId}` : '';
|
|
8
|
+
};
|