Skip to content

Commit

Permalink
feat(core): add tabs for customer account (#719)
Browse files Browse the repository at this point in the history
  • Loading branch information
bc-alexsaiannyi committed Apr 9, 2024
1 parent 71140c9 commit ab67b34
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/fuzzy-colts-draw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@bigcommerce/catalyst-core": minor
---

Add tabs for customer account
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
'use client';

import { Tabs, TabsContent, TabsList, TabsTrigger } from '@bigcommerce/components/tabs';
import { useTranslations } from 'next-intl';
import { PropsWithChildren } from 'react';

import { Link } from '~/components/link';

import { TabType } from '../layout';

interface Props extends PropsWithChildren {
tabs: TabType[];
activeTab?: TabType;
}

export const AccountTabs = ({ children, activeTab, tabs }: Props) => {
const t = useTranslations('Account.Home');

return (
<Tabs activationMode="manual" defaultValue={activeTab}>
<TabsList aria-label={t('accountTabsLabel')} className="mb-5 pb-3">
{tabs.map((tab) => (
<TabsTrigger asChild key={tab} value={tab}>
<Link
className="whitespace-nowrap font-semibold"
href={`/account/${tab}`}
prefetch="viewport"
prefetchKind="full"
>
{tab === 'recently-viewed' ? t('recentlyViewed') : t(tab)}
</Link>
</TabsTrigger>
))}
</TabsList>
<TabsContent value={activeTab ?? ''}>{children}</TabsContent>
</Tabs>
);
};
39 changes: 39 additions & 0 deletions apps/core/app/[locale]/(default)/account/[tab]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { NextIntlClientProvider } from 'next-intl';
import { getMessages, getTranslations, unstable_setRequestLocale } from 'next-intl/server';
import { PropsWithChildren } from 'react';

import { LocaleType } from '~/i18n';

import { AccountTabs } from './_components/account-tabs';

const tabList = [
'orders',
'messages',
'addresses',
'wishlists',
'recently-viewed',
'settings',
] as const;

export type TabType = (typeof tabList)[number];

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

export default async function AccountTabLayout({ children, params: { locale, tab } }: Props) {
unstable_setRequestLocale(locale);

const t = await getTranslations({ locale, namespace: 'Account.Home' });

const messages = await getMessages();

return (
<NextIntlClientProvider locale={locale} messages={{ Account: messages.Account ?? {} }}>
<h1 className="my-6 my-8 text-4xl font-black lg:my-8 lg:text-5xl">{t('heading')}</h1>
<AccountTabs activeTab={tab} tabs={[...tabList]}>
{children}
</AccountTabs>
</NextIntlClientProvider>
);
}
55 changes: 55 additions & 0 deletions apps/core/app/[locale]/(default)/account/[tab]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import type { Metadata } from 'next';
import { notFound } from 'next/navigation';
import { getTranslations } from 'next-intl/server';

import { LocaleType } from '~/i18n';

import { TabType } from './layout';

interface Props {
params: {
locale: LocaleType;
tab: TabType;
};
}

export async function generateMetadata({ params: { tab, locale } }: Props): Promise<Metadata> {
const t = await getTranslations({ locale, namespace: 'Account.Home' });

return {
title: t(tab === 'recently-viewed' ? 'recentlyViewed' : tab),
};
}

const tabHeading = async (heading: string, locale: LocaleType) => {
const t = await getTranslations({ locale, namespace: 'Account.Home' });

return <h2 className="mb-8 text-3xl font-black lg:text-4xl">{t(heading)}</h2>;
};

export default async function AccountTabPage({ params: { tab, locale } }: Props) {
switch (tab) {
case 'orders':
return tabHeading(tab, locale);

case 'messages':
return tabHeading(tab, locale);

case 'addresses':
return tabHeading(tab, locale);

case 'wishlists':
return tabHeading(tab, locale);

case 'recently-viewed':
return tabHeading('recentlyViewed', locale);

case 'settings':
return tabHeading(tab, locale);

default:
return notFound();
}
}

export const runtime = 'edge';
4 changes: 2 additions & 2 deletions apps/core/app/[locale]/(default)/account/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default async function AccountPage({ params: { locale } }: Props) {
}

return (
<div className="mx-auto max-w-screen-xl">
<div className="mx-auto">
<h1 className="my-6 my-8 text-4xl font-black lg:my-8 lg:text-5xl">{t('heading')}</h1>

<div className="mb-14 grid gap-6 md:grid-cols-2 lg:grid-cols-3">
Expand All @@ -63,7 +63,7 @@ export default async function AccountPage({ params: { locale } }: Props) {
<AccountItem href="/account/recently-viewed" title={t('recentlyViewed')}>
<Eye className="me-8" height={48} width={48} />
</AccountItem>
<AccountItem href="/account/settings" title={t('accountSettings')}>
<AccountItem href="/account/settings" title={t('settings')}>
<Settings className="me-8" height={48} width={48} />
</AccountItem>
</div>
Expand Down
3 changes: 2 additions & 1 deletion apps/core/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,13 @@
"Account": {
"Home": {
"heading": "My Account",
"accountTabsLabel": "Account Tabs",
"orders": "Orders",
"messages": "Messages",
"addresses": "Addresses",
"wishlists": "Wish lists",
"recentlyViewed": "Recently viewed",
"accountSettings": "Account settings"
"settings": "Account settings"
},
"Login": {
"heading": "Log In",
Expand Down

0 comments on commit ab67b34

Please sign in to comment.