Skip to content

Commit

Permalink
feat(core): remove quick add button from PLP (#1313)
Browse files Browse the repository at this point in the history
* feat(core): remove quick add button from PLP

* fix: update tests
  • Loading branch information
jorgemoya committed Aug 27, 2024
1 parent 1c3ecfe commit 6531bb2
Show file tree
Hide file tree
Showing 43 changed files with 134 additions and 492 deletions.
5 changes: 5 additions & 0 deletions .changeset/young-gorillas-hang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@bigcommerce/catalyst-core": patch
---

Remove "Quick add" button in PLP for products that have options. Will now just show a button that links to the product.
17 changes: 2 additions & 15 deletions core/app/[locale]/(default)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { NextIntlClientProvider } from 'next-intl';
import { getMessages, unstable_setRequestLocale } from 'next-intl/server';
import { PropsWithChildren, Suspense } from 'react';
import { unstable_setRequestLocale } from 'next-intl/server';
import { PropsWithChildren } from 'react';

import { getSessionCustomerId } from '~/auth';
import { client } from '~/client';
Expand All @@ -11,7 +10,6 @@ import { FooterFragment } from '~/components/footer/fragment';
import { Header } from '~/components/header';
import { Cart } from '~/components/header/cart';
import { HeaderFragment } from '~/components/header/fragment';
import { ProductSheet } from '~/components/product-sheet';
import { LocaleType } from '~/i18n';

interface Props extends PropsWithChildren {
Expand Down Expand Up @@ -40,8 +38,6 @@ export default async function DefaultLayout({ children, params: { locale } }: Pr
fetchOptions: customerId ? { cache: 'no-store' } : { next: { revalidate } },
});

const messages = await getMessages({ locale });

return (
<>
<Header cart={<Cart />} data={data.site} />
Expand All @@ -50,15 +46,6 @@ export default async function DefaultLayout({ children, params: { locale } }: Pr
{children}
</main>

<Suspense fallback={null}>
<NextIntlClientProvider
locale={locale}
messages={{ Product: messages.Product ?? {}, AddToCart: messages.AddToCart ?? {} }}
>
<ProductSheet />
</NextIntlClientProvider>
</Suspense>

<Footer data={data.site} />
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { useFormatter, useTranslations } from 'next-intl';
import { PricingFragment } from '~/client/fragments/pricing';
import { ProductItemFragment } from '~/client/fragments/product-item';
import { FragmentOf, graphql } from '~/client/graphql';
import { ProductForm } from '~/components/product-form';
import { ProductFormFragment } from '~/components/product-form/fragment';

import { ProductForm } from './product-form';
import { ProductFormFragment } from './product-form/fragment';
import { ProductSchema, ProductSchemaFragment } from './product-schema';
import { ReviewSummary, ReviewSummaryFragment } from './review-summary';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { graphql } from '~/client/graphql';

import { AddToCartButtonFragment } from '../add-to-cart-button/fragment';
import { AddToCartButtonFragment } from '~/components/add-to-cart-button/fragment';

import { CheckboxFieldFragment } from './fields/checkbox-field/fragment';
import { DateFieldFragment } from './fields/date-field/fragment';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
'use client';

import { removeEdgesAndNodes } from '@bigcommerce/catalyst-client';
import { FragmentOf } from 'gql.tada';
import { AlertCircle, Check, Heart, ShoppingCart } from 'lucide-react';
import { useTranslations } from 'next-intl';
import { FormProvider, useFormContext } from 'react-hook-form';
import { toast } from 'react-hot-toast';

import { ProductItemFragment } from '~/client/fragments/product-item';
import { FragmentOf } from '~/client/graphql';
import { AddToCartButton } from '~/components/add-to-cart-button';
import { Link } from '~/components/link';
import { Button } from '~/components/ui/button';
import { bodl } from '~/lib/bodl';

import { AddToCartButton } from '../add-to-cart-button';
import { Link } from '../link';

import { handleAddToCart } from './_actions/add-to-cart';
import { CheckboxField } from './fields/checkbox-field';
import { DateField } from './fields/date-field';
Expand Down
63 changes: 0 additions & 63 deletions core/app/api/product/[id]/route.ts

This file was deleted.

2 changes: 1 addition & 1 deletion core/client/fragments/product-item.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ProductFormFragment } from '~/app/[locale]/(default)/product/[slug]/_components/product-form/fragment';
import { graphql } from '~/client/graphql';
import { BreadcrumbsFragment } from '~/components/breadcrumbs/fragment';
import { ProductFormFragment } from '~/components/product-form/fragment';

import { PricingFragment } from './pricing';

Expand Down
72 changes: 72 additions & 0 deletions core/components/product-card/add-to-cart/form/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
'use client';

import { FragmentOf } from 'gql.tada';
import { AlertCircle, Check } from 'lucide-react';
import { useTranslations } from 'next-intl';
import { useFormStatus } from 'react-dom';
import { toast } from 'react-hot-toast';

import { AddToCartButton } from '~/components/add-to-cart-button';
import { Link } from '~/components/link';

import { AddToCartFragment } from '../fragment';

import { addToCart } from './_actions/add-to-cart';

interface Props {
data: FragmentOf<typeof AddToCartFragment>;
}

const SubmitButton = ({ data: product }: Props) => {
const { pending } = useFormStatus();

return <AddToCartButton className="mt-2" data={product} loading={pending} />;
};

export const Form = ({ data: product }: Props) => {
const t = useTranslations('AddToCart');

return (
<form
action={async (formData: FormData) => {
const result = await addToCart(formData);
const quantity = Number(formData.get('quantity'));

if (result.error) {
toast.error(t('errorAddingProductToCart'), {
icon: <AlertCircle className="text-error-secondary" />,
});

return;
}

toast.success(
() => (
<div className="flex items-center gap-3">
<span>
{t.rich('addedProductQuantity', {
cartItems: quantity,
cartLink: (chunks) => (
<Link
className="font-semibold text-primary"
href="/cart"
prefetch="viewport"
prefetchKind="full"
>
{chunks}
</Link>
),
})}
</span>
</div>
),
{ icon: <Check className="text-success-secondary" /> },
);
}}
>
<input name="product_id" type="hidden" value={product.entityId} />
<input name="quantity" type="hidden" value={1} />
<SubmitButton data={product} />
</form>
);
};
1 change: 1 addition & 0 deletions core/components/product-card/add-to-cart/fragment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const AddToCartFragment = graphql(
`
fragment AddToCartFragment on Product {
entityId
path
productOptions(first: 1) {
edges {
node {
Expand Down
78 changes: 7 additions & 71 deletions core/components/product-card/add-to-cart/index.tsx
Original file line number Diff line number Diff line change
@@ -1,94 +1,30 @@
'use client';

import { removeEdgesAndNodes } from '@bigcommerce/catalyst-client';
import { AlertCircle, Check } from 'lucide-react';
import { usePathname, useSearchParams } from 'next/navigation';
import { useTranslations } from 'next-intl';
import { useFormStatus } from 'react-dom';
import { toast } from 'react-hot-toast';
import { getTranslations } from 'next-intl/server';

import { FragmentOf } from '~/client/graphql';
import { AddToCartButton } from '~/components/add-to-cart-button';
import { Button } from '~/components/ui/button';

import { Link } from '../../link';
import { addToCart } from '../_actions/add-to-cart';

import { Form } from './form';
import { AddToCartFragment } from './fragment';

interface Props {
data: FragmentOf<typeof AddToCartFragment>;
}

const Submit = ({ data: product }: Props) => {
const { pending } = useFormStatus();

return <AddToCartButton className="mt-2" data={product} loading={pending} />;
};

export const AddToCart = ({ data: product }: Props) => {
const pathname = usePathname();
const searchParams = useSearchParams();

const t = useTranslations('AddToCart');

const newSearchParams = new URLSearchParams(searchParams);

newSearchParams.set('showQuickAdd', String(product.entityId));
export const AddToCart = async ({ data: product }: Props) => {
const t = await getTranslations('AddToCart');

const productOptions = removeEdgesAndNodes(product.productOptions);

return Array.isArray(productOptions) && productOptions.length > 0 ? (
<Button asChild>
<Link
className="mt-2 hover:text-white"
href={`${pathname}?${newSearchParams.toString()}`}
scroll={false}
>
{t('quickAdd')}
<Link className="mt-2 hover:text-white" href={product.path}>
{t('viewOptions')}
</Link>
</Button>
) : (
<form
action={async (formData: FormData) => {
const result = await addToCart(formData);
const quantity = Number(formData.get('quantity'));

if (result.error) {
toast.error(t('errorAddingProductToCart'), {
icon: <AlertCircle className="text-error-secondary" />,
});

return;
}

toast.success(
() => (
<div className="flex items-center gap-3">
<span>
{t.rich('addedProductQuantity', {
cartItems: quantity,
cartLink: (chunks) => (
<Link
className="font-semibold text-primary"
href="/cart"
prefetch="viewport"
prefetchKind="full"
>
{chunks}
</Link>
),
})}
</span>
</div>
),
{ icon: <Check className="text-success-secondary" /> },
);
}}
>
<input name="product_id" type="hidden" value={product.entityId} />
<input name="quantity" type="hidden" value={1} />
<Submit data={product} />
</form>
<Form data={product} />
);
};
28 changes: 0 additions & 28 deletions core/components/product-sheet/fragment.ts

This file was deleted.

Loading

0 comments on commit 6531bb2

Please sign in to comment.