All files / components/SideNav SideNav.server.ts

0% Statements 0/83
0% Branches 0/1
0% Functions 0/1
0% Lines 0/83

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84                                                                                                                                                                       
import type { PageMetadataMap, PageMetadataMapItem } from "$lib/loadPageMetadataMap";
import type { NavMenuType } from "$lib/components/Header/Nav/types";
import type { SideNavItem } from "./types";

type SideNavMap = Map<string, SideNavItem>;

const sideNavMap: SideNavMap = new Map();

// recursive function that builds out a tree of children, grandchildren, etc.
const buildSideNavTree = (
  pageMetadataMap: PageMetadataMap,
  featuredPages: string[],
  children: PageMetadataMapItem["children"],
): SideNavItem[] => {
  const tree: SideNavItem[] = [];
  if (children) {
    featuredPages.forEach((featuredPageId) => {
      const matchedChildId = children.find((childId) => childId === featuredPageId);
      if (matchedChildId) {
        const child = pageMetadataMap.get(matchedChildId);
        if (child && child.sys && child.title && child.url) {
          // push the child to the tree and build out its children
          tree.push({
            id: child.sys.id,
            title: child.title,
            link: child.url,
            children: buildSideNavTree(pageMetadataMap, featuredPages, child.children),
          });
        }
      }
    });
    // then add the rest in alphabetical order
    const nonFeaturedPages: SideNavItem[] = [];
    children.forEach((childId) => {
      // skip if we've already added it
      const childAlreadyInTree = tree.find((leaf) => leaf.id === childId);
      if (!childAlreadyInTree) {
        const child = pageMetadataMap.get(childId);
        if (child && child.sys && child.title && child.url) {
          nonFeaturedPages.push({
            id: child.sys.id,
            title: child.title,
            link: child.url,
            children: buildSideNavTree(pageMetadataMap, featuredPages, child.children),
          });
        }
      }
    });
    nonFeaturedPages.sort(({ title: a }, { title: b }) => a.localeCompare(b));
    tree.push(...nonFeaturedPages);
  }
  return tree;
};

export const loadSideNavMap = (
  pageMetadataMap: PageMetadataMap,
  mainMenu: NavMenuType[],
): SideNavMap => {
  // construct the full side navs for each top tier utilizing work done in the main menu
  mainMenu.forEach((topTier) => {
    const metadata = pageMetadataMap.get(topTier.id);
    if (
      metadata &&
      metadata.slug &&
      metadata.sys &&
      metadata.title &&
      metadata.url &&
      topTier.children
    ) {
      // utilize the sort order from the main menu
      const featuredPages = topTier.children.map((menuItem) => menuItem.id);
      // remove the first item since it's always the top tier page
      featuredPages.splice(0, 1);
      sideNavMap.set(metadata.slug, {
        id: metadata.sys.id,
        title: metadata.title,
        link: metadata.url,
        children: buildSideNavTree(pageMetadataMap, featuredPages, metadata.children),
      });
    }
  });
  return sideNavMap;
};