ordering-ui-react-native 0.16.14 → 0.16.17

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 (37) hide show
  1. package/package.json +1 -1
  2. package/src/components/OrderDetails/index.tsx +5 -1
  3. package/src/navigators/CheckoutNavigator.tsx +6 -0
  4. package/src/navigators/HomeNavigator.tsx +6 -0
  5. package/src/pages/MultiCheckout.tsx +31 -0
  6. package/src/pages/MultiOrdersDetails.tsx +27 -0
  7. package/themes/business/src/components/OrderDetails/OrderContentComponent.tsx +2 -2
  8. package/themes/original/index.tsx +6 -0
  9. package/themes/original/src/components/BusinessItemAccordion/index.tsx +3 -2
  10. package/themes/original/src/components/BusinessItemAccordion/styles.tsx +0 -2
  11. package/themes/original/src/components/BusinessProductsList/index.tsx +4 -1
  12. package/themes/original/src/components/BusinessProductsListing/index.tsx +16 -7
  13. package/themes/original/src/components/BusinessesListing/index.tsx +1 -1
  14. package/themes/original/src/components/Cart/index.tsx +46 -33
  15. package/themes/original/src/components/FavoriteList/index.tsx +4 -4
  16. package/themes/original/src/components/MultiCartsPaymethodsAndWallets/index.tsx +243 -0
  17. package/themes/original/src/components/MultiCartsPaymethodsAndWallets/styles.tsx +46 -0
  18. package/themes/original/src/components/MultiCheckout/index.tsx +292 -0
  19. package/themes/original/src/components/MultiCheckout/styles.tsx +59 -0
  20. package/themes/original/src/components/MultiOrdersDetails/SingleOrderCard.tsx +372 -0
  21. package/themes/original/src/components/MultiOrdersDetails/index.tsx +258 -0
  22. package/themes/original/src/components/MultiOrdersDetails/styles.tsx +50 -0
  23. package/themes/original/src/components/MyOrders/index.tsx +120 -32
  24. package/themes/original/src/components/MyOrders/styles.tsx +8 -1
  25. package/themes/original/src/components/OrderDetails/index.tsx +9 -7
  26. package/themes/original/src/components/OrdersOption/PreviousBusinessOrdered/index.tsx +150 -0
  27. package/themes/original/src/components/OrdersOption/PreviousBusinessOrdered/styles.tsx +6 -0
  28. package/themes/original/src/components/OrdersOption/PreviousProductsOrdered/index.tsx +51 -0
  29. package/themes/original/src/components/OrdersOption/PreviousProductsOrdered/styles.tsx +6 -0
  30. package/themes/original/src/components/OrdersOption/index.tsx +102 -28
  31. package/themes/original/src/components/OrdersOption/styles.tsx +4 -1
  32. package/themes/original/src/components/SingleOrderCard/index.tsx +5 -3
  33. package/themes/original/src/components/SingleProductCard/index.tsx +8 -6
  34. package/themes/original/src/components/StripeElementsForm/index.tsx +10 -2
  35. package/themes/original/src/components/StripeElementsForm/naked.tsx +2 -2
  36. package/themes/original/src/components/UserDetails/index.tsx +1 -1
  37. package/themes/original/src/types/index.tsx +44 -19
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ordering-ui-react-native",
3
- "version": "0.16.14",
3
+ "version": "0.16.17",
4
4
  "description": "Reusable components made in react native",
5
5
  "main": "src/index.tsx",
6
6
  "author": "ordering.inc",
@@ -276,7 +276,6 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
276
276
  };
277
277
  }, [])
278
278
 
279
-
280
279
  return (
281
280
  <OrderDetailsContainer keyboardShouldPersistTaps='handled'>
282
281
  {order && order?.id && !error && !loading && (
@@ -400,6 +399,11 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
400
399
  <InfoBlock>
401
400
  <OText size={18} style={{ textAlign: 'left' }} >{order?.customer?.name} {order?.customer?.lastname}</OText>
402
401
  <OText style={{ textAlign: 'left' }}>{order?.customer?.address}</OText>
402
+ {(!!order?.customer?.cellphone) && (
403
+ <OText size={18} style={{ textAlign: 'left' }}>
404
+ {(order?.customer?.country_phone_code) && `+${(order?.customer?.country_phone_code)} `}{(order?.customer?.cellphone)}
405
+ </OText>
406
+ )}
403
407
  </InfoBlock>
404
408
  </Customer>
405
409
  {order?.delivery_option !== undefined && order?.delivery_type === 1 && (
@@ -6,6 +6,7 @@ import AddressForm from '../pages/AddressForm'
6
6
  import CartList from '../pages/CartList'
7
7
  import CheckoutPage from '../pages/Checkout';
8
8
  import BusinessProductsList from '../pages/BusinessProductsList';
9
+ import MultiCheckout from '../pages/MultiCheckout';
9
10
 
10
11
  const Stack = createStackNavigator();
11
12
 
@@ -53,6 +54,11 @@ const CheckoutNavigator = (props: any) => {
53
54
  component={AddressForm}
54
55
  options={{ headerShown: false }}
55
56
  />
57
+ <Stack.Screen
58
+ name="MultiCheckout"
59
+ children={() => <MultiCheckout {...checkoutProps} />}
60
+ options={{ headerShown: false }}
61
+ />
56
62
  </Stack.Navigator>
57
63
  );
58
64
  }
@@ -23,6 +23,7 @@ import HelpAccountAndPayment from '../pages/HelpAccountAndPayment'
23
23
  import Sessions from '../pages/Sessions';
24
24
  import Splash from '../pages/Splash';
25
25
  import ProductDetails from '../pages/ProductDetails';
26
+ import MultiOrdersDetails from '../pages/MultiOrdersDetails';
26
27
  const Stack = createStackNavigator();
27
28
 
28
29
  const HomeNavigator = (e : any) => {
@@ -170,6 +171,11 @@ const HomeNavigator = (e : any) => {
170
171
  component={Sessions}
171
172
  options={{ headerShown: false }}
172
173
  />
174
+ <Stack.Screen
175
+ name="MultiOrdersDetails"
176
+ component={MultiOrdersDetails}
177
+ options={{ headerShown: false }}
178
+ />
173
179
  </>
174
180
  )}
175
181
  </>
@@ -0,0 +1,31 @@
1
+ import React from 'react'
2
+ import { Platform, KeyboardAvoidingView, StyleSheet } from 'react-native'
3
+ import { MultiCheckout as MultiCheckoutController } from '../../themes/original/src/components/MultiCheckout'
4
+
5
+ const MultiCheckout = (props: any) => {
6
+ const multiCheckoutProps = {
7
+ ...props,
8
+ onPlaceOrderClick: (orderUuids: any) => {
9
+ props.navigation.navigate('MultiOrdersDetails', { orderUuids: orderUuids, isFromMultiCheckout: true })
10
+ }
11
+ }
12
+
13
+ return (
14
+ <KeyboardAvoidingView
15
+ enabled
16
+ behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
17
+ style={styles.container}
18
+ >
19
+ <MultiCheckoutController {...multiCheckoutProps} />
20
+ </KeyboardAvoidingView>
21
+ )
22
+ }
23
+
24
+ const styles = StyleSheet.create({
25
+ container: {
26
+ flexGrow: 1,
27
+ paddingBottom: 70,
28
+ },
29
+ });
30
+
31
+ export default MultiCheckout
@@ -0,0 +1,27 @@
1
+ import React from 'react'
2
+ import { Platform } from 'react-native'
3
+ import { MultiOrdersDetails as MultiOrdersDetailsController } from '../../themes/original/src/components/MultiOrdersDetails'
4
+ import styled from 'styled-components/native';
5
+
6
+ const SafeAreaContainer = styled.SafeAreaView`
7
+ flex: 1;
8
+ background-color: ${(props: any) => props.theme.colors.backgroundPage};
9
+ padding-top: ${Platform.OS === 'ios' ? '0px' : '24px'};
10
+ `;
11
+
12
+ const MultiOrdersDetails = ({ navigation, route }: any) => {
13
+ const multiOrdersDetailsProps = {
14
+ navigation,
15
+ orderUuids: route.params?.orderUuids || [],
16
+ isFromMultiCheckout: route.params?.isFromMultiCheckout,
17
+ onRedirectPage: () => navigation.navigate('BusinessList')
18
+ }
19
+
20
+ return (
21
+ <SafeAreaContainer>
22
+ <MultiOrdersDetailsController {...multiOrdersDetailsProps} />
23
+ </SafeAreaContainer>
24
+ )
25
+ }
26
+
27
+ export default MultiOrdersDetails
@@ -274,8 +274,8 @@ export const OrderContentComponent = (props: OrderContent) => {
274
274
  <View style={styles.linkWithIcons}>
275
275
  <OLink
276
276
  PressStyle={styles.linkWithIcons}
277
- url={`tel:${order?.customer?.cellphone}`}
278
- shorcut={order?.customer?.cellphone}
277
+ url={`tel:${!!order?.customer?.country_phone_code ? '+' + order?.customer?.country_phone_code : ''} ${order?.customer?.cellphone}`}
278
+ shorcut={`${!!order?.customer?.country_phone_code ? '+' + order?.customer?.country_phone_code : ''} ${order?.customer?.cellphone}`}
279
279
  TextStyle={styles.textLink}
280
280
  />
281
281
  </View>
@@ -32,6 +32,7 @@ import { ReviewDriver } from './src/components/ReviewDriver';
32
32
  import { UserProfile } from './src/components/UserProfile';
33
33
  import { MessageListing } from './src/components/MessageListing';
34
34
  import { Messages } from './src/components/Messages';
35
+ import { MyOrders } from './src/components/MyOrders';
35
36
  import { Help } from './src/components/Help';
36
37
  import { HelpAccountAndPayment } from './src/components/HelpAccountAndPayment';
37
38
  import { HelpGuide } from './src/components/HelpGuide';
@@ -47,6 +48,8 @@ import { UpsellingProducts } from './src/components/UpsellingProducts';
47
48
  import { UserVerification } from './src/components/UserVerification';
48
49
  import { BusinessListingSearch } from './src/components/BusinessListingSearch';
49
50
  import { LastOrders } from './src/components/LastOrders';
51
+ import { MultiCheckout } from './src/components/MultiCheckout'
52
+ import { MultiOrdersDetails } from './src/components/MultiOrdersDetails'
50
53
  import NavBar from './src/components/NavBar';
51
54
  import { BusinessTypeFilter } from './src/components/BusinessTypeFilter';
52
55
  import { BusinessController } from './src/components/BusinessController';
@@ -187,6 +190,8 @@ export {
187
190
  HelpAccountAndPayment,
188
191
  HelpGuide,
189
192
  HelpOrder,
193
+ MultiCheckout,
194
+ MultiOrdersDetails,
190
195
  NetworkError,
191
196
  NotFoundSource,
192
197
  OrderTypeSelector,
@@ -240,6 +245,7 @@ export {
240
245
  UserFormDetailsUI,
241
246
  WalletTransactionItem,
242
247
  Promotions,
248
+ MyOrders,
243
249
  ORDER_TYPES,
244
250
  USER_TYPE,
245
251
 
@@ -21,7 +21,8 @@ export const BusinessItemAccordion = (props: any) => {
21
21
  singleBusiness,
22
22
  handleClearProducts,
23
23
  handleClickCheckout,
24
- checkoutButtonDisabled
24
+ checkoutButtonDisabled,
25
+ isMultiCheckout
25
26
  } = props
26
27
 
27
28
  const [orderState] = useOrder();
@@ -139,7 +140,7 @@ export const BusinessItemAccordion = (props: any) => {
139
140
  )}
140
141
  </BIActions>
141
142
  </BIHeader>
142
- {!isActive && !isClosed && !!isProducts && (
143
+ {!isActive && !isClosed && !!isProducts && !isMultiCheckout && (
143
144
  <PriceContainer>
144
145
  <OText>{parsePrice(cart?.total)}</OText>
145
146
  {cart?.valid_products && (
@@ -7,10 +7,8 @@ export const BIContainer = styled.View`
7
7
  opacity: 1;
8
8
  border-radius: 7.6px;
9
9
  overflow: hidden;
10
- min-height: 120px;
11
10
  ${(props: any) => props.isClosed && css`
12
11
  opacity: 0.5;
13
- min-height: 60px;
14
12
  `}
15
13
  `
16
14
 
@@ -124,6 +124,7 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
124
124
  isSoldOut={product.inventoried && !product.quantity}
125
125
  product={product}
126
126
  businessId={businessId}
127
+ categoryState={categoryState}
127
128
  onProductClick={() => onProductClick(product)}
128
129
  productAddedToCartLength={currentCart?.products?.reduce((productsLength: number, Cproduct: any) => { return productsLength + (Cproduct?.id === product?.id ? Cproduct?.quantity : 0) }, 0)}
129
130
  handleUpdateProducts={handleUpdateProducts}
@@ -148,6 +149,7 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
148
149
  isSoldOut={product.inventoried && !product.quantity}
149
150
  product={product}
150
151
  businessId={businessId}
152
+ categoryState={categoryState}
151
153
  onProductClick={onProductClick}
152
154
  handleUpdateProducts={handleUpdateProducts}
153
155
  productAddedToCartLength={currentCart?.products?.reduce((productsLength: number, Cproduct: any) => { return productsLength + (Cproduct?.id === product?.id ? Cproduct?.quantity : 0) }, 0)}
@@ -236,10 +238,11 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
236
238
  <>
237
239
  {products.sort((a: any, b: any) => a.rank - b.rank).map((product: any, i: any) => (
238
240
  <SingleProductCard
239
- key={i}
241
+ key={`${product?.id}_${i}`}
240
242
  isSoldOut={product.inventoried && !product.quantity}
241
243
  businessId={businessId}
242
244
  product={product}
245
+ categoryState={categoryState}
243
246
  onProductClick={onProductClick}
244
247
  handleUpdateProducts={handleUpdateProducts}
245
248
  productAddedToCartLength={currentCart?.products?.reduce((productsLength: number, Cproduct: any) => { return productsLength + (Cproduct?.id === product?.id ? Cproduct?.quantity : 0) }, 0)}
@@ -102,6 +102,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
102
102
  const [isCategoryClicked, setCategoryClicked] = useState(false)
103
103
  const [subcategoriesSelected, setSubcategoriesSelected] = useState([])
104
104
 
105
+ const isCheckoutMultiBusinessEnabled: Boolean = configs?.checkout_multi_business_enabled?.value === '1'
105
106
  const currentCart: any = Object.values(orderState.carts).find((cart: any) => cart?.business?.slug === business?.slug) ?? {}
106
107
  const isOpenFiltProducts = isOpenSearchBar && !!searchValue
107
108
  const filtProductsHeight = Platform.OS === 'ios' ? 0 : 35
@@ -123,13 +124,19 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
123
124
  }
124
125
 
125
126
  const handleUpsellingPage = () => {
126
- onRedirect('CheckoutNavigator', {
127
- screen: 'CheckoutPage',
128
- cartUuid: currentCart?.uuid,
129
- businessLogo: logo,
130
- businessName: business?.name,
131
- cartTotal: currentCart?.total
132
- })
127
+ if (isCheckoutMultiBusinessEnabled) {
128
+ onRedirect('CheckoutNavigator', {
129
+ screen: 'MultiCheckout'
130
+ })
131
+ } else {
132
+ onRedirect('CheckoutNavigator', {
133
+ screen: 'CheckoutPage',
134
+ cartUuid: currentCart?.uuid,
135
+ businessLogo: logo,
136
+ businessName: business?.name,
137
+ cartTotal: currentCart?.total
138
+ })
139
+ }
133
140
  setOpenUpselling(false)
134
141
  }
135
142
 
@@ -249,6 +256,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
249
256
 
250
257
  {business?.categories?.length > 0 && isOpenFiltProducts && (
251
258
  <FiltProductsContainer
259
+ isIos={Platform.OS === 'ios'}
252
260
  style={{
253
261
  height: Dimensions.get('window').height - filtProductsHeight
254
262
  }}
@@ -278,6 +286,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
278
286
  currentCart={currentCart}
279
287
  setSubcategoriesSelected={setSubcategoriesSelected}
280
288
  onClickCategory={handleChangeCategory}
289
+ handleUpdateProducts={handleUpdateProducts}
281
290
  isFiltMode
282
291
  />
283
292
  </View>
@@ -252,7 +252,7 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
252
252
  }
253
253
  >
254
254
  <HeaderWrapper
255
- source={theme.images.general.homeHero}
255
+ source={theme.images.backgrounds.business_list_header}
256
256
  style={{ paddingTop: top + 20 }}>
257
257
  {!auth && (
258
258
  <TouchableOpacity onPress={() => navigation?.canGoBack() && navigation.goBack()} style={{ position: 'absolute', marginStart: 40, paddingVertical: 20 }}>
@@ -39,7 +39,8 @@ const CartUI = (props: any) => {
39
39
  handleChangeComment,
40
40
  commentState,
41
41
  onNavigationRedirect,
42
- handleRemoveOfferClick
42
+ handleRemoveOfferClick,
43
+ isMultiCheckout
43
44
  } = props
44
45
 
45
46
  const theme = useTheme();
@@ -59,6 +60,7 @@ const CartUI = (props: any) => {
59
60
 
60
61
  const isCartPending = cart?.status === 2
61
62
  const isCouponEnabled = validationFields?.fields?.checkout?.coupon?.enabled
63
+ const isCheckoutMultiBusinessEnabled: Boolean = configs?.checkout_multi_business_enabled?.value === '1'
62
64
 
63
65
  const business: any = (orderState?.carts && Object.values(orderState.carts).find((_cart: any) => _cart?.uuid === props.cartuuid)) ?? {}
64
66
  const businessId = business?.business_id ?? null
@@ -96,13 +98,19 @@ const CartUI = (props: any) => {
96
98
  const handleUpsellingPage = () => {
97
99
  setOpenUpselling(false)
98
100
  setCanOpenUpselling(false)
99
- props.onNavigationRedirect('CheckoutNavigator', {
100
- screen: 'CheckoutPage',
101
- cartUuid: cart?.uuid,
102
- businessLogo: cart?.business?.logo,
103
- businessName: cart?.business?.name,
104
- cartTotal: cart?.total
105
- })
101
+ if (isCheckoutMultiBusinessEnabled) {
102
+ props.onNavigationRedirect('CheckoutNavigator', {
103
+ screen: 'MultiCheckout'
104
+ })
105
+ } else {
106
+ props.onNavigationRedirect('CheckoutNavigator', {
107
+ screen: 'CheckoutPage',
108
+ cartUuid: cart?.uuid,
109
+ businessLogo: cart?.business?.logo,
110
+ businessName: cart?.business?.name,
111
+ cartTotal: cart?.total
112
+ })
113
+ }
106
114
  }
107
115
 
108
116
  const getIncludedTaxes = () => {
@@ -165,6 +173,7 @@ const CartUI = (props: any) => {
165
173
  handleChangeStore={() => setOpenChangeStore(true)}
166
174
  handleClickCheckout={() => setOpenUpselling(true)}
167
175
  checkoutButtonDisabled={(openUpselling && !canOpenUpselling) || cart?.subtotal < cart?.minimum || !cart?.valid_address}
176
+ isMultiCheckout={isMultiCheckout}
168
177
  >
169
178
  {cart?.products?.length > 0 && cart?.products.map((product: any, i: number) => (
170
179
  <ProductItemAccordion
@@ -409,31 +418,35 @@ const CartUI = (props: any) => {
409
418
  )}
410
419
  </OSBill>
411
420
  )}
412
- {cart?.valid_products ? (
413
- <CheckoutAction>
414
- <OButton
415
- text={(cart?.subtotal >= cart?.minimum || !cart?.minimum) && cart?.valid_address ? (
416
- !openUpselling !== canOpenUpselling ? t('CHECKOUT', 'Checkout') : t('LOADING', 'Loading')
417
- ) : !cart?.valid_address ? (
418
- `${t('OUT_OF_COVERAGE', 'Out of Coverage')}`
419
- ) : (
420
- `${t('MINIMUN_SUBTOTAL_ORDER', 'Minimum subtotal order:')} ${parsePrice(cart?.minimum)}`
421
- )}
422
- bgColor={(cart?.subtotal < cart?.minimum || !cart?.valid_address) ? theme.colors.secundary : theme.colors.primary}
423
- isDisabled={(openUpselling && !canOpenUpselling) || cart?.subtotal < cart?.minimum || !cart?.valid_address}
424
- borderColor={theme.colors.primary}
425
- imgRightSrc={null}
426
- textStyle={{ color: 'white', textAlign: 'center', flex: 1 }}
427
- onClick={() => setOpenUpselling(true)}
428
- style={{ width: '100%', flexDirection: 'row', justifyContent: 'center', borderRadius: 7.6, shadowOpacity: 0 }}
429
- />
430
- </CheckoutAction>
431
- ) : (
432
- <View style={{ alignItems: 'center', width: '100%' }}>
433
- <OText size={12} color={theme.colors.red} style={{ textAlign: 'center', marginTop: 5 }}>
434
- {t('WARNING_INVALID_PRODUCTS_CHECKOUT', 'To continue with your checkout, please remove from your cart the products that are not available.')}
435
- </OText>
436
- </View>
421
+ {!isMultiCheckout && (
422
+ <>
423
+ {cart?.valid_products ? (
424
+ <CheckoutAction>
425
+ <OButton
426
+ text={(cart?.subtotal >= cart?.minimum || !cart?.minimum) && cart?.valid_address ? (
427
+ !openUpselling !== canOpenUpselling ? t('CHECKOUT', 'Checkout') : t('LOADING', 'Loading')
428
+ ) : !cart?.valid_address ? (
429
+ `${t('OUT_OF_COVERAGE', 'Out of Coverage')}`
430
+ ) : (
431
+ `${t('MINIMUN_SUBTOTAL_ORDER', 'Minimum subtotal order:')} ${parsePrice(cart?.minimum)}`
432
+ )}
433
+ bgColor={(cart?.subtotal < cart?.minimum || !cart?.valid_address) ? theme.colors.secundary : theme.colors.primary}
434
+ isDisabled={(openUpselling && !canOpenUpselling) || cart?.subtotal < cart?.minimum || !cart?.valid_address}
435
+ borderColor={theme.colors.primary}
436
+ imgRightSrc={null}
437
+ textStyle={{ color: 'white', textAlign: 'center', flex: 1 }}
438
+ onClick={() => setOpenUpselling(true)}
439
+ style={{ width: '100%', flexDirection: 'row', justifyContent: 'center', borderRadius: 7.6, shadowOpacity: 0 }}
440
+ />
441
+ </CheckoutAction>
442
+ ) : (
443
+ <View style={{ alignItems: 'center', width: '100%' }}>
444
+ <OText size={12} color={theme.colors.red} style={{ textAlign: 'center', marginTop: 5 }}>
445
+ {t('WARNING_INVALID_PRODUCTS_CHECKOUT', 'To continue with your checkout, please remove from your cart the products that are not available.')}
446
+ </OText>
447
+ </View>
448
+ )}
449
+ </>
437
450
  )}
438
451
  </BusinessItemAccordion>
439
452
 
@@ -194,9 +194,9 @@ const FavoriteListUI = (props: FavoriteParams) => {
194
194
  ))
195
195
  )}
196
196
  {!favoriteList?.loading && favoriteList?.favorites?.length > 0 && (
197
- favoriteList.favorites.map((order: any) => (
197
+ favoriteList.favorites.map((order: any, i: number) => (
198
198
  <SingleOrderCard
199
- key={order?.id}
199
+ key={`${order?.id}_${i}`}
200
200
  order={order}
201
201
  getOrderStatus={getOrderStatus}
202
202
  onNavigationRedirect={onNavigationRedirect}
@@ -231,9 +231,9 @@ const FavoriteListUI = (props: FavoriteParams) => {
231
231
  ))
232
232
  )}
233
233
  {!favoriteList?.loading && favoriteList?.favorites?.length > 0 && (
234
- favoriteList.favorites.map((product: any) => (
234
+ favoriteList.favorites.map((product: any, i: number) => (
235
235
  <SingleProductCard
236
- key={product?.id}
236
+ key={`${product?.id}_${i}`}
237
237
  isSoldOut={product.inventoried && !product.quantity}
238
238
  product={product}
239
239
  onProductClick={() => {}}