From d0ed97466c0bee40d305c3abe949fa590baa35ac Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Mon, 25 Jan 2021 14:32:18 +0100 Subject: [PATCH] Implement useUpdateItem & useRemoveItem --- framework/vendure/api/fragments/cart.ts | 27 +++++ .../vendure/api/fragments/category-tree.ts | 9 -- framework/vendure/api/fragments/product.ts | 113 ------------------ framework/vendure/cart/use-add-item.tsx | 19 +-- framework/vendure/cart/use-cart.tsx | 32 +---- framework/vendure/cart/use-remove-item.tsx | 34 +++--- framework/vendure/cart/use-update-item.tsx | 52 +++----- 7 files changed, 71 insertions(+), 215 deletions(-) create mode 100644 framework/vendure/api/fragments/cart.ts delete mode 100644 framework/vendure/api/fragments/category-tree.ts delete mode 100644 framework/vendure/api/fragments/product.ts diff --git a/framework/vendure/api/fragments/cart.ts b/framework/vendure/api/fragments/cart.ts new file mode 100644 index 000000000..ed720d24b --- /dev/null +++ b/framework/vendure/api/fragments/cart.ts @@ -0,0 +1,27 @@ +export const cartFragment = /* GraphQL */ ` + fragment Cart on Order { + id + code + totalQuantity + subTotal + subTotalWithTax + total + totalWithTax + currencyCode + lines { + id + quantity + featuredAsset { + id + preview + } + productVariant { + name + product { + slug + } + productId + } + } + } +` diff --git a/framework/vendure/api/fragments/category-tree.ts b/framework/vendure/api/fragments/category-tree.ts deleted file mode 100644 index e26f17195..000000000 --- a/framework/vendure/api/fragments/category-tree.ts +++ /dev/null @@ -1,9 +0,0 @@ -export const categoryTreeItemFragment = /* GraphQL */ ` - fragment categoryTreeItem on CategoryTreeItem { - entityId - name - path - description - productCount - } -` diff --git a/framework/vendure/api/fragments/product.ts b/framework/vendure/api/fragments/product.ts deleted file mode 100644 index d266b8c92..000000000 --- a/framework/vendure/api/fragments/product.ts +++ /dev/null @@ -1,113 +0,0 @@ -export const productPrices = /* GraphQL */ ` - fragment productPrices on Prices { - price { - value - currencyCode - } - salePrice { - value - currencyCode - } - retailPrice { - value - currencyCode - } - } -` - -export const swatchOptionFragment = /* GraphQL */ ` - fragment swatchOption on SwatchOptionValue { - isDefault - hexColors - } -` - -export const multipleChoiceOptionFragment = /* GraphQL */ ` - fragment multipleChoiceOption on MultipleChoiceOption { - values { - edges { - node { - label - ...swatchOption - } - } - } - } - - ${swatchOptionFragment} -` - -export const productInfoFragment = /* GraphQL */ ` - fragment productInfo on Product { - entityId - name - path - brand { - entityId - } - description - prices { - ...productPrices - } - images { - edges { - node { - urlOriginal - altText - isDefault - } - } - } - variants { - edges { - node { - entityId - defaultImage { - urlOriginal - altText - isDefault - } - } - } - } - productOptions { - edges { - node { - __typename - entityId - displayName - ...multipleChoiceOption - } - } - } - localeMeta: metafields(namespace: $locale, keys: ["name", "description"]) - @include(if: $hasLocale) { - edges { - node { - key - value - } - } - } - } - - ${productPrices} - ${multipleChoiceOptionFragment} -` - -export const productConnectionFragment = /* GraphQL */ ` - fragment productConnnection on ProductConnection { - pageInfo { - startCursor - endCursor - } - edges { - cursor - node { - ...productInfo - } - } - } - - ${productInfoFragment} -` diff --git a/framework/vendure/cart/use-add-item.tsx b/framework/vendure/cart/use-add-item.tsx index 0f8bb5278..fe889be7e 100644 --- a/framework/vendure/cart/use-add-item.tsx +++ b/framework/vendure/cart/use-add-item.tsx @@ -4,28 +4,15 @@ import fetchGraphqlApi from '@framework/api/utils/fetch-graphql-api' import useCartAddItem from '@commerce/cart/use-add-item' import useCart from './use-cart' import { useCallback } from 'react' +import { cartFragment } from '../api/fragments/cart' export const addItemToOrderMutation = /* GraphQL */ ` mutation addItemToOrder($variantId: ID!, $quantity: Int!) { addItemToOrder(productVariantId: $variantId, quantity: $quantity) { - ... on Order { - id - code - totalQuantity - total - totalWithTax - lines { - id - productVariant { - featuredAsset { - id - preview - } - } - } - } + ... Cart } } + ${cartFragment} ` export type AddItemInput = { productId?: number; variantId: number; quantity?: number; }; diff --git a/framework/vendure/cart/use-cart.tsx b/framework/vendure/cart/use-cart.tsx index 7219c2eb7..1f0c72bd5 100644 --- a/framework/vendure/cart/use-cart.tsx +++ b/framework/vendure/cart/use-cart.tsx @@ -6,35 +6,15 @@ import useResponse from '@commerce/utils/use-response' import useAction from '@commerce/utils/use-action' import { useCallback } from 'react' import { normalizeCart } from '../../bigcommerce/lib/normalize' +import { cartFragment } from '../api/fragments/cart' export const getCartQuery = /* GraphQL */ ` query activeOrder { activeOrder { - id - code - totalQuantity - subTotal - subTotalWithTax - total - totalWithTax - currencyCode - lines { - id - quantity - featuredAsset { - id - preview - } - productVariant { - name - product { - slug - } - productId - } - } + ...Cart } } + ${cartFragment} ` export const fetcher: HookFetcher = ( @@ -50,17 +30,17 @@ export function extendHook( swrOptions?: SwrOptions ) { const useCart = () => { - const response = useData({}, [], customFetcher, swrOptions) + const response = useData({ query: getCartQuery }, [], customFetcher, swrOptions) const res = useResponse(response, { normalizer: (data => { - const order = data?.activeOrder; - console.log({ order }); + const order = data?.activeOrder || data?.addItemToOrder || data?.adjustOrderLine || data?.removeOrderLine; return (order ? { id: order.id, currency: { code: order.currencyCode }, subTotal: order.subTotalWithTax / 100, total: order.totalWithTax / 100, items: order.lines?.map(l => ({ + id: l.id, name: l.productVariant.name, quantity: l.quantity, url: l.productVariant.product.slug, diff --git a/framework/vendure/cart/use-remove-item.tsx b/framework/vendure/cart/use-remove-item.tsx index e38c267af..16483954f 100644 --- a/framework/vendure/cart/use-remove-item.tsx +++ b/framework/vendure/cart/use-remove-item.tsx @@ -1,41 +1,41 @@ import { useCallback } from 'react' import { HookFetcher } from '@commerce/utils/types' import useCartRemoveItem from '@commerce/cart/use-remove-item' -import type { RemoveItemBody } from '../api/cart' import useCart, { Cart } from './use-cart' +import { cartFragment } from '@framework/api/fragments/cart' -const defaultOpts = { - url: '/api/bigcommerce/cart', - method: 'DELETE', -} +export const removeOrderLineMutation = /* GraphQL */ ` + mutation removeOrderLine($orderLineId: ID!) { + removeOrderLine(orderLineId: $orderLineId) { + ...Cart + } + } + ${cartFragment} +` -export type RemoveItemInput = { - id: string -} - -export const fetcher: HookFetcher = ( +export const fetcher: HookFetcher = ( options, - { itemId }, + { lineId }, fetch ) => { return fetch({ - ...defaultOpts, ...options, - body: { itemId }, + query: removeOrderLineMutation, + variables: { orderLineId: lineId }, }) } export function extendHook(customFetcher: typeof fetcher) { const useRemoveItem = (item?: any) => { const { mutate } = useCart() - const fn = useCartRemoveItem( - defaultOpts, + const fn = useCartRemoveItem( + {}, customFetcher ) return useCallback( - async function removeItem(input: RemoveItemInput) { - const data = await fn({ itemId: input.id ?? item?.id }) + async function removeItem(input: any) { + const data = await fn({ lineId: input.id }) await mutate(data, false) return data }, diff --git a/framework/vendure/cart/use-update-item.tsx b/framework/vendure/cart/use-update-item.tsx index ca5703505..fc42da311 100644 --- a/framework/vendure/cart/use-update-item.tsx +++ b/framework/vendure/cart/use-update-item.tsx @@ -1,59 +1,43 @@ import { useCallback } from 'react' import debounce from 'lodash.debounce' import type { HookFetcher } from '@commerce/utils/types' -import { CommerceError } from '@commerce/utils/errors' import useCartUpdateItem from '@commerce/cart/use-update-item' -import type { ItemBody, UpdateItemBody } from '../api/cart' -import { fetcher as removeFetcher } from './use-remove-item' import useCart, { Cart } from './use-cart' +import { cartFragment } from '@framework/api/fragments/cart' -const defaultOpts = { - url: '/api/bigcommerce/cart', - method: 'PUT', -} - -export type UpdateItemInput = Partial<{ id: string } & ItemBody> - -export const fetcher: HookFetcher = ( +export const adjustOrderLineMutation = /* GraphQL */ ` + mutation adjustOrderLine($orderLineId: ID!, $quantity: Int!) { + adjustOrderLine(orderLineId: $orderLineId, quantity: $quantity) { + ...Cart + } + } + ${cartFragment} +` +export const fetcher: HookFetcher = ( options, - { itemId, item }, + { lineId, quantity }, fetch ) => { - if (Number.isInteger(item.quantity)) { - // Also allow the update hook to remove an item if the quantity is lower than 1 - if (item.quantity! < 1) { - return removeFetcher(null, { itemId }, fetch) - } - } else if (item.quantity) { - throw new CommerceError({ - message: 'The item quantity has to be a valid integer', - }) - } - return fetch({ - ...defaultOpts, ...options, - body: { itemId, item }, + query: adjustOrderLineMutation, + variables: { orderLineId: lineId, quantity }, }) } function extendHook(customFetcher: typeof fetcher, cfg?: { wait?: number }) { const useUpdateItem = (item?: any) => { const { mutate } = useCart() - const fn = useCartUpdateItem( - defaultOpts, + const fn = useCartUpdateItem( + {}, customFetcher ) return useCallback( - debounce(async (input: UpdateItemInput) => { + debounce(async (input: any) => { const data = await fn({ - itemId: input.id ?? item?.id, - item: { - productId: input.productId ?? item?.product_id, - variantId: input.productId ?? item?.variant_id, - quantity: input.quantity, - }, + lineId: item.id, + quantity: input.quantity, }) await mutate(data, false) return data