feat(poc): improve footer to have two levels

This commit is contained in:
Björn Meyer 2023-07-07 09:21:20 +02:00
parent 51a0623569
commit a598b3f1e5
6 changed files with 59 additions and 38 deletions

View File

@ -10,37 +10,52 @@ const { SITE_NAME } = process.env;
export default async function Footer() { export default async function Footer() {
const currentYear = new Date().getFullYear(); const currentYear = new Date().getFullYear();
const copyrightDate = 2023 + (currentYear > 2023 ? `-${currentYear}` : ''); const copyrightDate = 2023 + (currentYear > 2023 ? `-${currentYear}` : '');
const menu = await getMenu({ type: 'footer-navigation' }); const menu = await getMenu({ type: 'footer-navigation', depth: 2 });
return ( return (
<footer className="border-t border-gray-700 bg-white text-black dark:bg-black dark:text-white"> <footer className="border-t border-gray-700 bg-white text-black dark:bg-black dark:text-white">
<div className="mx-auto w-full max-w-7xl px-6"> <div className="mx-auto w-full max-w-7xl px-6">
<div className="grid grid-cols-1 gap-8 border-b border-gray-700 py-12 transition-colors duration-150 lg:grid-cols-12"> <div className="grid grid-cols-1 gap-8 border-b border-gray-700 py-12 transition-colors duration-150 lg:grid-cols-12">
<div className="col-span-1 lg:col-span-3"> <div className="col-span-1 lg:col-span-4">
<a className="flex flex-initial items-center font-bold md:mr-24" href="/"> <a className="flex flex-initial items-center font-bold" href="/">
<span className="mr-2"> <span className="mr-4">
<LogoIcon className="h-8" /> <LogoIcon className="h-8" />
</span> </span>
<span>{SITE_NAME}</span> <span>{SITE_NAME}</span>
</a> </a>
</div> </div>
{menu.length ? ( {menu.map((item: Menu) => (
<nav className="col-span-1 lg:col-span-7"> < nav className="col-span-1 lg:col-span-3" key={item.title + item.type} >
<ul className="grid md:grid-flow-col md:grid-cols-3 md:grid-rows-4"> {
{menu.map((item: Menu) => ( item.type === "headline" ? (
<li key={item.title} className="py-3 md:py-0 md:pb-4"> <span className='font-bold'>{item.title}</span>
<Link ) : null
href={item.path} }
className="text-gray-800 transition duration-150 ease-in-out hover:text-gray-300 dark:text-gray-100" {item.children.length > 0 ? (
> <ul className="py-3 md:py-0 md:pt-4" key={item.title}>
{item.title} {item.children.map((item: Menu) => (
</Link> <li key={item.title} className="py-3 md:py-0 md:pb-4">
</li> <Link
))} href={item.path}
</ul> className="text-gray-800 transition duration-150 ease-in-out hover:text-gray-300 dark:text-gray-100"
>
{item.title}
</Link>
</li>
))}
</ul>
) :
// if there are no children, at least display a link
<Link
key={item.title}
href={item.path}
className="text-gray-800 transition duration-150 ease-in-out hover:text-gray-300 dark:text-gray-100"
>
{item.title}
</Link>}
</nav> </nav>
) : null} ))}
<div className="col-span-1 text-black dark:text-white lg:col-span-2"> <div className="col-span-1 text-black dark:text-white lg:col-span-2 inline-grid justify-items-end">
<a aria-label="Github Repository" href="https://github.com/vercel/commerce"> <a aria-label="Github Repository" href="https://github.com/vercel/commerce">
<GitHubIcon className="h-6" /> <GitHubIcon className="h-6" />
</a> </a>
@ -71,6 +86,6 @@ export default async function Footer() {
</div> </div>
</div> </div>
</div> </div>
</footer> </footer >
); );
} }

View File

@ -689,7 +689,7 @@ export type components = {
breadcrumb?: readonly unknown[]; breadcrumb?: readonly unknown[];
/** Format: int64 */ /** Format: int64 */
childCount?: number; childCount?: number;
children?: components['schemas']['Category']; children?: components['schemas']['Category'][];
cmsPage?: components['schemas']['CmsPage']; cmsPage?: components['schemas']['CmsPage'];
cmsPageId?: string; cmsPageId?: string;
/** Runtime field, cannot be used as part of the criteria. */ /** Runtime field, cannot be used as part of the criteria. */

View File

@ -18,14 +18,15 @@ const apiInstance = createAPIClient<operations, operationPaths>({
}); });
export async function requestNavigation( export async function requestNavigation(
type: StoreNavigationTypeSW type: StoreNavigationTypeSW,
depth: number
): Promise<ApiSchemas['NavigationRouteResponse']> { ): Promise<ApiSchemas['NavigationRouteResponse']> {
return await apiInstance.invoke( return await apiInstance.invoke(
'readNavigation post /navigation/{activeId}/{rootId} sw-include-seo-urls', 'readNavigation post /navigation/{activeId}/{rootId} sw-include-seo-urls',
{ {
activeId: type, activeId: type,
rootId: type, rootId: type,
depth: 1 depth: depth
} }
); );
} }

View File

@ -34,9 +34,10 @@ import {
transformStaticCollection transformStaticCollection
} from './transform'; } from './transform';
export async function getMenu(params?: { type?: StoreNavigationTypeSW }): Promise<Menu[]> { export async function getMenu(params?: { type?: StoreNavigationTypeSW, depth?: number }): Promise<Menu[]> {
const type = params?.type || 'main-navigation'; const type = params?.type || 'main-navigation';
const res = await requestNavigation(type); const depth = params?.depth || 1;
const res = await requestNavigation(type, depth);
return res ? transformMenu(res) : []; return res ? transformMenu(res) : [];
} }

View File

@ -12,20 +12,24 @@ import { ListItem } from 'components/layout/search/filter';
export function transformMenu(res: ApiSchemas['NavigationRouteResponse']) { export function transformMenu(res: ApiSchemas['NavigationRouteResponse']) {
let menu: Menu[] = []; let menu: Menu[] = [];
res.map((item) => res.map((item) => menu.push(transformMenuItem(item)));
menu.push({
id: item.id ?? '',
title: item.name,
path:
item.seoUrls && item.seoUrls.length > 0 && item.seoUrls[0] && item.seoUrls[0].seoPathInfo
? '/search/' + item.seoUrls[0].seoPathInfo
: ''
})
);
return menu; return menu;
} }
function transformMenuItem(item: ApiSchemas['Category']): Menu {
return {
id: item.id ?? '',
title: item.name,
children: item.children?.map((item) => transformMenuItem(item)) ?? [],
path:
item.seoUrls && item.seoUrls.length > 0 && item.seoUrls[0] && item.seoUrls[0].seoPathInfo
? '/search/' + item.seoUrls[0].seoPathInfo
: '',
type: item.children && item.children.length > 0 ? 'headline' : 'link'
};
}
export function transformPage( export function transformPage(
seoUrlElement: ApiSchemas['SeoUrl'], seoUrlElement: ApiSchemas['SeoUrl'],
resCategory: ApiSchemas['Category'] resCategory: ApiSchemas['Category']
@ -223,7 +227,7 @@ function transformVariants(parent: ApiSchemas['Product']): ProductVariant[] {
} }
}; };
productVariants.push(currentVariant) productVariants.push(currentVariant);
} }
}); });
} }

View File

@ -18,7 +18,7 @@ export type SeoURLResultSW = {
} & ApiSchemas['EntitySearchResult']; } & ApiSchemas['EntitySearchResult'];
/** Vercel Commerce Types */ /** Vercel Commerce Types */
export type Menu = { id: string; title: string; path: string }; export type Menu = { id: string; title: string; path: string, type: string, children: Menu[] };
export type Page = { export type Page = {
id: string; id: string;