From 09118b855ff42271003d119dc988034e49f9fad6 Mon Sep 17 00:00:00 2001 From: Victor Gerbrands Date: Thu, 4 Jul 2024 23:01:13 +0200 Subject: [PATCH] fix: sort 100 products --- src/lib/data/products.ts | 48 ++++++++++++++++ src/lib/util/sort-products-by-price.ts | 44 -------------- src/lib/util/sort-products.ts | 57 +++++++++++++++++++ .../components/filter-radio-group/index.tsx | 1 - .../store/templates/paginated-products.tsx | 17 ++---- 5 files changed, 110 insertions(+), 57 deletions(-) delete mode 100644 src/lib/util/sort-products-by-price.ts create mode 100644 src/lib/util/sort-products.ts diff --git a/src/lib/data/products.ts b/src/lib/data/products.ts index 10358a37b..d0a01846d 100644 --- a/src/lib/data/products.ts +++ b/src/lib/data/products.ts @@ -2,6 +2,8 @@ import { sdk } from "@lib/config" import { HttpTypes } from "@medusajs/types" import { cache } from "react" import { getRegion } from "./regions" +import { SortOptions } from "@modules/store/components/refinement-list/sort-products" +import { sortProducts } from "@lib/util/sort-products" export const getProductsById = cache(async function ({ ids, @@ -85,3 +87,49 @@ export const getProductsList = cache(async function ({ } }) }) + +export const getProductsListWithSort = cache(async function ({ + page = 0, + queryParams, + sortBy = "created_at", + countryCode, +}: { + page?: number + queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductParams + sortBy?: SortOptions + countryCode: string +}): Promise<{ + response: { products: HttpTypes.StoreProduct[]; count: number } + nextPage: number | null + queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductParams +}> { + const limit = queryParams?.limit || 12 + + const { + response: { products, count }, + } = await getProductsList({ + pageParam: 0, + queryParams: { + ...queryParams, + limit: 100, + }, + countryCode, + }) + + const sortedProducts = sortProducts(products, sortBy) + + const pageParam = (page - 1) * limit + + const nextPage = count > pageParam + limit ? pageParam + limit : null + + const paginatedProducts = sortedProducts.slice(pageParam, pageParam + limit) + + return { + response: { + products: paginatedProducts, + count, + }, + nextPage, + queryParams, + } +}) diff --git a/src/lib/util/sort-products-by-price.ts b/src/lib/util/sort-products-by-price.ts deleted file mode 100644 index 29a67bf4c..000000000 --- a/src/lib/util/sort-products-by-price.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { HttpTypes } from "@medusajs/types" - -interface PricedVariant extends HttpTypes.StoreProductVariant { - calculated_price: { - calculated_amount: number - } -} - -interface PricedProduct extends HttpTypes.StoreProduct { - variants: PricedVariant[] - _minPrice: number -} - -/** - * Helper function to sort products by price until the store API supports sorting by price - * @param products - * @param order - * @returns products sorted by price - */ -export function sortProductsByPrice( - products: HttpTypes.StoreProduct[], - order: "asc" | "desc" -): PricedProduct[] { - const pricedProducts = products as PricedProduct[] - - // Precompute the minimum price for each product - pricedProducts.forEach((product) => { - if (product.variants && product.variants.length > 0) { - product._minPrice = Math.min( - ...product.variants.map( - (variant) => variant?.calculated_price?.calculated_amount - ) - ) - } else { - product._minPrice = Infinity - } - }) - - // Sort products based on the precomputed minimum prices - return pricedProducts.sort((a, b) => { - const diff = a._minPrice - b._minPrice - return order === "asc" ? diff : -diff - }) -} diff --git a/src/lib/util/sort-products.ts b/src/lib/util/sort-products.ts new file mode 100644 index 000000000..2b996cccc --- /dev/null +++ b/src/lib/util/sort-products.ts @@ -0,0 +1,57 @@ +import { HttpTypes } from "@medusajs/types" +import { SortOptions } from "@modules/store/components/refinement-list/sort-products" + +interface PricedVariant extends HttpTypes.StoreProductVariant { + calculated_price: { + calculated_amount: number + } +} + +interface PricedProduct extends HttpTypes.StoreProduct { + variants: PricedVariant[] + _minPrice: number +} + +/** + * Helper function to sort products by price until the store API supports sorting by price + * @param products + * @param sortBy + * @returns products sorted by price + */ +export function sortProducts( + products: HttpTypes.StoreProduct[], + sortBy: SortOptions +): PricedProduct[] { + let sortedProducts = products as PricedProduct[] + + if (["price_asc", "price_desc"].includes(sortBy)) { + // Precompute the minimum price for each product + sortedProducts.forEach((product) => { + if (product.variants && product.variants.length > 0) { + product._minPrice = Math.min( + ...product.variants.map( + (variant) => variant?.calculated_price?.calculated_amount + ) + ) + } else { + product._minPrice = Infinity + } + }) + + // Sort products based on the precomputed minimum prices + sortedProducts.sort((a, b) => { + const diff = a._minPrice - b._minPrice + return sortBy === "price_asc" ? diff : -diff + }) + } + + if (sortBy === "created_at") { + sortedProducts.sort((a, b) => { + return ( + new Date(b.created_at!).getTime() - new Date(a.created_at!).getTime() + ) + }) + } + + return sortedProducts +} diff --git a/src/modules/common/components/filter-radio-group/index.tsx b/src/modules/common/components/filter-radio-group/index.tsx index a76863f4e..dc70edeb4 100644 --- a/src/modules/common/components/filter-radio-group/index.tsx +++ b/src/modules/common/components/filter-radio-group/index.tsx @@ -1,6 +1,5 @@ import { EllipseMiniSolid } from "@medusajs/icons" import { Label, RadioGroup, Text, clx } from "@medusajs/ui" -import { ChangeEvent, MouseEventHandler } from "react" type FilterRadioGroupProps = { title: string diff --git a/src/modules/store/templates/paginated-products.tsx b/src/modules/store/templates/paginated-products.tsx index 43a5ee708..7d3abd748 100644 --- a/src/modules/store/templates/paginated-products.tsx +++ b/src/modules/store/templates/paginated-products.tsx @@ -1,6 +1,5 @@ -import { getProductsList } from "@lib/data/products" +import { getProductsListWithSort } from "@lib/data/products" import { getRegion } from "@lib/data/regions" -import { sortProductsByPrice } from "@lib/util/sort-products-by-price" import ProductPreview from "@modules/products/components/product-preview" import { Pagination } from "@modules/store/components/pagination" import { SortOptions } from "@modules/store/components/refinement-list/sort-products" @@ -31,7 +30,7 @@ export default async function PaginatedProducts({ countryCode: string }) { const queryParams: PaginatedProductsParams = { - limit: PRODUCT_LIMIT, + limit: 100, } if (collectionId) { @@ -58,19 +57,13 @@ export default async function PaginatedProducts({ let { response: { products, count }, - } = await getProductsList({ - pageParam: page, + } = await getProductsListWithSort({ + page, queryParams, + sortBy, countryCode, }) - if (sortBy && ["price_asc", "price_desc"].includes(sortBy)) { - products = sortProductsByPrice( - products, - sortBy === "price_asc" ? "asc" : "desc" - ) - } - const totalPages = Math.ceil(count / PRODUCT_LIMIT) return (