From f369746e7655e7f01be7324443eeafb27ba5e7ff Mon Sep 17 00:00:00 2001 From: Lee Robinson Date: Sun, 1 Oct 2023 10:19:52 -0500 Subject: [PATCH] More! --- components/cart/actions.ts | 53 ++++++++---- components/cart/add-to-cart.tsx | 8 +- components/cart/delete-item-button.tsx | 63 +++++++------- components/cart/edit-item-quantity-button.tsx | 86 ++++++++++--------- components/cart/modal.tsx | 4 +- 5 files changed, 122 insertions(+), 92 deletions(-) diff --git a/components/cart/actions.ts b/components/cart/actions.ts index 72af2b9fc..7de539550 100644 --- a/components/cart/actions.ts +++ b/components/cart/actions.ts @@ -1,7 +1,13 @@ 'use server'; import { TAGS } from 'lib/constants'; -import { addToCart, createCart, getCart, removeFromCart, updateCart } from 'lib/shopify'; +import { + addToCart, + createCart, + getCart, + removeFromCart, + updateCart, +} from 'lib/shopify'; import { revalidateTag } from 'next/cache'; import { cookies } from 'next/headers'; @@ -24,49 +30,62 @@ export async function addItem(prevState: any, selectedVariantId: string) { } try { - await addToCart(cartId, [{ merchandiseId: selectedVariantId, quantity: 1 }]); - revalidateTag(TAGS.cart) + await addToCart(cartId, [ + { merchandiseId: selectedVariantId, quantity: 1 } + ]); + revalidateTag(TAGS.cart); } catch (e) { return 'Error adding item to cart'; } -}; +} -export const removeItem = async (lineId: string): Promise => { +export async function removeItem(prevState: any, lineId: string) { const cartId = cookies().get('cartId')?.value; if (!cartId) { return 'Missing cart ID'; } + try { await removeFromCart(cartId, [lineId]); + revalidateTag(TAGS.cart); } catch (e) { return 'Error removing item from cart'; } -}; +} -export const updateItemQuantity = async ({ - lineId, - variantId, - quantity -}: { - lineId: string; - variantId: string; - quantity: number; -}): Promise => { +export async function updateItemQuantity( + prevState: any, + payload: { + lineId: string; + variantId: string; + quantity: number; + } +) { const cartId = cookies().get('cartId')?.value; if (!cartId) { return 'Missing cart ID'; } + + const { lineId, variantId, quantity } = payload; + try { + if (quantity === 0) { + await removeFromCart(cartId, [lineId]); + revalidateTag(TAGS.cart); + return; + } + await updateCart(cartId, [ { id: lineId, merchandiseId: variantId, - quantity + quantity, } ]); + revalidateTag(TAGS.cart); } catch (e) { return 'Error updating item quantity'; } -}; +} diff --git a/components/cart/add-to-cart.tsx b/components/cart/add-to-cart.tsx index bb91596c4..c8907a520 100644 --- a/components/cart/add-to-cart.tsx +++ b/components/cart/add-to-cart.tsx @@ -6,8 +6,8 @@ import { addItem } from 'components/cart/actions'; import LoadingDots from 'components/loading-dots'; import { ProductVariant } from 'lib/shopify/types'; import { useSearchParams } from 'next/navigation'; -// @ts-ignore import { + // @ts-ignore experimental_useFormState as useFormState, experimental_useFormStatus as useFormStatus } from 'react-dom'; @@ -58,10 +58,10 @@ function SubmitButton({ })} >
- {!pending ? ( - - ) : ( + {pending ? ( + ) : ( + )}
Add To Cart diff --git a/components/cart/delete-item-button.tsx b/components/cart/delete-item-button.tsx index 605adcf51..a53550013 100644 --- a/components/cart/delete-item-button.tsx +++ b/components/cart/delete-item-button.tsx @@ -1,44 +1,49 @@ -import { XMarkIcon } from '@heroicons/react/24/outline'; -import LoadingDots from 'components/loading-dots'; -import { useRouter } from 'next/navigation'; +'use client'; +import { XMarkIcon } from '@heroicons/react/24/outline'; import clsx from 'clsx'; import { removeItem } from 'components/cart/actions'; +import LoadingDots from 'components/loading-dots'; import type { CartItem } from 'lib/shopify/types'; -import { useTransition } from 'react'; - -export default function DeleteItemButton({ item }: { item: CartItem }) { - const router = useRouter(); - const [isPending, startTransition] = useTransition(); +import { + // @ts-ignore + experimental_useFormState as useFormState, + experimental_useFormStatus as useFormStatus +} from 'react-dom'; +function SubmitButton() { + const { pending } = useFormStatus(); + return ( ); } + +export function DeleteItemButton({ item }: { item: CartItem }) { + const [message, formAction] = useFormState(removeItem, null); + const itemId = item.id; + const actionWithVariant = formAction.bind(null, itemId); + + return ( +
+ +

+ {message} +

+ + ); +} diff --git a/components/cart/edit-item-quantity-button.tsx b/components/cart/edit-item-quantity-button.tsx index e846196ca..7e14d6b2e 100644 --- a/components/cart/edit-item-quantity-button.tsx +++ b/components/cart/edit-item-quantity-button.tsx @@ -1,60 +1,66 @@ -import { useRouter } from 'next/navigation'; -import { useTransition } from 'react'; +'use client'; import { MinusIcon, PlusIcon } from '@heroicons/react/24/outline'; import clsx from 'clsx'; -import { removeItem, updateItemQuantity } from 'components/cart/actions'; +import { updateItemQuantity } from 'components/cart/actions'; import LoadingDots from 'components/loading-dots'; import type { CartItem } from 'lib/shopify/types'; +import { + // @ts-ignore + experimental_useFormState as useFormState, + experimental_useFormStatus as useFormStatus, +} from 'react-dom'; -export default function EditItemQuantityButton({ - item, - type -}: { - item: CartItem; - type: 'plus' | 'minus'; -}) { - const router = useRouter(); - const [isPending, startTransition] = useTransition(); +function SubmitButton({ type }: { type: 'plus' | 'minus' }) { + const { pending } = useFormStatus(); return ( ); } + +export function EditItemQuantityButton({ + item, + type, +}: { + item: CartItem; + type: 'plus' | 'minus'; +}) { + const [message, formAction] = useFormState(updateItemQuantity, null); + const payload = { + lineId: item.id, + variantId: item.merchandise.id, + quantity: type === 'plus' ? item.quantity + 1 : item.quantity - 1, + }; + const actionWithVariant = formAction.bind(null, payload); + + return ( +
+ +

+ {message} +

+ + ); +} diff --git a/components/cart/modal.tsx b/components/cart/modal.tsx index 4fbfcc6ad..aee2f7a47 100644 --- a/components/cart/modal.tsx +++ b/components/cart/modal.tsx @@ -10,8 +10,8 @@ import Image from 'next/image'; import Link from 'next/link'; import { Fragment, useEffect, useRef, useState } from 'react'; import CloseCart from './close-cart'; -import DeleteItemButton from './delete-item-button'; -import EditItemQuantityButton from './edit-item-quantity-button'; +import { DeleteItemButton } from './delete-item-button'; +import { EditItemQuantityButton } from './edit-item-quantity-button'; import OpenCart from './open-cart'; type MerchandiseSearchParams = {