Skip to content

Commit

Permalink
fix: fixing on seller wrapper when there is no seller available
Browse files Browse the repository at this point in the history
refactor: refactoring and adding some custom hooks
  • Loading branch information
arturmagalhaesjr committed Nov 30, 2023
1 parent 1e360ac commit 41c9720
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 90 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

### Fixed

- Fixing on seller wrapper when there is no seller available

## [1.28.1] - 2023-11-06

### Fixed
Expand Down
91 changes: 1 addition & 90 deletions react/SellerWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,92 +1,3 @@
import React, { useCallback, useEffect, useRef, useState } from 'react'
import { useProduct, useProductDispatch } from 'vtex.product-context'
import { useCssHandles } from 'vtex.css-handles'
import type { Item } from 'vtex.product-context/react/ProductTypes'

import useSeller from './hooks/useSeller'

const CSS_HANDLES = ['sellerWrapper', 'loadingSeller']
const SELECT_ITEM_EVENT = 'SET_SELECTED_ITEM'

type SellerWrapperProps = {
children: React.ReactNode
}

const SellerWrapper = ({ children }: SellerWrapperProps) => {
const { seller } = useSeller()
const dispatch = useProductDispatch()
const { selectedItem, product } = useProduct() ?? {}
const latestItem = useRef((null as unknown) as Item)
const handles = useCssHandles(CSS_HANDLES)
const [loadingSeller, setLoadingSeller] = useState(true)

const addSellerDefaultToItem = useCallback(
itemSeller => ({
...itemSeller,
sellerDefault: seller?.includes(itemSeller.sellerId),
}),
[seller]
)

useEffect(() => {
const shouldDispatchSelectItem =
!!seller && !!product && !!selectedItem && !!dispatch

if (!shouldDispatchSelectItem) return
const newCurrentSelectedItem =
product?.items?.find(item =>
item.sellers?.find(
itemSeller =>
seller?.includes(itemSeller.sellerId) &&
itemSeller.commertialOffer.AvailableQuantity > 0
)
) ?? ({} as Item)

if (!newCurrentSelectedItem) {
return
}

const { sellers } = newCurrentSelectedItem
const selectedItemWithSeller = {
...newCurrentSelectedItem,
sellers: sellers.map(addSellerDefaultToItem),
}

if (
JSON.stringify(latestItem.current) ===
JSON.stringify(selectedItemWithSeller)
) {
return
}

dispatch?.({
type: SELECT_ITEM_EVENT,
args: {
item: selectedItemWithSeller,
},
})

setLoadingSeller(false)

latestItem.current = selectedItemWithSeller
}, [
seller,
product,
selectedItem,
dispatch,
addSellerDefaultToItem,
latestItem,
])

return (
<div
className={`${handles.sellerWrapper} ${
loadingSeller ? handles.loadingSeller : ''
}`}
>
{children}
</div>
)
}
import SellerWrapper from './components/SellerWrapper/SellerWrapper'

export default SellerWrapper
30 changes: 30 additions & 0 deletions react/components/SellerWrapper/SellerWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React, { useEffect } from 'react'
import { useCssHandles } from 'vtex.css-handles'
import { useProduct } from 'vtex.product-context'

import { useSelectSeller } from '../../hooks/useSelectSeller'

type SellerWrapperProps = {
children: React.ReactNode
}

const CSS_HANDLES = ['sellerWrapper', 'sellerWrapperNoSeller']

const SellerWrapper = ({ children }: SellerWrapperProps) => {
const handles = useCssHandles(CSS_HANDLES)
const { currentSelectedItem, selectSeller } = useSelectSeller()

const { selectedItem } = useProduct() ?? {}

useEffect(() => {
selectSeller()
}, [selectedItem, selectSeller])

const className = currentSelectedItem
? `${handles.sellerWrapper}`
: `${handles.sellerWrapper} ${handles.sellerWrapperNoSeller}`

return <div className={className}>{children}</div>
}

export default SellerWrapper
67 changes: 67 additions & 0 deletions react/hooks/useSelectSeller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { useProduct, useProductDispatch } from 'vtex.product-context'
import { useCallback, useMemo, useRef, useState } from 'react'
import type { Item } from 'vtex.product-context/react/ProductTypes'

import useSeller from './useSeller'

const SELECT_ITEM_EVENT = 'SET_SELECTED_ITEM'

export const useSelectSeller = () => {
const { seller } = useSeller()
const { product } = useProduct() ?? {}
const latestItem = useRef((null as unknown) as Item)
const [loading, setLoading] = useState(true)
const productDispatch = useProductDispatch()

const addSellerDefaultToItem = useCallback(
itemSeller => ({
...itemSeller,
sellerDefault: seller?.includes(itemSeller.sellerId),
}),
[seller]
)

const currentSelectedItem = useMemo(
() =>
product?.items?.find(item =>
item.sellers?.find(
itemSeller =>
seller?.includes(itemSeller.sellerId) &&
itemSeller.commertialOffer.AvailableQuantity > 0
)
) ?? null,

[seller, product]
)

const selectSeller = () => {
if (!currentSelectedItem) {
return
}

setLoading(true)
const { sellers } = (currentSelectedItem as unknown) as Item
const selectedItemWithSeller = {
...((currentSelectedItem as unknown) as Item),
sellers: sellers.map(addSellerDefaultToItem),
}

if (
JSON.stringify(latestItem.current) ===
JSON.stringify(selectedItemWithSeller)
) {
return
}

productDispatch?.({
type: SELECT_ITEM_EVENT,
args: {
item: selectedItemWithSeller,
},
})
setLoading(false)
latestItem.current = selectedItemWithSeller
}

return { loading, seller, currentSelectedItem, selectSeller }
}
File renamed without changes.

0 comments on commit 41c9720

Please sign in to comment.