Skip to content

Commit ce04040

Browse files
authored
feat: update scoped hooks (#202)
* feat: add stand alone scoped hook for add product * feat: add use products hook with filter, offset and limit * feat: expose new cart scoped hooks * feat: clean up cart provider * refactor: use new scoped hooks * chore: added changeset
1 parent cd24024 commit ce04040

13 files changed

+225
-112
lines changed

.changeset/friendly-peas-mix.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@elasticpath/react-shopper-hooks": minor
3+
---
4+
5+
- Moved scoped hooks outside cart provider
6+
- Added default cart id to cart provider using the sdks cart id
7+
- Added useProducts hook

packages/react-shopper-hooks/src/cart/cart-provider.tsx

Lines changed: 10 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,16 @@
11
import React, { createContext, ReactNode } from "react"
2-
import {
3-
Cart,
4-
CartIncluded,
5-
ResourceIncluded,
6-
CartItem,
7-
CartItemsResponse,
8-
} from "@moltin/sdk"
2+
import { Cart, CartIncluded, ResourceIncluded, CartItem } from "@moltin/sdk"
93
import { CartState } from "./types/cart-types"
104
import { enhanceCartResponse } from "./util/enhance-cart-response"
115
import { StoreEvent } from "../shared"
12-
import { cartQueryKeys, useGetCart } from "./hooks/use-get-cart"
13-
import { useUpdateCartItem } from "./hooks/use-update-cart-items"
14-
import { useQueryClient } from "@tanstack/react-query"
15-
import { useRemoveCartItem } from "./hooks/use-remove-cart-item"
16-
import {
17-
useAddBundleProductToCart,
18-
useAddProductToCart,
19-
useAddPromotionToCart,
20-
useDeleteCartItems,
21-
} from "./hooks"
22-
import { useRemovePromotionCode } from "./hooks/use-remove-promotion"
6+
import { useGetCart } from "./hooks/use-get-cart"
7+
import { useElasticPath } from "../elasticpath"
238

249
export const CartItemsContext = createContext<
2510
| ({
2611
state: CartState | undefined
27-
cartId?: string
12+
cartId: string
2813
emit?: (event: StoreEvent) => void
29-
useScopedUpdateCartItem: () => ReturnType<typeof useUpdateCartItem>
30-
useScopedRemoveCartItem: () => ReturnType<typeof useRemoveCartItem>
31-
useScopedAddPromotion: () => ReturnType<typeof useAddPromotionToCart>
32-
useScopedRemovePromotion: () => ReturnType<typeof useRemovePromotionCode>
33-
useScopedAddProductToCart: () => ReturnType<typeof useAddProductToCart>
34-
useScopedAddBundleProductToCart: () => ReturnType<
35-
typeof useAddBundleProductToCart
36-
>
37-
useClearCart: () => ReturnType<typeof useDeleteCartItems>
3814
} & Omit<ReturnType<typeof useGetCart>, "data">)
3915
| undefined
4016
>(undefined)
@@ -52,104 +28,29 @@ export function CartProvider({
5228
initialState,
5329
children,
5430
emit,
55-
cartId = "",
31+
cartId: sourceCartId,
5632
}: CartProviderProps) {
57-
const queryClient = useQueryClient()
33+
const { client } = useElasticPath()
34+
35+
const cartId = sourceCartId ?? client.Cart().cartId
5836

5937
const { data: rawCartData, ...rest } = useGetCart(cartId, {
6038
initialData: initialState?.cart,
6139
})
6240

63-
async function invalidateCartQuery() {
64-
return queryClient.invalidateQueries({
65-
queryKey: cartQueryKeys.detail(cartId),
66-
})
67-
}
68-
69-
function setCartQueryData(updatedData: CartItemsResponse) {
70-
// Updates the cart items in the query cache
71-
return queryClient.setQueryData(
72-
cartQueryKeys.detail(cartId),
73-
createCartItemsUpdater(updatedData.data),
74-
)
75-
}
76-
7741
const state =
7842
rawCartData &&
7943
enhanceCartResponse({
8044
data: rawCartData,
8145
included: rest.included,
8246
})
8347

84-
const updateCartItem = () =>
85-
useUpdateCartItem(cartId, {
86-
onSuccess: (updatedData) => {
87-
setCartQueryData(updatedData)
88-
invalidateCartQuery()
89-
},
90-
})
91-
92-
const addProductToCart = () =>
93-
useAddProductToCart(cartId, {
94-
onSuccess: (updatedData) => {
95-
setCartQueryData(updatedData)
96-
invalidateCartQuery()
97-
},
98-
})
99-
100-
const removeCartItem = () =>
101-
useRemoveCartItem(cartId, {
102-
onSuccess: (updatedData) => {
103-
setCartQueryData(updatedData)
104-
invalidateCartQuery()
105-
},
106-
})
107-
108-
const addPromotion = () =>
109-
useAddPromotionToCart(cartId, {
110-
onSuccess: (updatedData) => {
111-
setCartQueryData(updatedData)
112-
invalidateCartQuery()
113-
},
114-
})
115-
116-
const removePromotion = () =>
117-
useRemovePromotionCode(cartId, {
118-
onSuccess: (updatedData) => {
119-
setCartQueryData(updatedData)
120-
invalidateCartQuery()
121-
},
122-
})
123-
124-
const addBundleItemToCart = () =>
125-
useAddBundleProductToCart(cartId, {
126-
onSuccess: (updatedData) => {
127-
setCartQueryData(updatedData)
128-
invalidateCartQuery()
129-
},
130-
})
131-
132-
const clearCart = () =>
133-
useDeleteCartItems(cartId, {
134-
onSuccess: async (updatedData) => {
135-
setCartQueryData(updatedData)
136-
await invalidateCartQuery()
137-
},
138-
})
139-
14048
return (
14149
<CartItemsContext.Provider
14250
value={{
14351
state,
14452
emit,
145-
cartId: cartId ? cartId : undefined,
146-
useScopedUpdateCartItem: updateCartItem,
147-
useScopedRemoveCartItem: removeCartItem,
148-
useScopedAddPromotion: addPromotion,
149-
useScopedRemovePromotion: removePromotion,
150-
useScopedAddProductToCart: addProductToCart,
151-
useScopedAddBundleProductToCart: addBundleItemToCart,
152-
useClearCart: clearCart,
53+
cartId,
15354
...rest,
15455
}}
15556
>
@@ -158,7 +59,7 @@ export function CartProvider({
15859
)
15960
}
16061

161-
function createCartItemsUpdater(updatedData: CartItem[]) {
62+
export function createCartItemsUpdater(updatedData: CartItem[]) {
16263
return function cartItemsUpdater(
16364
oldData: ResourceIncluded<Cart, CartIncluded>,
16465
) {

packages/react-shopper-hooks/src/cart/hooks/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,11 @@ export * from "./use-add-bundle-product-to-cart"
77
export * from "./use-checkout"
88
export * from "./use-add-custom-item"
99
export * from "./use-delete-cart-items"
10+
export * from "./use-cart-add-product"
11+
export * from "./use-cart-remove-item"
12+
export * from "./use-cart-update-item"
13+
export * from "./use-cart-add-promotion"
14+
export * from "./use-cart-add-bundle-item"
15+
export * from "./use-cart-clear"
16+
export * from "./use-cart-remove-promotion"
17+
export * from "./use-cart-remove-item"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { createCartItemsUpdater, useCart } from "../cart-provider"
2+
import { useQueryClient } from "@tanstack/react-query"
3+
import { cartQueryKeys } from "./use-get-cart"
4+
import { useAddBundleProductToCart } from "./use-add-bundle-product-to-cart"
5+
6+
export function useCartAddBundleItem() {
7+
const { cartId } = useCart()
8+
const queryClient = useQueryClient()
9+
return useAddBundleProductToCart(cartId, {
10+
onSuccess: (updatedData) => {
11+
// Updates the cart items in the query cache
12+
queryClient.setQueryData(
13+
cartQueryKeys.detail(cartId),
14+
createCartItemsUpdater(updatedData.data),
15+
)
16+
return queryClient.invalidateQueries({
17+
queryKey: cartQueryKeys.detail(cartId),
18+
})
19+
},
20+
})
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { useAddProductToCart } from "./use-add-product"
2+
import { createCartItemsUpdater, useCart } from "../cart-provider"
3+
import { useQueryClient } from "@tanstack/react-query"
4+
import { cartQueryKeys } from "./use-get-cart"
5+
6+
export function useCartAddProduct() {
7+
const { cartId } = useCart()
8+
const queryClient = useQueryClient()
9+
return useAddProductToCart(cartId, {
10+
onSuccess: (updatedData) => {
11+
// Updates the cart items in the query cache
12+
queryClient.setQueryData(
13+
cartQueryKeys.detail(cartId),
14+
createCartItemsUpdater(updatedData.data),
15+
)
16+
return queryClient.invalidateQueries({
17+
queryKey: cartQueryKeys.detail(cartId),
18+
})
19+
},
20+
})
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { createCartItemsUpdater, useCart } from "../cart-provider"
2+
import { useQueryClient } from "@tanstack/react-query"
3+
import { cartQueryKeys } from "./use-get-cart"
4+
import { useAddPromotionToCart } from "./use-add-promotion"
5+
6+
export function useCartAddPromotion() {
7+
const { cartId } = useCart()
8+
const queryClient = useQueryClient()
9+
return useAddPromotionToCart(cartId, {
10+
onSuccess: (updatedData) => {
11+
// Updates the cart items in the query cache
12+
queryClient.setQueryData(
13+
cartQueryKeys.detail(cartId),
14+
createCartItemsUpdater(updatedData.data),
15+
)
16+
return queryClient.invalidateQueries({
17+
queryKey: cartQueryKeys.detail(cartId),
18+
})
19+
},
20+
})
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { createCartItemsUpdater, useCart } from "../cart-provider"
2+
import { useQueryClient } from "@tanstack/react-query"
3+
import { cartQueryKeys } from "./use-get-cart"
4+
import { useDeleteCartItems } from "./use-delete-cart-items"
5+
6+
export function useCartClear() {
7+
const { cartId } = useCart()
8+
const queryClient = useQueryClient()
9+
return useDeleteCartItems(cartId, {
10+
onSuccess: (updatedData) => {
11+
// Updates the cart items in the query cache
12+
queryClient.setQueryData(
13+
cartQueryKeys.detail(cartId),
14+
createCartItemsUpdater(updatedData.data),
15+
)
16+
return queryClient.invalidateQueries({
17+
queryKey: cartQueryKeys.detail(cartId),
18+
})
19+
},
20+
})
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { createCartItemsUpdater, useCart } from "../cart-provider"
2+
import { useQueryClient } from "@tanstack/react-query"
3+
import { cartQueryKeys } from "./use-get-cart"
4+
import { useRemoveCartItem } from "./use-remove-cart-item"
5+
6+
export function useCartRemoveItem() {
7+
const { cartId } = useCart()
8+
const queryClient = useQueryClient()
9+
return useRemoveCartItem(cartId, {
10+
onSuccess: (updatedData) => {
11+
// Updates the cart items in the query cache
12+
queryClient.setQueryData(
13+
cartQueryKeys.detail(cartId),
14+
createCartItemsUpdater(updatedData.data),
15+
)
16+
return queryClient.invalidateQueries({
17+
queryKey: cartQueryKeys.detail(cartId),
18+
})
19+
},
20+
})
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { createCartItemsUpdater, useCart } from "../cart-provider"
2+
import { useQueryClient } from "@tanstack/react-query"
3+
import { cartQueryKeys } from "./use-get-cart"
4+
import { useRemovePromotionCode } from "./use-remove-promotion"
5+
6+
export function useCartRemovePromotion() {
7+
const { cartId } = useCart()
8+
const queryClient = useQueryClient()
9+
return useRemovePromotionCode(cartId, {
10+
onSuccess: (updatedData) => {
11+
// Updates the cart items in the query cache
12+
queryClient.setQueryData(
13+
cartQueryKeys.detail(cartId),
14+
createCartItemsUpdater(updatedData.data),
15+
)
16+
return queryClient.invalidateQueries({
17+
queryKey: cartQueryKeys.detail(cartId),
18+
})
19+
},
20+
})
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { createCartItemsUpdater, useCart } from "../cart-provider"
2+
import { useQueryClient } from "@tanstack/react-query"
3+
import { cartQueryKeys } from "./use-get-cart"
4+
import { useUpdateCartItem } from "./use-update-cart-items"
5+
6+
export function useCartUpdateItem() {
7+
const { cartId } = useCart()
8+
const queryClient = useQueryClient()
9+
return useUpdateCartItem(cartId, {
10+
onSuccess: (updatedData) => {
11+
// Updates the cart items in the query cache
12+
queryClient.setQueryData(
13+
cartQueryKeys.detail(cartId),
14+
createCartItemsUpdater(updatedData.data),
15+
)
16+
return queryClient.invalidateQueries({
17+
queryKey: cartQueryKeys.detail(cartId),
18+
})
19+
},
20+
})
21+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from "./use-product"
2+
export * from "./use-products"
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { useElasticPath } from "../../elasticpath/elasticpath"
2+
import { UseQueryOptionsWrapper } from "../../types"
3+
import type {
4+
Moltin,
5+
ShopperCatalogResourcePage,
6+
ProductResponse,
7+
} from "@moltin/sdk"
8+
import { useQuery, UseQueryResult } from "@tanstack/react-query"
9+
import { queryKeysFactory } from "../../shared/util/query-keys-factory"
10+
11+
const PRODUCTS_QUERY_KEY = "products" as const
12+
13+
export const productsQueryKeys = queryKeysFactory(PRODUCTS_QUERY_KEY)
14+
type ProductsQueryKey = typeof productsQueryKeys
15+
16+
export type UseProductsParams = NonNullable<
17+
Parameters<Moltin["ShopperCatalog"]["Products"]["All"]>
18+
>[0]
19+
20+
export function useProducts(
21+
params: UseProductsParams & {
22+
limit?: number
23+
offset?: number
24+
filter?: object
25+
},
26+
options?: UseQueryOptionsWrapper<
27+
ShopperCatalogResourcePage<ProductResponse>,
28+
Error,
29+
ReturnType<ProductsQueryKey["list"]>
30+
>,
31+
): UseQueryResult<ShopperCatalogResourcePage<ProductResponse>, Error> {
32+
const { client } = useElasticPath()
33+
34+
const { limit = 25, offset = 0, filter = {} } = params
35+
36+
return useQuery({
37+
queryKey: [
38+
...productsQueryKeys.list({ limit, offset, filter, ...options }),
39+
],
40+
queryFn: () =>
41+
client.ShopperCatalog.Products.Limit(limit)
42+
.Offset(offset)
43+
.Filter(filter)
44+
.With(["main_image", "component_products", "files"])
45+
.All(),
46+
...options,
47+
})
48+
}

0 commit comments

Comments
 (0)