Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 49 additions & 43 deletions components/cms-modern/Navigation/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const Navigation = ({ pages, style }: NavigationProps) => {
const { navigationToggle, toggleNavigation } = useUI();
const [selectedMenuKey, setSelectedMenuKey] = useState<number | null>(null);
const router = useRouter();
const vse = router.query.vse;
const isRouteActive = (href: string | undefined, category: any): boolean => {
// !!using the first word in the category slug as the current category
// => full path should be present in slugs, and 1st level category slug shouldn't contain '-'
Expand Down Expand Up @@ -61,52 +62,57 @@ const Navigation = ({ pages, style }: NavigationProps) => {
setSelectedMenuKey(null);
};

const itemType = (type: string) => {
switch (type) {
case 'ecommerce-category-generated':
return 'Commerce Item';
case 'category':
return 'CMS Override Item';
default:
return 'CMS Item';
}
};

return (
<nav className="navigation" style={style}>
<ul className="navigation__list">
{pages
.sort((p1, p2) => {
const menu1Priority = p1.content?.menu?.priority || 0;
const menu2Priority = p2.content?.menu?.priority || 0;
return menu1Priority > menu2Priority ? 1 : menu1Priority < menu2Priority ? -1 : 0;
})
.map(({ title, href = '', children = [], content, category }, index) => {
return (
<li
key={index}
className={clsx('navigation__list__item', {
['navigation__list__item--active']: isRouteActive(href || '', category),
['navigation__list__item--open']: isMenuOpen(index),
})}
>
{title && href && (
<Link
href={href || ''}
onClick={(event) =>
children.length === 0 ? handleRouteChange() : handleClick(event, index)
}
className="navigation__list__item__link"
title={`priority: ${content?.menu?.priority}`}
>
{title}
</Link>
)}
{children.length > 0 ? (
<MegaMenu
content={content?.menu?.content}
handleRouteChange={handleRouteChange}
closeMenu={closeMenu}
title={title}
href={href || ''}
>
{children}
</MegaMenu>
) : (
<div></div>
)}
</li>
);
})}
{pages.map(({ title, href = '', children = [], content, category, type }, index) => {
return (
<li
key={index}
className={clsx('navigation__list__item', {
['navigation__list__item--active']: isRouteActive(href || '', category),
['navigation__list__item--open']: isMenuOpen(index),
})}
>
{title && href && (
<Link
href={href || ''}
onClick={(event) =>
children.length === 0 ? handleRouteChange() : handleClick(event, index)
}
className="navigation__list__item__link"
title={vse && itemType(type)}
>
{title}
</Link>
)}
{children.length > 0 ? (
<MegaMenu
content={content?.menu?.content}
handleRouteChange={handleRouteChange}
closeMenu={closeMenu}
title={title}
href={href || ''}
>
{children}
</MegaMenu>
) : (
<div></div>
)}
</li>
);
})}
</ul>
<ul className="navigation__list--search">
<li className="navigation__list__item navigation__list__item--search" key={pages.length}>
Expand Down
48 changes: 18 additions & 30 deletions components/core/Masthead/NavigationContext.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { createContext, useMemo, useContext, PropsWithChildren } from 'react';
import { CmsHierarchyNode } from '@lib/cms/fetchHierarchy';
import { CmsContent } from '@lib/cms/CmsContent';
import walkNavigation, { enrichCmsEntries, getTypeFromSchema } from './walkNavigation';
import walkNavigation, { enrichHierarchyNodes, getTypeFromSchema } from './walkNavigation';
import { useUserContext } from '@lib/user/UserContext';
import { Category } from '@amplience/dc-integration-middleware';

export type NavigationItem = {
type: 'page' | 'external-page' | 'category' | 'group';
type: 'page' | 'external-page' | 'category' | 'group' | 'ecommerce-category-generated';
title: string;
href?: string;
children: NavigationItem[];
parents: NavigationItem[];

content?: CmsContent;
category?: any;
category?: Category;

nodeContentItem?: CmsContent;
};
Expand All @@ -22,26 +23,28 @@ export type NavigationState = {
findByHref: (href: string) => NavigationItem | undefined;
};

export type CategoryById = Record<string, Category>;

const NavigationContext = createContext<NavigationState | null>(null);

interface WithNavigationContextProps extends PropsWithChildren {
pages: CmsHierarchyNode;
categories: any;
categories: Category[];
}

export const WithNavigationContext = ({ pages, categories, children }: WithNavigationContextProps) => {
const { language } = useUserContext();
const flattenCategories = (categories: any[]) => {
const allCategories: any[] = [];
const bulldozeCategories = (cat: any) => {
const flattenCategories = (categories: Category[]) => {
const allCategories: Category[] = [];
const bulldozeCategories = (cat: Category) => {
allCategories.push(cat);
cat.children && cat.children.forEach(bulldozeCategories);
};
categories.forEach(bulldozeCategories);
return allCategories;
};
const categoriesById = useMemo(() => {
const result: any = {};
const result: CategoryById = {};
for (let item of flattenCategories(categories)) {
result[item.id] = item;
}
Expand All @@ -51,14 +54,14 @@ export const WithNavigationContext = ({ pages, categories, children }: WithNavig
const rootItems = useMemo(() => {
const buildCategoryItem = (
cmsCategory: CmsHierarchyNode | undefined,
ecommerceCategory: any | undefined,
ecommerceCategory: Category | undefined,
): NavigationItem | null => {
if (!cmsCategory && !ecommerceCategory) {
return null;
}
const children: NavigationItem[] = [];
const result = {
type: 'category',
type: getTypeFromSchema(cmsCategory?.content?._meta?.schema) || 'category',
title: ecommerceCategory?.name,
href: cmsCategory?.content?._meta?.deliveryKey
? `/category/${cmsCategory?.content?._meta?.deliveryKey.split('/')[1]}`
Expand Down Expand Up @@ -149,49 +152,34 @@ export const WithNavigationContext = ({ pages, categories, children }: WithNavig
if (!type) {
return null;
}
if (!node.content?.active) {
return null;
}
switch (type) {
case 'category':
let category = categoriesById[node.content.name];
return buildCategoryItem(node, category);
case 'ecommerce-category-generated':
return buildCategoryItem(node, categoriesById[node.content.categoryId]);
case 'group':
return buildGroupItem(node);
case 'page':
return buildPageItem(node);
case 'external-page':
return buildExternalPageItem(node);
}

return null;
};

const buildCmsEntries = (children: CmsHierarchyNode[] = []): NavigationItem[] => {
children.sort(function (a: any, b: any) {
const priorityA = a.menu?.priority || a.priority || a.title;
const priorityB = b.menu?.priority || b.priority || b.title;

if (priorityA < priorityB) {
return 1;
} else if (priorityA > priorityB) {
return -1;
}
return 0;
});
return children.map(buildCmsItem).filter((x) => x != null) as NavigationItem[];
};

enrichCmsEntries(pages, categoriesById, categories);
const enrichedPages = enrichHierarchyNodes(pages, categoriesById, categories);

const rootEntries = buildCmsEntries(pages.children);
const rootEntries = buildCmsEntries(enrichedPages.children);
rootEntries.forEach((rootEntry) => {
walkNavigation(rootEntry, (node: NavigationItem, parents: NavigationItem[]) => {
node.parents = parents;
});
});
return rootEntries as NavigationItem[];
}, [pages, categories, categoriesById, language]);
}, [pages, categoriesById, categories, language]);

const findByHref = (href: string) => {
let result: NavigationItem | undefined;
Expand Down
Loading
Loading