From 643033abb973942cbe2ff30bd7e2a539fa7984ed Mon Sep 17 00:00:00 2001 From: Jorge Moya Date: Thu, 28 Mar 2024 18:15:01 -0500 Subject: [PATCH] feat(core): fetch and show digital items in Cart (#713) --- .changeset/fair-shrimps-compete.md | 5 + .../cart/_components/cart-item-counter.tsx | 9 +- .../(default)/cart/_components/cart-item.tsx | 119 ++++++++++++++++++ .../core/app/[locale]/(default)/cart/page.tsx | 116 +---------------- apps/core/client/queries/get-cart.ts | 42 +++++++ 5 files changed, 177 insertions(+), 114 deletions(-) create mode 100644 .changeset/fair-shrimps-compete.md create mode 100644 apps/core/app/[locale]/(default)/cart/_components/cart-item.tsx diff --git a/.changeset/fair-shrimps-compete.md b/.changeset/fair-shrimps-compete.md new file mode 100644 index 000000000..eff7744bf --- /dev/null +++ b/.changeset/fair-shrimps-compete.md @@ -0,0 +1,5 @@ +--- +"@bigcommerce/catalyst-core": patch +--- + +Fetch and show digital items in Cart summary. diff --git a/apps/core/app/[locale]/(default)/cart/_components/cart-item-counter.tsx b/apps/core/app/[locale]/(default)/cart/_components/cart-item-counter.tsx index 5c858f8a7..2917f1642 100644 --- a/apps/core/app/[locale]/(default)/cart/_components/cart-item-counter.tsx +++ b/apps/core/app/[locale]/(default)/cart/_components/cart-item-counter.tsx @@ -8,6 +8,8 @@ import { getCart } from '~/client/queries/get-cart'; import { updateProductQuantity } from '../_actions/update-product-quantity'; +import { Product } from './cart-item'; + type CartLineItemInput = ReturnType>; type CartSelectedOptionsInput = ReturnType>; type UpdateCartLineItemInput = ReturnType>; @@ -124,9 +126,8 @@ const parseSelectedOptions = (selectedOptions: CartItemData['selectedOptions']) }, {}); }; -export const CartItemCounter = ({ itemData }: { itemData: CartItemData }) => { - const { quantity, lineItemEntityId, productEntityId, variantEntityId, selectedOptions } = - itemData; +export const CartItemCounter = ({ product }: { product: Product }) => { + const { quantity, entityId, productEntityId, variantEntityId, selectedOptions } = product; const [counterValue, setCounterValue] = useState<'' | number>(quantity); const handleCountUpdate = async (value: string | number) => { @@ -140,7 +141,7 @@ export const CartItemCounter = ({ itemData }: { itemData: CartItemData }) => { const productData: UpdateProductQuantityData = Object.assign( { - lineItemEntityId, + lineItemEntityId: entityId, productEntityId, quantity: Number(value), selectedOptions: parseSelectedOptions(selectedOptions), diff --git a/apps/core/app/[locale]/(default)/cart/_components/cart-item.tsx b/apps/core/app/[locale]/(default)/cart/_components/cart-item.tsx new file mode 100644 index 000000000..0a387fa45 --- /dev/null +++ b/apps/core/app/[locale]/(default)/cart/_components/cart-item.tsx @@ -0,0 +1,119 @@ +import { Trash } from 'lucide-react'; +import { getTranslations } from 'next-intl/server'; + +import { getCart } from '~/client/queries/get-cart'; +import { ExistingResultType } from '~/client/util'; +import { BcImage } from '~/components/bc-image'; + +import { removeProduct } from '../_actions/remove-products'; + +import { CartItemCounter } from './cart-item-counter'; + +export type Product = + | ExistingResultType['lineItems']['physicalItems'][number] + | ExistingResultType['lineItems']['digitalItems'][number]; + +export const CartItem = async ({ + currencyCode, + product, +}: { + currencyCode: string; + product: Product; +}) => { + const t = await getTranslations('Cart'); + + const currencyFormatter = new Intl.NumberFormat('en-US', { + style: 'currency', + currency: currencyCode, + }); + + return ( +
  • +
    +
    + +
    + +
    +

    {product.brand}

    +

    {product.name}

    + + {product.selectedOptions.length > 0 && ( +
    + {product.selectedOptions.map((selectedOption) => { + switch (selectedOption.__typename) { + case 'CartSelectedMultipleChoiceOption': + return ( +
    + {selectedOption.name}:{' '} + {selectedOption.value} +
    + ); + + case 'CartSelectedCheckboxOption': + return ( +
    + {selectedOption.name}:{' '} + {selectedOption.value} +
    + ); + + case 'CartSelectedNumberFieldOption': + return ( +
    + {selectedOption.name}:{' '} + {selectedOption.number} +
    + ); + + case 'CartSelectedMultiLineTextFieldOption': + return ( +
    + {selectedOption.name}:{' '} + {selectedOption.text} +
    + ); + + case 'CartSelectedTextFieldOption': + return ( +
    + {selectedOption.name}:{' '} + {selectedOption.text} +
    + ); + + case 'CartSelectedDateFieldOption': + return ( +
    + {selectedOption.name}:{' '} + + {Intl.DateTimeFormat().format(new Date(selectedOption.date.utc))} + +
    + ); + } + + return null; + })} +
    + )} +
    + + + +
    +

    + {currencyFormatter.format(product.extendedSalePrice.value)} +

    +
    + +
    + + +
    +
    +
  • + ); +}; diff --git a/apps/core/app/[locale]/(default)/cart/page.tsx b/apps/core/app/[locale]/(default)/cart/page.tsx index f9d7cfaff..8940b9c9b 100644 --- a/apps/core/app/[locale]/(default)/cart/page.tsx +++ b/apps/core/app/[locale]/(default)/cart/page.tsx @@ -1,5 +1,4 @@ import { Button } from '@bigcommerce/components/button'; -import { Trash2 as Trash } from 'lucide-react'; import { cookies } from 'next/headers'; import { useTranslations } from 'next-intl'; import { getTranslations } from 'next-intl/server'; @@ -7,11 +6,9 @@ import { Suspense } from 'react'; import { getCheckoutUrl } from '~/client/management/get-checkout-url'; import { getCart } from '~/client/queries/get-cart'; -import { BcImage } from '~/components/bc-image'; import { LocaleType } from '~/i18n'; -import { removeProduct } from './_actions/remove-products'; -import { CartItemCounter } from './_components/cart-item-counter'; +import { CartItem } from './_components/cart-item'; import { CheckoutSummary } from './_components/checkout-summary'; export const metadata = { @@ -62,118 +59,17 @@ export default async function CartPage({ params: { locale } }: Props) { return ; } - const extractCartlineItemsData = ({ - entityId, - productEntityId, - quantity, - variantEntityId, - selectedOptions, - }: (typeof cart.lineItems.physicalItems)[number]) => ({ - lineItemEntityId: entityId, - productEntityId, - quantity, - variantEntityId, - selectedOptions, - }); - return (

    {t('heading')}

      {cart.lineItems.physicalItems.map((product) => ( -
    • -
      -
      - -
      - -
      -

      {product.brand}

      -

      {product.name}

      - - {product.selectedOptions.length > 0 && ( -
      - {product.selectedOptions.map((selectedOption) => { - switch (selectedOption.__typename) { - case 'CartSelectedMultipleChoiceOption': - return ( -
      - {selectedOption.name}:{' '} - {selectedOption.value} -
      - ); - - case 'CartSelectedCheckboxOption': - return ( -
      - {selectedOption.name}:{' '} - {selectedOption.value} -
      - ); - - case 'CartSelectedNumberFieldOption': - return ( -
      - {selectedOption.name}:{' '} - {selectedOption.number} -
      - ); - - case 'CartSelectedMultiLineTextFieldOption': - return ( -
      - {selectedOption.name}:{' '} - {selectedOption.text} -
      - ); - - case 'CartSelectedTextFieldOption': - return ( -
      - {selectedOption.name}:{' '} - {selectedOption.text} -
      - ); - - case 'CartSelectedDateFieldOption': - return ( -
      - {selectedOption.name}:{' '} - - {Intl.DateTimeFormat().format(new Date(selectedOption.date.utc))} - -
      - ); - } - - return null; - })} -
      - )} -
      - - - -
      -

      - ${product.extendedSalePrice.value} -

      -
      - -
      - - -
      -
      -
    • + + ))} + + {cart.lineItems.digitalItems.map((product) => ( + ))}
    diff --git a/apps/core/client/queries/get-cart.ts b/apps/core/client/queries/get-cart.ts index 16d594471..6a54970a9 100644 --- a/apps/core/client/queries/get-cart.ts +++ b/apps/core/client/queries/get-cart.ts @@ -64,6 +64,48 @@ const GET_CART_QUERY = graphql( } } } + digitalItems { + name + brand + imageUrl + entityId + quantity + productEntityId + variantEntityId + extendedListPrice { + ...MoneyFields + } + extendedSalePrice { + ...MoneyFields + } + selectedOptions { + __typename + entityId + name + ... on CartSelectedMultipleChoiceOption { + value + valueEntityId + } + ... on CartSelectedCheckboxOption { + value + valueEntityId + } + ... on CartSelectedNumberFieldOption { + number + } + ... on CartSelectedMultiLineTextFieldOption { + text + } + ... on CartSelectedTextFieldOption { + text + } + ... on CartSelectedDateFieldOption { + date { + utc + } + } + } + } } amount { ...MoneyFields