Skip to content

Commit 091eebd

Browse files
authored
feat: add enhanced use products (#207)
* 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
1 parent dfc34e6 commit 091eebd

File tree

11 files changed

+150
-37
lines changed

11 files changed

+150
-37
lines changed

.changeset/cuddly-camels-swim.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@elasticpath/d2c-schematics": minor
3+
---
4+
5+
remove empty object on cart clear

.changeset/great-pumas-obey.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@elasticpath/react-shopper-hooks": minor
3+
---
4+
5+
- adds a hook that gives back the main image and other files associated with the products returned

examples/algolia/src/app/(checkout)/checkout/checkout-provider.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,7 @@ export function CheckoutProvider({ children }: CheckoutProviderProps) {
6565
{
6666
onSuccess: async (data) => {
6767
setConfirmationData(data);
68-
state?.id &&
69-
(await mutateClearCart({
70-
cartId: state.id,
71-
}));
68+
await mutateClearCart();
7269
},
7370
},
7471
);

examples/payments/src/app/(checkout)/checkout/checkout-provider.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,7 @@ export function StripeCheckoutProvider({ children }: CheckoutProviderProps) {
7777
{
7878
onSuccess: async (data) => {
7979
setConfirmationData(data);
80-
state?.id &&
81-
(await mutateClearCart({
82-
cartId: state.id,
83-
}));
80+
await mutateClearCart();
8481
},
8582
},
8683
);

examples/simple/src/app/(checkout)/checkout/checkout-provider.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,7 @@ export function CheckoutProvider({ children }: CheckoutProviderProps) {
6565
{
6666
onSuccess: async (data) => {
6767
setConfirmationData(data);
68-
state?.id &&
69-
(await mutateClearCart({
70-
cartId: state.id,
71-
}));
68+
await mutateClearCart();
7269
},
7370
},
7471
);

packages/d2c-schematics/ep-payments-payment-gateway/files/src/app/(checkout)/checkout/checkout-provider.tsx.template

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,7 @@ export function StripeCheckoutProvider({ children }: CheckoutProviderProps) {
7777
{
7878
onSuccess: async (data) => {
7979
setConfirmationData(data);
80-
state?.id &&
81-
(await mutateClearCart({
82-
cartId: state.id,
83-
}));
80+
await mutateClearCart();
8481
},
8582
},
8683
);

packages/d2c-schematics/manual-payment-gateway/files/src/app/(checkout)/checkout/checkout-provider.tsx.template

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,7 @@ export function CheckoutProvider({ children }: CheckoutProviderProps) {
6565
{
6666
onSuccess: async (data) => {
6767
setConfirmationData(data);
68-
state?.id &&
69-
(await mutateClearCart({
70-
cartId: state.id,
71-
}));
68+
await mutateClearCart();
7269
},
7370
},
7471
);

packages/d2c-schematics/utility/latest-versions/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"private": true,
55
"dependencies": {
66
"@moltin/sdk": "28.12.0",
7-
"@elasticpath/react-shopper-hooks": "0.9.0",
7+
"@elasticpath/react-shopper-hooks": "0.10.0",
88
"@elasticpath/shopper-common": "0.3.0",
99
"clsx": "^1.2.1",
1010
"cookies-next": "^4.0.0",

packages/react-shopper-hooks/example/ProductListExample.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
11
import React from "react"
2-
import { useProducts } from "../src"
2+
import { useProductsEnhanced } from "../src/product/hooks/use-products-enhanced"
33

44
export function ProductListExample() {
5-
const { data: products } = useProducts()
5+
const { data: products } = useProductsEnhanced()
66
return (
77
<div>
88
<h1>Product List</h1>
99
{products?.data.map((product) => (
1010
<div key={product.id}>
1111
<h2>{product.attributes.name}</h2>
1212
<p>{product.id}</p>
13+
<p>Main image: {product.enhanced.mainImage?.link?.href}</p>
14+
<p>
15+
Other images:{" "}
16+
{product.enhanced.otherImages
17+
?.map((x) => {
18+
return x.link.href
19+
})
20+
.toString()}
21+
</p>
1322
</div>
1423
))}
1524
</div>
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import type {
2+
ShopperCatalogResourcePage,
3+
ProductResponse,
4+
File,
5+
} from "@moltin/sdk"
6+
import { UseQueryResult } from "@tanstack/react-query"
7+
import {
8+
ShopperCatalogProductsInclude,
9+
useProducts,
10+
UseProductsParams,
11+
UseProductsQueryOptions,
12+
} from "./use-products"
13+
14+
type UseProductsEnhancedData = ShopperCatalogResourcePage<
15+
ProductResponse & {
16+
enhanced: { mainImage: File | null; otherImages: File[] | null }
17+
}
18+
>
19+
20+
export function useProductsEnhanced(
21+
params?: UseProductsParams,
22+
options?: UseProductsQueryOptions,
23+
): UseQueryResult<UseProductsEnhancedData, Error> {
24+
return useProducts(
25+
{
26+
...params,
27+
include: combineIncludes(
28+
["main_image", "files", "component_products"],
29+
params,
30+
),
31+
},
32+
{
33+
...options,
34+
select: (data): UseProductsEnhancedData => {
35+
const transformedData = options?.select?.(data) ?? data
36+
37+
const fileLookup = createFileLookupDict(transformedData.included)
38+
39+
const enhancedData = transformedData.data.map((originalData) => {
40+
return {
41+
...originalData,
42+
enhanced: {
43+
mainImage: getProductMainImage(originalData, fileLookup),
44+
otherImages: getProductOtherImages(originalData, fileLookup),
45+
},
46+
}
47+
})
48+
49+
return {
50+
...transformedData,
51+
data: enhancedData,
52+
}
53+
},
54+
},
55+
) as UseQueryResult<UseProductsEnhancedData, Error>
56+
}
57+
58+
function getProductMainImage(
59+
product: ProductResponse,
60+
fileLookup: Record<string, File>,
61+
): File | null {
62+
const mainImageId = product?.relationships?.main_image?.data?.id
63+
return mainImageId ? fileLookup[mainImageId] : null
64+
}
65+
66+
function getProductOtherImages(
67+
product: ProductResponse,
68+
fileLookup: Record<string, File>,
69+
): File[] | null {
70+
const otherImagesIds =
71+
product?.relationships?.files?.data?.map((file) => file.id) ?? []
72+
const mainImageId = product?.relationships?.main_image?.data?.id
73+
return otherImagesIds
74+
.map((id) => fileLookup[id])
75+
.filter((x) => x.id !== mainImageId)
76+
}
77+
78+
function createFileLookupDict(
79+
includes: ShopperCatalogResourcePage<ProductResponse>["included"],
80+
): Record<string, File> {
81+
return (
82+
includes?.files?.reduce((acc, curr) => {
83+
return { ...acc, [curr.id]: curr }
84+
}, {}) ?? {}
85+
)
86+
}
87+
88+
function combineIncludes(
89+
include: ShopperCatalogProductsInclude[],
90+
params: UseProductsParams,
91+
): ShopperCatalogProductsInclude[] {
92+
return [
93+
...new Set<ShopperCatalogProductsInclude>([
94+
...include,
95+
...extractIncludeFromParams(params),
96+
]),
97+
]
98+
}
99+
100+
function extractIncludeFromParams(
101+
params: UseProductsParams,
102+
): ShopperCatalogProductsInclude[] {
103+
if (!params?.include) {
104+
return []
105+
}
106+
return Array.isArray(params.include) ? params.include : [params.include]
107+
}

packages/react-shopper-hooks/src/product/hooks/use-products.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,29 @@ const PRODUCTS_QUERY_KEY = "products" as const
1313
export const productsQueryKeys = queryKeysFactory(PRODUCTS_QUERY_KEY)
1414
type ProductsQueryKey = typeof productsQueryKeys
1515

16-
export type UseProductsParams = NonNullable<
17-
Parameters<Moltin["ShopperCatalog"]["Products"]["All"]>
18-
>[0]
16+
export type UseProductsParams =
17+
| (NonNullable<Parameters<Moltin["ShopperCatalog"]["Products"]["All"]>>[0] & {
18+
limit?: number
19+
offset?: number
20+
filter?: object
21+
include?: ShopperCatalogProductsInclude | ShopperCatalogProductsInclude[]
22+
})
23+
| undefined
1924

2025
export type ShopperCatalogProductsInclude =
2126
| "main_image"
2227
| "files"
2328
| "component_products"
2429

30+
export type UseProductsQueryOptions = UseQueryOptionsWrapper<
31+
ShopperCatalogResourcePage<ProductResponse>,
32+
Error,
33+
ReturnType<ProductsQueryKey["list"]>
34+
>
35+
2536
export function useProducts(
26-
params?: UseProductsParams & {
27-
limit?: number
28-
offset?: number
29-
filter?: object
30-
include?: ShopperCatalogProductsInclude | ShopperCatalogProductsInclude[]
31-
},
32-
options?: UseQueryOptionsWrapper<
33-
ShopperCatalogResourcePage<ProductResponse>,
34-
Error,
35-
ReturnType<ProductsQueryKey["list"]>
36-
>,
37+
params?: UseProductsParams,
38+
options?: UseProductsQueryOptions,
3739
): UseQueryResult<ShopperCatalogResourcePage<ProductResponse>, Error> {
3840
const { client } = useElasticPath()
3941

0 commit comments

Comments
 (0)