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