Fix typescript errors & normalize cart

Signed-off-by: Chloe <pinkcloudvnn@gmail.com>
This commit is contained in:
Chloe 2022-04-28 19:09:35 +07:00
parent 7d1b542b6f
commit 2a32beb5cd
14 changed files with 59 additions and 39 deletions

View File

@ -5,7 +5,9 @@ import type {
HookFetcherContext,
} from '@vercel/commerce/utils/types'
import { ValidationError } from '@vercel/commerce/utils/errors'
import useUpdateItem, { UseUpdateItem } from '@vercel/commerce/cart/use-update-item'
import useUpdateItem, {
UseUpdateItem,
} from '@vercel/commerce/cart/use-update-item'
import type { LineItem, UpdateItemHook } from '@vercel/commerce/types/cart'
import { handler as removeItemHandler } from './use-remove-item'
import useCart from './use-cart'

View File

@ -4,7 +4,6 @@ import addCartItemsMutation from '../../mutations/add-cart-item'
import createCartMutation from '../../mutations/create-cart'
import type { CartEndpoint } from '.'
import { CreateCartPayload } from '../../../../schema'
const addItem: CartEndpoint['handlers']['addItem'] = async ({
res,
@ -37,20 +36,28 @@ const addItem: CartEndpoint['handlers']['addItem'] = async ({
}
if (!cartId) {
const { data } = await config.fetch(createCartMutation, { variables })
const {
data: { createCart },
} = await config.fetch(createCartMutation, { variables })
res.setHeader('Set-Cookie', [
getCartCookie(config.cartCookie, data.cart._id, config.cartCookieMaxAge),
getCartCookie(
config.cartCookie,
createCart.cart._id,
config.cartCookieMaxAge
),
getCartCookie(
config.anonymousCartTokenCookie,
data.token,
createCart.token,
config.cartCookieMaxAge
),
])
return res.status(200).json({ data: normalizeCart(data.cart) })
return res.status(200).json({ data: normalizeCart(createCart.cart) })
}
const { data } = await config.fetch(addCartItemsMutation, {
const {
data: { addCartItems },
} = await config.fetch(addCartItemsMutation, {
variables: {
input: {
items: variables.input.items,
@ -60,7 +67,7 @@ const addItem: CartEndpoint['handlers']['addItem'] = async ({
},
})
return res.status(200).json({ data: normalizeCart(data.cart) })
return res.status(200).json({ data: normalizeCart(addCartItems.cart) })
}
export default addItem

View File

@ -1,6 +1,5 @@
import { normalizeCart } from '../../../utils/normalize'
import getCartCookie from '../../utils/get-cart-cookie'
import getAnonymousCart from '../../queries/get-anonymous-cart'
import getAnonymousCartQuery from '../../queries/get-anonymous-cart'
import type { CartEndpoint } from '.'
// Return current cart info
@ -11,7 +10,9 @@ const getCart: CartEndpoint['handlers']['getCart'] = async ({
config,
}) => {
if (cartId && cookies[config.anonymousCartTokenCookie]) {
const { data } = await config.fetch(getAnonymousCart, {
const {
data: { cart: rawAnonymousCart },
} = await config.fetch(getAnonymousCartQuery, {
variables: {
cartId,
cartToken: cookies[config.anonymousCartTokenCookie],
@ -19,7 +20,7 @@ const getCart: CartEndpoint['handlers']['getCart'] = async ({
})
return res.status(200).json({
data: normalizeCart(data),
data: normalizeCart(rawAnonymousCart),
})
}

View File

@ -16,7 +16,9 @@ const removeItem: CartEndpoint['handlers']['removeItem'] = async ({
})
}
const { data } = await config.fetch(removeCartItemsMutation, {
const {
data: { removeCartItems },
} = await config.fetch(removeCartItemsMutation, {
variables: {
input: {
cartId,
@ -31,7 +33,7 @@ const removeItem: CartEndpoint['handlers']['removeItem'] = async ({
getCartCookie(config.cartCookie, cartId, config.cartCookieMaxAge)
)
res.status(200).json({ data: normalizeCart(data.cart) })
res.status(200).json({ data: normalizeCart(removeCartItems.cart) })
}
export default removeItem

View File

@ -2,6 +2,7 @@ import { normalizeCart } from '../../../utils/normalize'
import getCartCookie from '../../utils/get-cart-cookie'
import updateCartItemsQuantityMutation from '../../mutations/update-cart-item-quantity'
import type { CartEndpoint } from '.'
import { UpdateCartItemsQuantityPayload } from '../../../../schema'
const updateItem: CartEndpoint['handlers']['updateItem'] = async ({
res,
@ -16,9 +17,11 @@ const updateItem: CartEndpoint['handlers']['updateItem'] = async ({
})
}
const { data } = await config.fetch(updateCartItemsQuantityMutation, {
const {
data: { updateCartItemsQuantity },
} = await config.fetch(updateCartItemsQuantityMutation, {
variables: {
input: {
updateCartItemsQuantityInput: {
cartId,
cartToken: cookies[config.anonymousCartTokenCookie],
items: [{ cartItemId: itemId, quantity: item.quantity }],
@ -31,7 +34,7 @@ const updateItem: CartEndpoint['handlers']['updateItem'] = async ({
'Set-Cookie',
getCartCookie(config.cartCookie, cartId, config.cartCookieMaxAge)
)
res.status(200).json({ data: normalizeCart(data.cart) })
res.status(200).json({ data: normalizeCart(updateCartItemsQuantity.cart) })
}
export default updateItem

View File

@ -1,6 +1,6 @@
import { cartPayloadFragment } from '../queries/get-cart-query'
const updateCartItemsQuantityMutation = `
const updateCartItemsQuantityMutation = /* GraphQL */ `
mutation updateCartItemsQuantity($updateCartItemsQuantityInput: UpdateCartItemsQuantityInput!) {
updateCartItemsQuantity(input: $updateCartItemsQuantityInput) {
cart {

View File

@ -1,7 +1,7 @@
import { cartQueryFragment } from './get-cart-query'
export const getAnonymousCart = /* GraphQL */ `
query anonymousCartByCartIdQuery($cartId: ID!, $cartToken: String!) {
export const getAnonymousCart = `
query anonymousCartByCartIdQuery($cartId: ID!, $cartToken: String!, $itemsAfterCursor: ConnectionCursor) {
cart: anonymousCartByCartId(cartId: $cartId, cartToken: $cartToken) {
${cartQueryFragment}
}

View File

@ -3,11 +3,12 @@ import useAddItem, { UseAddItem } from '@vercel/commerce/cart/use-add-item'
import type { AddItemHook } from '@vercel/commerce/types/cart'
import { CommerceError } from '@vercel/commerce/utils/errors'
import { MutationHook } from '@vercel/commerce/utils/types'
import { CartTypes } from '../types/cart'
import useCart from './use-cart'
export default useAddItem as UseAddItem<typeof handler>
export const handler: MutationHook<AddItemHook> = {
export const handler: MutationHook<AddItemHook<CartTypes>> = {
fetchOptions: {
url: '/api/cart',
method: 'POST',

View File

@ -1,6 +1,7 @@
import { useCallback } from 'react'
import {
HookFetcherContext,
MutationHook,
MutationHookContext,
} from '@vercel/commerce/utils/types'
import useRemoveItem, {
@ -24,16 +25,12 @@ export type RemoveItemFn<T = any> = T extends LineItem
export default useRemoveItem as UseRemoveItem<typeof handler>
export const handler = {
export const handler: MutationHook<RemoveItemHook> = {
fetchOptions: {
url: '/api/cart',
method: 'DELETE',
},
async fetcher({
input: { itemId },
options,
fetch,
}: HookFetcherContext<RemoveItemHook>) {
async fetcher({ input: { itemId }, options, fetch }) {
return await fetch({ ...options, body: { itemId } })
},
useHook:
@ -54,6 +51,6 @@ export const handler = {
return data
}
return useCallback(removeItem, [fetch, mutate])
return useCallback(removeItem as RemoveItemFn<T>, [fetch, mutate])
},
}

View File

@ -17,14 +17,14 @@ export default useUpdateItem as UseUpdateItem<typeof handler>
export const handler: MutationHook<UpdateItemHook> = {
fetchOptions: {
query: '/api/cart',
url: '/api/cart',
method: 'PUT',
},
async fetcher({ input: { itemId, item }, options, 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 removeItemHandler.fetcher({
return removeItemHandler.fetcher!({
options: removeItemHandler.fetchOptions,
input: { itemId },
fetch,

View File

@ -8,15 +8,13 @@ export type Cart = Core.Cart & {
}
export type CartItemBody = Core.CartItemBody & {
price: {
price?: {
amount: number
currency: string
currencyCode: string
}
}
export type CartTypes = {
cart: Cart
item: Core.LineItem
export type CartTypes = Core.CartTypes & {
itemBody: CartItemBody
}

View File

@ -273,6 +273,7 @@ function normalizeLineItem(cartItemEdge: CartItemEdge): LineItem {
optionTitle,
variantTitle,
quantity,
productSlug,
} = <CartItem>cartItem
return {
@ -292,7 +293,7 @@ function normalizeLineItem(cartItemEdge: CartItemEdge): LineItem {
price: priceWhenAdded?.amount,
listPrice: compareAtPrice?.amount ?? 0,
},
path: '',
path: productSlug ?? '',
discounts: [],
options: [
{

View File

@ -45,13 +45,17 @@ const CartItem = ({
target: { value },
}: ChangeEvent<HTMLInputElement>) => {
setQuantity(Number(value))
await updateItem({ quantity: Number(value) })
await updateItem({
quantity: Number(value),
variantId: item.variantId,
id: item.id,
})
}
const increaseQuantity = async (n = 1) => {
const val = Number(quantity) + n
setQuantity(val)
await updateItem({ quantity: val })
await updateItem({ quantity: val, variantId: item.variantId, id: item.id })
}
const handleRemove = async () => {
@ -93,7 +97,7 @@ const CartItem = ({
width={150}
height={150}
src={item.variant.image?.url || placeholderImg}
alt={item.variant.image?.altText || "Product Image"}
alt={item.variant.image?.altText || 'Product Image'}
unoptimized
/>
</a>

View File

@ -32,6 +32,10 @@ const ProductSidebar: FC<ProductSidebarProps> = ({ product, className }) => {
await addItem({
productId: String(product.id),
variantId: String(variant ? variant.id : product.variants[0]?.id),
price: {
amount: product.price.value,
currencyCode: String(product.price.currencyCode),
},
})
openSidebar()
setLoading(false)