Skip to content

Commit

Permalink
feat(core): Next 15 upgrade (#1508)
Browse files Browse the repository at this point in the history
* feat(client): add async support to beforeRequest hook

* feat(core): Next 15 upgrade
  • Loading branch information
deini authored Oct 23, 2024
1 parent 0d76ad1 commit 3ebb617
Show file tree
Hide file tree
Showing 62 changed files with 1,102 additions and 758 deletions.
5 changes: 5 additions & 0 deletions .changeset/bright-dancers-turn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@bigcommerce/catalyst-core": minor
---

Next 15 upgrade
5 changes: 5 additions & 0 deletions .changeset/lemon-insects-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@bigcommerce/eslint-config-catalyst": patch
---

allow props not to be spread
5 changes: 5 additions & 0 deletions .changeset/smooth-carrots-punch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@bigcommerce/catalyst-client": minor
---

Adds async support to beforeRequest hook
2 changes: 1 addition & 1 deletion .github/workflows/regression-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ jobs:
- name: Run Playwright tests
run: |
cd core
npx playwright test tests/ui/ --project=tests-chromium
npx playwright test tests/ui/ --project=tests-chromium
- uses: actions/upload-artifact@v4
if: failure()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
'use client';

import { useTranslations } from 'next-intl';
import { ChangeEvent, useRef, useState } from 'react';
import { useFormState, useFormStatus } from 'react-dom';
import { ChangeEvent, useActionState, useRef, useState } from 'react';
import { useFormStatus } from 'react-dom';

import { Button } from '~/components/ui/button';
import {
Expand Down Expand Up @@ -48,7 +48,7 @@ export const ChangePasswordForm = ({ customerId, customerToken }: Props) => {

const form = useRef<HTMLFormElement>(null);
const router = useRouter();
const [state, formAction] = useFormState(changePassword, {
const [state, formAction] = useActionState(changePassword, {
status: 'idle',
message: '',
});
Expand Down
9 changes: 4 additions & 5 deletions core/app/[locale]/(default)/(auth)/change-password/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useLocale, useTranslations } from 'next-intl';
import { getTranslations } from 'next-intl/server';
import { use } from 'react';

import { redirect } from '~/i18n/routing';

Expand All @@ -14,19 +15,17 @@ export async function generateMetadata() {
}

interface Props {
searchParams: {
searchParams: Promise<{
c?: string;
t?: string;
};
}>;
}

export default function ChangePassword({ searchParams }: Props) {
const { c: customerId, t: customerToken } = use(searchParams);
const t = useTranslations('ChangePassword');
const locale = useLocale();

const customerId = searchParams.c;
const customerToken = searchParams.t;

if (!customerId || !customerToken) {
redirect({ href: '/login', locale });
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
'use client';

import { useTranslations } from 'next-intl';
import { ChangeEvent, useState } from 'react';
import { useFormState, useFormStatus } from 'react-dom';
import { ChangeEvent, useActionState, useState } from 'react';
import { useFormStatus } from 'react-dom';

import { Link } from '~/components/link';
import { Button } from '~/components/ui/button';
Expand Down Expand Up @@ -41,7 +41,7 @@ export const LoginForm = () => {

const [isEmailValid, setIsEmailValid] = useState(true);
const [isPasswordValid, setIsPasswordValid] = useState(true);
const [state, formAction] = useFormState(login, { status: 'idle' });
const [state, formAction] = useActionState(login, { status: 'idle' });
const { accountState } = useAccountStatusContext();

const isFormInvalid = state?.status === 'error';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ export const ResetPasswordForm = ({ reCaptchaSettings }: Props) => {

{reCaptchaSettings?.isEnabledOnStorefront && (
<Field className="relative col-span-full max-w-full space-y-2 pb-7" name="ReCAPTCHA">
{/* https://github.com/dozoisch/react-google-recaptcha/issues/277 */}
{/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */}
{/* @ts-expect-error */}
<ReCaptcha
onChange={onReCatpchaChange}
ref={reCaptchaRef}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ export default async function Reset() {
fetchOptions: { next: { revalidate } },
});

const recaptchaSettings = await bypassReCaptcha(data.site.settings?.reCaptcha);

return (
<div className="mx-auto my-6 max-w-4xl">
<h2 className="mb-8 text-4xl font-black lg:text-5xl">{t('heading')}</h2>
<ResetPasswordForm reCaptchaSettings={bypassReCaptcha(data.site.settings?.reCaptcha)} />
<ResetPasswordForm reCaptchaSettings={recaptchaSettings} />
</div>
);
}
Expand Down
7 changes: 5 additions & 2 deletions core/app/[locale]/(default)/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useTranslations } from 'next-intl';
import { getTranslations, setRequestLocale } from 'next-intl/server';
import { use } from 'react';

import { Link } from '~/components/link';
import { Button } from '~/components/ui/button';
Expand All @@ -16,10 +17,12 @@ export async function generateMetadata() {
}

interface Props {
params: { locale: LocaleType };
params: Promise<{ locale: LocaleType }>;
}

export default function Login({ params: { locale } }: Props) {
export default function Login({ params }: Props) {
const { locale } = use(params);

setRequestLocale(locale);

const t = useTranslations('Login');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,9 @@ export const RegisterCustomerForm = ({
})}
{reCaptchaSettings?.isEnabledOnStorefront && (
<Field className="relative col-span-full max-w-full space-y-2 pb-7" name="ReCAPTCHA">
{/* https://github.com/dozoisch/react-google-recaptcha/issues/277 */}
{/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */}
{/* @ts-expect-error */}
<ReCaptcha
onChange={onReCaptchaChange}
ref={reCaptchaRef}
Expand Down
2 changes: 1 addition & 1 deletion core/app/[locale]/(default)/(auth)/register/page-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export const getRegisterCustomerQuery = cache(async ({ address, customer }: Prop
const countries = response.data.geography.countries;
const defaultCountry = response.data.site.settings?.contact?.country;

const reCaptchaSettings = bypassReCaptcha(response.data.site.settings?.reCaptcha);
const reCaptchaSettings = await bypassReCaptcha(response.data.site.settings?.reCaptcha);

if (!addressFields || !customerFields || !countries) {
return null;
Expand Down
3 changes: 2 additions & 1 deletion core/app/[locale]/(default)/(auth)/register/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ export default async function Register() {
}

const { addressFields, customerFields, reCaptchaSettings } = registerCustomerData;
const reCaptcha = await bypassReCaptcha(reCaptchaSettings);

return (
<div className="mx-auto mb-10 mt-8 text-base lg:w-2/3">
<h1 className="my-6 text-4xl font-black lg:my-8 lg:text-5xl">{t('heading')}</h1>
<RegisterCustomerForm
addressFields={addressFields}
customerFields={customerFields}
reCaptchaSettings={bypassReCaptcha(reCaptchaSettings)}
reCaptchaSettings={reCaptcha}
/>
</div>
);
Expand Down
16 changes: 11 additions & 5 deletions core/app/[locale]/(default)/(faceted)/brand/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ import { fetchFacetedSearch } from '../../fetch-faceted-search';
import { getBrand } from './page-data';

interface Props {
params: {
params: Promise<{
slug: string;
locale: LocaleType;
};
searchParams: Record<string, string | string[] | undefined>;
}>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}

export async function generateMetadata({ params }: Props): Promise<Metadata> {
export async function generateMetadata(props: Props): Promise<Metadata> {
const params = await props.params;
const brandId = Number(params.slug);

const brand = await getBrand({ entityId: brandId });
Expand All @@ -39,7 +40,12 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
};
}

export default async function Brand({ params: { slug, locale }, searchParams }: Props) {
export default async function Brand(props: Props) {
const searchParams = await props.searchParams;
const params = await props.params;

const { slug, locale } = params;

setRequestLocale(locale);

const t = await getTranslations('Brand');
Expand Down
16 changes: 11 additions & 5 deletions core/app/[locale]/(default)/(faceted)/category/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,16 @@ import { SubCategories } from './_components/sub-categories';
import { getCategoryPageData } from './page-data';

interface Props {
params: {
params: Promise<{
slug: string;
locale: LocaleType;
};
searchParams: Record<string, string | string[] | undefined>;
}>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}

export async function generateMetadata({ params }: Props): Promise<Metadata> {
const categoryId = Number(params.slug);
const { slug } = await params;
const categoryId = Number(slug);

const data = await getCategoryPageData({
categoryId,
Expand All @@ -47,7 +48,12 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
};
}

export default async function Category({ params: { locale, slug }, searchParams }: Props) {
export default async function Category(props: Props) {
const searchParams = await props.searchParams;
const params = await props.params;

const { locale, slug } = params;

setRequestLocale(locale);

const t = await getTranslations('Category');
Expand Down
5 changes: 3 additions & 2 deletions core/app/[locale]/(default)/(faceted)/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ export async function generateMetadata() {
}

interface Props {
searchParams: Record<string, string | string[] | undefined>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}

export default async function Search({ searchParams }: Props) {
export default async function Search(props: Props) {
const searchParams = await props.searchParams;
const t = await getTranslations('Search');

const searchTerm = typeof searchParams.term === 'string' ? searchParams.term : undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,9 @@ export const AddAddressForm = ({

{reCaptchaSettings?.isEnabledOnStorefront && (
<Field className="relative col-span-full max-w-full space-y-2 pb-7" name="ReCAPTCHA">
{/* https://github.com/dozoisch/react-google-recaptcha/issues/277 */}
{/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */}
{/* @ts-expect-error */}
<ReCaptcha
onChange={onReCaptchaChange}
ref={reCaptchaRef}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ export default async function AddPage() {
});

const addressFields = [...(data.site.settings?.formFields.shippingAddress ?? [])];
const reCaptchaSettings = data.site.settings?.reCaptcha;
const countries = data.geography.countries;
const defaultCountry = data.site.settings?.contact?.country || FALLBACK_COUNTRY.name;

Expand All @@ -92,14 +91,16 @@ export default async function AddPage() {
statesOrProvinces: defaultCountryStates = FALLBACK_COUNTRY.states,
} = countries?.find(({ name: country }) => country === defaultCountry) || {};

const recaptchaSettings = await bypassReCaptcha(data.site.settings?.reCaptcha);

return (
<div className="mx-auto mb-14 lg:w-2/3">
<h1 className="mb-8 text-3xl font-black lg:text-4xl">{t('heading')}</h1>
<AddAddressForm
addressFields={addressFields}
countries={countries || []}
defaultCountry={{ id: entityId, code, states: defaultCountryStates }}
reCaptchaSettings={bypassReCaptcha(reCaptchaSettings)}
reCaptchaSettings={recaptchaSettings}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,9 @@ export const EditAddressForm = ({

{reCaptchaSettings?.isEnabledOnStorefront && (
<Field className="relative col-span-full max-w-full space-y-2 pb-7" name="ReCAPTCHA">
{/* https://github.com/dozoisch/react-google-recaptcha/issues/277 */}
{/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */}
{/* @ts-expect-error */}
<ReCaptcha
onChange={onReCaptchaChange}
ref={reCaptchaRef}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,12 @@ export async function generateMetadata() {
}

interface Props {
params: { slug: string };
searchParams: Record<string, string | string[] | undefined>;
params: Promise<{ slug: string }>;
}

export default async function Edit({ params: { slug } }: Props) {
export default async function Edit({ params }: Props) {
const { slug } = await params;

const t = await getTranslations('Account.Addresses.Edit');

const customerId = await getSessionCustomerId();
Expand All @@ -117,7 +118,6 @@ export default async function Edit({ params: { slug } }: Props) {
},
});

const reCaptchaSettings = data.site.settings?.reCaptcha;
const countries = data.geography.countries;
const addressFields = [...(data.site.settings?.formFields.shippingAddress ?? [])];
const addresses = removeEdgesAndNodes({ edges: data.customer?.addresses.edges });
Expand All @@ -132,6 +132,8 @@ export default async function Edit({ params: { slug } }: Props) {
return notFound();
}

const reCaptchaSettings = await bypassReCaptcha(data.site.settings?.reCaptcha);

return (
<div className="mx-auto mb-14 lg:w-2/3">
<h1 className="mb-8 text-3xl font-black lg:text-4xl">{t('heading')}</h1>
Expand All @@ -140,7 +142,7 @@ export default async function Edit({ params: { slug } }: Props) {
addressFields={addressFields}
countries={countries || []}
isAddressRemovable={addresses.length > 1}
reCaptchaSettings={bypassReCaptcha(reCaptchaSettings)}
reCaptchaSettings={reCaptchaSettings}
/>
</div>
);
Expand Down
6 changes: 3 additions & 3 deletions core/app/[locale]/(default)/account/(tabs)/addresses/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import { AddressBook } from './_components/address-book';
import { getCustomerAddresses } from './page-data';

interface Props {
searchParams: {
searchParams: Promise<{
[key: string]: string | string[] | undefined;
before?: string;
after?: string;
};
}>;
}

export async function generateMetadata() {
Expand All @@ -25,7 +25,7 @@ export async function generateMetadata() {
}

export default async function Addresses({ searchParams }: Props) {
const { before, after } = searchParams;
const { before, after } = await searchParams;

const data = await getCustomerAddresses({
...(after && { after }),
Expand Down
8 changes: 5 additions & 3 deletions core/app/[locale]/(default)/account/(tabs)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useTranslations } from 'next-intl';
import { setRequestLocale } from 'next-intl/server';
import { PropsWithChildren } from 'react';
import { PropsWithChildren, use } from 'react';

import { Link } from '~/components/link';
import { LocaleType } from '~/i18n/routing';
Expand All @@ -11,10 +11,12 @@ const tabList = ['addresses', 'settings'] as const;
export type TabType = (typeof tabList)[number];

interface Props extends PropsWithChildren {
params: { locale: LocaleType; tab?: TabType };
params: Promise<{ locale: LocaleType; tab?: TabType }>;
}

export default function AccountTabLayout({ children, params: { locale } }: Props) {
export default function AccountTabLayout({ children, params }: Props) {
const { locale } = use(params);

setRequestLocale(locale);

const t = useTranslations('Account.Home');
Expand Down
Loading

0 comments on commit 3ebb617

Please sign in to comment.