diff --git a/.changeset/quiet-sloths-beg.md b/.changeset/quiet-sloths-beg.md new file mode 100644 index 000000000..abc03295c --- /dev/null +++ b/.changeset/quiet-sloths-beg.md @@ -0,0 +1,5 @@ +--- +"@bigcommerce/catalyst-core": minor +--- + +Convert the messages that were displayed when deleting an address over to using the toast functionality. diff --git a/core/app/[locale]/(default)/account/addresses/_actions/delete-address.ts b/core/app/[locale]/(default)/account/addresses/_actions/delete-address.ts index ec5f3cf24..d3b2941f9 100644 --- a/core/app/[locale]/(default)/account/addresses/_actions/delete-address.ts +++ b/core/app/[locale]/(default)/account/addresses/_actions/delete-address.ts @@ -1,13 +1,12 @@ 'use server'; -import { revalidatePath } from 'next/cache'; +import { revalidateTag } from 'next/cache'; import { getTranslations } from 'next-intl/server'; import { getSessionCustomerAccessToken } from '~/auth'; import { client } from '~/client'; import { graphql } from '~/client/graphql'; - -import { State } from '../../settings/change-password/_actions/change-password'; +import { TAGS } from '~/client/tags'; const DeleteCustomerAddressMutation = graphql(` mutation DeleteCustomerAddressMutation( @@ -19,11 +18,9 @@ const DeleteCustomerAddressMutation = graphql(` errors { __typename ... on CustomerAddressDeletionError { - __typename message } ... on CustomerNotLoggedInError { - __typename message } } @@ -32,7 +29,12 @@ const DeleteCustomerAddressMutation = graphql(` } `); -export const deleteAddress = async (addressId: number): Promise => { +interface DeleteAddressResponse { + status: 'success' | 'error'; + message: string; +} + +export const deleteAddress = async (addressId: number): Promise => { const t = await getTranslations('Account.Addresses.Delete'); const customerAccessToken = await getSessionCustomerAccessToken(); @@ -50,24 +52,24 @@ export const deleteAddress = async (addressId: number): Promise => { const result = response.data.customer.deleteCustomerAddress; - revalidatePath('/account/addresses', 'page'); - - if (result.errors.length === 0) { - return { status: 'success', messages: [t('success')] }; + if (result.errors.length > 0) { + result.errors.forEach((error) => { + // Throw the first error message, as we should only handle one error at a time + throw new Error(error.message); + }); } - return { - status: 'error', - messages: result.errors.map((error) => error.message), - }; + revalidateTag(TAGS.customer); + + return { status: 'success', message: t('success') }; } catch (error: unknown) { if (error instanceof Error) { return { status: 'error', - messages: [error.message], + message: error.message, }; } - return { status: 'error', messages: [t('error')] }; + return { status: 'error', message: t('error') }; } }; diff --git a/core/app/[locale]/(default)/account/addresses/_components/address-book.tsx b/core/app/[locale]/(default)/account/addresses/_components/address-book.tsx index 22ff3ba67..2af1a6083 100644 --- a/core/app/[locale]/(default)/account/addresses/_components/address-book.tsx +++ b/core/app/[locale]/(default)/account/addresses/_components/address-book.tsx @@ -1,88 +1,51 @@ 'use client'; +import { AlertCircle, Check } from 'lucide-react'; import { useTranslations } from 'next-intl'; -import { PropsWithChildren, useEffect } from 'react'; +import { PropsWithChildren } from 'react'; +import { toast } from 'react-hot-toast'; import { ExistingResultType } from '~/client/util'; import { Link } from '~/components/link'; import { Button } from '~/components/ui/button'; -import { Message } from '~/components/ui/message'; -import { useRouter } from '~/i18n/routing'; -import { useAccountStatusContext } from '../../_components/account-status-provider'; import { Modal } from '../../_components/modal'; -import { SubmitMessagesList } from '../../_components/submit-messages-list'; import { deleteAddress } from '../_actions/delete-address'; import { getCustomerAddresses } from '../page-data'; export type Addresses = ExistingResultType['addresses']; -interface AddressChangeProps { - addressId: number; - isAddressRemovable: boolean; -} - -const AddressChangeButtons = ({ addressId, isAddressRemovable }: AddressChangeProps) => { - const { setAccountState } = useAccountStatusContext(); - const t = useTranslations('Account.Addresses'); - - const handleDeleteAddress = async () => { - const submit = await deleteAddress(addressId); - - if (submit.status === 'success') { - setAccountState({ - status: 'success', - messages: submit.messages || [''], - }); - } - }; - - return ( -
- - - - -
- ); -}; - interface AddressBookProps { customerAddresses: Addresses; - addressesCount: number; + totalAddresses: number; } export const AddressBook = ({ children, - addressesCount, + totalAddresses, customerAddresses, }: PropsWithChildren) => { const t = useTranslations('Account.Addresses'); - const { accountState } = useAccountStatusContext(); - const router = useRouter(); - useEffect(() => { - if (customerAddresses.length === 0) { - router.push(`/account/addresses/`); + const handleDeleteAddress = (addressId: number) => async () => { + const { status, message } = await deleteAddress(addressId); + + if (status === 'error') { + toast.error(message, { + icon: , + }); + + return; } - }, [customerAddresses, router]); + + toast.success(message, { + icon: , + }); + }; return ( <> - {(accountState.status === 'error' || accountState.status === 'success') && ( - - - - )} - {!addressesCount &&

{t('emptyAddresses')}

} + {totalAddresses === 0 &&

{t('emptyAddresses')}

}
    {customerAddresses.map( ({ @@ -111,7 +74,24 @@ export const AddressBook = ({

    {countryCode}

    - 1} /> +
    + + + + +
    ), )} diff --git a/core/app/[locale]/(default)/account/addresses/edit/[slug]/_components/edit-address-form.tsx b/core/app/[locale]/(default)/account/addresses/edit/[slug]/_components/edit-address-form.tsx index e88a6e8a0..42ec7557a 100644 --- a/core/app/[locale]/(default)/account/addresses/edit/[slug]/_components/edit-address-form.tsx +++ b/core/app/[locale]/(default)/account/addresses/edit/[slug]/_components/edit-address-form.tsx @@ -232,11 +232,11 @@ export const EditAddressForm = ({ const submit = await deleteAddress(address.entityId); if (submit.status === 'success') { - setAccountState({ status: submit.status, messages: submit.messages || [''] }); + setAccountState({ status: submit.status, messages: [submit.message] }); } if (submit.status === 'error') { - setAccountState({ status: submit.status, messages: submit.messages || [''] }); + setAccountState({ status: submit.status, messages: [submit.message] }); } router.push('/account/addresses'); diff --git a/core/app/[locale]/(default)/account/addresses/page-data.ts b/core/app/[locale]/(default)/account/addresses/page-data.ts index 1a635e1fb..e61e09a5d 100644 --- a/core/app/[locale]/(default)/account/addresses/page-data.ts +++ b/core/app/[locale]/(default)/account/addresses/page-data.ts @@ -6,6 +6,7 @@ import { client } from '~/client'; import { FormFieldValuesFragment } from '~/client/fragments/form-fields-values'; import { PaginationFragment } from '~/client/fragments/pagination'; import { graphql } from '~/client/graphql'; +import { TAGS } from '~/client/tags'; const GetCustomerAddressesQuery = graphql( ` @@ -59,7 +60,7 @@ export const getCustomerAddresses = cache( document: GetCustomerAddressesQuery, variables: { ...paginationArgs }, customerAccessToken, - fetchOptions: { cache: 'no-store' }, + fetchOptions: { cache: 'no-store', next: { tags: [TAGS.customer] } }, }); const addresses = response.data.customer?.addresses; @@ -70,7 +71,7 @@ export const getCustomerAddresses = cache( return { pageInfo: addresses.pageInfo, - addressesCount: addresses.collectionInfo?.totalItems ?? 0, + totalAddresses: addresses.collectionInfo?.totalItems ?? 0, addresses: removeEdgesAndNodes({ edges: addresses.edges }), }; }, diff --git a/core/app/[locale]/(default)/account/addresses/page.tsx b/core/app/[locale]/(default)/account/addresses/page.tsx index a6384f368..27e9b76fa 100644 --- a/core/app/[locale]/(default)/account/addresses/page.tsx +++ b/core/app/[locale]/(default)/account/addresses/page.tsx @@ -36,13 +36,13 @@ export default async function Addresses({ searchParams }: Props) { notFound(); } - const { addresses, pageInfo, addressesCount } = data; + const { addresses, pageInfo, totalAddresses } = data; const { hasNextPage, hasPreviousPage, startCursor, endCursor } = pageInfo; return ( <> - + // More info: https://github.com/amannn/next-intl/issues/1335 await expect(page).toHaveURL('/account/'); - await expect(page.getByRole('link', { name: 'Orders' })).toBeVisible(); - await expect(page.getByRole('link', { name: 'Addresses' })).toBeVisible(); - await expect(page.getByRole('link', { name: 'Account settings' })).toBeVisible(); + const tabs = page.getByRole('navigation', { name: 'Account Tabs' }); - await page.getByRole('link', { name: 'Orders' }).click(); + await expect(tabs.getByRole('link', { name: 'Orders' })).toBeVisible(); + await expect(tabs.getByRole('link', { name: 'Addresses' })).toBeVisible(); + await expect(tabs.getByRole('link', { name: 'Account settings' })).toBeVisible(); + + await tabs.getByRole('link', { name: 'Orders' }).click(); await expect(page).toHaveURL('/account/orders/'); await expect(page.getByRole('heading', { name: 'Orders' })).toBeVisible(); - await page.getByRole('link', { name: 'Addresses' }).click(); + await tabs.getByRole('link', { name: 'Addresses' }).click(); await expect(page).toHaveURL('/account/addresses/'); await expect(page.getByRole('heading', { name: 'Addresses' })).toBeVisible(); - await page.getByRole('link', { name: 'Account settings' }).click(); + await tabs.getByRole('link', { name: 'Account settings' }).click(); await expect(page).toHaveURL('/account/settings/'); await expect(page.getByRole('heading', { name: 'Account settings' })).toBeVisible(); diff --git a/core/tests/ui/e2e/addresses.spec.ts b/core/tests/ui/e2e/addresses.spec.ts index 4463cd1d7..69f0e04e3 100644 --- a/core/tests/ui/e2e/addresses.spec.ts +++ b/core/tests/ui/e2e/addresses.spec.ts @@ -31,7 +31,7 @@ test('Add new address', async ({ page, account }) => { await page.getByRole('button', { name: 'Add new address' }).click(); await page.waitForURL('/account/addresses/'); - await expect(page.getByText('Address added to your account.')).toBeVisible(); + // await expect(page.getByText('Address added to your account.')).toBeVisible(); await customer.logout(); }); @@ -47,7 +47,7 @@ test('Edit address', async ({ page, account }) => { await page.getByRole('button', { name: 'Edit address' }).click(); await page.waitForURL('/account/addresses/'); - await expect(page.getByText('The address has been successfully updated.')).toBeVisible(); + // await expect(page.getByText('The address has been successfully updated.')).toBeVisible(); await customer.logout(); });