ordering-ui-react-native 0.18.58 → 0.18.60
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/package.json +4 -1
- package/themes/business/src/components/OrderDetails/Delivery.tsx +162 -1
- package/themes/business/src/components/OrderDetails/OrderHeaderComponent.tsx +20 -16
- package/themes/business/src/components/ReviewCustomer/index.tsx +1 -1
- package/themes/original/index.tsx +2 -2
- package/themes/original/src/components/AnalyticsSegment/index.tsx +3 -3
- package/themes/original/src/components/Cart/index.tsx +1 -1
- package/themes/original/src/components/DriverTips/index.tsx +6 -3
- package/themes/original/src/components/LoginForm/index.tsx +11 -3
- package/themes/original/src/components/MultiCheckout/index.tsx +20 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ordering-ui-react-native",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.60",
|
|
4
4
|
"description": "Reusable components made in react native",
|
|
5
5
|
"main": "src/index.tsx",
|
|
6
6
|
"author": "ordering.inc",
|
|
@@ -49,6 +49,8 @@
|
|
|
49
49
|
"@react-navigation/material-bottom-tabs": "^5.3.14",
|
|
50
50
|
"@react-navigation/native": "^5.7.6",
|
|
51
51
|
"@react-navigation/stack": "^5.9.3",
|
|
52
|
+
"@segment/analytics-react-native": "2.1.11",
|
|
53
|
+
"@segment/sovran-react-native": "0.2.6",
|
|
52
54
|
"@sentry/react-native": "^2.6.0",
|
|
53
55
|
"@stripe/stripe-react-native": "^0.2.0",
|
|
54
56
|
"@types/react-native-loading-spinner-overlay": "^0.5.2",
|
|
@@ -81,6 +83,7 @@
|
|
|
81
83
|
"react-native-fbsdk-next": "^7.0.1",
|
|
82
84
|
"react-native-geocoding": "^0.5.0",
|
|
83
85
|
"react-native-gesture-handler": "^1.8.0",
|
|
86
|
+
"react-native-get-random-values": "1.8.0",
|
|
84
87
|
"react-native-gifted-chat": "^0.16.3",
|
|
85
88
|
"react-native-google-places-autocomplete": "^2.1.3",
|
|
86
89
|
"react-native-html-to-pdf": "^0.10.0",
|
|
@@ -4,6 +4,7 @@ import { StyleSheet, View } from 'react-native';
|
|
|
4
4
|
|
|
5
5
|
// Thirds
|
|
6
6
|
import { Placeholder, PlaceholderLine, Fade } from 'rn-placeholder';
|
|
7
|
+
import Clipboard from '@react-native-clipboard/clipboard';
|
|
7
8
|
|
|
8
9
|
//OrderingComponent
|
|
9
10
|
import {
|
|
@@ -12,6 +13,7 @@ import {
|
|
|
12
13
|
useToast,
|
|
13
14
|
useSession,
|
|
14
15
|
ToastType,
|
|
16
|
+
useUtils
|
|
15
17
|
} from 'ordering-components/native';
|
|
16
18
|
|
|
17
19
|
//Components
|
|
@@ -26,7 +28,7 @@ import { OrderDetailsParams } from '../../types';
|
|
|
26
28
|
import { USER_TYPE } from '../../config/constants';
|
|
27
29
|
import { useTheme } from 'styled-components/native';
|
|
28
30
|
import { NotFoundSource } from '../NotFoundSource';
|
|
29
|
-
import { getOrderStatus } from '../../utils';
|
|
31
|
+
import { verifyDecimals, getProductPrice, getOrderStatus } from '../../utils';
|
|
30
32
|
import { OrderHeaderComponent } from './OrderHeaderComponent';
|
|
31
33
|
import { OrderContentComponent } from './OrderContentComponent';
|
|
32
34
|
//Styles
|
|
@@ -56,6 +58,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
56
58
|
isGrantedPermissions,
|
|
57
59
|
} = props;
|
|
58
60
|
const [, { showToast }] = useToast();
|
|
61
|
+
const [{ parsePrice, parseNumber }] = useUtils();
|
|
59
62
|
const { order } = props.order
|
|
60
63
|
const theme = useTheme();
|
|
61
64
|
const [, t] = useLanguage();
|
|
@@ -134,6 +137,163 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
134
137
|
}
|
|
135
138
|
};
|
|
136
139
|
|
|
140
|
+
const getFormattedSubOptionName = ({ quantity, name, position, price }: any) => {
|
|
141
|
+
if (name !== 'No') {
|
|
142
|
+
const pos = position && position !== 'whole' ? `(${t(position.toUpperCase(), position)})` : '';
|
|
143
|
+
return pos
|
|
144
|
+
? `${quantity} x ${name} ${pos} +${parsePrice(price)}\n`
|
|
145
|
+
: `${quantity} x ${name} +${parsePrice(price)}\n`;
|
|
146
|
+
} else {
|
|
147
|
+
return 'No\n';
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const handleCopyClipboard = () => {
|
|
152
|
+
const businessName = !!order?.business?.name
|
|
153
|
+
? `${order?.business?.name} \n`
|
|
154
|
+
: '';
|
|
155
|
+
|
|
156
|
+
const businessEmail = !!order?.business?.email
|
|
157
|
+
? `${order?.business?.email} \n`
|
|
158
|
+
: '';
|
|
159
|
+
|
|
160
|
+
const businessCellphone = !!order?.business?.cellphone
|
|
161
|
+
? `${order?.business?.cellphone} \n`
|
|
162
|
+
: '';
|
|
163
|
+
|
|
164
|
+
const businessPhone = !!order?.business?.phone
|
|
165
|
+
? `${order?.business?.phone} \n`
|
|
166
|
+
: '';
|
|
167
|
+
|
|
168
|
+
const businessAddress = !!order?.business?.address
|
|
169
|
+
? `${order?.business?.address} \n`
|
|
170
|
+
: '';
|
|
171
|
+
|
|
172
|
+
const businessSpecialAddress = !!order?.business?.address_notes
|
|
173
|
+
? `${order?.business?.address_notes} \n \n`
|
|
174
|
+
: '';
|
|
175
|
+
|
|
176
|
+
const customerName = !!order?.customer?.name
|
|
177
|
+
? `${order?.customer?.name} ${order?.customer?.middle_name || ''} ${order?.customer?.lastname || ''
|
|
178
|
+
} ${order?.customer?.second_lastname || ''} \n`
|
|
179
|
+
: '';
|
|
180
|
+
|
|
181
|
+
const customerEmail = !!order?.customer.email
|
|
182
|
+
? `${order?.customer.email} \n`
|
|
183
|
+
: '';
|
|
184
|
+
|
|
185
|
+
const customerCellPhone = !!order?.customer?.cellphone
|
|
186
|
+
? `${order?.customer?.cellphone} \n`
|
|
187
|
+
: '';
|
|
188
|
+
|
|
189
|
+
const customerPhone = !!order?.customer?.phone
|
|
190
|
+
? `${order?.customer?.phone} \n`
|
|
191
|
+
: '';
|
|
192
|
+
|
|
193
|
+
const customerAddress = !!order?.customer?.address
|
|
194
|
+
? `${order?.customer?.address} \n`
|
|
195
|
+
: '';
|
|
196
|
+
|
|
197
|
+
const customerSpecialAddress = !!order?.customer?.address_notes
|
|
198
|
+
? `${order?.customer?.address_notes} \n`
|
|
199
|
+
: '';
|
|
200
|
+
|
|
201
|
+
const payment = order?.paymethod?.name
|
|
202
|
+
? `${order?.paymethod?.name} - ${order.delivery_type === 1
|
|
203
|
+
? t('DELIVERY', 'Delivery')
|
|
204
|
+
: order.delivery_type === 2
|
|
205
|
+
? t('PICKUP', 'Pickup')
|
|
206
|
+
: order.delivery_type === 3
|
|
207
|
+
? t('EAT_IN', 'Eat in')
|
|
208
|
+
: order.delivery_type === 4
|
|
209
|
+
? t('CURBSIDE', 'Curbside')
|
|
210
|
+
: t('DRIVER_THRU', 'Driver thru')
|
|
211
|
+
}\n`
|
|
212
|
+
: '';
|
|
213
|
+
|
|
214
|
+
const getSuboptions = (suboptions: any) => {
|
|
215
|
+
const array: any = []
|
|
216
|
+
suboptions?.length > 0 &&
|
|
217
|
+
suboptions?.map((suboption: any) => {
|
|
218
|
+
const string = `${getFormattedSubOptionName(suboption)}`
|
|
219
|
+
array.push(string)
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
return array.join('')
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const getOptions = (options: any, productComment: string = '') => {
|
|
226
|
+
const array: any = [];
|
|
227
|
+
|
|
228
|
+
options?.length &&
|
|
229
|
+
options?.map((option: any) => {
|
|
230
|
+
const string =
|
|
231
|
+
` ${option.name}\n ${getSuboptions(option.suboptions)}`;
|
|
232
|
+
|
|
233
|
+
array.push(string)
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
if (productComment) {
|
|
237
|
+
array.push(` ${t('COMMENT', 'Comment')}\n ${productComment}\n`)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return array.join('')
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const productsInArray =
|
|
244
|
+
order?.products.length &&
|
|
245
|
+
order?.products.map((product: any, i: number) => {
|
|
246
|
+
const string =
|
|
247
|
+
`${product?.quantity} X ${product?.name} ${parsePrice(product.total ?? getProductPrice(product))}\n${getOptions(product.options, product.comment)}`;
|
|
248
|
+
|
|
249
|
+
return i === 0 ? ` ${string}` : string
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
const productsInString = productsInArray.join(' ');
|
|
253
|
+
const orderDetails = `${t(
|
|
254
|
+
'ORDER_DETAILS',
|
|
255
|
+
'Order Details',
|
|
256
|
+
)}:\n${productsInString}\n`;
|
|
257
|
+
|
|
258
|
+
const subtotal = `${t('SUBTOTAL', 'Subtotal')}: ${parsePrice(
|
|
259
|
+
order?.subtotal,
|
|
260
|
+
)}\n`;
|
|
261
|
+
|
|
262
|
+
const drivertip = `${t('DRIVER_TIP', 'Driver tip')} ${parsePrice(
|
|
263
|
+
order?.summary?.driver_tip || order?.totalDriverTip,
|
|
264
|
+
)}\n`;
|
|
265
|
+
|
|
266
|
+
const deliveryFee = `${t('DELIVERY_FEE', 'Delivery fee')} ${verifyDecimals(
|
|
267
|
+
order?.service_fee,
|
|
268
|
+
parseNumber,
|
|
269
|
+
)}% ${parsePrice(order?.summary?.service_fee || order?.serviceFee || 0)}\n`;
|
|
270
|
+
|
|
271
|
+
const total = `${t('TOTAL', 'Total')} ${parsePrice(
|
|
272
|
+
order?.summary?.total || order?.total,
|
|
273
|
+
)}\n`;
|
|
274
|
+
|
|
275
|
+
const orderStatus = `${t('INVOICE_ORDER_NO', 'Order No.')} ${order.id} ${t(
|
|
276
|
+
'IS',
|
|
277
|
+
'is',
|
|
278
|
+
)} ${getOrderStatus(order?.status, t)?.value}\n`;
|
|
279
|
+
|
|
280
|
+
Clipboard.setString(
|
|
281
|
+
`${orderStatus} ${payment} ${t(
|
|
282
|
+
'BUSINESS_DETAILS',
|
|
283
|
+
'Business Details',
|
|
284
|
+
)}\n ${businessName} ${businessEmail} ${businessCellphone} ${businessPhone} ${businessAddress} ${businessSpecialAddress}${t(
|
|
285
|
+
'CUSTOMER_DETAILS',
|
|
286
|
+
'Customer Details',
|
|
287
|
+
)}\n ${customerName} ${customerEmail} ${customerCellPhone} ${customerPhone} ${customerAddress} ${customerSpecialAddress}\n${orderDetails} ${subtotal} ${drivertip} ${deliveryFee} ${total}`,
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
showToast(
|
|
291
|
+
ToastType.Info,
|
|
292
|
+
t('COPY_TO_CLIPBOARD', 'Copy to clipboard.'),
|
|
293
|
+
1000,
|
|
294
|
+
);
|
|
295
|
+
};
|
|
296
|
+
|
|
137
297
|
const handleViewActionOrder = (action: string) => {
|
|
138
298
|
if (!isGrantedPermissions) {
|
|
139
299
|
navigation.navigate('RequestPermissions')
|
|
@@ -362,6 +522,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
362
522
|
order={order}
|
|
363
523
|
handleOpenMapView={handleOpenMapView}
|
|
364
524
|
handleOpenMessagesForBusiness={handleOpenMessagesForBusiness}
|
|
525
|
+
handleCopyClipboard={handleCopyClipboard}
|
|
365
526
|
getOrderStatus={getOrderStatus}
|
|
366
527
|
handleArrowBack={handleArrowBack}
|
|
367
528
|
logisticOrderStatus={logisticOrderStatus}
|
|
@@ -140,14 +140,16 @@ export const OrderHeaderComponent = (props: OrderHeader) => {
|
|
|
140
140
|
style={styles.icons}
|
|
141
141
|
/>
|
|
142
142
|
</TouchableOpacity>
|
|
143
|
-
|
|
144
|
-
<
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
143
|
+
{!!handleViewSummaryOrder && (
|
|
144
|
+
<TouchableOpacity onPress={() => handleViewSummaryOrder?.()}>
|
|
145
|
+
<SimpleLineIcons
|
|
146
|
+
name='printer'
|
|
147
|
+
color={theme.colors.textGray}
|
|
148
|
+
size={20}
|
|
149
|
+
style={styles.icons}
|
|
150
|
+
/>
|
|
151
|
+
</TouchableOpacity>
|
|
152
|
+
)}
|
|
151
153
|
</>
|
|
152
154
|
)}
|
|
153
155
|
<OIconButton
|
|
@@ -205,14 +207,16 @@ export const OrderHeaderComponent = (props: OrderHeader) => {
|
|
|
205
207
|
style={styles.icons}
|
|
206
208
|
/>
|
|
207
209
|
</TouchableOpacity>
|
|
208
|
-
|
|
209
|
-
<
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
210
|
+
{!!handleViewSummaryOrder && (
|
|
211
|
+
<TouchableOpacity onPress={() => handleViewSummaryOrder?.()}>
|
|
212
|
+
<SimpleLineIcons
|
|
213
|
+
name='printer'
|
|
214
|
+
color={theme.colors.textGray}
|
|
215
|
+
size={20}
|
|
216
|
+
style={styles.icons}
|
|
217
|
+
/>
|
|
218
|
+
</TouchableOpacity>
|
|
219
|
+
)}
|
|
216
220
|
</>
|
|
217
221
|
)}
|
|
218
222
|
<OIconButton
|
|
@@ -159,7 +159,7 @@ const ReviewCustomerUI = (props: ReviewCustomerParams) => {
|
|
|
159
159
|
useEffect(() => {
|
|
160
160
|
if (scrollref?.current) {
|
|
161
161
|
Keyboard.addListener('keyboardDidShow', () => {
|
|
162
|
-
scrollref.current.scrollToEnd()
|
|
162
|
+
scrollref?.current && scrollref.current.scrollToEnd()
|
|
163
163
|
})
|
|
164
164
|
}
|
|
165
165
|
}, [scrollref?.current])
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AddressForm } from './src/components/AddressForm';
|
|
2
2
|
import { AddressDetails } from './src/components/AddressDetails';
|
|
3
|
-
|
|
3
|
+
import { AnalyticsSegment } from './src/components/AnalyticsSegment';
|
|
4
4
|
import { Home } from './src/components/Home';
|
|
5
5
|
import { LoginForm } from './src/components/LoginForm';
|
|
6
6
|
import { SignupForm } from './src/components/SignupForm';
|
|
@@ -167,7 +167,7 @@ import {
|
|
|
167
167
|
export {
|
|
168
168
|
AddressForm,
|
|
169
169
|
AddressDetails,
|
|
170
|
-
|
|
170
|
+
AnalyticsSegment,
|
|
171
171
|
Home as HomeView,
|
|
172
172
|
SignupForm,
|
|
173
173
|
LoginForm,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
createClient,
|
|
4
|
-
|
|
4
|
+
AnalyticsProvider
|
|
5
5
|
} from '@segment/analytics-react-native';
|
|
6
6
|
import { useEvent, useConfig, useLanguage } from 'ordering-components/native';
|
|
7
7
|
|
|
@@ -302,9 +302,9 @@ export const AnalyticsSegment = (props: any) => {
|
|
|
302
302
|
|
|
303
303
|
return (
|
|
304
304
|
<>
|
|
305
|
-
|
|
305
|
+
<AnalyticsProvider client={segmentClient}>
|
|
306
306
|
{children}
|
|
307
|
-
</AnalyticsProvider>
|
|
307
|
+
</AnalyticsProvider>
|
|
308
308
|
</>
|
|
309
309
|
)
|
|
310
310
|
}
|
|
@@ -345,7 +345,7 @@ const CartUI = (props: any) => {
|
|
|
345
345
|
<TouchableOpacity style={{ marginLeft: 3 }} onPress={() => setOpenTaxModal({ open: true, data: offer, type: 'offer_target_3' })}>
|
|
346
346
|
<AntIcon name='infocirlceo' size={16} color={theme.colors.primary} />
|
|
347
347
|
</TouchableOpacity>
|
|
348
|
-
{
|
|
348
|
+
{!!offer?.id && (
|
|
349
349
|
<OfferAlert offerId={offer?.id} />
|
|
350
350
|
)}
|
|
351
351
|
</OSRow>
|
|
@@ -23,6 +23,7 @@ const DriverTipsUI = (props: any) => {
|
|
|
23
23
|
driverTip,
|
|
24
24
|
driverTipsOptions,
|
|
25
25
|
isMulti,
|
|
26
|
+
isLoading,
|
|
26
27
|
cart,
|
|
27
28
|
carts,
|
|
28
29
|
isDriverTipUseCustom,
|
|
@@ -79,8 +80,10 @@ const DriverTipsUI = (props: any) => {
|
|
|
79
80
|
<TouchableOpacity
|
|
80
81
|
key={i}
|
|
81
82
|
onPress={() => {
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
if (!isLoading) {
|
|
84
|
+
handlerChangeOption(option)
|
|
85
|
+
setCustomTip(false)
|
|
86
|
+
}
|
|
84
87
|
}}
|
|
85
88
|
>
|
|
86
89
|
<DTCard
|
|
@@ -95,7 +98,7 @@ const DriverTipsUI = (props: any) => {
|
|
|
95
98
|
))}
|
|
96
99
|
{isDriverTipUseCustom && (
|
|
97
100
|
<TouchableOpacity
|
|
98
|
-
onPress={() => setCustomTip(true)}
|
|
101
|
+
onPress={() => { !isLoading && setCustomTip(true) }}
|
|
99
102
|
>
|
|
100
103
|
<DTCard
|
|
101
104
|
style={style.semicircle}
|
|
@@ -256,10 +256,18 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
256
256
|
setOtpType(type)
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
-
const handleLoginOtp = (code: string) => {
|
|
259
|
+
const handleLoginOtp = async (code: string) => {
|
|
260
260
|
if (!code) return
|
|
261
|
-
handleButtonLoginClick({ code })
|
|
262
|
-
|
|
261
|
+
const logged = await handleButtonLoginClick({ code })
|
|
262
|
+
if (logged){
|
|
263
|
+
setWillVerifyOtpState(false)
|
|
264
|
+
} else {
|
|
265
|
+
setAlertState({
|
|
266
|
+
open: true,
|
|
267
|
+
title: '',
|
|
268
|
+
content: t('OTP_CODE_INCORRECT', 'Otp code incorrect')
|
|
269
|
+
})
|
|
270
|
+
}
|
|
263
271
|
}
|
|
264
272
|
|
|
265
273
|
const closeAlert = () => {
|
|
@@ -90,6 +90,15 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
90
90
|
const isMultiDriverTips = configs?.checkout_multi_business_enabled?.value === '1'
|
|
91
91
|
const walletCarts = (Object.values(carts)?.filter((cart: any) => cart?.products && cart?.products?.length && cart?.status !== 2 && cart?.valid_schedule && cart?.valid_products && cart?.valid_address && cart?.valid_maximum && cart?.valid_minimum && cart?.wallets) || null) || []
|
|
92
92
|
|
|
93
|
+
const walletName: any = {
|
|
94
|
+
cash: {
|
|
95
|
+
name: t('PAY_WITH_CASH_WALLET', 'Pay with Cash Wallet'),
|
|
96
|
+
},
|
|
97
|
+
credit_point: {
|
|
98
|
+
name: t('PAY_WITH_CREDITS_POINTS_WALLET', 'Pay with Credit Points Wallet'),
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
93
102
|
const driverTipsOptions = typeof configs?.driver_tip_options?.value === 'string'
|
|
94
103
|
? JSON.parse(configs?.driver_tip_options?.value) || []
|
|
95
104
|
: configs?.driver_tip_options?.value || []
|
|
@@ -316,6 +325,7 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
316
325
|
</OText>
|
|
317
326
|
<DriverTips
|
|
318
327
|
isMulti
|
|
328
|
+
isLoading={loading}
|
|
319
329
|
carts={openCarts}
|
|
320
330
|
businessIds={openCarts.map((cart: any) => cart.business_id)}
|
|
321
331
|
driverTipsOptions={driverTipsOptions}
|
|
@@ -413,6 +423,16 @@ const MultiCheckoutUI = (props: any) => {
|
|
|
413
423
|
</OText>
|
|
414
424
|
</View>
|
|
415
425
|
)}
|
|
426
|
+
{!cartGroup?.loading && cartGroup?.result?.payment_events?.length > 0 && cartGroup?.result?.payment_events?.map((event: any) => (
|
|
427
|
+
<View key={event.id} style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
|
428
|
+
<OText size={14} lineHeight={24} color={theme.colors.textNormal} weight={'400'}>
|
|
429
|
+
{walletName[cartGroup?.result?.wallets?.find((wallet: any) => wallet.wallet_id === event.wallet_id)?.type]?.name}
|
|
430
|
+
</OText>
|
|
431
|
+
<OText size={14} lineHeight={24} color={theme.colors.textNormal} weight={'400'}>
|
|
432
|
+
-{parsePrice(event.amount, { isTruncable: true })}
|
|
433
|
+
</OText>
|
|
434
|
+
</View>
|
|
435
|
+
))}
|
|
416
436
|
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
|
417
437
|
<OText size={16} lineHeight={24} color={theme.colors.textNormal} weight={'500'}>
|
|
418
438
|
{t('TOTAL_FOR_ALL_CARTS', 'Total for all Carts')}
|