ordering-ui-react-native 0.12.43 → 0.12.47

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.
Files changed (60) hide show
  1. package/package.json +1 -1
  2. package/src/components/AppleLogin/index.tsx +145 -0
  3. package/src/components/AppleLogin/styles.tsx +22 -0
  4. package/src/components/BusinessesListing/index.tsx +1 -1
  5. package/src/components/Cart/index.tsx +56 -23
  6. package/src/components/LoginForm/index.tsx +34 -17
  7. package/src/components/OrderDetails/index.tsx +90 -35
  8. package/src/components/OrderSummary/index.tsx +59 -27
  9. package/src/components/OrderSummary/styles.tsx +6 -0
  10. package/src/components/ProductForm/index.tsx +1 -1
  11. package/src/components/SignupForm/index.tsx +52 -35
  12. package/src/components/SingleProductCard/index.tsx +1 -1
  13. package/src/components/TaxInformation/index.tsx +51 -0
  14. package/src/components/TaxInformation/styles.tsx +9 -0
  15. package/src/components/UserFormDetails/index.tsx +0 -2
  16. package/src/navigators/BottomNavigator.tsx +1 -1
  17. package/src/types/index.tsx +7 -1
  18. package/themes/business/src/components/AcceptOrRejectOrder/index.tsx +12 -7
  19. package/themes/doordash/src/components/Cart/index.tsx +55 -22
  20. package/themes/doordash/src/components/OrderDetails/index.tsx +444 -386
  21. package/themes/doordash/src/components/OrderSummary/index.tsx +252 -221
  22. package/themes/doordash/src/components/OrderSummary/styles.tsx +6 -0
  23. package/themes/doordash/src/components/SingleProductCard/index.tsx +1 -1
  24. package/themes/doordash/src/components/TaxInformation/index.tsx +51 -0
  25. package/themes/doordash/src/components/TaxInformation/styles.tsx +9 -0
  26. package/themes/franchises/src/components/Cart/index.tsx +55 -23
  27. package/themes/franchises/src/components/OrderDetails/index.tsx +77 -23
  28. package/themes/franchises/src/components/OrderSummary/index.tsx +58 -24
  29. package/themes/franchises/src/components/OrderSummary/styles.tsx +6 -0
  30. package/themes/franchises/src/components/SingleProductCard/index.tsx +1 -1
  31. package/themes/franchises/src/components/TaxInformation/index.tsx +51 -0
  32. package/themes/franchises/src/components/TaxInformation/styles.tsx +9 -0
  33. package/themes/instacart/src/components/Cart/index.tsx +57 -17
  34. package/themes/instacart/src/components/OrderDetails/index.tsx +490 -433
  35. package/themes/instacart/src/components/OrderSummary/index.tsx +236 -194
  36. package/themes/instacart/src/components/OrderSummary/styles.tsx +6 -0
  37. package/themes/instacart/src/components/SingleProductCard/index.tsx +2 -2
  38. package/themes/instacart/src/components/TaxInformation/index.tsx +51 -0
  39. package/themes/instacart/src/components/TaxInformation/styles.tsx +9 -0
  40. package/themes/original/src/components/Cart/index.tsx +55 -13
  41. package/themes/original/src/components/OrderDetails/index.tsx +76 -23
  42. package/themes/original/src/components/OrderSummary/index.tsx +208 -173
  43. package/themes/original/src/components/OrderSummary/styles.tsx +6 -0
  44. package/themes/original/src/components/SingleProductCard/index.tsx +1 -1
  45. package/themes/original/src/components/TaxInformation/index.tsx +51 -0
  46. package/themes/original/src/components/TaxInformation/styles.tsx +9 -0
  47. package/themes/single-business/src/components/Cart/index.tsx +57 -24
  48. package/themes/single-business/src/components/OrderDetails/index.tsx +77 -23
  49. package/themes/single-business/src/components/OrderSummary/index.tsx +58 -24
  50. package/themes/single-business/src/components/OrderSummary/styles.tsx +6 -0
  51. package/themes/single-business/src/components/SingleProductCard/index.tsx +1 -1
  52. package/themes/single-business/src/components/TaxInformation/index.tsx +51 -0
  53. package/themes/single-business/src/components/TaxInformation/styles.tsx +9 -0
  54. package/themes/uber-eats/src/components/Cart/index.tsx +56 -14
  55. package/themes/uber-eats/src/components/OrderDetails/index.tsx +81 -22
  56. package/themes/uber-eats/src/components/OrderSummary/index.tsx +56 -23
  57. package/themes/uber-eats/src/components/OrderSummary/styles.tsx +6 -0
  58. package/themes/uber-eats/src/components/SingleProductCard/index.tsx +1 -1
  59. package/themes/uber-eats/src/components/TaxInformation/index.tsx +51 -0
  60. package/themes/uber-eats/src/components/TaxInformation/styles.tsx +9 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ordering-ui-react-native",
3
- "version": "0.12.43",
3
+ "version": "0.12.47",
4
4
  "description": "Reusable components made in react native",
5
5
  "main": "src/index.tsx",
6
6
  "author": "ordering.inc",
@@ -0,0 +1,145 @@
1
+ import React, { useEffect } from 'react';
2
+ import { Platform, StyleSheet } from 'react-native';
3
+ import { appleAuthAndroid, appleAuth } from '@invertase/react-native-apple-authentication';
4
+ import { useConfig, useApi, useLanguage } from 'ordering-components/native'
5
+ import uuid from 'react-native-uuid';
6
+ import Icon from 'react-native-vector-icons/FontAwesome5';
7
+
8
+ import { Container, AppleButton } from './styles';
9
+ import { useTheme } from 'styled-components/native';
10
+ import { OText } from '../shared';
11
+ import { AppleLoginParams } from '../../types';
12
+
13
+ export const AppleLogin = (props : AppleLoginParams) => {
14
+
15
+ const {
16
+ notificationState,
17
+ handleErrors,
18
+ handleLoading,
19
+ handleSuccessApple,
20
+ } = props
21
+
22
+ const [{ configs }] = useConfig()
23
+ const [ordering] = useApi()
24
+ const [, t] = useLanguage()
25
+ const theme = useTheme()
26
+
27
+ const buttonText = t('LOGIN_WITH_APPLE', 'Login with Apple');
28
+
29
+ const onAppleButtonPress = async () => {
30
+ const rawNonce: any = uuid.v4()
31
+ const state: any = uuid.v4()
32
+
33
+ if (Platform.OS === 'ios') {
34
+ try {
35
+ const appleAuthRequestResponse = await appleAuth.performRequest({
36
+ requestedOperation: appleAuth.Operation.LOGIN,
37
+ requestedScopes: [appleAuth.Scope.EMAIL, appleAuth.Scope.FULL_NAME],
38
+ nonce: rawNonce,
39
+ state
40
+ });
41
+ console.log('appleAuthRequestResponse', appleAuthRequestResponse);
42
+
43
+ const {
44
+ user,
45
+ email,
46
+ identityToken,
47
+ authorizationCode,
48
+ } = appleAuthRequestResponse
49
+
50
+ if (identityToken && authorizationCode) {
51
+ console.log('auth code: ', authorizationCode)
52
+ handleLoginApple(authorizationCode)
53
+ console.warn(`Apple Authentication Completed, ${user}, ${email}`);
54
+ } else {
55
+ handleErrors && handleErrors(t('ERROR_LOGIN_APPLE', 'Error login with apple'))
56
+ }
57
+
58
+ } catch (error : any) {
59
+ handleErrors && handleErrors(error.message)
60
+ }
61
+ } else {
62
+ try {
63
+ appleAuthAndroid.configure({
64
+ clientId: configs?.apple_login_client_id?.value,
65
+ redirectUri: 'https://example-app.com/redirect',
66
+ responseType: appleAuthAndroid.ResponseType.ALL,
67
+ scope: appleAuthAndroid.Scope.ALL,
68
+ nonce: rawNonce,
69
+ state,
70
+ });
71
+ const { code } = await appleAuthAndroid.signIn();
72
+ handleLoginApple(code)
73
+ } catch (error : any) {
74
+ handleErrors && handleErrors(error?.message)
75
+ }
76
+ }
77
+ }
78
+ const handleLoginApple = async (code: string) => {
79
+ const body: any = {
80
+ code,
81
+ platform: Platform.OS === 'ios' && 'ios'
82
+ }
83
+ if (notificationState?.notification_token) {
84
+ body.notification_token = notificationState.notification_token
85
+ body.notification_app = notificationState.notification_app
86
+ }
87
+
88
+ try {
89
+ handleLoading && handleLoading(true)
90
+ const response: any = await fetch(`${ordering.root}/auth/apple`, {
91
+ method: 'POST',
92
+ headers: { 'Content-Type': 'application/json' },
93
+ body: JSON.stringify(body)
94
+ })
95
+ const { error, result } = await response.json()
96
+ handleLoading && handleLoading(false)
97
+ if (!error && result) {
98
+ handleSuccessApple && handleSuccessApple(result)
99
+ } else {
100
+ handleErrors && handleErrors(result || t('ERROR_LOGIN_AUTH_APPLE', 'Error login auth with apple'))
101
+ }
102
+ } catch (error : any) {
103
+ handleLoading && handleLoading(false)
104
+ handleErrors && handleErrors(error?.message)
105
+ }
106
+ }
107
+
108
+ useEffect(() => {
109
+ if (Platform.OS !== 'ios' && !appleAuth.isSupported) return
110
+ return appleAuth.onCredentialRevoked(async () => {
111
+ handleErrors && handleErrors(t('USER_CREDENTIALS_REVOKED', 'User credentials revoked'))
112
+ });
113
+ }, []);
114
+
115
+ return (
116
+ <Container>
117
+ <AppleButton
118
+ onPress={onAppleButtonPress}
119
+ >
120
+ <Icon
121
+ name="apple"
122
+ size={34}
123
+ color={theme.colors.black}
124
+ style={style.appleBtn}
125
+ />
126
+ <OText style={style.textBtn}>
127
+ {buttonText}
128
+ </OText>
129
+ </AppleButton>
130
+ </Container>
131
+ );
132
+ }
133
+
134
+ const style = StyleSheet.create({
135
+ appleBtn: {
136
+ position: 'absolute',
137
+ left: 0,
138
+ marginHorizontal: 10
139
+ },
140
+ textBtn: {
141
+ fontSize: 16,
142
+ color: '#000000',
143
+ marginLeft: 20
144
+ }
145
+ })
@@ -0,0 +1,22 @@
1
+ import styled from 'styled-components/native'
2
+
3
+ export const Container = styled.View``
4
+
5
+ export const AppleButton = styled.TouchableOpacity`
6
+ background-color: #EFEFEF;
7
+ border-color: #EFEFEF;
8
+ border-radius: 30px;
9
+ font-size: 16px;
10
+ padding: 15px 30px;
11
+ font-size: 16px;
12
+ font-weight: 400;
13
+ text-align: center;
14
+ width: 100%;
15
+ display: flex;
16
+ flex-direction: row;
17
+ align-items: center;
18
+ justify-content: center;
19
+ position: relative;
20
+ height: 52px;
21
+ margin-top: 10px;
22
+ `
@@ -101,7 +101,7 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
101
101
  style={{ paddingBottom: 0 }}
102
102
  />
103
103
  )}
104
- {auth && (
104
+ {auth && user?.name && (
105
105
  <WelcomeTitle>
106
106
  <View style={styles.welcome}>
107
107
  <OText style={{ fontWeight: 'bold' }} size={28} >
@@ -8,9 +8,9 @@ import {
8
8
  useValidationFields,
9
9
  } from 'ordering-components/native';
10
10
 
11
- import { CContainer, CheckoutAction } from './styles';
11
+ import { CContainer, CheckoutAction, } from './styles';
12
12
 
13
- import { OSBill, OSTable, OSCoupon, OSTotal } from '../OrderSummary/styles';
13
+ import { OSBill, OSTable, OSCoupon, OSTotal, OSRow } from '../OrderSummary/styles';
14
14
 
15
15
  import { ProductItemAccordion } from '../ProductItemAccordion';
16
16
  import { BusinessItemAccordion } from '../BusinessItemAccordion';
@@ -21,6 +21,9 @@ import { ProductForm } from '../ProductForm';
21
21
  import { UpsellingProducts } from '../UpsellingProducts';
22
22
  import { verifyDecimals } from '../../utils';
23
23
  import { useTheme } from 'styled-components/native';
24
+ import AntIcon from 'react-native-vector-icons/AntDesign'
25
+ import { TaxInformation } from '../TaxInformation';
26
+ import { TouchableOpacity } from 'react-native';
24
27
 
25
28
  const CartUI = (props: any) => {
26
29
  const {
@@ -45,6 +48,7 @@ const CartUI = (props: any) => {
45
48
  const [curProduct, setCurProduct] = useState<any>(null)
46
49
  const [openUpselling, setOpenUpselling] = useState(false)
47
50
  const [canOpenUpselling, setCanOpenUpselling] = useState(false)
51
+ const [openTaxModal, setOpenTaxModal] = useState<any>({ open: false, data: null })
48
52
 
49
53
  const isCartPending = cart?.status === 2
50
54
  const isCouponEnabled = validationFields?.fields?.checkout?.coupon?.enabled
@@ -90,6 +94,16 @@ const CartUI = (props: any) => {
90
94
  })
91
95
  }
92
96
 
97
+ const getIncludedTaxes = () => {
98
+ if (cart?.taxes === null) {
99
+ return cart.business.tax_type === 1 ? cart?.tax : 0
100
+ } else {
101
+ return cart?.taxes.reduce((taxIncluded: number, tax: any) => {
102
+ return taxIncluded + (tax.type === 1 ? tax.summary?.tax : 0)
103
+ }, 0)
104
+ }
105
+ }
106
+
93
107
  return (
94
108
  <CContainer>
95
109
  <BusinessItemAccordion
@@ -118,9 +132,7 @@ const CartUI = (props: any) => {
118
132
  <OSTable>
119
133
  <OText>{t('SUBTOTAL', 'Subtotal')}</OText>
120
134
  <OText>
121
- {cart.business.tax_type === 1
122
- ? parsePrice((cart?.subtotal + cart?.tax) || 0)
123
- : parsePrice(cart?.subtotal || 0)}
135
+ {parsePrice(cart?.subtotal + getIncludedTaxes())}
124
136
  </OText>
125
137
  </OSTable>
126
138
  {cart?.discount > 0 && cart?.total >= 0 && (
@@ -151,15 +163,38 @@ const CartUI = (props: any) => {
151
163
  )}
152
164
  </OSTable>
153
165
  )}
154
- {cart.business.tax_type !== 1 && (
155
- <OSTable>
156
- <OText>
157
- {t('TAX', 'Tax')}
158
- {`(${verifyDecimals(cart?.business?.tax, parseNumber)}%)`}
159
- </OText>
160
- <OText>{parsePrice(cart?.tax || 0)}</OText>
161
- </OSTable>
162
- )}
166
+ {
167
+ cart.taxes?.length > 0 && cart.taxes.filter((tax: any) => tax.type === 2 && tax?.rate !== 0).map((tax: any) => (
168
+ <OSTable key={tax.id}>
169
+ <OSRow>
170
+ <OText numberOfLines={1} >
171
+ {tax.name || t('INHERIT_FROM_BUSINESS', 'Inherit from business')}{' '}
172
+ {`(${verifyDecimals(tax?.rate, parseNumber)}%)`}{' '}
173
+ </OText>
174
+ <TouchableOpacity onPress={() => setOpenTaxModal({ open: true, data: tax })} >
175
+ <AntIcon name='exclamationcircleo' size={18} color={theme.colors.primary} />
176
+ </TouchableOpacity>
177
+ </OSRow>
178
+ <OText>{parsePrice(tax?.summary?.tax || 0)}</OText>
179
+ </OSTable>
180
+ ))
181
+ }
182
+ {
183
+ cart?.fees?.length > 0 && cart?.fees?.filter((fee : any) => !(fee.fixed === 0 && fee.percentage === 0)).map((fee: any) => (
184
+ <OSTable key={fee?.id}>
185
+ <OSRow>
186
+ <OText numberOfLines={1}>
187
+ {fee.name || t('INHERIT_FROM_BUSINESS', 'Inherit from business')}{' '}
188
+ ({parsePrice(fee?.fixed)} + {fee?.percentage}%){' '}
189
+ </OText>
190
+ <TouchableOpacity onPress={() => setOpenTaxModal({ open: true, data: fee })} >
191
+ <AntIcon name='exclamationcircleo' size={18} color={theme.colors.primary} />
192
+ </TouchableOpacity>
193
+ </OSRow>
194
+ <OText>{parsePrice(fee?.summary?.fixed + fee?.summary?.percentage || 0)}</OText>
195
+ </OSTable>
196
+ ))
197
+ }
163
198
  {orderState?.options?.type === 1 && cart?.delivery_price > 0 && (
164
199
  <OSTable>
165
200
  <OText>{t('DELIVERY_FEE', 'Delivery Fee')}</OText>
@@ -180,15 +215,6 @@ const CartUI = (props: any) => {
180
215
  <OText>{parsePrice(cart?.driver_tip)}</OText>
181
216
  </OSTable>
182
217
  )}
183
- {cart?.service_fee > 0 && (
184
- <OSTable>
185
- <OText>
186
- {t('SERVICE_FEE', 'Service Fee')}
187
- {`(${verifyDecimals(cart?.business?.service_fee, parseNumber)}%)`}
188
- </OText>
189
- <OText>{parsePrice(cart?.service_fee)}</OText>
190
- </OSTable>
191
- )}
192
218
  {isCouponEnabled && !isCartPending && (
193
219
  <OSTable>
194
220
  <OSCoupon>
@@ -263,6 +289,13 @@ const CartUI = (props: any) => {
263
289
  setCanOpenUpselling={setCanOpenUpselling}
264
290
  />
265
291
  )}
292
+ <OModal
293
+ open={openTaxModal.open}
294
+ onClose={() => setOpenTaxModal({ open: false, data: null })}
295
+ entireModal
296
+ >
297
+ <TaxInformation data={openTaxModal.data} products={cart.products} />
298
+ </OModal>
266
299
  </CContainer>
267
300
  )
268
301
  }
@@ -37,6 +37,7 @@ import NavBar from '../NavBar'
37
37
  import { OText, OButton, OInput, OModal } from '../shared';
38
38
  import { LoginParams } from '../../types';
39
39
  import { useTheme } from 'styled-components/native';
40
+ import { AppleLogin } from '../AppleLogin'
40
41
 
41
42
  const LoginFormUI = (props: LoginParams) => {
42
43
  const {
@@ -80,7 +81,7 @@ const LoginFormUI = (props: LoginParams) => {
80
81
  const [passwordSee, setPasswordSee] = useState(false);
81
82
  const [isLoadingVerifyModal, setIsLoadingVerifyModal] = useState(false);
82
83
  const [isModalVisible, setIsModalVisible] = useState(false);
83
- const [isFBLoading, setIsFBLoading] = useState(false);
84
+ const [isLoadingSocialButton, setIsLoadingSocialButton] = useState(false);
84
85
  const [phoneInputData, setPhoneInputData] = useState({
85
86
  error: '',
86
87
  phone: {
@@ -91,6 +92,10 @@ const LoginFormUI = (props: LoginParams) => {
91
92
 
92
93
  const inputRef = useRef<any>({})
93
94
 
95
+ const anySocialButtonActivated = ((configs?.facebook_login?.value === 'true' || configs?.facebook_login?.value === '1') && configs?.facebook_id?.value) ||
96
+ (configs?.google_login_client_id?.value !== '' && configs?.google_login_client_id?.value !== null) ||
97
+ (configs?.apple_login_client_id?.value !== '' && configs?.apple_login_client_id?.value !== null)
98
+
94
99
  const handleChangeTab = (val: string) => {
95
100
  props.handleChangeTab(val);
96
101
  setPasswordSee(false);
@@ -133,7 +138,15 @@ const LoginFormUI = (props: LoginParams) => {
133
138
  })
134
139
  }
135
140
 
136
- const handleChangeInputEmail = (value : string, onChange : any) => {
141
+ const handleSuccessApple = (user: any) => {
142
+ _removeStoreData('isGuestUser')
143
+ login({
144
+ user,
145
+ token: user?.session?.access_token
146
+ })
147
+ }
148
+
149
+ const handleChangeInputEmail = (value: string, onChange: any) => {
137
150
  onChange(value.toLowerCase().replace(/[&,()%";:ç?<>{}\\[\]\s]/g, ''))
138
151
  }
139
152
 
@@ -353,10 +366,7 @@ const LoginFormUI = (props: LoginParams) => {
353
366
  )
354
367
  }
355
368
 
356
- {configs && Object.keys(configs).length > 0 && (
357
- (((configs?.facebook_login?.value === 'true' || configs?.facebook_login?.value === '1') && configs?.facebook_id?.value) ||
358
- (configs?.google_login_client_id?.value !== '' && configs?.google_login_client_id?.value !== null)) &&
359
- (
369
+ {configs && Object.keys(configs).length > 0 && anySocialButtonActivated && (
360
370
  <ButtonsWrapper>
361
371
  <OText size={18} mBottom={10} color={theme.colors.disabled}>
362
372
  {t('SELECT_AN_OPTION_TO_LOGIN', 'Select an option to login')}
@@ -364,26 +374,33 @@ const LoginFormUI = (props: LoginParams) => {
364
374
  <SocialButtons>
365
375
  {(configs?.facebook_login?.value === 'true' || configs?.facebook_login?.value === '1') &&
366
376
  configs?.facebook_id?.value && (
367
- <FacebookLogin
368
- notificationState={notificationState}
369
- handleErrors={(err: any) => showToast(ToastType.Error, err)}
370
- handleLoading={(val: boolean) => setIsFBLoading(val)}
371
- handleSuccessFacebookLogin={handleSuccessFacebook}
372
- />
373
- )}
377
+ <FacebookLogin
378
+ notificationState={notificationState}
379
+ handleErrors={(err: any) => showToast(ToastType.Error, err)}
380
+ handleLoading={(val: boolean) => setIsLoadingSocialButton(val)}
381
+ handleSuccessFacebookLogin={handleSuccessFacebook}
382
+ />
383
+ )}
374
384
  {(configs?.google_login_client_id?.value !== '' && configs?.google_login_client_id?.value !== null) && (
375
385
  <GoogleLogin
376
386
  notificationState={notificationState}
377
387
  webClientId={configs?.google_login_client_id?.value}
378
388
  handleErrors={(err: any) => showToast(ToastType.Error, err)}
379
- handleLoading={(val: boolean) => setIsFBLoading(val)}
389
+ handleLoading={(val: boolean) => setIsLoadingSocialButton(val)}
380
390
  handleSuccessGoogleLogin={handleSuccessFacebook}
381
391
  />
382
392
  )}
393
+ {(configs?.apple_login_client_id?.value !== '' && configs?.apple_login_client_id?.value !== null) && (
394
+ <AppleLogin
395
+ notificationState={notificationState}
396
+ handleErrors={(err: any) => showToast(ToastType.Error, err)}
397
+ handleLoading={(val: boolean) => setIsLoadingSocialButton(val)}
398
+ handleSuccessApple={handleSuccessApple}
399
+ />
400
+ )}
383
401
  </SocialButtons>
384
402
  </ButtonsWrapper>
385
- )
386
- )}
403
+ )}
387
404
 
388
405
  {onNavigationRedirect && registerButtonText && (
389
406
  <ButtonsWrapper>
@@ -411,7 +428,7 @@ const LoginFormUI = (props: LoginParams) => {
411
428
  handleVerifyCodeClick={handleVerifyCodeClick}
412
429
  />
413
430
  </OModal>
414
- <Spinner visible={isFBLoading} />
431
+ <Spinner visible={isLoadingSocialButton} />
415
432
  </Container>
416
433
  );
417
434
  };
@@ -3,6 +3,7 @@ import { View, StyleSheet, BackHandler, TouchableOpacity, I18nManager } from 're
3
3
  import LinearGradient from 'react-native-linear-gradient'
4
4
  import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder';
5
5
  import MaterialCommunityIcon from 'react-native-vector-icons/MaterialCommunityIcons'
6
+ import AntIcon from 'react-native-vector-icons/AntDesign'
6
7
  import { Messages } from '../Messages'
7
8
  import { ShareComponent } from '../ShareComponent'
8
9
  import AsyncStorage from '@react-native-async-storage/async-storage';
@@ -48,6 +49,8 @@ import { verifyDecimals } from '../../utils'
48
49
  import { useTheme } from 'styled-components/native'
49
50
  import { NotFoundSource } from '../NotFoundSource'
50
51
  import { OrderCreating } from '../OrderCreating';
52
+ import { OSRow } from '../OrderSummary/styles';
53
+ import { TaxInformation } from '../TaxInformation';
51
54
 
52
55
  export const OrderDetailsUI = (props: OrderDetailsParams) => {
53
56
  const {
@@ -103,6 +106,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
103
106
  const [unreadAlert, setUnreadAlert] = useState({ business: false, driver: false })
104
107
  const [isReviewed, setIsReviewed] = useState(false)
105
108
  const [openOrderCreating, setOpenOrderCreating] = useState(true)
109
+ const [openTaxModal, setOpenTaxModal] = useState<any>({ open: false, data: null })
106
110
  const { order, loading, businessData, error } = props.order
107
111
  const isTaxIncluded = order?.tax_type === 1
108
112
 
@@ -195,6 +199,16 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
195
199
  )
196
200
  }
197
201
 
202
+ const getIncludedTaxes = () => {
203
+ if (order?.taxes?.length === 0) {
204
+ return order.tax_type === 1 ? order?.summary?.tax ?? 0 : 0
205
+ } else {
206
+ return order?.taxes.reduce((taxIncluded: number, tax: any) => {
207
+ return taxIncluded + (tax.type === 1 ? tax.summary?.tax : 0)
208
+ }, 0)
209
+ }
210
+ }
211
+
198
212
  useEffect(() => {
199
213
  BackHandler.addEventListener('hardwareBackPress', handleArrowBack);
200
214
  return () => {
@@ -216,7 +230,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
216
230
 
217
231
  useEffect(() => {
218
232
  if (driverLocation) {
219
- locations[0] = {...locations[0], lat: driverLocation.lat, lng: driverLocation.lng}
233
+ locations[0] = { ...locations[0], lat: driverLocation.lat, lng: driverLocation.lng }
220
234
  }
221
235
  }, [driverLocation])
222
236
 
@@ -341,7 +355,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
341
355
  </OrderStatus>
342
356
  </View>
343
357
  <OrderCustomer>
344
- <OText size={18} style={{textAlign: 'left'}}>{t('CUSTOMER', 'Customer')}</OText>
358
+ <OText size={18} style={{ textAlign: 'left' }}>{t('CUSTOMER', 'Customer')}</OText>
345
359
  <Customer>
346
360
  <CustomerPhoto>
347
361
  <OIcon
@@ -352,8 +366,8 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
352
366
  />
353
367
  </CustomerPhoto>
354
368
  <InfoBlock>
355
- <OText size={18} style={{textAlign: 'left'}} >{order?.customer?.name} {order?.customer?.lastname}</OText>
356
- <OText style={{textAlign: 'left'}}>{order?.customer?.address}</OText>
369
+ <OText size={18} style={{ textAlign: 'left' }} >{order?.customer?.name} {order?.customer?.lastname}</OText>
370
+ <OText style={{ textAlign: 'left' }}>{order?.customer?.address}</OText>
357
371
  </InfoBlock>
358
372
  </Customer>
359
373
  {order?.driver && (
@@ -398,7 +412,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
398
412
  </OrderDriver>
399
413
  )}
400
414
  <OrderProducts>
401
- <OText size={18} style={{textAlign: 'left'}}>{t('YOUR_ORDER', 'Your Order')}</OText>
415
+ <OText size={18} style={{ textAlign: 'left' }}>{t('YOUR_ORDER', 'Your Order')}</OText>
402
416
  {order?.products?.length && order?.products.map((product: any, i: number) => (
403
417
  <ProductItemAccordion
404
418
  key={product?.id || i}
@@ -410,10 +424,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
410
424
  <Table>
411
425
  <OText>{t('SUBTOTAL', 'Subtotal')}</OText>
412
426
  <OText>
413
- {parsePrice(isTaxIncluded
414
- ? (order?.summary?.subtotal + order?.summary?.tax) ?? 0
415
- : order?.summary?.subtotal ?? 0
416
- )}
427
+ {parsePrice(((order?.summary?.subtotal || order?.subtotal) + getIncludedTaxes()))}
417
428
  </OText>
418
429
  </Table>
419
430
  {order?.summary?.discount > 0 && (
@@ -435,40 +446,77 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
435
446
  <OText>{parsePrice(order?.summary?.subtotal_with_discount ?? 0)}</OText>
436
447
  </Table>
437
448
  )}
438
- {order?.tax_type !== 1 && (
439
- <Table>
440
- <OText>
441
- {t('TAX', 'Tax')}
442
- {`(${verifyDecimals(order?.summary?.tax_rate, parseNumber)}%)`}
443
- </OText>
444
- <OText>{parsePrice(order?.summary?.tax)}</OText>
445
- </Table>
446
- )}
449
+ {
450
+ order?.taxes?.length === 0 && order?.tax_type === 2 && (
451
+ <Table>
452
+ <OText>
453
+ {t('TAX', 'Tax')} {`(${verifyDecimals(order?.tax, parseNumber)}%)`}
454
+ </OText>
455
+ <OText>{parsePrice(order?.summary?.tax || 0)}</OText>
456
+ </Table>
457
+ )
458
+ }
459
+ {
460
+ order?.fees?.length === 0 && (
461
+ <Table>
462
+ <OText>
463
+ {t('SERVICE_FEE', 'Service fee')}
464
+ {`(${verifyDecimals(order?.service_fee, parseNumber)}%)`}
465
+ </OText>
466
+ <OText>{parsePrice(order?.summary?.service_fee || 0)}</OText>
467
+ </Table>
468
+ )
469
+ }
470
+ {
471
+ order?.taxes?.length > 0 && order?.taxes?.filter((tax: any) => tax?.type === 2 && tax?.rate !== 0).map((tax: any) => (
472
+ <Table key={tax.id}>
473
+ <OSRow>
474
+ <OText numberOfLines={1}>
475
+ {tax.name || t('INHERIT_FROM_BUSINESS', 'Inherit from business')}
476
+ {`(${verifyDecimals(tax?.rate, parseNumber)}%)`}{' '}
477
+ </OText>
478
+ <TouchableOpacity onPress={() => setOpenTaxModal({ open: true, data: tax })}>
479
+ <AntIcon name='exclamationcircleo' size={18} color={theme.colors.primary} />
480
+ </TouchableOpacity>
481
+ </OSRow>
482
+ <OText>{parsePrice(tax?.summary?.tax || 0)}</OText>
483
+ </Table>
484
+ ))
485
+ }
486
+ {
487
+ order?.fees?.length > 0 && order?.fees?.filter((fee : any) => !(fee.fixed === 0 && fee.percentage === 0))?.map((fee: any) => (
488
+ <Table key={fee.id}>
489
+ <OSRow>
490
+ <OText numberOfLines={1}>
491
+ {fee.name || t('INHERIT_FROM_BUSINESS', 'Inherit from business')}
492
+ ({parsePrice(fee?.fixed)} + {fee.percentage}%){' '}
493
+ </OText>
494
+ <TouchableOpacity onPress={() => setOpenTaxModal({ open: true, data: fee })}>
495
+ <AntIcon name='exclamationcircleo' size={18} color={theme.colors.primary} />
496
+ </TouchableOpacity>
497
+ </OSRow>
498
+ <OText>{parsePrice(fee?.fixed + fee?.summary?.percentage || 0)}</OText>
499
+ </Table>
500
+ ))
501
+ }
447
502
  {order?.summary?.delivery_price > 0 && (
448
503
  <Table>
449
504
  <OText>{t('DELIVERY_FEE', 'Delivery Fee')}</OText>
450
505
  <OText>{parsePrice(order?.summary?.delivery_price)}</OText>
451
506
  </Table>
452
507
  )}
453
- <Table>
454
- <OText>
455
- {t('DRIVER_TIP', 'Driver tip')}
456
- {order?.summary?.driver_tip > 0 &&
457
- parseInt(configs?.driver_tip_type?.value, 10) === 2 &&
458
- !parseInt(configs?.driver_tip_use_custom?.value, 10) &&
459
- (
460
- `(${verifyDecimals(order?.summary?.driver_tip, parseNumber)}%)`
461
- )}
462
- </OText>
463
- <OText>{parsePrice(order?.summary?.driver_tip ?? 0)}</OText>
464
- </Table>
465
- {order?.summary?.service_fee > 0 && (
508
+ {order?.summary?.driver_tip > 0 && (
466
509
  <Table>
467
510
  <OText>
468
- {t('SERVICE_FEE', 'Service Fee')}
469
- {`(${verifyDecimals(order?.summary?.service_fee, parseNumber)}%)`}
511
+ {t('DRIVER_TIP', 'Driver tip')}
512
+ {order?.summary?.driver_tip > 0 &&
513
+ parseInt(configs?.driver_tip_type?.value, 10) === 2 &&
514
+ !parseInt(configs?.driver_tip_use_custom?.value, 10) &&
515
+ (
516
+ `(${verifyDecimals(order?.summary?.driver_tip, parseNumber)}%)`
517
+ )}
470
518
  </OText>
471
- <OText>{parsePrice(order?.summary?.service_fee)}</OText>
519
+ <OText>{parsePrice(order?.summary?.driver_tip ?? 0)}</OText>
472
520
  </Table>
473
521
  )}
474
522
  <Total>
@@ -483,7 +531,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
483
531
  (
484
532
  parseInt(order?.status) === 1 ||
485
533
  parseInt(order?.status) === 11 ||
486
- parseInt(order?.status) === 15
534
+ parseInt(order?.status) === 15
487
535
  ) && !order.review && !isReviewed && (
488
536
  <OButton
489
537
  onClick={() => handleClickOrderReview(order)}
@@ -548,6 +596,13 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
548
596
  isOrderDetail
549
597
  />
550
598
  </OModal>
599
+ <OModal
600
+ open={openTaxModal.open}
601
+ onClose={() => setOpenTaxModal({ open: false, data: null })}
602
+ entireModal
603
+ >
604
+ <TaxInformation data={openTaxModal.data} products={order?.products} />
605
+ </OModal>
551
606
  </OrderDetailsContainer>
552
607
  )
553
608
  }