Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Filter with next/dynamic and lazy import #2596

Merged
merged 6 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 0 additions & 101 deletions packages/core/src/components/search/Filter/Filter.tsx

This file was deleted.

34 changes: 34 additions & 0 deletions packages/core/src/components/search/Filter/FilterDesktop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
FilterFacetRange as UIFilterFacetRange,
FilterFacets as UIFilterFacets,
} from '@faststore/ui'
import { gql } from '@generated/gql'
import type { Filter_FacetsFragment } from '@generated/graphql'
import { useFormattedPrice } from 'src/sdk/product/useFormattedPrice'
import { useFilter } from 'src/sdk/search/useFilter'
Expand Down Expand Up @@ -110,4 +111,37 @@ function FilterDesktop({
)
}

export const fragment = gql(`
fragment Filter_facets on StoreFacet {
... on StoreFacetRange {
key
label

min {
selected
absolute
}

max {
selected
absolute
}

__typename
}
... on StoreFacetBoolean {
key
label
values {
label
value
selected
quantity
}

__typename
}
}
`)

export default FilterDesktop
47 changes: 38 additions & 9 deletions packages/core/src/components/search/Filter/FilterSlider.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,43 @@
import dynamic from 'next/dynamic'

import { useSearch } from '@faststore/sdk'
import {
Filter as UIFilter,
FilterFacetBoolean as UIFilterFacetBoolean,
FilterFacetBooleanItem as UIFilterFacetBooleanItem,
FilterFacetRange as UIFilterFacetRange,
FilterFacets as UIFilterFacets,
FilterSlider as UIFilterSlider,
} from '@faststore/ui'
import { useFormattedPrice } from 'src/sdk/product/useFormattedPrice'

import type {
FilterFacetBooleanItemProps as UIFilterFacetBooleanItemProps,
FilterFacetRangeProps as UIFilterFacetRangeProps,
FilterFacetsProps as UIFilterFacetsProps,
FilterProps as UIFilterProps,
FilterSliderProps as UIFilterSliderProps,
} from '@faststore/ui'

const UIFilter = dynamic<{ children: React.ReactNode } & UIFilterProps>(() =>
/* webpackChunkName: "UIFilter" */
import('@faststore/ui').then((mod) => mod.Filter)
)
const UIFilterFacetBoolean = dynamic<{ children: React.ReactNode }>(() =>
/* webpackChunkName: "UIFilterFacetBoolean" */
import('@faststore/ui').then((mod) => mod.FilterFacetBoolean)
)
const UIFilterFacetBooleanItem = dynamic<UIFilterFacetBooleanItemProps>(() =>
/* webpackChunkName: "UIFilterFacetBooleanItem" */
import('@faststore/ui').then((mod) => mod.FilterFacetBooleanItem)
)
const UIFilterFacetRange = dynamic<UIFilterFacetRangeProps>(() =>
/* webpackChunkName: "UIFilterFacetRange" */
import('@faststore/ui').then((mod) => mod.FilterFacetRange)
)
const UIFilterFacets = dynamic<
{ children: React.ReactNode } & UIFilterFacetsProps
>(() =>
/* webpackChunkName: "UIFilterFacets" */
import('@faststore/ui').then((mod) => mod.FilterFacets)
)
const UIFilterSlider = dynamic<UIFilterSliderProps>(() =>
/* webpackChunkName: "UIFilterSlider" */
import('@faststore/ui').then((mod) => mod.FilterSlider)
)

import type { Filter_FacetsFragment } from '@generated/graphql'

import type { useFilter } from 'src/sdk/search/useFilter'
Expand Down Expand Up @@ -87,7 +116,7 @@ function FilterSlider({
<UIFilter
testId={`mobile-${testId}`}
indicesExpanded={expanded}
onAccordionChange={(index) =>
onAccordionChange={(index: number) =>
dispatch({ type: 'toggleExpanded', payload: index })
}
>
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components/search/Filter/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { default } from './Filter'
export { default as FilterDesktop } from './FilterDesktop'
export { default as FilterSlider } from './FilterSlider'
Original file line number Diff line number Diff line change
@@ -1,18 +1,34 @@
import { lazy } from 'react'
import {
Button as UIButton,
Icon as UIIcon,
LinkButton as UILinkButton,
Skeleton as UISkeleton,
Icon as UIIcon,
} from '@faststore/ui'

import ProductCard from 'src/components/product/ProductCard'
import FilterDesktop from 'src/components/search/Filter/FilterDesktop'
import EmptyGallery from './EmptyGallery'
import dynamic from 'next/dynamic'

const FilterSlider = lazy(
() => import('src/components/search/Filter/FilterSlider')
const ProductCard = dynamic(
() =>
/* webpackChunkName: "ProductCard" */
import('src/components/product/ProductCard')
)
const EmptyGallery = dynamic(
() =>
/* webpackChunkName: "EmptyGallery" */
import('./EmptyGallery')
)

const FilterDesktop = dynamic(
() =>
/* webpackChunkName: "FilterDesktop" */
import('src/components/search/Filter/FilterDesktop')
)
const FilterSlider = dynamic(
() =>
/* webpackChunkName: "FilterSlider" */
import('src/components/search/Filter/FilterSlider')
)

export const ProductGalleryDefaultComponents = {
MobileFilterButton: UIButton,
FilterIcon: UIIcon,
Expand Down
62 changes: 48 additions & 14 deletions packages/core/src/components/ui/ProductGallery/ProductGallery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import type { MouseEvent } from 'react'
import { Suspense, lazy } from 'react'

import { useUI } from '@faststore/ui'
import Filter from 'src/components/search/Filter'
import Sort from 'src/components/search/Sort'
import FilterSkeleton from 'src/components/skeletons/FilterSkeleton'
import ProductGridSkeleton from 'src/components/skeletons/ProductGridSkeleton'

import dynamic from 'next/dynamic'

import { ProductCardProps } from 'src/components/product/ProductCard'
import { FilterSliderProps } from 'src/components/search/Filter/FilterSlider'
import { SortProps } from 'src/components/search/Sort/Sort'
Expand All @@ -21,8 +21,18 @@ import {
import { useProductsPrefetch } from 'src/sdk/product/useProductsPrefetch'
import { useDelayedFacets } from 'src/sdk/search/useDelayedFacets'
import { useDelayedPagination } from 'src/sdk/search/useDelayedPagination'
import { useFilter } from 'src/sdk/search/useFilter'
import useScreenResize from 'src/sdk/ui/useScreenResize'

const ProductGalleryPage = lazy(() => import('./ProductGalleryPage'))
const FilterSkeleton = dynamic(
() =>
import(
/* webpackChunkName: "FilterSkeleton" */
'src/components/skeletons/FilterSkeleton'
)
)

const GalleryPageSkeleton = <ProductGridSkeleton loading />

export interface ProductGalleryProps {
Expand Down Expand Up @@ -69,7 +79,7 @@ function ProductGallery({
totalCount,
searchTermLabel,
totalCountLabel,
filter,
filter: filterCmsData,
previousPageButton,
loadMorePageButton,
sortBySelector,
Expand All @@ -84,20 +94,25 @@ function ProductGallery({
PrevIcon,
ResultsCountSkeleton,
SortSkeleton,
__experimentalFilterDesktop: FilterDesktop,
__experimentalFilterSlider: FilterSlider,
} = useOverrideComponents<'ProductGallery'>()

const { openFilter } = useUI()
const { openFilter, filter: displayFilter } = useUI()
const { pages, addNextPage, addPrevPage, itemsPerPage } = useSearch()
const context = usePage<SearchPageContext | PLPContext>()
const data = context?.data
const facets = useDelayedFacets(data) ?? []
const { next, prev } = useDelayedPagination(totalCount)

const { isDesktop } = useScreenResize()

useProductsPrefetch(prev ? prev.cursor : null)
useProductsPrefetch(next ? next.cursor : null)

const hasFacetsLoaded = Boolean(data?.search?.facets)
const hasProductsLoaded = Boolean(data?.search?.products)
const filter = useFilter(facets)

return (
<section data-testid="product-gallery" data-fs-product-listing>
Expand All @@ -115,13 +130,32 @@ function ProductGallery({
data-fs-product-listing-content-grid
data-fs-content="product-gallery"
>
<div data-fs-product-listing-filters>
<FilterSkeleton loading={!hasFacetsLoaded}>
{hasFacetsLoaded && facets?.length > 0 && (
<Filter facets={facets} filter={filter} />
)}
</FilterSkeleton>
</div>
{isDesktop && (
<div data-fs-product-listing-filters>
<FilterSkeleton loading={!hasFacetsLoaded}>
{hasFacetsLoaded && facets?.length > 0 && (
<div className="hidden-mobile">
<FilterDesktop.Component
{...FilterDesktop.props}
{...filter}
title={filterCmsData?.title}
/>
</div>
)}
</FilterSkeleton>
</div>
)}
{!isDesktop && displayFilter && (
eduardoformiga marked this conversation as resolved.
Show resolved Hide resolved
<div data-fs-product-listing-filters>
<FilterSlider.Component
{...FilterSlider.props}
{...filter}
title={filterCmsData?.title}
clearButtonLabel={filterCmsData?.mobileOnly?.clearButtonLabel}
applyButtonLabel={filterCmsData?.mobileOnly?.applyButtonLabel}
/>
</div>
)}
<div data-fs-product-listing-results-count data-count={totalCount}>
<ResultsCountSkeleton.Component
data-fs-product-listing-results-count-skeleton
Expand Down Expand Up @@ -168,11 +202,11 @@ function ProductGallery({
height={16}
{...FilterIcon.props}
name={
filter?.mobileOnly?.filterButton?.icon?.icon ??
filterCmsData?.mobileOnly?.filterButton?.icon?.icon ??
FilterIcon.props.name
}
aria-label={
filter?.mobileOnly?.filterButton?.icon?.alt ??
filterCmsData?.mobileOnly?.filterButton?.icon?.alt ??
FilterIcon.props['aria-label']
}
/>
Expand All @@ -183,7 +217,7 @@ function ProductGallery({
// This decision can be reviewed later if needed
onClick={openFilter}
>
{filter?.mobileOnly?.filterButton?.label}
{filterCmsData?.mobileOnly?.filterButton?.label}
</MobileFilterButton.Component>
)}
</FilterButtonSkeleton.Component>
Expand Down
Loading