mirror of
https://github.com/vercel/commerce.git
synced 2025-07-23 04:36:49 +00:00
✨ feat: filter products from menu filter (in header)
:%s
This commit is contained in:
@@ -7,9 +7,11 @@ interface Props {
|
|||||||
categories: { name: string, slug?: string, code?: string }[],
|
categories: { name: string, slug?: string, code?: string }[],
|
||||||
type: string,
|
type: string,
|
||||||
onChange: (value: string, type: string, isSellect?: boolean) => void
|
onChange: (value: string, type: string, isSellect?: boolean) => void
|
||||||
|
isSingleSelect?: boolean
|
||||||
|
singleSelectedValue?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const MenuFilter = ({ heading, categories, type, onChange }: Props) => {
|
const MenuFilter = ({ heading, categories, type, onChange, singleSelectedValue, isSingleSelect }: Props) => {
|
||||||
function handleChange(value: string, isSellect: boolean) {
|
function handleChange(value: string, isSellect: boolean) {
|
||||||
onChange(value, type, isSellect)
|
onChange(value, type, isSellect)
|
||||||
}
|
}
|
||||||
@@ -25,6 +27,7 @@ const MenuFilter = ({ heading, categories, type, onChange }: Props) => {
|
|||||||
type={type}
|
type={type}
|
||||||
value={item.slug || item.code || ''}
|
value={item.slug || item.code || ''}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
isActive={isSingleSelect && (item.slug || item.code) === singleSelectedValue}
|
||||||
/>)
|
/>)
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
|
@@ -8,12 +8,18 @@ interface Props {
|
|||||||
name: string,
|
name: string,
|
||||||
value: string,
|
value: string,
|
||||||
type: string,
|
type: string,
|
||||||
|
isActive?: boolean
|
||||||
onChange: (value: string, isSellect: boolean) => void
|
onChange: (value: string, isSellect: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const MenuFilterItem = ({ name, value, type, onChange }: Props) => {
|
const MenuFilterItem = ({ name, value, type, isActive, onChange }: Props) => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const [isSelected, setIsSelected] = useState<boolean>()
|
const [isSelected, setIsSelected] = useState<boolean>()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setIsSelected(isActive)
|
||||||
|
}, [isActive])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const rs = (router.query[type] || []).includes(value)
|
const rs = (router.query[type] || []).includes(value)
|
||||||
setIsSelected(rs)
|
setIsSelected(rs)
|
||||||
|
@@ -38,7 +38,7 @@ const MenuNavigationProductList = ({ visible, onClose }: Props) => {
|
|||||||
const { collections, loading: collectionLoading } = useGetAllCollection()
|
const { collections, loading: collectionLoading } = useGetAllCollection()
|
||||||
const [brandQuery, setBrandQuery] = useState<string[]>([])
|
const [brandQuery, setBrandQuery] = useState<string[]>([])
|
||||||
const [featuredQuery, setFeaturedQuery] = useState<string[]>([])
|
const [featuredQuery, setFeaturedQuery] = useState<string[]>([])
|
||||||
const [categoryQuery, setCategoryQuery] = useState<string[]>([])
|
const [categoryQuery, setCategoryQuery] = useState<string>()
|
||||||
const [sortValue, setSortValue] = useState<string>();
|
const [sortValue, setSortValue] = useState<string>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -48,11 +48,18 @@ const MenuNavigationProductList = ({ visible, onClose }: Props) => {
|
|||||||
}
|
}
|
||||||
}, [router.query])
|
}, [router.query])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const rs = router.query[QUERY_KEY.CATEGORY] as string
|
||||||
|
if (rs) {
|
||||||
|
setCategoryQuery(rs)
|
||||||
|
}
|
||||||
|
}, [router.query])
|
||||||
|
|
||||||
function onSubmit() {
|
function onSubmit() {
|
||||||
let newURL = `${ROUTE.PRODUCTS}?`
|
let newURL = `${ROUTE.PRODUCTS}?`
|
||||||
|
|
||||||
if (categoryQuery.length > 0) {
|
if (categoryQuery) {
|
||||||
newURL += `&${QUERY_KEY.CATEGORY}=${categoryQuery.join(",")}`
|
newURL += `&${QUERY_KEY.CATEGORY}=${categoryQuery}`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (brandQuery.length > 0) {
|
if (brandQuery.length > 0) {
|
||||||
@@ -74,24 +81,33 @@ const MenuNavigationProductList = ({ visible, onClose }: Props) => {
|
|||||||
setSortValue(value)
|
setSortValue(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onFilterOptionChange = (value: string, type: string, isSelect: boolean = true) => {
|
const onCategoryChange = (value: string, isSelect: boolean) => {
|
||||||
let rs = [...categoryQuery]
|
|
||||||
let setDataFunction = setCategoryQuery
|
|
||||||
|
|
||||||
if (type === CODE_FACET_BRAND) {
|
|
||||||
rs = [...brandQuery]
|
|
||||||
setDataFunction = setBrandQuery
|
|
||||||
} else if (type === CODE_FACET_FEATURED) {
|
|
||||||
rs = [...featuredQuery]
|
|
||||||
setDataFunction = setFeaturedQuery
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isSelect) {
|
if (isSelect) {
|
||||||
rs.push(value)
|
setCategoryQuery(value)
|
||||||
} else {
|
} else {
|
||||||
rs = rs.filter(item => item !== value)
|
setCategoryQuery('')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onFilterOptionChange = (value: string, type: string, isSelect: boolean = true) => {
|
||||||
|
if (type === QUERY_KEY.CATEGORY) {
|
||||||
|
onCategoryChange(value, isSelect)
|
||||||
|
} else {
|
||||||
|
let rs = [...featuredQuery]
|
||||||
|
let setDataFunction = setFeaturedQuery
|
||||||
|
|
||||||
|
if (type === CODE_FACET_BRAND) {
|
||||||
|
rs = [...brandQuery]
|
||||||
|
setDataFunction = setBrandQuery
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSelect) {
|
||||||
|
rs.push(value)
|
||||||
|
} else {
|
||||||
|
rs = rs.filter(item => item !== value)
|
||||||
|
}
|
||||||
|
setDataFunction(rs)
|
||||||
}
|
}
|
||||||
setDataFunction(rs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -103,8 +119,16 @@ const MenuNavigationProductList = ({ visible, onClose }: Props) => {
|
|||||||
<h3>FILTER</h3>
|
<h3>FILTER</h3>
|
||||||
<div onClick={onClose}><IconHide /></div>
|
<div onClick={onClose}><IconHide /></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{collectionLoading && <SkeletonParagraph rows={5} />}
|
{collectionLoading && <SkeletonParagraph rows={5} />}
|
||||||
<MenuFilter categories={collections} heading="Categories" type={QUERY_KEY.CATEGORY} onChange={onFilterOptionChange} />
|
<MenuFilter categories={collections}
|
||||||
|
heading="Categories"
|
||||||
|
type={QUERY_KEY.CATEGORY}
|
||||||
|
onChange={onFilterOptionChange}
|
||||||
|
singleSelectedValue={categoryQuery}
|
||||||
|
isSingleSelect={true}
|
||||||
|
/>
|
||||||
|
|
||||||
{facetsLoading && <>
|
{facetsLoading && <>
|
||||||
<SkeletonParagraph rows={5} />
|
<SkeletonParagraph rows={5} />
|
||||||
<SkeletonParagraph rows={5} />
|
<SkeletonParagraph rows={5} />
|
||||||
@@ -118,7 +142,7 @@ const MenuNavigationProductList = ({ visible, onClose }: Props) => {
|
|||||||
onChange={onFilterOptionChange}
|
onChange={onFilterOptionChange}
|
||||||
/>)
|
/>)
|
||||||
}
|
}
|
||||||
<MenuSort heading="SORT BY" onChange={onSortChange} value={sortValue} options={OPTIONS_SORT_PRODUCT}/>
|
<MenuSort heading="SORT BY" onChange={onSortChange} value={sortValue} options={OPTIONS_SORT_PRODUCT} />
|
||||||
<div className={s.foot}>
|
<div className={s.foot}>
|
||||||
<ButtonCommon size="large" onClick={onSubmit}>{LANGUAGE.BUTTON_LABEL.CONFIRM}</ButtonCommon>
|
<ButtonCommon size="large" onClick={onSubmit}>{LANGUAGE.BUTTON_LABEL.CONFIRM}</ButtonCommon>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -6,7 +6,6 @@ import useSWR from 'swr'
|
|||||||
|
|
||||||
const useSearchProducts = (options?: QuerySearchArgs) => {
|
const useSearchProducts = (options?: QuerySearchArgs) => {
|
||||||
const { data, isValidating, ...rest } = useSWR<GetAllProductsQuery>([getAllProductsQuery, options], gglFetcher)
|
const { data, isValidating, ...rest } = useSWR<GetAllProductsQuery>([getAllProductsQuery, options], gglFetcher)
|
||||||
console.log("on search ", data?.search.totalItems, options, data?.search.items)
|
|
||||||
|
|
||||||
return { products: data?.search.items.map((item) => normalizeSearchResult(item)), totalItems: data?.search.totalItems, loading: isValidating, ...rest }
|
return { products: data?.search.items.map((item) => normalizeSearchResult(item)), totalItems: data?.search.totalItems, loading: isValidating, ...rest }
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user