ordering-ui-react-native 0.15.13 → 0.15.15-release

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 (154) hide show
  1. package/package.json +5 -3
  2. package/src/DeliveryApp.tsx +43 -1
  3. package/src/components/BusinessTypeFilter/index.tsx +12 -2
  4. package/src/components/BusinessTypeFilter/styles.tsx +1 -1
  5. package/src/components/BusinessesListing/index.tsx +1 -1
  6. package/src/components/Checkout/index.tsx +0 -1
  7. package/src/components/LanguageSelector/index.tsx +1 -0
  8. package/src/components/OrderDetails/index.tsx +26 -5
  9. package/src/components/PaymentOptions/index.tsx +9 -16
  10. package/src/components/PaymentOptionsWebView/index.tsx +123 -124
  11. package/src/components/ProductForm/index.tsx +1 -1
  12. package/src/components/ProductForm/styles.tsx +1 -0
  13. package/src/components/StripeElementsForm/index.tsx +27 -48
  14. package/src/components/VerifyPhone/styles.tsx +1 -2
  15. package/src/config.json +0 -2
  16. package/src/navigators/HomeNavigator.tsx +6 -0
  17. package/src/pages/BusinessProductsList.tsx +1 -0
  18. package/src/pages/BusinessesListing.tsx +1 -1
  19. package/src/pages/Checkout.tsx +1 -1
  20. package/src/pages/Sessions.tsx +22 -0
  21. package/src/types/index.tsx +1 -9
  22. package/src/utils/index.tsx +68 -1
  23. package/themes/business/index.tsx +2 -0
  24. package/themes/business/src/components/AcceptOrRejectOrder/index.tsx +56 -8
  25. package/themes/business/src/components/AcceptOrRejectOrder/styles.tsx +5 -0
  26. package/themes/business/src/components/Home/index.tsx +128 -55
  27. package/themes/business/src/components/Home/styles.tsx +8 -1
  28. package/themes/business/src/components/NewOrderNotification/index.tsx +59 -98
  29. package/themes/business/src/components/OrderDetails/Business.tsx +2 -1
  30. package/themes/business/src/components/OrderDetails/Delivery.tsx +19 -12
  31. package/themes/business/src/components/OrderDetails/OrderContentComponent.tsx +150 -89
  32. package/themes/business/src/components/OrderDetails/OrderHeaderComponent.tsx +91 -17
  33. package/themes/business/src/components/OrderDetails/styles.tsx +7 -0
  34. package/themes/business/src/components/OrdersListManager/index.tsx +874 -0
  35. package/themes/business/src/components/OrdersListManager/styles.tsx +123 -0
  36. package/themes/business/src/components/OrdersListManager/utils.tsx +216 -0
  37. package/themes/business/src/components/OrdersOption/index.tsx +70 -116
  38. package/themes/business/src/components/OrdersOption/styles.tsx +2 -5
  39. package/themes/business/src/components/PreviousOrders/index.tsx +82 -23
  40. package/themes/business/src/types/index.tsx +2 -1
  41. package/themes/doordash/src/components/BusinessesListing/index.tsx +1 -1
  42. package/themes/doordash/src/components/LoginForm/index.tsx +1 -2
  43. package/themes/instacart/src/components/BusinessesListing/index.tsx +1 -1
  44. package/themes/kiosk/src/components/BusinessController/index.tsx +27 -6
  45. package/themes/kiosk/src/components/BusinessController/styles.tsx +1 -1
  46. package/themes/kiosk/src/components/BusinessProductsListing/index.tsx +48 -21
  47. package/themes/kiosk/src/components/Cart/index.tsx +98 -24
  48. package/themes/kiosk/src/components/Cart/styles.tsx +6 -0
  49. package/themes/kiosk/src/components/CartBottomSheet/index.tsx +1 -1
  50. package/themes/kiosk/src/components/CartBottomSheet/styles.tsx +1 -1
  51. package/themes/kiosk/src/components/CartContent/index.tsx +13 -3
  52. package/themes/kiosk/src/components/CartItem/index.tsx +20 -8
  53. package/themes/kiosk/src/components/CategoriesMenu/index.tsx +6 -5
  54. package/themes/kiosk/src/components/CustomerName/index.tsx +89 -88
  55. package/themes/kiosk/src/components/Intro/index.tsx +13 -13
  56. package/themes/kiosk/src/components/LanguageSelector/index.tsx +12 -8
  57. package/themes/kiosk/src/components/NavBar/index.tsx +14 -14
  58. package/themes/kiosk/src/components/OptionCard/index.tsx +1 -1
  59. package/themes/kiosk/src/components/OrderDetails/index.tsx +136 -41
  60. package/themes/kiosk/src/components/OrderDetails/styles.tsx +5 -0
  61. package/themes/kiosk/src/components/OrderSummary/index.tsx +1 -1
  62. package/themes/kiosk/src/components/OrderTypeCardSelector/index.tsx +10 -12
  63. package/themes/kiosk/src/components/ProductForm/index.tsx +174 -125
  64. package/themes/kiosk/src/components/ProductForm/styles.tsx +1 -1
  65. package/themes/kiosk/src/components/ProductOption/index.tsx +1 -0
  66. package/themes/kiosk/src/components/ProductOption/styles.tsx +1 -0
  67. package/themes/kiosk/src/components/UpsellingProducts/index.tsx +48 -34
  68. package/themes/kiosk/src/components/shared/OButton.tsx +5 -18
  69. package/themes/kiosk/src/components/shared/OCard.tsx +112 -78
  70. package/themes/kiosk/src/types/index.d.ts +2 -0
  71. package/themes/original/index.tsx +179 -0
  72. package/themes/original/src/components/AddressForm/index.tsx +15 -10
  73. package/themes/original/src/components/AddressList/index.tsx +56 -18
  74. package/themes/original/src/components/AppleLogin/index.tsx +117 -78
  75. package/themes/original/src/components/BusinessBasicInformation/index.tsx +96 -45
  76. package/themes/original/src/components/BusinessBasicInformation/styles.tsx +28 -1
  77. package/themes/original/src/components/BusinessController/index.tsx +52 -22
  78. package/themes/original/src/components/BusinessController/styles.tsx +22 -0
  79. package/themes/original/src/components/BusinessFeaturedController/index.tsx +20 -1
  80. package/themes/original/src/components/BusinessFeaturedController/styles.tsx +23 -0
  81. package/themes/original/src/components/BusinessListingSearch/index.tsx +4 -0
  82. package/themes/original/src/components/BusinessMenuList/index.tsx +11 -4
  83. package/themes/original/src/components/BusinessPreorder/index.tsx +141 -121
  84. package/themes/original/src/components/BusinessProductsCategories/index.tsx +7 -5
  85. package/themes/original/src/components/BusinessProductsList/index.tsx +129 -22
  86. package/themes/original/src/components/BusinessProductsList/styles.tsx +29 -2
  87. package/themes/original/src/components/BusinessProductsListing/index.tsx +92 -37
  88. package/themes/original/src/components/BusinessProductsListing/styles.tsx +22 -0
  89. package/themes/original/src/components/BusinessReviews/index.tsx +4 -25
  90. package/themes/original/src/components/BusinessTypeFilter/index.tsx +1 -2
  91. package/themes/original/src/components/BusinessesListing/index.tsx +49 -58
  92. package/themes/original/src/components/Cart/index.tsx +58 -21
  93. package/themes/original/src/components/CartContent/index.tsx +2 -2
  94. package/themes/original/src/components/Checkout/index.tsx +24 -28
  95. package/themes/original/src/components/CouponControl/index.tsx +1 -0
  96. package/themes/original/src/components/DriverTips/index.tsx +1 -1
  97. package/themes/original/src/components/ForgotPasswordForm/index.tsx +8 -12
  98. package/themes/original/src/components/HighestRatedBusinesses/index.tsx +97 -89
  99. package/themes/original/src/components/Home/index.tsx +1 -1
  100. package/themes/original/src/components/LoginForm/index.tsx +156 -70
  101. package/themes/original/src/components/LoginForm/styles.tsx +6 -1
  102. package/themes/original/src/components/MessageListing/index.tsx +10 -1
  103. package/themes/original/src/components/Messages/index.tsx +50 -45
  104. package/themes/original/src/components/Messages/styles.tsx +1 -3
  105. package/themes/original/src/components/MomentOption/index.tsx +10 -1
  106. package/themes/original/src/components/MomentOption/styles.tsx +1 -1
  107. package/themes/original/src/components/OrderDetails/index.tsx +105 -127
  108. package/themes/original/src/components/OrderDetails/styles.tsx +3 -1
  109. package/themes/original/src/components/OrderProgress/index.tsx +4 -4
  110. package/themes/original/src/components/OrderProgress/styles.tsx +1 -0
  111. package/themes/original/src/components/OrderSummary/index.tsx +35 -2
  112. package/themes/original/src/components/OrderTypeSelector/index.tsx +4 -2
  113. package/themes/original/src/components/OrdersOption/index.tsx +25 -33
  114. package/themes/original/src/components/OrdersOption/styles.tsx +0 -6
  115. package/themes/original/src/components/PaymentOptionWallet/index.tsx +9 -4
  116. package/themes/original/src/components/PaymentOptionWallet/styles.tsx +1 -1
  117. package/themes/original/src/components/PaymentOptions/index.tsx +9 -19
  118. package/themes/original/src/components/PhoneInputNumber/index.tsx +15 -8
  119. package/themes/original/src/components/PlaceSpot/index.tsx +114 -0
  120. package/themes/original/src/components/PlaceSpot/styles.tsx +11 -0
  121. package/themes/original/src/components/PreviousOrders/index.tsx +19 -13
  122. package/themes/original/src/components/ProductForm/index.tsx +47 -36
  123. package/themes/original/src/components/ProductForm/styles.tsx +2 -2
  124. package/themes/original/src/components/ProductOptionSubOption/index.tsx +5 -3
  125. package/themes/original/src/components/Promotions/index.tsx +234 -0
  126. package/themes/original/src/components/Promotions/styles.tsx +60 -0
  127. package/themes/original/src/components/ReviewOrder/index.tsx +10 -9
  128. package/themes/original/src/components/ReviewProducts/index.tsx +1 -1
  129. package/themes/original/src/components/Sessions/index.tsx +160 -0
  130. package/themes/original/src/components/Sessions/styles.tsx +15 -0
  131. package/themes/original/src/components/SignupForm/index.tsx +173 -154
  132. package/themes/original/src/components/SingleProductCard/index.tsx +47 -21
  133. package/themes/original/src/components/SingleProductCard/styles.tsx +28 -1
  134. package/themes/original/src/components/StripeElementsForm/index.tsx +55 -72
  135. package/themes/original/src/components/TaxInformation/index.tsx +17 -7
  136. package/themes/original/src/components/UpsellingProducts/index.tsx +87 -71
  137. package/themes/original/src/components/UserDetails/index.tsx +4 -95
  138. package/themes/original/src/components/UserFormDetails/index.tsx +32 -31
  139. package/themes/original/src/components/UserProfile/index.tsx +70 -20
  140. package/themes/original/src/components/UserProfileForm/index.tsx +28 -24
  141. package/themes/original/src/components/VerifyPhone/index.tsx +10 -7
  142. package/themes/original/src/components/VerifyPhone/styles.tsx +2 -1
  143. package/themes/original/src/components/Wallets/index.tsx +75 -8
  144. package/themes/original/src/components/Wallets/styles.tsx +21 -0
  145. package/themes/original/src/components/shared/HeaderTitle.tsx +21 -0
  146. package/themes/original/src/components/shared/index.tsx +2 -0
  147. package/themes/original/src/config/constants.tsx +6 -6
  148. package/themes/original/src/types/index.tsx +79 -25
  149. package/themes/original/src/utils/index.tsx +12 -2
  150. package/themes/single-business/src/components/AddressList/index.tsx +1 -1
  151. package/themes/single-business/src/components/OrderTypeSelector/index.tsx +6 -6
  152. package/themes/single-business/src/components/UserProfile/index.tsx +1 -1
  153. package/themes/uber-eats/src/components/BusinessesListing/index.tsx +1 -1
  154. package/src/components/StripeMethodForm/index.tsx +0 -168
@@ -0,0 +1,160 @@
1
+ import React, { useState } from 'react'
2
+ import { View, TouchableOpacity } from 'react-native'
3
+ import { useLanguage, useSession, useUtils, Sessions as SessionsController } from 'ordering-components/native'
4
+ import NavBar from '../NavBar'
5
+ import { SessionsParams } from '../../types'
6
+ import { OAlert } from '../../../../../src/components/shared'
7
+ import { OButton, OIcon, OText } from '../shared'
8
+ import { useTheme } from 'styled-components/native'
9
+ import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder'
10
+ import AntIcon from 'react-native-vector-icons/AntDesign'
11
+
12
+ import {
13
+ SessionsWrapper,
14
+ SessionItem,
15
+ DurationWrapper
16
+ } from './styles'
17
+
18
+ export const SessionsUI = (props: SessionsParams) => {
19
+ const {
20
+ navigation,
21
+ sessionsList,
22
+ actionState,
23
+ handleDeleteSession,
24
+ handleDeleteAllSessions
25
+ } = props
26
+
27
+ const [, t] = useLanguage()
28
+ const [{ user }] = useSession()
29
+ const [{ parseDate }] = useUtils()
30
+ const theme = useTheme()
31
+ const [confirm, setConfirm] = useState<any>({ open: false, content: null, handleOnAccept: null, id: null, title: null })
32
+ const goToBack = () => navigation?.canGoBack() && navigation.goBack()
33
+
34
+ const onDeleteSession = (session: any) => {
35
+ setConfirm({
36
+ open: true,
37
+ title: t('WEB_APPNAME', 'Ordering'),
38
+ content: [t('QUESTION_DELETE_SESSION', 'Are you sure to delete this session?')],
39
+ handleOnAccept: () => {
40
+ handleDeleteSession(session)
41
+ setConfirm({ ...confirm, open: false })
42
+ }
43
+ })
44
+ }
45
+
46
+ const onDeleteAllSessions = (isOldUser: any, deleteCurrent: any) => {
47
+ setConfirm({
48
+ open: true,
49
+ title: t('WEB_APPNAME', 'Ordering'),
50
+ content:
51
+ isOldUser
52
+ ? [t('QUESTION_ENABLE_ALL_SESSIONS', 'Are you sure to enable all sessions?')]
53
+ : deleteCurrent
54
+ ? [t('QUESTION_DELETE_ALL_SESSIONS', 'Are you sure that you want to delete all sessions?')]
55
+ : [t('QUESTION_DELETE_ALL_SESSIONS_EXCEPT_CURRENT', 'Are you sure that you want to delete all sessions except current?')],
56
+ handleOnAccept: () => {
57
+ handleDeleteAllSessions(deleteCurrent)
58
+ setConfirm({ ...confirm, open: false })
59
+ }
60
+ })
61
+ }
62
+
63
+ return (
64
+ <>
65
+ <NavBar
66
+ title={t('SESSIONS', 'Sessions')}
67
+ titleAlign={'center'}
68
+ onActionLeft={goToBack}
69
+ showCall={false}
70
+ paddingTop={10}
71
+ btnStyle={{ paddingLeft: 0 }}
72
+ />
73
+ {user?.session_strategy === 'jwt_session' ? (
74
+ <>
75
+ {sessionsList.loading ? (
76
+ [...Array(5).keys()].map(i => (
77
+ <SessionItem key={i}>
78
+ <Placeholder Animation={Fade}>
79
+ <View style={{ flexDirection: 'row', alignItems: 'center' }}>
80
+ <View style={{ flex: 1}}>
81
+ <PlaceholderLine width={40} />
82
+ <PlaceholderLine width={40} />
83
+ </View>
84
+ <PlaceholderLine width={5}/>
85
+ </View>
86
+ </Placeholder>
87
+ </SessionItem>
88
+ ))
89
+ ) : (
90
+ sessionsList.sessions.length > 0 ? (
91
+ <SessionsWrapper>
92
+ {sessionsList.sessions.map((session: any) => (
93
+ <SessionItem key={session.id}>
94
+ <DurationWrapper>
95
+ <OText>{parseDate(session.created_at)}</OText>
96
+ <OText>{parseDate(session.valid_thru)}</OText>
97
+ </DurationWrapper>
98
+ {session.current && (
99
+ <OText mLeft={15} style={{ flex: 1 }}>({t('CURRENT', 'Current')})</OText>
100
+ )}
101
+ <TouchableOpacity
102
+ onPress={() => onDeleteSession(session)}
103
+ >
104
+ <AntIcon name='close' size={16} color={theme.colors.red} />
105
+ </TouchableOpacity>
106
+ </SessionItem>
107
+ ))}
108
+ <OButton
109
+ text={t('DELETE_ALL_SESSIONS', 'Delete all sessions')}
110
+ isDisabled={actionState.loading}
111
+ textStyle={{ color: theme.colors.white, fontSize: 14 }}
112
+ onClick={() => onDeleteAllSessions(false, true)}
113
+ style={{ borderRadius: 7.6, marginTop: 30 }}
114
+ />
115
+ <OButton
116
+ text={t('DELETE_ALL_SESSIONS_EXCEPT_CURRENT', 'Delete all sessions except current')}
117
+ isDisabled={actionState.loading}
118
+ textStyle={{ color: theme.colors.white, fontSize: 14 }}
119
+ onClick={() => onDeleteAllSessions(false, false)}
120
+ style={{ borderRadius: 7.6, marginTop: 20 }}
121
+ />
122
+ </SessionsWrapper>
123
+ ) : (
124
+ <OText>{t('YOU_DONT_HAVE_ANY_SESSIONS', 'You don\'t have any sessions')}</OText>
125
+ )
126
+ )}
127
+ </>
128
+ ) : (
129
+ <View>
130
+ <OText>
131
+ {t('YOU_DONT_HAVE_ENABLED_THE_SESSIONS', 'You don\'t have enabled the sessions, please active them to have a better control of your sessions.')}
132
+ </OText>
133
+ <OButton
134
+ text={t('ACTIVE_SESSIONS', 'Active sessions')}
135
+ isDisabled={actionState.loading}
136
+ textStyle={{ color: theme.colors.white, fontSize: 14 }}
137
+ onClick={() => onDeleteAllSessions(true, false)}
138
+ style={{ borderRadius: 7.6, marginTop: 20 }}
139
+ />
140
+ </View>
141
+ )}
142
+ <OAlert
143
+ open={confirm.open}
144
+ title={confirm.title}
145
+ content={confirm.content}
146
+ onAccept={confirm.handleOnAccept}
147
+ onCancel={() => setConfirm({ ...confirm, open: false, title: null })}
148
+ onClose={() => setConfirm({ ...confirm, open: false, title: null })}
149
+ />
150
+ </>
151
+ )
152
+ }
153
+
154
+ export const Sessions = (props: SessionsParams) => {
155
+ const sessionsProps = {
156
+ ...props,
157
+ UIComponent: SessionsUI
158
+ }
159
+ return <SessionsController {...sessionsProps} />
160
+ }
@@ -0,0 +1,15 @@
1
+ import styled from 'styled-components/native'
2
+
3
+ export const SessionsWrapper = styled.View`
4
+ `
5
+ export const SessionItem = styled.View`
6
+ flex-direction: row;
7
+ align-items: center;
8
+ justify-content: space-between;
9
+ padding-vertical: 15px;
10
+ border-bottom-color: ${(props: any) => props.theme.colors.lightGray};
11
+ border-bottom-width: 1px;
12
+ `
13
+ export const DurationWrapper = styled.View`
14
+ /* flex-direction: row; */
15
+ `
@@ -68,7 +68,6 @@ const SignupFormUI = (props: SignupParams) => {
68
68
 
69
69
  const theme = useTheme();
70
70
 
71
-
72
71
  const style = StyleSheet.create({
73
72
  btnOutline: {
74
73
  backgroundColor: '#FFF',
@@ -77,7 +76,6 @@ const SignupFormUI = (props: SignupParams) => {
77
76
  inputStyle: {
78
77
  marginBottom: 20,
79
78
  borderWidth: 1,
80
- borderColor: theme.colors.border,
81
79
  borderRadius: 7.6,
82
80
  },
83
81
  wrappText: {
@@ -102,7 +100,7 @@ const SignupFormUI = (props: SignupParams) => {
102
100
  const [, t] = useLanguage();
103
101
  const [, { login }] = useSession();
104
102
  const [{ configs }] = useConfig();
105
- const { control, handleSubmit, errors } = useForm();
103
+ const { control, handleSubmit, errors, register, setValue } = useForm();
106
104
 
107
105
  const [passwordSee, setPasswordSee] = useState(false);
108
106
  const [formValues, setFormValues] = useState(null);
@@ -227,7 +225,7 @@ const SignupFormUI = (props: SignupParams) => {
227
225
  handleButtonSignupClick &&
228
226
  handleButtonSignupClick({
229
227
  ...values,
230
- ...phoneInputData.phone,
228
+ ...((phoneInputData.phone.cellphone !== null && phoneInputData.phone.country_phone_code !== null) && {...phoneInputData.phone}),
231
229
  });
232
230
  if (
233
231
  !formState.loading &&
@@ -298,36 +296,23 @@ const SignupFormUI = (props: SignupParams) => {
298
296
 
299
297
  useEffect(() => {
300
298
  if (Object.keys(errors).length > 0) {
301
- // Convert all errors in one string to show in toast provider
302
- const list = Object.values(errors);
303
- if (phoneInputData.error) {
304
- list.push({ message: phoneInputData.error });
305
- }
306
- if (
307
- !phoneInputData.error &&
308
- !phoneInputData.phone.country_phone_code &&
309
- !phoneInputData.phone.cellphone &&
310
- ((validationFields?.fields?.checkout?.cellphone?.enabled &&
311
- validationFields?.fields?.checkout?.cellphone?.required) ||
312
- configs?.verification_phone_required?.value === '1')
313
- ) {
314
- list.push({
315
- message: t(
316
- 'VALIDATION_ERROR_MOBILE_PHONE_REQUIRED',
317
- 'The field Mobile phone is required.',
318
- ),
319
- });
320
- }
321
- let stringError = '';
322
- list.map((item: any, i: number) => {
323
- stringError +=
324
- i + 1 === list.length ? `- ${item.message}` : `- ${item.message}\n`;
325
- });
326
- showToast(ToastType.Error, stringError);
327
299
  setIsLoadingVerifyModal(false);
328
300
  }
329
301
  }, [errors]);
330
302
 
303
+ useEffect(() => {
304
+ register('cellphone', {
305
+ required: isRequiredField('cellphone')
306
+ ? t('VALIDATION_ERROR_MOBILE_PHONE_REQUIRED', 'The field Mobile phone is required').replace('_attribute_', t('CELLPHONE', 'Cellphone'))
307
+ : null
308
+ })
309
+ }, [register])
310
+
311
+ useEffect(() => {
312
+ if (phoneInputData?.phone?.cellphone) setValue('cellphone', phoneInputData?.phone?.cellphone, '')
313
+ else setValue('cellphone', '')
314
+ }, [phoneInputData?.phone?.cellphone])
315
+
331
316
  useEffect(() => {
332
317
  if (verifyPhoneState && !verifyPhoneState?.loading) {
333
318
  if (verifyPhoneState.result?.error) {
@@ -412,48 +397,58 @@ const SignupFormUI = (props: SignupParams) => {
412
397
  !notValidationFields.includes(field.code) &&
413
398
  showField &&
414
399
  showField(field.code) && (
415
- <Controller
416
- key={field.id}
417
- control={control}
418
- render={({ onChange, value }: any) => (
419
- <OInput
420
- placeholder={t(field.name)}
421
- style={style.inputStyle}
422
- icon={
423
- field.code === 'email'
424
- ? theme.images.general.email
425
- : theme.images.general.user
426
- }
427
- value={value}
428
- onChange={(val: any) =>
429
- field.code !== 'email'
430
- ? onChange(val)
431
- : handleChangeInputEmail(val, onChange)
432
- }
433
- autoCapitalize={
434
- field.code === 'email' ? 'none' : 'sentences'
435
- }
436
- autoCorrect={field.code === 'email' && false}
437
- type={
438
- field.code === 'email' ? 'email-address' : 'default'
439
- }
440
- autoCompleteType={
441
- field.code === 'email' ? 'email' : 'off'
442
- }
443
- returnKeyType="next"
444
- blurOnSubmit={false}
445
- forwardRef={(ref: any) => handleRefs(ref, field.code)}
446
- onSubmitEditing={() =>
447
- field.code === 'email'
448
- ? phoneRef?.current?.focus?.()
449
- : handleFocusRef(getNextFieldCode(i))
450
- }
451
- />
400
+ <React.Fragment key={field.id}>
401
+ {errors?.[`${field.code}`] && (
402
+ <OText
403
+ size={14}
404
+ color={theme.colors.danger5}
405
+ weight={'normal'}>
406
+ {errors?.[`${field.code}`]?.message} {errors?.[`${field.code}`]?.type === 'required' && '*'}
407
+ </OText>
452
408
  )}
453
- name={field.code}
454
- rules={getInputRules(field)}
455
- defaultValue=""
456
- />
409
+ <Controller
410
+ control={control}
411
+ render={({ onChange, value }: any) => (
412
+ <OInput
413
+ placeholder={t(field.name)}
414
+ style={style.inputStyle}
415
+ icon={
416
+ field.code === 'email'
417
+ ? theme.images.general.email
418
+ : theme.images.general.user
419
+ }
420
+ value={value}
421
+ onChange={(val: any) =>
422
+ field.code !== 'email'
423
+ ? onChange(val)
424
+ : handleChangeInputEmail(val, onChange)
425
+ }
426
+ autoCapitalize={
427
+ field.code === 'email' ? 'none' : 'sentences'
428
+ }
429
+ autoCorrect={field.code === 'email' && false}
430
+ type={
431
+ field.code === 'email' ? 'email-address' : 'default'
432
+ }
433
+ autoCompleteType={
434
+ field.code === 'email' ? 'email' : 'off'
435
+ }
436
+ returnKeyType="next"
437
+ blurOnSubmit={false}
438
+ forwardRef={(ref: any) => handleRefs(ref, field.code)}
439
+ onSubmitEditing={() =>
440
+ field.code === 'email'
441
+ ? phoneRef?.current?.focus?.()
442
+ : handleFocusRef(getNextFieldCode(i))
443
+ }
444
+ borderColor={errors?.[`${field.code}`] ? theme.colors.danger5 : theme.colors.border}
445
+ />
446
+ )}
447
+ name={field.code}
448
+ rules={getInputRules(field)}
449
+ defaultValue=""
450
+ />
451
+ </React.Fragment>
457
452
  ),
458
453
  )}
459
454
 
@@ -467,6 +462,7 @@ const SignupFormUI = (props: SignupParams) => {
467
462
  returnKeyType: 'next',
468
463
  onSubmitEditing: () => passwordRef?.current?.focus?.(),
469
464
  }}
465
+ isStartValidation={errors?.cellphone}
470
466
  />
471
467
  </View>
472
468
  )}
@@ -499,99 +495,122 @@ const SignupFormUI = (props: SignupParams) => {
499
495
  </View>
500
496
 
501
497
  {configs?.terms_and_conditions?.value === 'true' && (
502
- <View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 20 }}>
498
+ <>
499
+ {errors?.termsAccept && (
500
+ <OText
501
+ size={14}
502
+ color={theme.colors.danger5}
503
+ weight={'normal'}>
504
+ {errors?.termsAccept?.message}*
505
+ </OText>
506
+ )}
507
+ <View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 20 }}>
508
+ <Controller
509
+ control={control}
510
+ render={({ onChange, value }: any) => (
511
+ <CheckBox
512
+ value={value}
513
+ onValueChange={newValue => {
514
+ onChange(newValue)
515
+ }}
516
+ boxType={'square'}
517
+ tintColors={{
518
+ true: theme.colors.primary,
519
+ false: theme.colors.disabled
520
+ }}
521
+ tintColor={theme.colors.disabled}
522
+ onCheckColor={theme.colors.primary}
523
+ onTintColor={theme.colors.primary}
524
+ style={Platform.OS === 'ios' && style.checkBoxStyle}
525
+ />
526
+ )}
527
+ name='termsAccept'
528
+ rules={{
529
+ required: t('VALIDATION_ERROR_ACCEPTED', 'The _attribute_ must be accepted.').replace('_attribute_', t('TERMS_AND_CONDITIONS', 'Terms & Conditions'))
530
+ }}
531
+ defaultValue={false}
532
+ />
533
+ <OText style={{ fontSize: 14, paddingHorizontal: 5 }}>{t('TERMS_AND_CONDITIONS_TEXT', 'I agree with')}</OText>
534
+ <OButton
535
+ imgRightSrc={null}
536
+ text={t('TERMS_AND_CONDITIONS', 'Terms & Conditions')}
537
+ bgColor='#FFF'
538
+ borderColor='#FFF'
539
+ style={{ paddingLeft: 0, paddingRight: 0, height: 30, shadowColor: '#FFF' }}
540
+ textStyle={{ color: theme.colors.primary, marginLeft: 0, marginRight: 0 }}
541
+ onClick={() => handleOpenTermsUrl(configs?.terms_and_conditions_url?.value)}
542
+ />
543
+ </View>
544
+ </>
545
+
546
+ )}
547
+
548
+ {signupTab !== 'cellphone' && (
549
+ <>
550
+ {errors?.password && (
551
+ <OText
552
+ size={14}
553
+ color={theme.colors.danger5}
554
+ weight={'normal'}>
555
+ {errors?.password?.message} {errors?.password?.type === 'required' && '*'}
556
+ </OText>
557
+ )}
503
558
  <Controller
504
559
  control={control}
505
560
  render={({ onChange, value }: any) => (
506
- <CheckBox
561
+ <OInput
562
+ isSecured={!passwordSee ? true : false}
563
+ placeholder={t('PASSWORD', 'Password')}
564
+ style={style.inputStyle}
565
+ icon={theme.images.general.lock}
566
+ iconCustomRight={
567
+ !passwordSee ? (
568
+ <MaterialCommunityIcons
569
+ name="eye-outline"
570
+ color={theme.colors.disabled}
571
+ size={24}
572
+ onPress={() => setPasswordSee(!passwordSee)}
573
+ />
574
+ ) : (
575
+ <MaterialCommunityIcons
576
+ name="eye-off-outline"
577
+ color={theme.colors.disabled}
578
+ size={24}
579
+ onPress={() => setPasswordSee(!passwordSee)}
580
+ />
581
+ )
582
+ }
507
583
  value={value}
508
- onValueChange={newValue => {
509
- onChange(newValue)
510
- }}
511
- boxType={'square'}
512
- tintColors={{
513
- true: theme.colors.primary,
514
- false: theme.colors.disabled
515
- }}
516
- tintColor={theme.colors.disabled}
517
- onCheckColor={theme.colors.primary}
518
- onTintColor={theme.colors.primary}
519
- style={Platform.OS === 'ios' && style.checkBoxStyle}
584
+ onChange={(val: any) => onChange(val)}
585
+ returnKeyType="done"
586
+ onSubmitEditing={handleSubmit(onSubmit)}
587
+ blurOnSubmit
588
+ forwardRef={passwordRef}
589
+ borderColor={errors?.password ? theme.colors.danger5 : theme.colors.border}
520
590
  />
521
591
  )}
522
- name='termsAccept'
592
+ name="password"
523
593
  rules={{
524
- required: t('VALIDATION_ERROR_ACCEPTED', 'The _attribute_ must be accepted.').replace('_attribute_', t('TERMS_AND_CONDITIONS', 'Terms & Conditions'))
594
+ required: isRequiredField('password')
595
+ ? t(
596
+ 'VALIDATION_ERROR_PASSWORD_REQUIRED',
597
+ 'The field Password is required',
598
+ ).replace('_attribute_', t('PASSWORD', 'password'))
599
+ : null,
600
+ minLength: {
601
+ value: 8,
602
+ message: t(
603
+ 'VALIDATION_ERROR_PASSWORD_MIN_STRING',
604
+ 'The Password must be at least 8 characters.',
605
+ )
606
+ .replace('_attribute_', t('PASSWORD', 'Password'))
607
+ .replace('_min_', 8),
608
+ },
525
609
  }}
526
- defaultValue={false}
527
- />
528
- <OText style={{ fontSize: 14, paddingHorizontal: 5 }}>{t('TERMS_AND_CONDITIONS_TEXT', 'I agree with')}</OText>
529
- <OButton
530
- imgRightSrc={null}
531
- text={t('TERMS_AND_CONDITIONS', 'Terms & Conditions')}
532
- bgColor='#FFF'
533
- borderColor='#FFF'
534
- style={{ paddingLeft: 0, paddingRight: 0, height: 30, shadowColor: '#FFF' }}
535
- textStyle={{ color: theme.colors.primary, marginLeft: 0, marginRight: 0 }}
536
- onClick={() => handleOpenTermsUrl(configs?.terms_and_conditions_url?.value)}
610
+ defaultValue=""
537
611
  />
538
- </View>
539
- )}
612
+ </>
540
613
 
541
- {signupTab !== 'cellphone' && (
542
- <Controller
543
- control={control}
544
- render={({ onChange, value }: any) => (
545
- <OInput
546
- isSecured={!passwordSee ? true : false}
547
- placeholder={t('PASSWORD', 'Password')}
548
- style={style.inputStyle}
549
- icon={theme.images.general.lock}
550
- iconCustomRight={
551
- !passwordSee ? (
552
- <MaterialCommunityIcons
553
- name="eye-outline"
554
- color={theme.colors.disabled}
555
- size={24}
556
- onPress={() => setPasswordSee(!passwordSee)}
557
- />
558
- ) : (
559
- <MaterialCommunityIcons
560
- name="eye-off-outline"
561
- color={theme.colors.disabled}
562
- size={24}
563
- onPress={() => setPasswordSee(!passwordSee)}
564
- />
565
- )
566
- }
567
- value={value}
568
- onChange={(val: any) => onChange(val)}
569
- returnKeyType="done"
570
- onSubmitEditing={handleSubmit(onSubmit)}
571
- blurOnSubmit
572
- forwardRef={passwordRef}
573
- />
574
- )}
575
- name="password"
576
- rules={{
577
- required: isRequiredField('password')
578
- ? t(
579
- 'VALIDATION_ERROR_PASSWORD_REQUIRED',
580
- 'The field Password is required',
581
- ).replace('_attribute_', t('PASSWORD', 'password'))
582
- : null,
583
- minLength: {
584
- value: 8,
585
- message: t(
586
- 'VALIDATION_ERROR_PASSWORD_MIN_STRING',
587
- 'The Password must be at least 8 characters.',
588
- )
589
- .replace('_attribute_', t('PASSWORD', 'Password'))
590
- .replace('_min_', 8),
591
- },
592
- }}
593
- defaultValue=""
594
- />
595
614
  )}
596
615
  </>
597
616
  ) : (
@@ -7,14 +7,20 @@ import {
7
7
  } from 'ordering-components/native';
8
8
  import { useTheme } from 'styled-components/native';
9
9
  import { SingleProductCardParams } from '../../types';
10
- import { CardContainer, CardInfo, SoldOut, QuantityContainer, PricesContainer } from './styles';
10
+ import { CardContainer, CardInfo, SoldOut, QuantityContainer, PricesContainer, RibbonBox, LogoWrapper } from './styles';
11
11
  import { StyleSheet } from 'react-native';
12
12
  import { OText, OIcon } from '../shared';
13
13
  import FastImage from 'react-native-fast-image'
14
+ import { shape } from '../../utils';
14
15
 
15
- export const SingleProductCard = (props: SingleProductCardParams) => {
16
+ function SingleProductCardPropsAreEqual(prevProps : any, nextProps : any) {
17
+ return JSON.stringify(prevProps.product) === JSON.stringify(nextProps.product) &&
18
+ prevProps.isSoldOut === nextProps.isSoldOut &&
19
+ prevProps.productAddedToCartLength === nextProps.productAddedToCartLength
20
+ }
21
+
22
+ export const SingleProductCard = React.memo((props: SingleProductCardParams) => {
16
23
  const {
17
- businessId,
18
24
  product,
19
25
  isSoldOut,
20
26
  onProductClick,
@@ -46,8 +52,7 @@ export const SingleProductCard = (props: SingleProductCardParams) => {
46
52
  productStyle: {
47
53
  width: 75,
48
54
  height: 75,
49
- borderRadius: 7.6,
50
- marginStart: 12
55
+ borderRadius: 7.6
51
56
  },
52
57
  quantityContainer: {
53
58
  position: 'absolute',
@@ -136,21 +141,42 @@ export const SingleProductCard = (props: SingleProductCardParams) => {
136
141
  {product?.description}
137
142
  </OText>
138
143
  </CardInfo>
139
- {product?.images ? (
140
- <FastImage
141
- style={styles.productStyle}
142
- source={{
143
- uri: optimizeImage(product?.images, 'h_250,c_limit'),
144
- priority: FastImage.priority.normal,
145
- }}
146
- resizeMode={FastImage.resizeMode.cover}
147
- />
148
- ) : (
149
- <OIcon
150
- src={theme?.images?.dummies?.product}
151
- style={styles.productStyle}
152
- />
153
- )}
144
+ <LogoWrapper>
145
+ {product?.ribbon?.enabled && (
146
+ <RibbonBox
147
+ bgColor={product?.ribbon?.color}
148
+ isRoundRect={product?.ribbon?.shape === shape?.rectangleRound}
149
+ isCapsule={product?.ribbon?.shape === shape?.capsuleShape}
150
+ >
151
+ <OText
152
+ size={10}
153
+ weight={'400'}
154
+ color={theme.colors.white}
155
+ numberOfLines={2}
156
+ ellipsizeMode='tail'
157
+ lineHeight={13}
158
+ >
159
+ {product?.ribbon?.text}
160
+ </OText>
161
+ </RibbonBox>
162
+ )}
163
+ {product?.images ? (
164
+ <FastImage
165
+ style={styles.productStyle}
166
+ source={{
167
+ uri: optimizeImage(product?.images, 'h_250,c_limit'),
168
+ priority: FastImage.priority.normal,
169
+ }}
170
+ resizeMode={FastImage.resizeMode.cover}
171
+ />
172
+ ) : (
173
+ <OIcon
174
+ src={theme?.images?.dummies?.product}
175
+ style={styles.productStyle}
176
+ />
177
+ )}
178
+ </LogoWrapper>
179
+
154
180
  {(isSoldOut || maxProductQuantity <= 0) && (
155
181
  <SoldOut>
156
182
  <OText size={12} weight="bold" color={theme.colors.textSecondary} style={styles.soldOutTextStyle}>
@@ -160,4 +186,4 @@ export const SingleProductCard = (props: SingleProductCardParams) => {
160
186
  )}
161
187
  </CardContainer>
162
188
  );
163
- };
189
+ }, SingleProductCardPropsAreEqual);