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