Skip to content

Commit

Permalink
feat: add enhanced use products (#207)
Browse files Browse the repository at this point in the history
* feat: add use product enhanced hooks

- adds a hook that gives back the main image and other files associated with the products returned

* chore: add changeset

- adds a hook that gives back the main image and other files associated with the products returned

* fix: remove empty object on cart clear

* chore: add changeset

- adds a hook that gives back the main image and other files associated with the products returned

* feat: use latest hooks

- adds a hook that gives back the main image and other files associated with the products returned
  • Loading branch information
field123 authored May 1, 2024
1 parent dfc34e6 commit 091eebd
Show file tree
Hide file tree
Showing 11 changed files with 150 additions and 37 deletions.
5 changes: 5 additions & 0 deletions .changeset/cuddly-camels-swim.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@elasticpath/d2c-schematics": minor
---

remove empty object on cart clear
5 changes: 5 additions & 0 deletions .changeset/great-pumas-obey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@elasticpath/react-shopper-hooks": minor
---

- adds a hook that gives back the main image and other files associated with the products returned
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,7 @@ export function CheckoutProvider({ children }: CheckoutProviderProps) {
{
onSuccess: async (data) => {
setConfirmationData(data);
state?.id &&
(await mutateClearCart({
cartId: state.id,
}));
await mutateClearCart();
},
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,7 @@ export function StripeCheckoutProvider({ children }: CheckoutProviderProps) {
{
onSuccess: async (data) => {
setConfirmationData(data);
state?.id &&
(await mutateClearCart({
cartId: state.id,
}));
await mutateClearCart();
},
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,7 @@ export function CheckoutProvider({ children }: CheckoutProviderProps) {
{
onSuccess: async (data) => {
setConfirmationData(data);
state?.id &&
(await mutateClearCart({
cartId: state.id,
}));
await mutateClearCart();
},
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,7 @@ export function StripeCheckoutProvider({ children }: CheckoutProviderProps) {
{
onSuccess: async (data) => {
setConfirmationData(data);
state?.id &&
(await mutateClearCart({
cartId: state.id,
}));
await mutateClearCart();
},
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,7 @@ export function CheckoutProvider({ children }: CheckoutProviderProps) {
{
onSuccess: async (data) => {
setConfirmationData(data);
state?.id &&
(await mutateClearCart({
cartId: state.id,
}));
await mutateClearCart();
},
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"dependencies": {
"@moltin/sdk": "28.12.0",
"@elasticpath/react-shopper-hooks": "0.9.0",
"@elasticpath/react-shopper-hooks": "0.10.0",
"@elasticpath/shopper-common": "0.3.0",
"clsx": "^1.2.1",
"cookies-next": "^4.0.0",
Expand Down
13 changes: 11 additions & 2 deletions packages/react-shopper-hooks/example/ProductListExample.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
import React from "react"
import { useProducts } from "../src"
import { useProductsEnhanced } from "../src/product/hooks/use-products-enhanced"

export function ProductListExample() {
const { data: products } = useProducts()
const { data: products } = useProductsEnhanced()
return (
<div>
<h1>Product List</h1>
{products?.data.map((product) => (
<div key={product.id}>
<h2>{product.attributes.name}</h2>
<p>{product.id}</p>
<p>Main image: {product.enhanced.mainImage?.link?.href}</p>
<p>
Other images:{" "}
{product.enhanced.otherImages
?.map((x) => {
return x.link.href
})
.toString()}
</p>
</div>
))}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import type {
ShopperCatalogResourcePage,
ProductResponse,
File,
} from "@moltin/sdk"
import { UseQueryResult } from "@tanstack/react-query"
import {
ShopperCatalogProductsInclude,
useProducts,
UseProductsParams,
UseProductsQueryOptions,
} from "./use-products"

type UseProductsEnhancedData = ShopperCatalogResourcePage<
ProductResponse & {
enhanced: { mainImage: File | null; otherImages: File[] | null }
}
>

export function useProductsEnhanced(
params?: UseProductsParams,
options?: UseProductsQueryOptions,
): UseQueryResult<UseProductsEnhancedData, Error> {
return useProducts(
{
...params,
include: combineIncludes(
["main_image", "files", "component_products"],
params,
),
},
{
...options,
select: (data): UseProductsEnhancedData => {
const transformedData = options?.select?.(data) ?? data

const fileLookup = createFileLookupDict(transformedData.included)

const enhancedData = transformedData.data.map((originalData) => {
return {
...originalData,
enhanced: {
mainImage: getProductMainImage(originalData, fileLookup),
otherImages: getProductOtherImages(originalData, fileLookup),
},
}
})

return {
...transformedData,
data: enhancedData,
}
},
},
) as UseQueryResult<UseProductsEnhancedData, Error>
}

function getProductMainImage(
product: ProductResponse,
fileLookup: Record<string, File>,
): File | null {
const mainImageId = product?.relationships?.main_image?.data?.id
return mainImageId ? fileLookup[mainImageId] : null
}

function getProductOtherImages(
product: ProductResponse,
fileLookup: Record<string, File>,
): File[] | null {
const otherImagesIds =
product?.relationships?.files?.data?.map((file) => file.id) ?? []
const mainImageId = product?.relationships?.main_image?.data?.id
return otherImagesIds
.map((id) => fileLookup[id])
.filter((x) => x.id !== mainImageId)
}

function createFileLookupDict(
includes: ShopperCatalogResourcePage<ProductResponse>["included"],
): Record<string, File> {
return (
includes?.files?.reduce((acc, curr) => {
return { ...acc, [curr.id]: curr }
}, {}) ?? {}
)
}

function combineIncludes(
include: ShopperCatalogProductsInclude[],
params: UseProductsParams,
): ShopperCatalogProductsInclude[] {
return [
...new Set<ShopperCatalogProductsInclude>([
...include,
...extractIncludeFromParams(params),
]),
]
}

function extractIncludeFromParams(
params: UseProductsParams,
): ShopperCatalogProductsInclude[] {
if (!params?.include) {
return []
}
return Array.isArray(params.include) ? params.include : [params.include]
}
30 changes: 16 additions & 14 deletions packages/react-shopper-hooks/src/product/hooks/use-products.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,29 @@ const PRODUCTS_QUERY_KEY = "products" as const
export const productsQueryKeys = queryKeysFactory(PRODUCTS_QUERY_KEY)
type ProductsQueryKey = typeof productsQueryKeys

export type UseProductsParams = NonNullable<
Parameters<Moltin["ShopperCatalog"]["Products"]["All"]>
>[0]
export type UseProductsParams =
| (NonNullable<Parameters<Moltin["ShopperCatalog"]["Products"]["All"]>>[0] & {
limit?: number
offset?: number
filter?: object
include?: ShopperCatalogProductsInclude | ShopperCatalogProductsInclude[]
})
| undefined

export type ShopperCatalogProductsInclude =
| "main_image"
| "files"
| "component_products"

export type UseProductsQueryOptions = UseQueryOptionsWrapper<
ShopperCatalogResourcePage<ProductResponse>,
Error,
ReturnType<ProductsQueryKey["list"]>
>

export function useProducts(
params?: UseProductsParams & {
limit?: number
offset?: number
filter?: object
include?: ShopperCatalogProductsInclude | ShopperCatalogProductsInclude[]
},
options?: UseQueryOptionsWrapper<
ShopperCatalogResourcePage<ProductResponse>,
Error,
ReturnType<ProductsQueryKey["list"]>
>,
params?: UseProductsParams,
options?: UseProductsQueryOptions,
): UseQueryResult<ShopperCatalogResourcePage<ProductResponse>, Error> {
const { client } = useElasticPath()

Expand Down

0 comments on commit 091eebd

Please sign in to comment.