All files / components/Header/Nav Nav.server.ts

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

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 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144                                                                                                                                                                                                                                                                                               
import gql from "graphql-tag";
import { print as printQuery } from "graphql";

import type { ContentfulClient } from "$lib/services/server/contentful";
import mainNavTestContent from "./__tests__/MainNavTestContent";
import secondaryNavTestContent from "./__tests__/SecondaryNavTestContent";

import type { HeaderMainMenuQuery } from "./$queries.generated";
import type { NavLinkType, NavMenuType } from "./types";
import type { PageMetadataMap } from "$lib/loadPageMetadataMap";

const headerMainMenuQuery = gql`
  query HeaderMainMenu($preview: Boolean = false) {
    menuCollection(limit: 1, where: { menuType: "Header Main Menu" }, preview: $preview) {
      items {
        childrenCollection(limit: 10) {
          items {
            ... on TopTier {
              __typename
              sys {
                id
              }
              pageMetadata {
                ... on PageMetadata {
                  sys {
                    id
                  }
                }
              }
              featuredServiceListCollection(limit: 7) {
                items {
                  ... on ServiceGroup {
                    pageMetadata {
                      ... on PageMetadata {
                        sys {
                          # eslint-disable-next-line @graphql-eslint/selection-set-depth
                          id
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
`;

export const loadMainNav = async ({
  pageMetadataMap,
  contentfulClient,
}: {
  pageMetadataMap: PageMetadataMap;
  contentfulClient?: ContentfulClient;
}): Promise<NavMenuType[]> => {
  if (!contentfulClient) return mainNavTestContent;
  const mainMenu: NavMenuType[] = [];
  const data = await contentfulClient.fetch<HeaderMainMenuQuery>(printQuery(headerMainMenuQuery));
  if (data?.menuCollection?.items?.length === 1) {
    const menuData = data.menuCollection.items[0]?.childrenCollection?.items;
    if (menuData) {
      menuData.forEach((topTier) => {
        if (topTier?.__typename === "TopTier") {
          const topTierMetadataId = topTier.pageMetadata?.sys?.id;
          if (topTierMetadataId) {
            const topTierMetadata = pageMetadataMap.get(topTierMetadataId);
            if (topTierMetadata && topTierMetadata.title && topTierMetadata.url) {
              // construct the top tier menu items, with the first child of each linking to relevant Top Tier page
              const menu: NavMenuType = {
                id: topTierMetadataId,
                name: topTierMetadata.title,
                children: [
                  {
                    id: topTierMetadataId,
                    name: `View ${topTierMetadata.title}`,
                    link: topTierMetadata.url,
                  },
                ],
              };
              // the next set of links for each menu should be the featured Service Groups on the Top Tier page
              const featuredServiceGroupMetadataIds =
                topTier?.featuredServiceListCollection?.items?.map(
                  (featuredServiceGroup) => featuredServiceGroup?.pageMetadata?.sys?.id,
                );
              if (featuredServiceGroupMetadataIds && featuredServiceGroupMetadataIds.length > 0) {
                featuredServiceGroupMetadataIds.forEach((id) => {
                  if (id) {
                    const metadata = pageMetadataMap.get(id);
                    if (metadata) {
                      const { sys, title, url } = metadata;
                      if (sys?.id && title && url) {
                        menu?.children?.push({
                          id: sys.id,
                          name: title,
                          link: url,
                        });
                      }
                    }
                  }
                });
              }
              // the last set of links are all second-tier pages not already included from the featured services
              const secondTierMenuItems: NavLinkType[] = [];
              topTierMetadata.children?.forEach((secondTierMetadataId) => {
                const foundDuplicateIndex = menu?.children?.findIndex(
                  (page) => page.id === secondTierMetadataId,
                );
                if (foundDuplicateIndex && foundDuplicateIndex < 0) {
                  const secondTierMetadata = pageMetadataMap.get(secondTierMetadataId);
                  if (secondTierMetadata) {
                    const { sys, title, url } = secondTierMetadata;
                    if (sys?.id && title && url) {
                      secondTierMenuItems.push({
                        id: sys.id,
                        name: title,
                        link: url,
                      });
                    }
                  }
                }
              });
              // sort alphabetically by the link name
              secondTierMenuItems.sort(({ name: a }, { name: b }) => {
                return a && b ? a.localeCompare(b) : -1;
              });
              secondTierMenuItems.forEach((item) => {
                menu?.children?.push(item);
              });
              mainMenu.push(menu);
            }
          }
        }
      });
    }
  }
  return mainMenu;
};

// TODO: Fetch from Contentful
export const loadSecondaryNav = () => secondaryNavTestContent;