Skip to content
Open
Changes from 3 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
69 changes: 47 additions & 22 deletions src/components/sections/ProductListing/AlgoliaProductsListing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import { useSearchParams } from "next/navigation"
import { getFacedFilters } from "@/lib/helpers/get-faced-filters"
import { PRODUCT_LIMIT } from "@/const"
import { ProductListingSkeleton } from "@/components/organisms/ProductListingSkeleton/ProductListingSkeleton"
import { useEffect, useState } from "react"
import { useEffect, useMemo, useState } from "react"
import { listProducts } from "@/lib/data/products"
import { getProductPrice } from "@/lib/helpers/get-product-price"
import { SkeletonProductCard } from "@/components/organisms/ProductCard/SkeletonProductCard"

export const AlgoliaProductsListing = ({
category_id,
Expand All @@ -31,10 +32,11 @@ export const AlgoliaProductsListing = ({
seller_handle?: string
currency_code: string
}) => {
const searchParamas = useSearchParams()
const searchParams = useSearchParams()

const facetFilters: string = getFacedFilters(searchParamas)
const query: string = searchParamas.get("query") || ""
const facetFilters: string = getFacedFilters(searchParams)
const query: string = searchParams.get("query") || ""
const page: number = +(searchParams.get("page") || 1)

const filters = `${
seller_handle
Expand All @@ -52,7 +54,12 @@ export const AlgoliaProductsListing = ({

return (
<InstantSearchNext searchClient={client} indexName="products">
<Configure query={query} filters={filters} />
<Configure
query={query}
filters={filters}
hitsPerPage={PRODUCT_LIMIT}
page={page - 1}
/>
<ProductsListing
locale={locale}
currency_code={currency_code}
Expand All @@ -74,13 +81,19 @@ const ProductsListing = ({
const [apiProducts, setApiProducts] = useState<
HttpTypes.StoreProduct[] | null
>(null)
const [isLoadingProducts, setIsLoadingProducts] = useState(false)
const { items, results } = useHits()

const searchParamas = useSearchParams()
const searchParams = useSearchParams()

const itemsKey = useMemo(
() => items.map((item) => item.objectID).join(","),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there any chance for items to be undefined?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useHits returns empty array if there's no items

[items]
)

async function handleSetProducts() {
try {
setApiProducts(null)
setIsLoadingProducts(true)
const { response } = await listProducts({
countryCode: locale,
queryParams: {
Expand All @@ -99,34 +112,40 @@ const ProductsListing = ({
)
} catch (error) {
setApiProducts(null)
} finally {
setIsLoadingProducts(false)
}
}

useEffect(() => {
handleSetProducts()
}, [items.length])
if (items.length > 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there any chance for items to be undefined?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useHits returns empty array if there's no items

handleSetProducts()
} else {
setApiProducts([])
setIsLoadingProducts(false)
}
}, [itemsKey])

if (!results?.processingTimeMS) return <ProductListingSkeleton />

const page: number = +(searchParamas.get("page") || 1)
const isLoading = isLoadingProducts && items.length > 0

const filteredProducts = items.filter((pr) =>
apiProducts?.some((p: any) => p.id === pr.objectID)
apiProducts?.some((p) => p.id === pr.objectID)
)

const products = filteredProducts
.filter((pr) =>
apiProducts?.some(
(p: any) => p.id === pr.objectID && filterProductsByCurrencyCode(p)
)
const products = filteredProducts.filter((pr) =>
apiProducts?.some(
(p) => p.id === pr.objectID && filterProductsByCurrencyCode(p)
)
.slice((page - 1) * PRODUCT_LIMIT, page * PRODUCT_LIMIT)
)

const count = filteredProducts?.length || 0
const pages = Math.ceil(count / PRODUCT_LIMIT) || 1
const count = results?.nbHits || 0
const pages = results?.nbPages || 1

function filterProductsByCurrencyCode(product: HttpTypes.StoreProduct) {
const minPrice = searchParamas.get("min_price")
const maxPrice = searchParamas.get("max_price")
const minPrice = searchParams.get("min_price")
const maxPrice = searchParams.get("max_price")

if ([minPrice, maxPrice].some((price) => typeof price === "string")) {
const variantsWithCurrencyCode = product?.variants?.filter(
Expand Down Expand Up @@ -174,7 +193,13 @@ const ProductsListing = ({
<AlgoliaProductSidebar />
</div>
<div className="w-full">
{!items.length ? (
{isLoading ? (
<div className="flex flex-wrap gap-4">
{Array.from({ length: PRODUCT_LIMIT }).map((_, idx) => (
<SkeletonProductCard key={idx} />
))}
</div>
) : !items.length ? (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about extracting 'no results view' and products view to separate component to remove this chained ternary operator?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extracted the views. Also moved pagination component, it's now centered relative to the right section (not full page width like before), according to the design

<div className="text-center w-full my-10">
<h2 className="uppercase text-primary heading-lg">no results</h2>
<p className="mt-4 text-lg">
Expand Down