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