ordering-ui-react-native 0.16.49 → 0.16.50-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 (205) hide show
  1. package/package.json +6 -5
  2. package/src/DeliveryApp.tsx +43 -1
  3. package/src/components/ActiveOrders/index.tsx +61 -63
  4. package/src/components/ActiveOrders/styles.tsx +8 -14
  5. package/src/components/BusinessInformation/index.tsx +33 -4
  6. package/src/components/BusinessInformation/styles.tsx +2 -2
  7. package/src/components/BusinessProductsList/index.tsx +10 -10
  8. package/src/components/BusinessesListing/index.tsx +1 -1
  9. package/src/components/Checkout/index.tsx +2 -1
  10. package/src/components/LanguageSelector/index.tsx +21 -16
  11. package/src/components/Messages/index.tsx +2 -2
  12. package/src/components/NotificationSetting/index.tsx +85 -0
  13. package/src/components/OrdersOption/index.tsx +54 -56
  14. package/src/components/PaymentOptions/index.tsx +298 -345
  15. package/src/components/PaymentOptionsWebView/index.tsx +120 -121
  16. package/src/components/ReviewProducts/index.tsx +11 -0
  17. package/src/components/SingleProductReview/index.tsx +8 -5
  18. package/src/components/StripeElementsForm/index.tsx +25 -16
  19. package/src/components/VerifyPhone/styles.tsx +1 -2
  20. package/src/components/shared/OBottomPopup.tsx +6 -2
  21. package/src/components/shared/OToast.tsx +4 -4
  22. package/src/index.tsx +2 -0
  23. package/src/types/@fatnlazycat/react-native-recaptcha-v3/index.d.ts +1 -0
  24. package/src/utils/index.tsx +2 -1
  25. package/themes/business/src/components/AcceptOrRejectOrder/index.tsx +259 -238
  26. package/themes/business/src/components/AcceptOrRejectOrder/styles.tsx +6 -4
  27. package/themes/business/src/components/BusinessController/index.tsx +2 -2
  28. package/themes/business/src/components/Chat/index.tsx +40 -32
  29. package/themes/business/src/components/DriverMap/index.tsx +7 -5
  30. package/themes/business/src/components/DriverSchedule/index.tsx +36 -19
  31. package/themes/business/src/components/LoginForm/index.tsx +111 -74
  32. package/themes/business/src/components/MapView/index.tsx +12 -1
  33. package/themes/business/src/components/MessagesOption/index.tsx +11 -1
  34. package/themes/business/src/components/NewOrderNotification/index.tsx +26 -41
  35. package/themes/business/src/components/OrderDetails/OrderContentComponent.tsx +40 -30
  36. package/themes/business/src/components/OrderDetails/OrderHeaderComponent.tsx +3 -3
  37. package/themes/business/src/components/OrdersListManager/index.tsx +10 -3
  38. package/themes/business/src/components/OrdersOption/index.tsx +76 -77
  39. package/themes/business/src/components/OrdersOption/styles.tsx +5 -1
  40. package/themes/business/src/components/OrdersOptionBusiness/index.tsx +15 -1
  41. package/themes/business/src/components/OrdersOptionCity/index.tsx +15 -1
  42. package/themes/business/src/components/OrdersOptionDate/index.tsx +19 -6
  43. package/themes/business/src/components/OrdersOptionDelivery/index.tsx +15 -1
  44. package/themes/business/src/components/OrdersOptionDriver/index.tsx +15 -1
  45. package/themes/business/src/components/OrdersOptionPaymethod/index.tsx +15 -1
  46. package/themes/business/src/components/OrdersOptionStatus/index.tsx +10 -1
  47. package/themes/business/src/components/PreviousMessages/index.tsx +17 -18
  48. package/themes/business/src/components/PreviousOrders/OrderItem.tsx +250 -0
  49. package/themes/business/src/components/PreviousOrders/OrdersGroupedItem.tsx +115 -0
  50. package/themes/business/src/components/PreviousOrders/index.tsx +332 -244
  51. package/themes/business/src/components/PreviousOrders/styles.tsx +30 -2
  52. package/themes/business/src/components/ProductItemAccordion/index.tsx +3 -2
  53. package/themes/business/src/components/ReviewCustomer/index.tsx +39 -15
  54. package/themes/business/src/components/ScheduleBlocked/index.tsx +2 -2
  55. package/themes/business/src/components/UserFormDetails/index.tsx +5 -2
  56. package/themes/business/src/components/UserProfileForm/index.tsx +2 -0
  57. package/themes/business/src/components/shared/ODropDown.tsx +42 -8
  58. package/themes/business/src/components/shared/ODropDownCalendar.tsx +36 -7
  59. package/themes/business/src/components/shared/OLink.tsx +24 -12
  60. package/themes/business/src/components/shared/OText.tsx +3 -2
  61. package/themes/business/src/types/index.tsx +25 -11
  62. package/themes/business/src/utils/index.tsx +10 -0
  63. package/themes/doordash/src/components/BusinessesListing/index.tsx +1 -1
  64. package/themes/doordash/src/components/LoginForm/index.tsx +1 -2
  65. package/themes/instacart/src/components/BusinessesListing/index.tsx +1 -1
  66. package/themes/kiosk/src/components/BusinessesListing/index.tsx +2 -1
  67. package/themes/kiosk/src/components/Checkout/index.tsx +6 -0
  68. package/themes/kiosk/src/components/LoginForm/index.tsx +121 -10
  69. package/themes/kiosk/src/components/LoginForm/styles.tsx +5 -0
  70. package/themes/kiosk/src/components/NavBar/index.tsx +14 -14
  71. package/themes/kiosk/src/components/OptionCard/index.tsx +1 -1
  72. package/themes/kiosk/src/components/OrderTypeCardSelector/index.tsx +8 -10
  73. package/themes/kiosk/src/components/ProductForm/index.tsx +1 -14
  74. package/themes/kiosk/src/components/shared/OButton.tsx +5 -18
  75. package/themes/kiosk/src/types/index.d.ts +2 -0
  76. package/themes/original/index.tsx +8 -0
  77. package/themes/original/src/components/AddressDetails/index.tsx +10 -8
  78. package/themes/original/src/components/AddressForm/index.tsx +157 -140
  79. package/themes/original/src/components/AddressList/index.tsx +1 -1
  80. package/themes/original/src/components/AppleLogin/index.tsx +4 -4
  81. package/themes/original/src/components/BusinessBasicInformation/index.tsx +218 -147
  82. package/themes/original/src/components/BusinessBasicInformation/styles.tsx +2 -2
  83. package/themes/original/src/components/BusinessController/index.tsx +203 -94
  84. package/themes/original/src/components/BusinessController/styles.tsx +14 -9
  85. package/themes/original/src/components/BusinessInformation/index.tsx +10 -31
  86. package/themes/original/src/components/BusinessItemAccordion/index.tsx +12 -6
  87. package/themes/original/src/components/BusinessListingSearch/BusinessControllerSkeletons/index.tsx +57 -0
  88. package/themes/original/src/components/BusinessListingSearch/MaxSectionItem/index.tsx +59 -0
  89. package/themes/original/src/components/BusinessListingSearch/MaxSectionItem/styles.tsx +13 -0
  90. package/themes/original/src/components/BusinessListingSearch/index.tsx +85 -137
  91. package/themes/original/src/components/BusinessListingSearch/styles.tsx +10 -12
  92. package/themes/original/src/components/BusinessProductsList/SubcategoriesComponent/index.tsx +87 -0
  93. package/themes/original/src/components/BusinessProductsList/SubcategoriesComponent/styles.tsx +12 -0
  94. package/themes/original/src/components/BusinessProductsList/index.tsx +59 -60
  95. package/themes/original/src/components/BusinessProductsList/styles.tsx +0 -3
  96. package/themes/original/src/components/BusinessProductsListing/index.tsx +179 -83
  97. package/themes/original/src/components/BusinessProductsListing/styles.tsx +19 -12
  98. package/themes/original/src/components/BusinessTypeFilter/index.tsx +3 -2
  99. package/themes/original/src/components/BusinessesListing/Layout/Appointment/index.tsx +15 -4
  100. package/themes/original/src/components/BusinessesListing/Layout/Appointment/styles.tsx +3 -2
  101. package/themes/original/src/components/BusinessesListing/Layout/Original/index.tsx +276 -122
  102. package/themes/original/src/components/BusinessesListing/Layout/Original/styles.tsx +48 -11
  103. package/themes/original/src/components/BusinessesListing/index.tsx +82 -28
  104. package/themes/original/src/components/Cart/index.tsx +82 -15
  105. package/themes/original/src/components/Cart/styles.tsx +4 -0
  106. package/themes/original/src/components/CartContent/index.tsx +27 -17
  107. package/themes/original/src/components/CartContent/styles.tsx +1 -1
  108. package/themes/original/src/components/Checkout/index.tsx +114 -118
  109. package/themes/original/src/components/Checkout/styles.tsx +4 -3
  110. package/themes/original/src/components/CitiesControl/index.tsx +89 -0
  111. package/themes/original/src/components/CitiesControl/styles.tsx +17 -0
  112. package/themes/original/src/components/DriverTips/index.tsx +4 -4
  113. package/themes/original/src/components/DriverTips/styles.tsx +2 -1
  114. package/themes/original/src/components/FavoriteList/index.tsx +69 -45
  115. package/themes/original/src/components/FloatingButton/index.tsx +13 -11
  116. package/themes/original/src/components/FloatingButton/styles.tsx +1 -1
  117. package/themes/original/src/components/GPSButton/index.tsx +20 -19
  118. package/themes/original/src/components/GPSButton/styles.ts +3 -3
  119. package/themes/original/src/components/GoogleMap/index.tsx +20 -12
  120. package/themes/original/src/components/HelpAccountAndPayment/index.tsx +25 -10
  121. package/themes/original/src/components/HelpAccountAndPayment/styles.tsx +4 -0
  122. package/themes/original/src/components/HelpGuide/index.tsx +9 -8
  123. package/themes/original/src/components/HelpOrder/index.tsx +9 -8
  124. package/themes/original/src/components/LanguageSelector/index.tsx +19 -14
  125. package/themes/original/src/components/LoginForm/Otp/index.tsx +89 -73
  126. package/themes/original/src/components/LoginForm/Otp/styles.tsx +0 -1
  127. package/themes/original/src/components/LoginForm/index.tsx +98 -41
  128. package/themes/original/src/components/LottieAnimation/index.tsx +69 -0
  129. package/themes/original/src/components/Messages/index.tsx +35 -20
  130. package/themes/original/src/components/MomentOption/index.tsx +8 -6
  131. package/themes/original/src/components/MultiCart/index.tsx +63 -0
  132. package/themes/original/src/components/MultiCartsPaymethodsAndWallets/index.tsx +92 -93
  133. package/themes/original/src/components/MultiCheckout/index.tsx +10 -2
  134. package/themes/original/src/components/MultiOrdersDetails/index.tsx +34 -16
  135. package/themes/original/src/components/MyOrders/index.tsx +88 -24
  136. package/themes/original/src/components/NavBar/index.tsx +11 -5
  137. package/themes/original/src/components/NetworkError/index.tsx +5 -3
  138. package/themes/original/src/components/NotFoundSource/index.tsx +2 -1
  139. package/themes/original/src/components/Notifications/index.tsx +148 -0
  140. package/themes/original/src/components/Notifications/styles.tsx +17 -0
  141. package/themes/original/src/components/OrderDetails/index.tsx +162 -50
  142. package/themes/original/src/components/OrderDetails/styles.tsx +15 -2
  143. package/themes/original/src/components/OrderItAgain/index.tsx +75 -0
  144. package/themes/original/src/components/OrderItAgain/styles.tsx +10 -0
  145. package/themes/original/src/components/OrderProgress/index.tsx +77 -66
  146. package/themes/original/src/components/OrderProgress/styles.tsx +5 -0
  147. package/themes/original/src/components/OrderSummary/index.tsx +2 -35
  148. package/themes/original/src/components/OrderTypeSelector/index.tsx +85 -36
  149. package/themes/original/src/components/OrderTypeSelector/styles.tsx +19 -1
  150. package/themes/original/src/components/OrdersOption/PreviousBusinessOrdered/index.tsx +94 -98
  151. package/themes/original/src/components/OrdersOption/PreviousProductsOrdered/index.tsx +3 -0
  152. package/themes/original/src/components/OrdersOption/index.tsx +91 -53
  153. package/themes/original/src/components/PaymentOptionWallet/index.tsx +56 -56
  154. package/themes/original/src/components/PaymentOptions/index.tsx +1 -2
  155. package/themes/original/src/components/PhoneInputNumber/index.tsx +1 -1
  156. package/themes/original/src/components/PlaceSpot/index.tsx +249 -47
  157. package/themes/original/src/components/PlaceSpot/styles.tsx +0 -2
  158. package/themes/original/src/components/PreviousOrders/index.tsx +3 -2
  159. package/themes/original/src/components/ProductForm/index.tsx +645 -664
  160. package/themes/original/src/components/ProductForm/styles.tsx +10 -11
  161. package/themes/original/src/components/ProductItemAccordion/index.tsx +199 -128
  162. package/themes/original/src/components/ProductOption/index.tsx +1 -1
  163. package/themes/original/src/components/ProductOptionSubOption/index.tsx +16 -8
  164. package/themes/original/src/components/ProductOptionSubOption/styles.tsx +0 -1
  165. package/themes/original/src/components/ProfessionalFilter/index.tsx +2 -1
  166. package/themes/original/src/components/ProfessionalProfile/index.tsx +19 -8
  167. package/themes/original/src/components/Promotions/index.tsx +232 -219
  168. package/themes/original/src/components/Promotions/styles.tsx +7 -2
  169. package/themes/original/src/components/ReviewDriver/index.tsx +3 -3
  170. package/themes/original/src/components/ReviewOrder/index.tsx +120 -108
  171. package/themes/original/src/components/ReviewOrder/styles.tsx +5 -7
  172. package/themes/original/src/components/ReviewProducts/index.tsx +8 -5
  173. package/themes/original/src/components/ReviewTrigger/index.tsx +136 -0
  174. package/themes/original/src/components/ReviewTrigger/styles.tsx +41 -0
  175. package/themes/original/src/components/ScheduleAccordion/index.tsx +68 -0
  176. package/themes/original/src/components/ScheduleAccordion/styles.tsx +14 -0
  177. package/themes/original/src/components/ServiceForm/index.tsx +341 -267
  178. package/themes/original/src/components/SignupForm/index.tsx +160 -113
  179. package/themes/original/src/components/SingleOrderCard/index.tsx +219 -129
  180. package/themes/original/src/components/SingleOrderCard/styles.tsx +10 -8
  181. package/themes/original/src/components/SingleProductCard/index.tsx +182 -105
  182. package/themes/original/src/components/SingleProductCard/styles.tsx +3 -10
  183. package/themes/original/src/components/SingleProductReview/index.tsx +38 -5
  184. package/themes/original/src/components/SingleProductReview/styles.tsx +12 -0
  185. package/themes/original/src/components/StripeElementsForm/index.tsx +13 -2
  186. package/themes/original/src/components/UpsellingProducts/index.tsx +15 -5
  187. package/themes/original/src/components/UserDetails/index.tsx +5 -3
  188. package/themes/original/src/components/UserFormDetails/index.tsx +6 -48
  189. package/themes/original/src/components/UserProfile/index.tsx +58 -35
  190. package/themes/original/src/components/UserProfile/styles.ts +17 -0
  191. package/themes/original/src/components/WalletTransactions/index.tsx +76 -0
  192. package/themes/original/src/components/WalletTransactions/styles.tsx +13 -0
  193. package/themes/original/src/components/Wallets/index.tsx +176 -164
  194. package/themes/original/src/components/Wallets/styles.tsx +12 -8
  195. package/themes/original/src/components/shared/CardAnimation.tsx +47 -0
  196. package/themes/original/src/components/shared/HeaderTitle.tsx +8 -3
  197. package/themes/original/src/components/shared/OBottomPopup.tsx +48 -15
  198. package/themes/original/src/components/shared/OButton.tsx +10 -3
  199. package/themes/original/src/components/shared/OIcon.tsx +8 -1
  200. package/themes/original/src/components/shared/OInput.tsx +10 -1
  201. package/themes/original/src/layouts/Container.tsx +13 -9
  202. package/themes/original/src/layouts/FloatingBottomContainer.tsx +5 -1
  203. package/themes/original/src/types/index.tsx +86 -28
  204. package/themes/original/src/utils/index.tsx +103 -58
  205. package/themes/uber-eats/src/components/BusinessesListing/index.tsx +1 -1
@@ -1,4 +1,16 @@
1
- import React, { useEffect, useRef, useCallback } from 'react';
1
+ import React, { useEffect, useRef, useState, useCallback } from 'react';
2
+ import {
3
+ View,
4
+ Keyboard,
5
+ TextInput,
6
+ TouchableOpacity,
7
+ StyleSheet,
8
+ Dimensions,
9
+ I18nManager,
10
+ SafeAreaView,
11
+ Platform,
12
+ Button
13
+ } from 'react-native';
2
14
  import {
3
15
  ProductForm as ProductOptions,
4
16
  useSession,
@@ -15,17 +27,10 @@ import Swiper from 'react-native-swiper'
15
27
  import FastImage from 'react-native-fast-image';
16
28
  import IconAntDesign from 'react-native-vector-icons/AntDesign';
17
29
  import YoutubePlayer from "react-native-youtube-iframe"
18
- import { TextInput } from 'react-native'
19
- import {
20
- Grayscale
21
- } from 'react-native-color-matrix-image-filters'
22
-
23
- import { View, TouchableOpacity, StyleSheet, Dimensions, I18nManager, SafeAreaView, Platform, Button } from 'react-native';
24
30
 
25
31
  import {
26
32
  WrapHeader,
27
33
  TopHeader,
28
- WrapContent,
29
34
  ProductTitle,
30
35
  ProductDescription,
31
36
  ProductEditions,
@@ -45,8 +50,6 @@ import { ScrollView } from 'react-native-gesture-handler';
45
50
  import { ProductOptionSubOption } from '../ProductOptionSubOption';
46
51
  import { NotFoundSource } from '../NotFoundSource';
47
52
  import { Placeholder, PlaceholderLine, Fade } from 'rn-placeholder';
48
- import { useState } from 'react';
49
- const windowHeight = Dimensions.get('window').height;
50
53
  const windowWidth = Dimensions.get('window').width;
51
54
 
52
55
  export const ProductOptionsUI = (props: any) => {
@@ -66,11 +69,14 @@ export const ProductOptionsUI = (props: any) => {
66
69
  handleChangeSuboptionState,
67
70
  handleChangeCommentState,
68
71
  productObject,
72
+ productAddedToCartLength
69
73
  } = props;
70
74
 
71
75
  const theme = useTheme();
72
76
  const [, { showToast }] = useToast()
73
77
 
78
+ const isChewLayout = theme?.header?.components?.layout?.type === 'chew'
79
+
74
80
  const styles = StyleSheet.create({
75
81
  mainContainer: {
76
82
 
@@ -122,6 +128,7 @@ export const ProductOptionsUI = (props: any) => {
122
128
  },
123
129
  slide1: {
124
130
  flex: 1,
131
+ alignItems: 'center'
125
132
  },
126
133
  mainSwiper: {
127
134
  height: 258,
@@ -151,6 +158,13 @@ export const ProductOptionsUI = (props: any) => {
151
158
  productTagNameStyle: {
152
159
  paddingHorizontal: 6,
153
160
  marginRight: 5
161
+ },
162
+ actionContainer: {
163
+ flexDirection: 'row',
164
+ alignItems: 'center',
165
+ justifyContent: 'space-between',
166
+ width: '100%',
167
+ marginTop: 10
154
168
  }
155
169
  });
156
170
 
@@ -162,7 +176,7 @@ export const ProductOptionsUI = (props: any) => {
162
176
  const [gallery, setGallery] = useState([])
163
177
  const [thumbsSwiper, setThumbsSwiper] = useState(0)
164
178
  const [indexGallery, setIndexGallery] = useState(0)
165
- const [selOpt, setSelectedOpt] = useState(0);
179
+ const [selOpt, setSelectedOpt] = useState(-1);
166
180
  const [isHaveWeight, setIsHaveWeight] = useState(false)
167
181
  const [playing, setPlaying] = useState(false);
168
182
  const [qtyBy, setQtyBy] = useState({
@@ -176,6 +190,7 @@ export const ProductOptionsUI = (props: any) => {
176
190
  const [headerRefHeight, setHeaderRefHeight] = useState(0)
177
191
  const [summaryRefHeight, setSummaryRefHeight] = useState(0)
178
192
  const [isScrollAvailable, setIsScrollAvailable] = useState(null)
193
+ const [editionsLayoutY, setEditionsLayoutY] = useState(null)
179
194
 
180
195
  const isError = (id: number) => {
181
196
  let bgColor = theme.colors.white;
@@ -284,6 +299,7 @@ export const ProductOptionsUI = (props: any) => {
284
299
  maxProductQuantity === 0 ||
285
300
  Object.keys(errors).length > 0;
286
301
 
302
+
287
303
  const ExtraOptions = ({ eID, options }: any) => (
288
304
  <>
289
305
  {options.map(({ id, name, respect_to, suboptions }: any) => (
@@ -291,20 +307,28 @@ export const ProductOptionsUI = (props: any) => {
291
307
  {respect_to == null && suboptions?.length > 0 && (
292
308
  <TouchableOpacity
293
309
  key={`eopt_key_${id}`}
294
- onPress={() => setSelectedOpt(id)}
310
+ onPress={() => {
311
+ setSelectedOpt(id)
312
+ scrollViewRef?.current?.scrollTo && scrollViewRef.current.scrollTo({
313
+ y: optionLayout[`id:${id}`]?.y + editionsLayoutY - 50,
314
+ animated: true
315
+ })
316
+ }}
295
317
  style={[
296
318
  styles.extraItem,
297
319
  {
298
320
  borderBottomColor:
299
- selOpt == id ? theme.colors.textNormal : theme.colors.border,
321
+ selOpt == id ? theme.colors.textNormal : theme.colors.backgroundPage,
300
322
  },
301
323
  ]}>
302
324
  <OText
303
325
  color={
304
326
  selOpt == id ? theme.colors.textNormal : theme.colors.textSecondary
305
327
  }
306
- size={selOpt == id ? 14 : 12}
307
- weight={selOpt == id ? '600' : 'normal'}>
328
+ size={12}
329
+ weight={selOpt == id ? '600' : 'normal'}
330
+ style={{ maxWidth: 150 }}
331
+ numberOfLines={1}>
308
332
  {name}
309
333
  </OText>
310
334
  </TouchableOpacity>
@@ -314,6 +338,14 @@ export const ProductOptionsUI = (props: any) => {
314
338
  </>
315
339
  );
316
340
 
341
+ const handleScroll = ({ nativeEvent: { contentOffset, layoutMeasurement } }: any) => {
342
+
343
+ const _topOption = Object.keys(optionLayout).find(((option: any) => Math.abs(contentOffset?.y - layoutMeasurement?.height - optionLayout[option]?.y) < 20))
344
+ if (_topOption) {
345
+ const _topOptionId = Number(_topOption.replace('id:', ''))
346
+ }
347
+ }
348
+
317
349
  const handleGoBack = navigation?.canGoBack()
318
350
  ? () => navigation.goBack()
319
351
  : () => navigation.navigate('Business', { store: props.businessSlug })
@@ -328,7 +360,10 @@ export const ProductOptionsUI = (props: any) => {
328
360
  useEffect(() => {
329
361
  const imageList: any = []
330
362
  const videoList: any = []
331
- product?.images && imageList.push(product.images)
363
+ imageList.push(product?.images?.length > 0
364
+ ? product.images
365
+ : theme?.images?.dummies?.product)
366
+
332
367
  if (product?.gallery && product?.gallery.length > 0) {
333
368
  for (const img of product?.gallery) {
334
369
  if (img?.file) {
@@ -366,693 +401,629 @@ export const ProductOptionsUI = (props: any) => {
366
401
  }
367
402
  }, [product])
368
403
 
404
+ const ActionButton = () => {
405
+ return (
406
+ <View
407
+ style={{
408
+ width: isHaveWeight ? '100%' : ((isSoldOut || maxProductQuantity <= 0) ? '60%' : '40%'),
409
+ }}>
410
+ {((productCart &&
411
+ auth &&
412
+ orderState.options?.address_id) || (isSoldOut || maxProductQuantity <= 0)) && (
413
+ <OButton
414
+ onClick={() => handleSaveProduct()}
415
+ imgRightSrc=""
416
+ text={`${orderState.loading
417
+ ? t('LOADING', 'Loading')
418
+ : (isSoldOut || maxProductQuantity <= 0)
419
+ ? t('SOLD_OUT', 'Sold out')
420
+ : editMode
421
+ ? t('UPDATE', 'Update')
422
+ : t('ADD', 'Add')
423
+ }`}
424
+ isDisabled={isSoldOut || maxProductQuantity <= 0 || (product?.minimum_per_order && ((productCart?.quantity + productAddedToCartLength) < product?.minimum_per_order)) || (product?.maximum_per_order && ((productCart?.quantity + productAddedToCartLength) > product?.maximum_per_order))}
425
+ textStyle={{
426
+ color: saveErrors || isSoldOut || maxProductQuantity <= 0 ? theme.colors.primary : theme.colors.white,
427
+ fontSize: orderState.loading || editMode ? 10 : 14
428
+ }}
429
+ style={{
430
+ backgroundColor: saveErrors || isSoldOut || maxProductQuantity <= 0 || (product?.minimum_per_order && ((productCart?.quantity + productAddedToCartLength) < product?.minimum_per_order)) || (product?.maximum_per_order && ((productCart?.quantity + productAddedToCartLength) > product?.maximum_per_order)) ? theme.colors.lightGray : theme.colors.primary,
431
+ borderColor: saveErrors || isSoldOut || maxProductQuantity <= 0 || (product?.minimum_per_order && ((productCart?.quantity + productAddedToCartLength) < product?.minimum_per_order)) || (product?.maximum_per_order && ((productCart?.quantity + productAddedToCartLength) > product?.maximum_per_order)) ? theme.colors.white : theme.colors.primary,
432
+ opacity: saveErrors || isSoldOut || maxProductQuantity <= 0 ? 0.3 : 1,
433
+ borderRadius: 7.6,
434
+ height: 44,
435
+ shadowOpacity: 0,
436
+ borderWidth: 1,
437
+ marginTop: isHaveWeight ? 10 : 0
438
+ }}
439
+ />
440
+ )}
441
+ {auth &&
442
+ !orderState.options?.address_id &&
443
+ (orderState.loading ? (
444
+ <OButton
445
+ isDisabled
446
+ text={t('LOADING', 'Loading')}
447
+ imgRightSrc=""
448
+ textStyle={{ fontSize: 10 }}
449
+ />
450
+ ) : (
451
+ <OButton onClick={navigation.navigate('AddressList')} />
452
+ ))}
453
+ {!auth && (
454
+ <OButton
455
+ isDisabled={isSoldOut || maxProductQuantity <= 0}
456
+ onClick={() => handleRedirectLogin()}
457
+ text={
458
+ isSoldOut || maxProductQuantity <= 0
459
+ ? t('SOLD_OUT', 'Sold out')
460
+ : t('LOGIN_SIGNUP', 'Login / Sign Up')
461
+ }
462
+ imgRightSrc=""
463
+ textStyle={{ color: theme.colors.primary, fontSize: 14 }}
464
+ style={{
465
+ height: 44,
466
+ borderColor: theme.colors.primary,
467
+ backgroundColor: theme.colors.white,
468
+ }}
469
+ />
470
+ )}
471
+ </View>
472
+ )
473
+ }
474
+
475
+ useEffect(() => {
476
+ const keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', () => {
477
+ scrollViewRef.current.scrollToEnd({ animated: true })
478
+ })
479
+ return () => {
480
+ keyboardDidShowListener.remove()
481
+ }
482
+ }, [])
483
+
484
+
369
485
  return (
370
486
  <SafeAreaView style={{ flex: 1 }}>
371
487
  <TopHeader>
372
488
  <TopActions onPress={() => handleGoBack()}>
373
- <OIcon src={theme.images.general.arrow_left} width={30} />
489
+ <IconAntDesign name='arrowleft' size={26} />
374
490
  </TopActions>
375
491
  </TopHeader>
376
- <ScrollView ref={scrollViewRef}>
377
- {!error && (
378
- <View style={{ paddingBottom: 80 }}>
379
- <WrapHeader onLayout={(event: any) => setHeaderRefHeight(event.nativeEvent.layout?.height)}>
380
- {loading && !product ? (
381
- <View style={styles.productHeaderSkeleton}>
382
- <Placeholder Animation={Fade}>
383
- <PlaceholderLine
384
- height={258}
385
- style={{ borderRadius: 0 }}
386
- width={windowWidth}
387
- />
388
- </Placeholder>
389
- </View>
390
- ) : (
391
- <>
392
- <Swiper
393
- loop={false}
394
- ref={swiperRef}
395
- showsButtons={true}
396
- style={styles.mainSwiper}
397
- showsPagination={false}
398
- onIndexChanged={(index) => handleChangeMainIndex(index)}
399
- prevButton={
400
- <View style={styles.swiperButton}>
401
- <IconAntDesign
402
- name="caretleft"
403
- color={theme.colors.white}
404
- size={13}
405
- // style={styles.starIcon}
406
- />
407
- </View>
408
- }
409
- nextButton={
410
- <View style={styles.swiperButton}>
411
- <IconAntDesign
412
- name="caretright"
413
- color={theme.colors.white}
414
- size={13}
415
- // style={styles.starIcon}
492
+ {!error && (
493
+ <ScrollView
494
+ ref={scrollViewRef}
495
+ contentContainerStyle={{ paddingBottom: 80 }}
496
+ stickyHeaderIndices={[2]}
497
+ onScroll={handleScroll}
498
+ >
499
+ <WrapHeader onLayout={(event: any) => setHeaderRefHeight(event.nativeEvent.layout?.height)}>
500
+ {loading && !product ? (
501
+ <View style={styles.productHeaderSkeleton}>
502
+ <Placeholder Animation={Fade}>
503
+ <PlaceholderLine
504
+ height={258}
505
+ style={{ borderRadius: 0 }}
506
+ width={windowWidth}
507
+ />
508
+ </Placeholder>
509
+ </View>
510
+ ) : (
511
+ <>
512
+ <Swiper
513
+ loop={false}
514
+ ref={swiperRef}
515
+ showsButtons={true}
516
+ style={styles.mainSwiper}
517
+ showsPagination={false}
518
+ onIndexChanged={(index) => handleChangeMainIndex(index)}
519
+ prevButton={
520
+ <View style={styles.swiperButton}>
521
+ <IconAntDesign
522
+ name="caretleft"
523
+ color={theme.colors.white}
524
+ size={13}
525
+ // style={styles.starIcon}
526
+ />
527
+ </View>
528
+ }
529
+ nextButton={
530
+ <View style={styles.swiperButton}>
531
+ <IconAntDesign
532
+ name="caretright"
533
+ color={theme.colors.white}
534
+ size={13}
535
+ // style={styles.starIcon}
536
+ />
537
+ </View>
538
+ }
539
+ >
540
+ {gallery && gallery.length > 0 && gallery.map((img, i) => (
541
+ <View
542
+ style={styles.slide1}
543
+ key={i}
544
+ >
545
+ {(String(img).includes('http') || typeof img === 'number') ? (
546
+ <FastImage
547
+ style={{ height: '100%', opacity: isSoldOut ? 0.5 : 1, aspectRatio: 3 / 2 }}
548
+ source={typeof img !== 'number' ? {
549
+ uri: optimizeImage(img, 'h_1024,c_limit'),
550
+ priority: FastImage.priority.normal,
551
+ } : img}
416
552
  />
417
- </View>
418
- }
419
- >
420
- {gallery && gallery.length > 0 && gallery.map((img, i) => (
553
+ ) : (
554
+ <>
555
+ <YoutubePlayer
556
+ height={'100%'}
557
+ width={'100%'}
558
+ play={playing}
559
+ videoId={img}
560
+ onChangeState={onStateChange}
561
+ />
562
+ <Button title={playing ? "pause" : "play"} onPress={togglePlaying} />
563
+ </>
564
+ )}
565
+ </View>
566
+ ))}
567
+ </Swiper>
568
+ <ScrollView
569
+ horizontal
570
+ contentContainerStyle={{
571
+ paddingHorizontal: 30,
572
+ paddingVertical: 15
573
+ }}
574
+ >
575
+ {gallery.length > 0 && gallery.map((img, index) => (
576
+ <TouchableOpacity
577
+ key={index}
578
+ onPress={() => handleClickThumb(index)}
579
+ >
421
580
  <View
422
- style={styles.slide1}
423
- key={i}
581
+ style={{
582
+ height: 56,
583
+ borderRadius: 8,
584
+ margin: 8,
585
+ opacity: index === thumbsSwiper ? 1 : 0.8
586
+ }}
424
587
  >
425
- {img.includes('image') ? (
426
- <FastImage
427
- style={{ height: '100%', opacity: isSoldOut ? 0.5 : 1 }}
428
- source={{
429
- uri: optimizeImage(img, 'h_1024,c_limit'),
430
- priority: FastImage.priority.normal,
588
+ {String(img).includes('http') ? (
589
+ <OIcon
590
+ url={img}
591
+ style={{
592
+ borderColor: theme.colors.lightGray,
593
+ borderRadius: 8,
594
+ minHeight: '100%',
595
+ opacity: isSoldOut ? 0.5 : 1
431
596
  }}
597
+ width={56}
598
+ height={56}
599
+ cover
432
600
  />
433
601
  ) : (
434
- <>
435
- <YoutubePlayer
436
- height={300}
437
- play={playing}
438
- videoId={img}
439
- onChangeState={onStateChange}
440
- />
441
- <Button title={playing ? "pause" : "play"} onPress={togglePlaying} />
442
- </>
602
+ <OIcon
603
+ url={'https://img.youtube.com/vi/' + img + '/0.jpg'}
604
+ style={{
605
+ borderColor: theme.colors.lightGray,
606
+ borderRadius: 8,
607
+ minHeight: '100%',
608
+ opacity: isSoldOut ? 0.5 : 1
609
+ }}
610
+ width={56}
611
+ height={56}
612
+ cover
613
+ />
443
614
  )}
444
615
  </View>
445
- ))}
446
- </Swiper>
447
- <ScrollView
448
- horizontal
449
- contentContainerStyle={{
450
- paddingHorizontal: 30,
451
- paddingVertical: 15
452
- }}
453
- >
454
- {gallery.length > 0 && gallery.map((img, index) => (
455
- <TouchableOpacity
456
- key={index}
457
- onPress={() => handleClickThumb(index)}
458
- >
459
- <View
460
- style={{
461
- height: 56,
462
- borderRadius: 8,
463
- margin: 8,
464
- opacity: index === thumbsSwiper ? 1 : 0.8
465
- }}
466
- >
467
- {img.includes('image') ? (
468
- <OIcon
469
- url={img}
470
- style={{
471
- borderColor: theme.colors.lightGray,
472
- borderRadius: 8,
473
- minHeight: '100%',
474
- opacity: isSoldOut ? 0.5 : 1
475
- }}
476
- width={56}
477
- height={56}
478
- cover
479
- />
480
- ) : (
481
- <OIcon
482
- url={'http://img.youtube.com/vi/' + img + '/0.jpg'}
483
- style={{
484
- borderColor: theme.colors.lightGray,
485
- borderRadius: 8,
486
- minHeight: '100%',
487
- opacity: isSoldOut ? 0.5 : 1
488
- }}
489
- width={56}
490
- height={56}
491
- cover
492
- />
493
- )}
494
- </View>
495
- </TouchableOpacity>
616
+ </TouchableOpacity>
496
617
 
497
- ))}
498
- </ScrollView>
499
- </>
500
- )}
501
- </WrapHeader>
502
- <WrapContent>
503
- <ProductSummary onLayout={(event: any) => setSummaryRefHeight(event.nativeEvent.layout?.height)}>
504
- <ProductTitle>
505
- {loading && !product ? (
506
- <Placeholder Animation={Fade}>
507
- <View
508
- style={{
509
- flexDirection: 'row',
510
- justifyContent: 'space-between',
511
- }}>
512
- <PlaceholderLine width={40} height={20} />
513
- <PlaceholderLine width={30} height={20} />
514
- </View>
515
- </Placeholder>
516
- ) : (
517
- <>
518
- <View style={{ flexDirection: 'row' }}>
519
- <OText
520
- size={20}
521
- lineHeight={30}
522
- weight={'600'}
523
- style={{ flex: 1, marginBottom: 10 }}>
524
- {product?.name || productCart.name}
525
- </OText>
526
- {!!product?.calories && (
527
- <OText size={16} style={{ color: '#808080' }}>{product?.calories} cal
528
- </OText>
529
- )}
530
- </View>
531
- {((!!product?.sku && product?.sku !== '-1' && product?.sku !== '1') || (!!product?.estimated_person)) && (
532
- <OText size={14} style={{ flex: I18nManager.isRTL ? 1 : 0 }} color={'#909BA9'} mBottom={7}>
533
- {
534
- ((product?.sku && product?.sku !== '-1' && product?.sku !== '1') || (productCart?.sku && productCart?.sku !== '-1' && productCart?.sku !== '1'))
535
- && <>{t('SKU', 'Sku')}{' '}{product?.sku || productCart?.sku}</>
536
- }
537
- {product?.sku && product?.sku !== '-1' && product?.sku !== '1' && product?.estimated_person && (
538
- <>&nbsp;&#183;&nbsp;</>
539
- )}
540
- {product?.estimated_person
541
- && <>{product?.estimated_person}{' '}{t('ESTIMATED_PERSONS', 'persons')}</>
542
- }
543
- </OText>
544
- )}
545
- {isHaveWeight ? (
546
- <OText size={16} lineHeight={24} color={theme.colors.primary}>{parsePrice(pricePerWeightUnit)} / {product?.weight_unit}</OText>
547
- ) : (
548
- <View style={{ flexDirection: 'row', marginBottom: 10 }}>
549
- <OText size={16} style={{ flex: I18nManager.isRTL ? 1 : 0 }} color={theme.colors.primary}>{productCart.price ? parsePrice(productCart.price) : ''}</OText>
550
- {product?.offer_price !== null && product?.in_offer && (
551
- <OText style={{
552
- fontSize: 14,
553
- color: '#808080',
554
- textDecorationLine: 'line-through',
555
- marginLeft: 7,
556
- marginRight: 7
557
- }}>{product?.offer_price ? parsePrice(product?.offer_price) : ''}</OText>
558
- )}
559
- </View>
560
- )}
561
- </>
562
- )}
563
- </ProductTitle>
564
- <ProductDescription>
565
- <OText color={theme.colors.textSecondary} size={12} lineHeight={18}>
566
- {product?.description || productCart?.description}
567
- </OText>
568
- </ProductDescription>
569
- <ScrollView
570
- horizontal
571
- showsHorizontalScrollIndicator={false}
572
- contentContainerStyle={{ paddingBottom: 30 }}
573
- >
574
- {product?.tags?.map((tag: any) => (
575
- <View
576
- key={tag.id}
577
- style={styles.productTagWrapper}
578
- >
579
- {!!tag?.image ? (
580
- <OIcon
581
- url={optimizeImage(tag?.image, 'h_40,c_limit')}
582
- style={styles.productTagImageStyle}
583
- />
584
- ) : (
585
- <OIcon
586
- src={theme.images?.dummies?.product}
587
- style={styles.productTagImageStyle}
588
- />
589
- )}
590
- <OText color={theme.colors.textSecondary} size={12} style={styles.productTagNameStyle}>{tag.name}</OText>
591
- </View>
592
618
  ))}
593
619
  </ScrollView>
594
- </ProductSummary>
620
+ </>
621
+ )}
622
+ </WrapHeader>
623
+ <ProductSummary
624
+ ph={isChewLayout ? 20 : 40}
625
+ onLayout={(event: any) => setSummaryRefHeight(event.nativeEvent.layout?.height)}
626
+ >
627
+ <ProductTitle>
595
628
  {loading && !product ? (
596
- <>
597
- {[...Array(2)].map((item, i) => (
598
- <Placeholder
599
- key={i}
600
- style={{ marginBottom: 20 }}
601
- Animation={Fade}>
602
- <PlaceholderLine
603
- height={40}
604
- style={{ flex: 1, marginTop: 10 }}
605
- />
606
- {[...Array(3)].map((item, i) => (
607
- <View
608
- key={'place_key_' + i}
609
- style={{
610
- flexDirection: 'row',
611
- justifyContent: 'space-between',
612
- }}>
613
- <PlaceholderLine
614
- height={30}
615
- width={10}
616
- style={{ marginBottom: 20 }}
617
- />
618
- <PlaceholderLine
619
- height={30}
620
- width={50}
621
- style={{ marginBottom: 20 }}
622
- />
623
- <PlaceholderLine
624
- height={30}
625
- width={30}
626
- style={{ marginBottom: 20 }}
627
- />
628
- </View>
629
- ))}
630
- </Placeholder>
631
- ))}
632
- </>
629
+ <Placeholder Animation={Fade}>
630
+ <View
631
+ style={{
632
+ flexDirection: 'row',
633
+ justifyContent: 'space-between',
634
+ }}>
635
+ <PlaceholderLine width={40} height={20} />
636
+ <PlaceholderLine width={30} height={20} />
637
+ </View>
638
+ </Placeholder>
633
639
  ) : (
634
- <ProductEditions>
635
- <ExtraOptionWrap
636
- horizontal
637
- showsHorizontalScrollIndicator={false}
638
- style={{ marginBottom: 20 }}
639
- contentContainerStyle={{ paddingHorizontal: 33 }}
640
- >
641
- <TouchableOpacity
642
- key={`eopt_all_0`}
643
- onPress={() => setSelectedOpt(0)}
644
- style={[
645
- styles.extraItem,
646
- {
647
- borderBottomColor: selOpt == 0 ? theme.colors.textNormal : theme.colors.border,
648
- },
649
- ]}>
650
- <OText
651
- color={selOpt == 0 ? theme.colors.textNormal : theme.colors.textSecondary}
652
- size={selOpt == 0 ? 14 : 12}
653
- weight={selOpt == 0 ? '600' : 'normal'}>
654
- {t('ALL', 'All')}
640
+ <>
641
+ <View style={{ flexDirection: 'row' }}>
642
+ <OText
643
+ size={20}
644
+ lineHeight={30}
645
+ weight={'600'}
646
+ style={{ flex: 1, marginBottom: 10 }}>
647
+ {product?.name || productCart.name}
648
+ </OText>
649
+ {!!product?.calories && (
650
+ <OText size={16} style={{ color: '#808080' }}>{product?.calories} cal
655
651
  </OText>
656
- </TouchableOpacity>
657
- {product?.ingredients.length > 0 && (
658
- <TouchableOpacity
659
- key={`eopt_all_00`}
660
- onPress={() => setSelectedOpt(-1)}
661
- style={[
662
- styles.extraItem,
663
- {
664
- borderBottomColor:
665
- selOpt == -1 ? theme.colors.textNormal : theme.colors.border,
666
- },
667
- ]}>
668
- <OText
669
- color={selOpt == -1 ? theme.colors.textNormal : theme.colors.textSecondary}
670
- size={selOpt == -1 ? 14 : 12}
671
- weight={selOpt == -1 ? '600' : 'normal'}>
672
- {t('INGREDIENTS', 'Ingredients')}
673
- </OText>
674
- </TouchableOpacity>
675
- )}
676
- {product?.extras.map((extra: any) =>
677
- <ExtraOptions key={extra.id} options={extra.options} />
678
652
  )}
679
- </ExtraOptionWrap>
680
-
681
- {selOpt == 0 ? (
682
- <>
683
- {product?.ingredients.length > 0 && (
684
- <View style={styles.optionContainer}>
685
- <SectionTitle>
686
- <OText size={16}>
687
- {t('INGREDIENTS', 'Ingredients')}
688
- </OText>
689
- </SectionTitle>
690
- <WrapperIngredients>
691
- {product?.ingredients.map((ingredient: any) => (
692
- <ProductIngredient
693
- key={ingredient.id}
694
- ingredient={ingredient}
695
- state={
696
- productCart.ingredients[`id:${ingredient.id}`]
697
- }
698
- onChange={handleChangeIngredientState}
699
- isSoldOut={isSoldOut}
700
- />
701
- ))}
702
- </WrapperIngredients>
703
- </View>
704
- )}
705
- {product?.extras.sort((a: any, b: any) => a.rank - b.rank).map((extra: any) =>
706
- extra.options.sort((a: any, b: any) => a.rank - b.rank).map((option: any) => {
707
- const currentState =
708
- productCart.options[`id:${option.id}`] || {};
709
- return (
710
- <React.Fragment key={`popt_${option.id}`}>
711
- {showOption(option) && (
712
- <View style={styles.optionContainer} onLayout={(event: any) => handleOnLayout(event, option?.id)}>
713
- <ProductOption
714
- option={option}
715
- currentState={currentState}
716
- error={errors[`id:${option.id}`]}>
717
- <WrapperSubOption
718
- style={{
719
- backgroundColor: isError(option.id),
720
- borderRadius: 7.6
721
- }}>
722
- {option.suboptions.sort((a: any, b: any) => a.rank - b.rank).map(
723
- (suboption: any) => {
724
- const currentState =
725
- productCart.options[
726
- `id:${option.id}`
727
- ]?.suboptions[
728
- `id:${suboption.id}`
729
- ] || {};
730
- const balance =
731
- productCart.options[
732
- `id:${option.id}`
733
- ]?.balance || 0;
734
- return (
735
- <ProductOptionSubOption
736
- key={suboption.id}
737
- isSoldOut={isSoldOut}
738
- onChange={
739
- handleChangeSuboptionState
740
- }
741
- balance={balance}
742
- option={option}
743
- suboption={suboption}
744
- state={currentState}
745
- disabled={
746
- isSoldOut ||
747
- maxProductQuantity <= 0
748
- }
749
- setIsScrollAvailable={setIsScrollAvailable}
750
- error={errors[`id:${option.id}`]}
751
- />
752
- );
753
- },
754
- )}
755
- </WrapperSubOption>
756
- </ProductOption>
757
- </View>
758
- )}
759
- </React.Fragment>
760
- );
761
- }),
653
+ </View>
654
+ {((!!product?.sku && product?.sku !== '-1' && product?.sku !== '1') || (!!product?.estimated_person)) && (
655
+ <OText size={14} style={{ flex: I18nManager.isRTL ? 1 : 0 }} color={'#909BA9'} mBottom={7}>
656
+ {
657
+ ((product?.sku && product?.sku !== '-1' && product?.sku !== '1') || (productCart?.sku && productCart?.sku !== '-1' && productCart?.sku !== '1'))
658
+ && <>{t('SKU', 'Sku')}{' '}{product?.sku || productCart?.sku}</>
659
+ }
660
+ {product?.sku && product?.sku !== '-1' && product?.sku !== '1' && product?.estimated_person && (
661
+ <>&nbsp;&#183;&nbsp;</>
762
662
  )}
763
- </>
663
+ {product?.estimated_person
664
+ && <>{product?.estimated_person}{' '}{t('ESTIMATED_PERSONS', 'persons')}</>
665
+ }
666
+ </OText>
667
+ )}
668
+ {isHaveWeight ? (
669
+ <OText size={16} lineHeight={24} color={theme.colors.primary}>{parsePrice(pricePerWeightUnit)} / {product?.weight_unit}</OText>
764
670
  ) : (
765
- <>
766
- {selOpt == -1 ? (
767
- <View style={styles.optionContainer}>
768
- <SectionTitle>
769
- <OText size={16}>
770
- {t('INGREDIENTS', 'Ingredients')}
771
- </OText>
772
- </SectionTitle>
773
- <WrapperIngredients>
774
- {product?.ingredients.map((ingredient: any) => (
775
- <ProductIngredient
776
- key={ingredient.id}
777
- ingredient={ingredient}
778
- state={
779
- productCart.ingredients[`id:${ingredient.id}`]
780
- }
781
- onChange={handleChangeIngredientState}
782
- isSoldOut={isSoldOut}
783
- />
784
- ))}
785
- </WrapperIngredients>
786
- </View>
787
- ) : (
788
- <>
789
- {product?.extras.map((extra: any) =>
790
- extra.options.sort((a: any, b: any) => a.rank - b.rank).map((option: any) => {
791
- if (
792
- option.id == selOpt ||
793
- (hasRespected(
794
- extra.options,
795
- option.respect_to,
796
- ) &&
797
- showOption(option))
798
- ) {
799
- const currentState =
800
- productCart.options[`id:${option.id}`] || {};
801
- return (
802
- <React.Fragment key={option.id}>
803
- {showOption(option) && (
804
- <View style={styles.optionContainer}>
805
- <ProductOption
806
- option={option}
807
- currentState={currentState}
808
- error={errors[`id:${option.id}`]}>
809
- <WrapperSubOption
810
- style={{
811
- backgroundColor: isError(
812
- option.id,
813
- ),
814
- }}>
815
- {option.suboptions.sort((a: any, b: any) => a.rank - b.rank).map(
816
- (suboption: any) => {
817
- const currentState =
818
- productCart.options[
819
- `id:${option.id}`
820
- ]?.suboptions[
821
- `id:${suboption.id}`
822
- ] || {};
823
- const balance =
824
- productCart.options[
825
- `id:${option.id}`
826
- ]?.balance || 0;
827
- return (
828
- <ProductOptionSubOption
829
- key={suboption.id}
830
- onChange={
831
- handleChangeSuboptionState
832
- }
833
- balance={balance}
834
- option={option}
835
- suboption={suboption}
836
- state={currentState}
837
- disabled={
838
- isSoldOut ||
839
- maxProductQuantity <= 0
840
- }
841
- />
842
- );
843
- },
844
- )}
845
- </WrapperSubOption>
846
- </ProductOption>
847
- </View>
848
- )}
849
- </React.Fragment>
850
- );
851
- }
852
- }),
853
- )}
854
- </>
671
+ <View style={{ flexDirection: 'row', marginBottom: 10 }}>
672
+ <OText size={16} style={{ flex: I18nManager.isRTL ? 1 : 0 }} color={theme.colors.primary}>{productCart.price ? parsePrice(productCart.price) : ''}</OText>
673
+ {product?.offer_price !== null && product?.in_offer && (
674
+ <OText style={{
675
+ fontSize: 14,
676
+ color: '#808080',
677
+ textDecorationLine: 'line-through',
678
+ marginLeft: 7,
679
+ marginRight: 7
680
+ }}>{product?.offer_price ? parsePrice(product?.offer_price) : ''}</OText>
855
681
  )}
856
- </>
857
- )}
858
- {!product?.hide_special_instructions && (
859
- <ProductComment>
860
- <SectionTitle>
861
- <OText size={16} weight={'600'} lineHeight={24}>
862
- {t('SPECIAL_COMMENT', 'Special comment')}
863
- </OText>
864
- </SectionTitle>
865
- <OInput
866
- multiline
867
- placeholder={t('SPECIAL_COMMENT', 'Special comment')}
868
- value={productCart.comment}
869
- onChange={(val: string) =>
870
- handleChangeCommentState({ target: { value: val } })
871
- }
872
- isDisabled={
873
- !(productCart && !isSoldOut && maxProductQuantity)
874
- }
875
- style={styles.comment}
876
- />
877
- </ProductComment>
682
+ </View>
878
683
  )}
879
- </ProductEditions>
684
+ </>
880
685
  )}
881
- </WrapContent>
882
- </View>
883
- )}
884
- {!!error && error.length > 0 && (
885
- <NotFoundSource content={error[0]?.message || error[0]} />
886
- )}
887
- </ScrollView>
888
- {!loading && !error && product && (
889
- <ProductActions ios={Platform?.OS === 'ios'}>
890
- <View>
891
- <OText size={16} lineHeight={24} weight={'600'}>
892
- {productCart.total ? parsePrice(productCart?.total) : ''}
893
- </OText>
894
- {product?.minimum_per_order && productCart?.quantity < product?.minimum_per_order && <OText size={12} color={theme.colors?.red}>{t('MOBILE_MINIMUM_TO_ORDER', 'Min. _number_ ').replace('_number_', product?.minimum_per_order)}</OText>}
895
- {product?.maximum_per_order && productCart?.quantity > product?.maximum_per_order && <OText size={12} color={theme.colors?.red}>{t('MOBILE_MAXIMUM_TO_ORDER', 'Max. _number_'.replace('_number_', product?.maximum_per_order))}</OText>}
896
- </View>
897
- {productCart && !isSoldOut && maxProductQuantity > 0 && (
898
- <View style={styles.quantityControl}>
899
- <TouchableOpacity
900
- onPress={decrement}
901
- disabled={productCart.quantity === 1 || isSoldOut}>
902
- <OIcon
903
- src={theme.images.general.minus}
904
- width={16}
905
- color={
906
- productCart.quantity === 1 || isSoldOut
907
- ? theme.colors.backgroundGray
908
- : theme.colors.backgroundDark
909
- }
910
- />
911
- </TouchableOpacity>
912
- {qtyBy?.pieces && (
913
- <TextInput
914
- keyboardType='numeric'
915
- value={`${productCart?.quantity > 0 ? productCart?.quantity : ''}`}
916
- onChangeText={(val: any) => onChangeProductCartQuantity(parseInt(val))}
917
- editable={!orderState.loading}
918
- style={{
919
- borderWidth: 1,
920
- textAlign: 'center',
921
- minWidth: 60,
922
- borderRadius: 8,
923
- borderColor: theme.colors.inputBorderColor,
924
- height: 44,
925
- marginHorizontal: 10
686
+ </ProductTitle>
687
+ <ProductDescription>
688
+ <OText color={theme.colors.textSecondary} size={12} lineHeight={18}>
689
+ {product?.description || productCart?.description}
690
+ </OText>
691
+ </ProductDescription>
692
+ <ScrollView
693
+ horizontal
694
+ showsHorizontalScrollIndicator={false}
695
+ contentContainerStyle={{ paddingBottom: 30 }}
696
+ >
697
+ {product?.tags?.map((tag: any) => (
698
+ <View
699
+ key={tag.id}
700
+ style={styles.productTagWrapper}
701
+ >
702
+ {!!tag?.image ? (
703
+ <OIcon
704
+ url={optimizeImage(tag?.image, 'h_40,c_limit')}
705
+ style={styles.productTagImageStyle}
706
+ />
707
+ ) : (
708
+ <OIcon
709
+ src={theme.images?.dummies?.product}
710
+ style={styles.productTagImageStyle}
711
+ />
712
+ )}
713
+ <OText color={theme.colors.textSecondary} size={12} style={styles.productTagNameStyle}>{tag.name}</OText>
714
+ </View>
715
+ ))}
716
+ </ScrollView>
717
+ </ProductSummary>
718
+ {(!loading && product) && (
719
+ <ExtraOptionWrap
720
+ horizontal
721
+ showsHorizontalScrollIndicator={false}
722
+ style={{
723
+ marginBottom: 20,
724
+ borderBottomWidth: 1,
725
+ borderBottomColor: theme.colors.border,
726
+ marginHorizontal: isChewLayout ? 20 : 30,
727
+ backgroundColor: theme.colors.backgroundPage,
728
+ }}
729
+ >
730
+ {product?.ingredients.length > 0 && (
731
+ <TouchableOpacity
732
+ key={`eopt_key_01`}
733
+ onPress={() => {
734
+ setSelectedOpt(0)
735
+ scrollViewRef?.current?.scrollTo && scrollViewRef.current.scrollTo({
736
+ y: optionLayout[`id:0`]?.y + editionsLayoutY - 50,
737
+ animated: true
738
+ })
926
739
  }}
927
- />
740
+ style={[
741
+ styles.extraItem,
742
+ {
743
+ borderBottomColor:
744
+ selOpt == 0 ? theme.colors.textNormal : theme.colors.backgroundPage,
745
+ },
746
+ ]}>
747
+ <OText
748
+ color={selOpt == 0 ? theme.colors.textNormal : theme.colors.textSecondary}
749
+ size={12}
750
+ weight={selOpt == 0 ? '600' : 'normal'}>
751
+ {t('INGREDIENTS', 'Ingredients')}
752
+ </OText>
753
+ </TouchableOpacity>
928
754
  )}
929
- {qtyBy?.weight_unit && (
930
- <OText
931
- size={12}
932
- lineHeight={18}
933
- style={{ minWidth: 40, textAlign: 'center' }}
934
- >
935
- {productCart.quantity * product?.weight}
936
- </OText>
755
+ {product?.extras.map((extra: any) =>
756
+ <ExtraOptions key={extra.id} options={extra.options} />
937
757
  )}
938
- <TouchableOpacity
939
- onPress={increment}
940
- disabled={
941
- maxProductQuantity <= 0 ||
942
- productCart.quantity >= maxProductQuantity ||
943
- isSoldOut
944
- }>
945
- <OIcon
946
- src={theme.images.general.plus}
947
- width={16}
948
- color={
949
- maxProductQuantity <= 0 ||
950
- productCart.quantity >= maxProductQuantity ||
951
- isSoldOut
952
- ? theme.colors.backgroundGray
953
- : theme.colors.backgroundDark
954
- }
955
- />
956
- </TouchableOpacity>
957
- {isHaveWeight && (
958
- <WeightUnitSwitch>
959
- <TouchableOpacity
960
- onPress={() => handleSwitchQtyUnit('pieces')}
961
- >
962
- <WeightUnitItem active={qtyBy?.pieces}>
963
- <OText
964
- size={12}
965
- lineHeight={18}
966
- color={qtyBy?.pieces ? theme.colors.primary : theme.colors.textNormal}
967
- >
968
- {t('PIECES', 'pcs')}
758
+ </ExtraOptionWrap>
759
+ )}
760
+ {loading && !product ? (
761
+ <>
762
+ {[...Array(2)].map((item, i) => (
763
+ <Placeholder
764
+ key={i}
765
+ style={{ marginBottom: 20 }}
766
+ Animation={Fade}>
767
+ <PlaceholderLine
768
+ height={40}
769
+ style={{ flex: 1, marginTop: 10 }}
770
+ />
771
+ {[...Array(3)].map((item, i) => (
772
+ <View
773
+ key={'place_key_' + i}
774
+ style={{
775
+ flexDirection: 'row',
776
+ justifyContent: 'space-between',
777
+ }}>
778
+ <PlaceholderLine
779
+ height={30}
780
+ width={10}
781
+ style={{ marginBottom: 20 }}
782
+ />
783
+ <PlaceholderLine
784
+ height={30}
785
+ width={50}
786
+ style={{ marginBottom: 20 }}
787
+ />
788
+ <PlaceholderLine
789
+ height={30}
790
+ width={30}
791
+ style={{ marginBottom: 20 }}
792
+ />
793
+ </View>
794
+ ))}
795
+ </Placeholder>
796
+ ))}
797
+ </>
798
+ ) : (
799
+ <ProductEditions
800
+ style={{ paddingHorizontal: isChewLayout ? 20 : 40 }}
801
+ onLayout={(event: any) => {
802
+ setEditionsLayoutY(event.nativeEvent.layout?.y)
803
+ }}
804
+ >
805
+ <>
806
+ {product?.ingredients.length > 0 && (
807
+ <View style={styles.optionContainer} onLayout={(event: any) => handleOnLayout(event, 0)}>
808
+ <SectionTitle>
809
+ <OText size={16}>
810
+ {t('INGREDIENTS', 'Ingredients')}
969
811
  </OText>
970
- </WeightUnitItem>
812
+ </SectionTitle>
813
+ <WrapperIngredients>
814
+ {product?.ingredients.map((ingredient: any) => (
815
+ <ProductIngredient
816
+ key={ingredient.id}
817
+ ingredient={ingredient}
818
+ state={
819
+ productCart.ingredients[`id:${ingredient.id}`]
820
+ }
821
+ onChange={handleChangeIngredientState}
822
+ isSoldOut={isSoldOut}
823
+ />
824
+ ))}
825
+ </WrapperIngredients>
826
+ </View>
827
+ )}
828
+ {product?.extras.sort((a: any, b: any) => a.rank - b.rank).map((extra: any) =>
829
+ extra.options.sort((a: any, b: any) => a.rank - b.rank).map((option: any) => {
830
+ const currentState =
831
+ productCart.options[`id:${option.id}`] || {};
832
+ return (
833
+ <React.Fragment key={`popt_${option.id}`}>
834
+ {showOption(option) && (
835
+ <View style={styles.optionContainer} onLayout={(event: any) => handleOnLayout(event, option?.id)}>
836
+ <ProductOption
837
+ option={option}
838
+ currentState={currentState}
839
+ error={errors[`id:${option.id}`]}>
840
+ <WrapperSubOption
841
+ style={{
842
+ backgroundColor: isError(option.id),
843
+ borderRadius: 7.6
844
+ }}>
845
+ {option.suboptions.sort((a: any, b: any) => a.rank - b.rank).map(
846
+ (suboption: any) => {
847
+ const currentState =
848
+ productCart.options[
849
+ `id:${option.id}`
850
+ ]?.suboptions[
851
+ `id:${suboption.id}`
852
+ ] || {};
853
+ const balance =
854
+ productCart.options[
855
+ `id:${option.id}`
856
+ ]?.balance || 0;
857
+ return (
858
+ <ProductOptionSubOption
859
+ key={suboption.id}
860
+ isSoldOut={isSoldOut}
861
+ onChange={
862
+ handleChangeSuboptionState
863
+ }
864
+ balance={balance}
865
+ option={option}
866
+ suboption={suboption}
867
+ state={currentState}
868
+ disabled={
869
+ isSoldOut ||
870
+ maxProductQuantity <= 0
871
+ }
872
+ setIsScrollAvailable={setIsScrollAvailable}
873
+ error={errors[`id:${option.id}`]}
874
+ />
875
+ );
876
+ },
877
+ )}
878
+ </WrapperSubOption>
879
+ </ProductOption>
880
+ </View>
881
+ )}
882
+ </React.Fragment>
883
+ );
884
+ }),
885
+ )}
886
+ </>
887
+ {!product?.hide_special_instructions && (
888
+ <ProductComment>
889
+ <SectionTitle>
890
+ <OText size={16} weight={'600'} lineHeight={24}>
891
+ {t('SPECIAL_COMMENT', 'Special comment')}
892
+ </OText>
893
+ </SectionTitle>
894
+ <OInput
895
+ multiline
896
+ placeholder={t('SPECIAL_COMMENT', 'Special comment')}
897
+ value={productCart.comment}
898
+ onChange={(val: string) =>
899
+ handleChangeCommentState({ target: { value: val } })
900
+ }
901
+ isDisabled={
902
+ !(productCart && !isSoldOut && maxProductQuantity)
903
+ }
904
+ style={styles.comment}
905
+ />
906
+ </ProductComment>
907
+ )}
908
+ </ProductEditions>
909
+ )}
910
+ {!!error && error.length > 0 && (
911
+ <NotFoundSource content={error[0]?.message || error[0]} />
912
+ )}
913
+ </ScrollView>
914
+ )}
915
+ {!loading && !error && product && (
916
+ <ProductActions ios={Platform?.OS === 'ios'} isColumn={isHaveWeight}>
917
+ <View style={styles.actionContainer}>
918
+ <View>
919
+ <OText size={16} lineHeight={24} weight={'600'}>
920
+ {productCart.total ? parsePrice(productCart?.total) : ''}
921
+ </OText>
922
+ {product?.minimum_per_order && (productCart?.quantity + productAddedToCartLength) <= product?.minimum_per_order && productCart?.quantity !== 1 && <OText size={12} color={theme.colors?.red}>{t('MOBILE_MINIMUM_TO_ORDER', 'Min. _number_ ').replace('_number_', product?.minimum_per_order)}</OText>}
923
+ {product?.maximum_per_order && (productCart?.quantity + productAddedToCartLength) >= product?.maximum_per_order && <OText size={12} color={theme.colors?.red}>{t('MOBILE_MAXIMUM_TO_ORDER', 'Max. _number_'.replace('_number_', product?.maximum_per_order))}</OText>}
924
+ </View>
925
+ {productCart && !isSoldOut && maxProductQuantity > 0 && (
926
+ <>
927
+ <View style={styles.quantityControl}>
928
+ <TouchableOpacity
929
+ onPress={decrement}
930
+ disabled={productCart.quantity === 1 || !productCart.quantity || isSoldOut || ((productCart?.quantity + productAddedToCartLength) <= product?.minimum_per_order)}>
931
+ <OIcon
932
+ src={theme.images.general.minus}
933
+ width={20}
934
+ color={
935
+ productCart.quantity === 1 || isSoldOut
936
+ ? theme.colors.backgroundGray
937
+ : theme.colors.backgroundDark
938
+ }
939
+ />
940
+ </TouchableOpacity>
941
+ {qtyBy?.pieces && (
942
+ <TextInput
943
+ keyboardType='numeric'
944
+ value={`${productCart?.quantity > 0 ? productCart?.quantity : ''}`}
945
+ onChangeText={(val: any) => onChangeProductCartQuantity(parseInt(val))}
946
+ editable={!orderState.loading}
947
+ style={{
948
+ borderWidth: 1,
949
+ textAlign: 'center',
950
+ minWidth: 60,
951
+ borderRadius: 8,
952
+ borderColor: theme.colors.inputBorderColor,
953
+ height: 44,
954
+ marginHorizontal: 10,
955
+ fontSize: 16
956
+ }}
957
+ />
958
+ )}
959
+ {qtyBy?.weight_unit && (
960
+ <OText
961
+ size={12}
962
+ lineHeight={18}
963
+ style={{ minWidth: 40, textAlign: 'center' }}
964
+ >
965
+ {productCart.quantity * product?.weight}
966
+ </OText>
967
+ )}
968
+ <TouchableOpacity
969
+ onPress={increment}
970
+ disabled={
971
+ maxProductQuantity <= 0 ||
972
+ (productCart?.quantity + productAddedToCartLength) >= maxProductQuantity ||
973
+ ((productCart?.quantity + productAddedToCartLength) >= product?.maximum_per_order && product?.maximum_per_order) ||
974
+ isSoldOut
975
+ }>
976
+ <OIcon
977
+ src={theme.images.general.plus}
978
+ width={20}
979
+ color={
980
+ maxProductQuantity <= 0 ||
981
+ (productCart?.quantity + productAddedToCartLength) >= maxProductQuantity ||
982
+ ((productCart?.quantity + productAddedToCartLength) >= product?.maximum_per_order && product?.maximum_per_order) ||
983
+ isSoldOut
984
+ ? theme.colors.backgroundGray
985
+ : theme.colors.backgroundDark
986
+ }
987
+ />
971
988
  </TouchableOpacity>
972
- <View style={{ alignItems: 'flex-start' }}>
989
+ </View>
990
+ {isHaveWeight && (
991
+ <WeightUnitSwitch>
973
992
  <TouchableOpacity
974
- onPress={() => handleSwitchQtyUnit('weight_unit')}
993
+ onPress={() => handleSwitchQtyUnit('pieces')}
975
994
  >
976
- <WeightUnitItem active={qtyBy?.weight_unit}>
995
+ <WeightUnitItem active={qtyBy?.pieces}>
977
996
  <OText
978
997
  size={12}
979
998
  lineHeight={18}
980
- color={qtyBy?.weight_unit ? theme.colors.primary : theme.colors.textNormal}
999
+ color={qtyBy?.pieces ? theme.colors.primary : theme.colors.textNormal}
981
1000
  >
982
- {product?.weight_unit}
1001
+ {t('PIECES', 'pcs')}
983
1002
  </OText>
984
1003
  </WeightUnitItem>
985
1004
  </TouchableOpacity>
986
- </View>
987
- </WeightUnitSwitch>
988
- )}
989
- </View>
990
- )}
991
- <View
992
- style={{
993
- width: isSoldOut || maxProductQuantity <= 0 ? '60%' : '40%',
994
- }}>
995
- {((productCart &&
996
- auth &&
997
- orderState.options?.address_id) || (isSoldOut || maxProductQuantity <= 0)) && (
998
- <OButton
999
- onClick={() => handleSaveProduct()}
1000
- imgRightSrc=""
1001
- text={`${orderState.loading
1002
- ? t('LOADING', 'Loading')
1003
- : (isSoldOut || maxProductQuantity <= 0)
1004
- ? t('SOLD_OUT', 'Sold out')
1005
- : editMode
1006
- ? t('UPDATE', 'Update')
1007
- : t('ADD', 'Add')
1008
- }`}
1009
- isDisabled={isSoldOut || maxProductQuantity <= 0 || (product?.minimum_per_order && (productCart?.quantity < product?.minimum_per_order)) || (product?.maximum_per_order && (productCart?.quantity > product?.maximum_per_order))}
1010
- textStyle={{
1011
- color: saveErrors || isSoldOut || maxProductQuantity <= 0 ? theme.colors.primary : theme.colors.white,
1012
- fontSize: orderState.loading || editMode ? 10 : 14
1013
- }}
1014
- style={{
1015
- backgroundColor: saveErrors || isSoldOut || maxProductQuantity <= 0 || (product?.minimum_per_order && (productCart?.quantity < product?.minimum_per_order)) || (product?.maximum_per_order && (productCart?.quantity > product?.maximum_per_order)) ? theme.colors.lightGray : theme.colors.primary,
1016
- borderColor: saveErrors || isSoldOut || maxProductQuantity <= 0 || (product?.minimum_per_order && (productCart?.quantity < product?.minimum_per_order)) || (product?.maximum_per_order && (productCart?.quantity > product?.maximum_per_order)) ? theme.colors.white : theme.colors.primary,
1017
- opacity: saveErrors || isSoldOut || maxProductQuantity <= 0 ? 0.3 : 1,
1018
- borderRadius: 7.6,
1019
- height: 44,
1020
- shadowOpacity: 0,
1021
- borderWidth: 1,
1022
- }}
1023
- />
1024
- )}
1025
- {auth &&
1026
- !orderState.options?.address_id &&
1027
- (orderState.loading ? (
1028
- <OButton
1029
- isDisabled
1030
- text={t('LOADING', 'Loading')}
1031
- imgRightSrc=""
1032
- textStyle={{ fontSize: 10 }}
1033
- />
1034
- ) : (
1035
- <OButton onClick={navigation.navigate('AddressList')} />
1036
- ))}
1037
- {!auth && (
1038
- <OButton
1039
- isDisabled={isSoldOut || maxProductQuantity <= 0}
1040
- onClick={() => handleRedirectLogin()}
1041
- text={
1042
- isSoldOut || maxProductQuantity <= 0
1043
- ? t('SOLD_OUT', 'Sold out')
1044
- : t('LOGIN_SIGNUP', 'Login / Sign Up')
1045
- }
1046
- imgRightSrc=""
1047
- textStyle={{ color: theme.colors.primary, fontSize: 14 }}
1048
- style={{
1049
- height: 44,
1050
- borderColor: theme.colors.primary,
1051
- backgroundColor: theme.colors.white,
1052
- }}
1053
- />
1005
+ <View style={{ alignItems: 'flex-start' }}>
1006
+ <TouchableOpacity
1007
+ onPress={() => handleSwitchQtyUnit('weight_unit')}
1008
+ >
1009
+ <WeightUnitItem active={qtyBy?.weight_unit}>
1010
+ <OText
1011
+ size={12}
1012
+ lineHeight={18}
1013
+ color={qtyBy?.weight_unit ? theme.colors.primary : theme.colors.textNormal}
1014
+ >
1015
+ {product?.weight_unit}
1016
+ </OText>
1017
+ </WeightUnitItem>
1018
+ </TouchableOpacity>
1019
+ </View>
1020
+ </WeightUnitSwitch>
1021
+ )}
1022
+ </>
1054
1023
  )}
1024
+ {!isHaveWeight && <ActionButton />}
1055
1025
  </View>
1026
+ {isHaveWeight && <ActionButton />}
1056
1027
  </ProductActions>
1057
1028
  )}
1058
1029
  </SafeAreaView>
@@ -1063,8 +1034,18 @@ export const ProductOptionsUI = (props: any) => {
1063
1034
  export const ProductForm = (props: any) => {
1064
1035
  const productOptionsProps = {
1065
1036
  ...props,
1066
- UIComponent: ProductOptionsUI,
1067
- };
1037
+ productCart: {
1038
+ ...props.productCart,
1039
+ quantity: props.productCart?.code
1040
+ ? props.productCart?.quantity
1041
+ : props?.product?.minimum_per_order || 1
1042
+ },
1043
+ UIComponent: ProductOptionsUI
1044
+ }
1068
1045
 
1069
- return <ProductOptions {...productOptionsProps} />;
1046
+ return <ProductOptions {...productOptionsProps} />
1070
1047
  };
1048
+
1049
+ ProductForm.defaultProps = {
1050
+ productAddedToCartLength: 0
1051
+ }