diff --git a/lib/bigcommerce/index.tsx b/lib/bigcommerce/index.tsx index fb2d15757..f02d7d5ab 100644 --- a/lib/bigcommerce/index.tsx +++ b/lib/bigcommerce/index.tsx @@ -4,6 +4,7 @@ import { CommerceProvider as CoreCommerceProvider, useCommerce as useCoreCommerce, } from 'lib/commerce' +import { FetcherError } from '@lib/commerce/utils/errors' async function getText(res: Response) { try { @@ -16,9 +17,9 @@ async function getText(res: Response) { async function getError(res: Response) { if (res.headers.get('Content-Type')?.includes('application/json')) { const data = await res.json() - return data.errors[0] + return new FetcherError({ errors: data.errors, status: res.status }) } - return { message: await getText(res) } + return new FetcherError({ message: await getText(res), status: res.status }) } export const bigcommerceConfig: CommerceConfig = { diff --git a/lib/bigcommerce/use-signup.tsx b/lib/bigcommerce/use-signup.tsx index 68183aa6c..2756bdf09 100644 --- a/lib/bigcommerce/use-signup.tsx +++ b/lib/bigcommerce/use-signup.tsx @@ -1,5 +1,6 @@ import { useCallback } from 'react' -import { HookFetcher } from '@lib/commerce/utils/types' +import { CommerceError } from '@lib/commerce/utils/errors' +import type { HookFetcher } from '@lib/commerce/utils/types' import useCommerceSignup from '@lib/commerce/use-signup' import type { SignupBody } from './api/customers/signup' @@ -16,9 +17,10 @@ export const fetcher: HookFetcher = ( fetch ) => { if (!(firstName && lastName && email && password)) { - throw new Error( - 'A first name, last name, email and password are required to signup' - ) + throw new CommerceError({ + message: + 'A first name, last name, email and password are required to signup', + }) } return fetch({ diff --git a/lib/commerce/utils/errors.ts b/lib/commerce/utils/errors.ts new file mode 100644 index 000000000..76f899ab7 --- /dev/null +++ b/lib/commerce/utils/errors.ts @@ -0,0 +1,40 @@ +export type ErrorData = { + message: string + code?: string +} + +export type ErrorProps = { + code?: string +} & ( + | { message: string; errors?: never } + | { message?: never; errors: ErrorData[] } +) + +export class CommerceError extends Error { + code?: string + errors: ErrorData[] + + constructor({ message, code, errors }: ErrorProps) { + const error: ErrorData = message + ? { message, ...(code ? { code } : {}) } + : errors![0] + + super(error.message) + this.errors = message ? [error] : errors! + + if (error.code) this.code = error.code + } +} + +export class FetcherError extends CommerceError { + status: number + + constructor( + options: { + status: number + } & ErrorProps + ) { + super(options) + this.status = options.status + } +} diff --git a/pages/login.tsx b/pages/login.tsx index b9cec445e..ce12ce401 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -1,7 +1,29 @@ +import useSignup from '@lib/bigcommerce/use-signup' import { Layout } from '@components/core' import { Logo, Modal, Button } from '@components/ui' export default function Login() { + const signup = useSignup() + // TODO: use this method + const handleSignup = async () => { + // TODO: validate the password and email before calling the signup + // Passwords must be at least 7 characters and contain both alphabetic + // and numeric characters. + try { + await signup({ + // This account already exists, so it will throw the "duplicated_email" error + email: 'luis@vercel.com', + firstName: 'Luis', + lastName: 'Alvarez', + password: 'luis123', + }) + } catch (error) { + if (error.code === 'duplicated_email') { + // TODO: handle duplicated email + } + } + } + return (
{}}> @@ -22,7 +44,9 @@ export default function Login() { className="focus:outline-none focus:shadow-outline-gray border-none py-2 px-6 w-full appearance-none transition duration-150 ease-in-out placeholder-accents-5 pr-10" />
- + Don't have an account? {` `}