diff --git a/packages/react-shopper-hooks/src/account/hooks/use-account-addresses.tsx b/packages/react-shopper-hooks/src/account/hooks/use-account-addresses.tsx new file mode 100644 index 00000000..b73478cb --- /dev/null +++ b/packages/react-shopper-hooks/src/account/hooks/use-account-addresses.tsx @@ -0,0 +1,37 @@ +import { useElasticPath } from "../../elasticpath" +import { UseQueryOptionsWrapper } from "../../types" +import { AccountAddress, ResourcePage } from "@moltin/sdk" +import { useQuery, UseQueryResult } from "@tanstack/react-query" +import { queryKeysFactory } from "../../shared/util/query-keys-factory" + +const ACCOUNT_ADDRESSES_QUERY_KEY = "account-addresses" as const + +export const accountAddressesQueryKeys = queryKeysFactory( + ACCOUNT_ADDRESSES_QUERY_KEY, +) +type AccountAddressesQueryKey = typeof accountAddressesQueryKeys + +export function useAccountAddresses( + accountId: string, + options?: UseQueryOptionsWrapper< + ResourcePage, + Error, + ReturnType + > & { ep?: { accountMemberToken?: string } }, +): Partial> & + Omit, Error>, "data"> { + const { client } = useElasticPath() + const { data, ...rest } = useQuery({ + queryKey: [...accountAddressesQueryKeys.list({ accountId })], + queryFn: () => + client.AccountAddresses.All({ + account: accountId, + ...(options?.ep?.accountMemberToken && { + token: options.ep.accountMemberToken, + }), + }), + ...options, + }) + + return { ...data, ...rest } as const +} diff --git a/packages/react-shopper-hooks/src/account/index.ts b/packages/react-shopper-hooks/src/account/index.ts index e8c635f3..850ba992 100644 --- a/packages/react-shopper-hooks/src/account/index.ts +++ b/packages/react-shopper-hooks/src/account/index.ts @@ -1,3 +1,4 @@ export * from "./hooks/use-account-member" export * from "./hooks/use-authed-account-member" export * from "./account-provider" +export * from "./hooks/use-account-addresses" diff --git a/packages/react-shopper-hooks/src/cart/cart-provider.tsx b/packages/react-shopper-hooks/src/cart/cart-provider.tsx index 7315fc2a..d922da51 100644 --- a/packages/react-shopper-hooks/src/cart/cart-provider.tsx +++ b/packages/react-shopper-hooks/src/cart/cart-provider.tsx @@ -17,6 +17,7 @@ import { useAddBundleProductToCart, useAddProductToCart, useAddPromotionToCart, + useDeleteCartItems, } from "./hooks" import { useRemovePromotionCode } from "./hooks/use-remove-promotion" @@ -33,6 +34,7 @@ export const CartItemsContext = createContext< useScopedAddBundleProductToCart: () => ReturnType< typeof useAddBundleProductToCart > + useClearCart: () => ReturnType } & Omit, "data">) | undefined >(undefined) @@ -127,6 +129,14 @@ export function CartProvider({ }, }) + const clearCart = () => + useDeleteCartItems(cartId, { + onSuccess: async (updatedData) => { + setCartQueryData(updatedData) + await invalidateCartQuery() + }, + }) + return ( diff --git a/packages/react-shopper-hooks/src/cart/hooks/index.ts b/packages/react-shopper-hooks/src/cart/hooks/index.ts index 2e6ad7f4..135b0575 100644 --- a/packages/react-shopper-hooks/src/cart/hooks/index.ts +++ b/packages/react-shopper-hooks/src/cart/hooks/index.ts @@ -1,6 +1,9 @@ export * from "./use-get-cart" export * from "./use-remove-cart-item" export * from "./use-update-cart-items" -export * from "./use-add-cart-item" +export * from "./use-add-product" export * from "./use-add-promotion" export * from "./use-add-bundle-product-to-cart" +export * from "./use-checkout" +export * from "./use-add-custom-item" +export * from "./use-delete-cart-items" diff --git a/packages/react-shopper-hooks/src/cart/hooks/use-add-custom-item.ts b/packages/react-shopper-hooks/src/cart/hooks/use-add-custom-item.ts new file mode 100644 index 00000000..c40726f4 --- /dev/null +++ b/packages/react-shopper-hooks/src/cart/hooks/use-add-custom-item.ts @@ -0,0 +1,31 @@ +import { useMutation, UseMutationOptions } from "@tanstack/react-query" +import { CartItemsResponse } from "@moltin/sdk" +import { useElasticPath } from "../../elasticpath" + +export type CartAddCustomItemReq = { + type: "custom_item" + name: string + description?: string + sku?: string + quantity: number + price: { + amount: number + includes_tax: boolean + } + custom_inputs?: Record + shipping_group_id?: string + tax?: any[] +} + +export const useAddCustomItemToCart = ( + cartId: string, + options?: UseMutationOptions, +) => { + const { client } = useElasticPath() + return useMutation({ + mutationFn: async (props) => { + return client.Cart(cartId).AddCustomItem(props) + }, + ...options, + }) +} diff --git a/packages/react-shopper-hooks/src/cart/hooks/use-add-cart-item.ts b/packages/react-shopper-hooks/src/cart/hooks/use-add-product.ts similarity index 93% rename from packages/react-shopper-hooks/src/cart/hooks/use-add-cart-item.ts rename to packages/react-shopper-hooks/src/cart/hooks/use-add-product.ts index 0a8c3d0c..8fa74668 100644 --- a/packages/react-shopper-hooks/src/cart/hooks/use-add-cart-item.ts +++ b/packages/react-shopper-hooks/src/cart/hooks/use-add-product.ts @@ -1,7 +1,6 @@ import { useMutation, UseMutationOptions } from "@tanstack/react-query" import { useElasticPath } from "../../elasticpath" import { CartAdditionalHeaders, CartItemsResponse } from "@moltin/sdk" -import { SelectedOptions } from "../types/bundle.type" type CartAddProductReq = { productId: string diff --git a/packages/react-shopper-hooks/src/cart/hooks/use-checkout.ts b/packages/react-shopper-hooks/src/cart/hooks/use-checkout.ts new file mode 100644 index 00000000..8f56fcd2 --- /dev/null +++ b/packages/react-shopper-hooks/src/cart/hooks/use-checkout.ts @@ -0,0 +1,75 @@ +import { useMutation, UseMutationOptions } from "@tanstack/react-query" +import { useElasticPath } from "../../elasticpath" +import { + Address, + CartAdditionalHeaders, + CheckoutCustomer, + CheckoutCustomerObject, + Order, + Resource, +} from "@moltin/sdk" + +export type UseCheckoutReq = { + customer: string | CheckoutCustomer | CheckoutCustomerObject + billingAddress: Partial
+ shippingAddress?: Partial
+ additionalHeaders?: CartAdditionalHeaders +} + +export const useCheckout = ( + cartId: string, + options?: UseMutationOptions, Error, UseCheckoutReq>, +) => { + const { client } = useElasticPath() + return useMutation({ + mutationFn: async ({ + customer, + billingAddress, + shippingAddress, + additionalHeaders, + }: UseCheckoutReq) => { + return client + .Cart(cartId) + .Checkout(customer, billingAddress, shippingAddress, additionalHeaders) + }, + ...options, + }) +} + +export type UseCheckoutWithAccountReq = { + contact: string | CheckoutCustomer | CheckoutCustomerObject + billingAddress: Partial
+ token: string + shippingAddress?: Partial
+ additionalHeaders?: CartAdditionalHeaders +} + +export const useCheckoutWithAccount = ( + cartId: string, + options?: UseMutationOptions< + Resource, + Error, + UseCheckoutWithAccountReq + >, +) => { + const { client } = useElasticPath() + return useMutation({ + mutationFn: async ({ + contact, + billingAddress, + shippingAddress, + token, + additionalHeaders, + }: UseCheckoutWithAccountReq) => { + return client.Cart(cartId).CheckoutWithAccountManagementToken( + contact, + billingAddress, + shippingAddress, + token, + // @ts-ignore TODO: Fix type definition in js-sdk + additionalHeaders, + ) + }, + ...options, + }) +} diff --git a/packages/react-shopper-hooks/src/cart/hooks/use-delete-cart-items.ts b/packages/react-shopper-hooks/src/cart/hooks/use-delete-cart-items.ts new file mode 100644 index 00000000..d75db1f9 --- /dev/null +++ b/packages/react-shopper-hooks/src/cart/hooks/use-delete-cart-items.ts @@ -0,0 +1,22 @@ +import { useMutation, UseMutationOptions } from "@tanstack/react-query" +import { useElasticPath } from "../../elasticpath" +import { CartItemsResponse } from "@moltin/sdk" + +type CartDeleteCartItemsReq = {} + +export const useDeleteCartItems = ( + cartId: string, + options?: UseMutationOptions< + CartItemsResponse, + Error, + CartDeleteCartItemsReq + >, +) => { + const { client } = useElasticPath() + return useMutation({ + mutationFn: async () => { + return client.Cart(cartId).RemoveAllItems() + }, + ...options, + }) +} diff --git a/packages/react-shopper-hooks/src/cart/index.ts b/packages/react-shopper-hooks/src/cart/index.ts index ab1076b7..c4fd9b5d 100644 --- a/packages/react-shopper-hooks/src/cart/index.ts +++ b/packages/react-shopper-hooks/src/cart/index.ts @@ -2,4 +2,4 @@ export * from "./cart-provider" export * from "./use-cart-hook" export * from "./types/cart-types" export * from "./hooks" -export * from "./util/enhance-cart-response" +export * from "./util" diff --git a/packages/react-shopper-hooks/src/cart/util/enhance-cart-response.ts b/packages/react-shopper-hooks/src/cart/util/enhance-cart-response.ts index 746d3c5d..bd02f4e5 100644 --- a/packages/react-shopper-hooks/src/cart/util/enhance-cart-response.ts +++ b/packages/react-shopper-hooks/src/cart/util/enhance-cart-response.ts @@ -3,18 +3,11 @@ import { CartState, RefinedCartItem } from "../../cart" import { groupCartItems } from "./group-cart-items" export function enhanceCartResponse( - cart?: ResourceIncluded, -): CartState | undefined { - if (!cart) { - return undefined - } - - const items = - cart.included?.items - .filter( - (item) => item.type === "cart_item" || item.type === "custom_item", - ) - .sort(sortItemByCreatedAsc) ?? [] + cart: ResourceIncluded, +): CartState { + const items = !!cart.included?.items + ? enhanceCartItems(cart.included.items) + : [] const groupedItems = groupCartItems(cart.included?.items ?? []) @@ -33,3 +26,14 @@ function sortItemByCreatedAsc(a: CartItem, b: CartItem) { new Date(b.meta.timestamps.created_at).getTime() ) } + +export function enhanceCartItems(items: CartItem[]) { + const enhanced = + items + ?.filter( + (item) => item.type === "cart_item" || item.type === "custom_item", + ) + .sort(sortItemByCreatedAsc) ?? [] + + return enhanced as ReadonlyArray +} diff --git a/packages/react-shopper-hooks/src/cart/util/index.ts b/packages/react-shopper-hooks/src/cart/util/index.ts new file mode 100644 index 00000000..fc202909 --- /dev/null +++ b/packages/react-shopper-hooks/src/cart/util/index.ts @@ -0,0 +1,2 @@ +export * from "./enhance-cart-response" +export * from "./group-cart-items" diff --git a/packages/react-shopper-hooks/src/currency/hooks/index.ts b/packages/react-shopper-hooks/src/currency/hooks/index.ts new file mode 100644 index 00000000..aaee86ef --- /dev/null +++ b/packages/react-shopper-hooks/src/currency/hooks/index.ts @@ -0,0 +1 @@ +export * from "./use-currencies" diff --git a/packages/react-shopper-hooks/src/currency/hooks/use-currencies.tsx b/packages/react-shopper-hooks/src/currency/hooks/use-currencies.tsx new file mode 100644 index 00000000..c7fcf01f --- /dev/null +++ b/packages/react-shopper-hooks/src/currency/hooks/use-currencies.tsx @@ -0,0 +1,27 @@ +import { useElasticPath } from "../../elasticpath" +import { UseQueryOptionsWrapper } from "../../types" +import type { Currency, ResourcePage } from "@moltin/sdk" +import { useQuery, UseQueryResult } from "@tanstack/react-query" +import { queryKeysFactory } from "../../shared/util/query-keys-factory" + +const CURRENCY_QUERY_KEY = "currency" as const + +export const currencyQueryKeys = queryKeysFactory(CURRENCY_QUERY_KEY) +type CurrencyQueryKey = typeof currencyQueryKeys + +export function useCurrencies( + options?: UseQueryOptionsWrapper< + ResourcePage, + Error, + ReturnType + >, +): Partial> & + Omit, Error>, "data"> { + const { client } = useElasticPath() + const { data, ...rest } = useQuery({ + queryKey: currencyQueryKeys.list(), + queryFn: () => client.Currencies.All(), + ...options, + }) + return { ...data, ...rest } as const +} diff --git a/packages/react-shopper-hooks/src/currency/index.ts b/packages/react-shopper-hooks/src/currency/index.ts new file mode 100644 index 00000000..351e313d --- /dev/null +++ b/packages/react-shopper-hooks/src/currency/index.ts @@ -0,0 +1 @@ +export * from "./hooks" diff --git a/packages/react-shopper-hooks/src/index.ts b/packages/react-shopper-hooks/src/index.ts index 1c9bb9ce..755fe624 100644 --- a/packages/react-shopper-hooks/src/index.ts +++ b/packages/react-shopper-hooks/src/index.ts @@ -6,4 +6,6 @@ export * from "./store" export * from "./product" export * from "./account" export * from "./elasticpath" +export * from "./payments" +export * from "./currency" export * from "@elasticpath/shopper-common" diff --git a/packages/react-shopper-hooks/src/payments/hooks/index.ts b/packages/react-shopper-hooks/src/payments/hooks/index.ts new file mode 100644 index 00000000..3e371f94 --- /dev/null +++ b/packages/react-shopper-hooks/src/payments/hooks/index.ts @@ -0,0 +1 @@ +export * from "./use-payments" diff --git a/packages/react-shopper-hooks/src/payments/hooks/use-payments.ts b/packages/react-shopper-hooks/src/payments/hooks/use-payments.ts new file mode 100644 index 00000000..a2262c55 --- /dev/null +++ b/packages/react-shopper-hooks/src/payments/hooks/use-payments.ts @@ -0,0 +1,20 @@ +import { useMutation, UseMutationOptions } from "@tanstack/react-query" +import { useElasticPath } from "../../elasticpath" +import { ConfirmPaymentResponse, PaymentRequestBody } from "@moltin/sdk" + +export type UsePaymentsReq = { + orderId: string + payment: PaymentRequestBody +} + +export const usePayments = ( + options?: UseMutationOptions, +) => { + const { client } = useElasticPath() + return useMutation({ + mutationFn: async ({ orderId, payment }: UsePaymentsReq) => { + return client.Orders.Payment(orderId, payment) + }, + ...options, + }) +} diff --git a/packages/react-shopper-hooks/src/payments/index.ts b/packages/react-shopper-hooks/src/payments/index.ts new file mode 100644 index 00000000..351e313d --- /dev/null +++ b/packages/react-shopper-hooks/src/payments/index.ts @@ -0,0 +1 @@ +export * from "./hooks"