feat(sw-187): Refactor footer output and fixed urls to include language

This commit is contained in:
Pontus Dreij
2024-09-09 13:59:36 +02:00
parent 093ea1a99a
commit ef33d082d8
15 changed files with 253 additions and 282 deletions

View File

@@ -62,11 +62,17 @@ export default function FooterSecondaryNav({
key={link.title}
target={link.openInNewTab ? "_blank" : "_self"}
aria-label={link.title}
className={styles.secondaryNavigationLink}
>
{link.title}
</a>
) : (
<Link href={link.url} key={link.title}>
<Link
href={link.url}
key={link.title}
target={link.openInNewTab ? "_blank" : "_self"}
color="burgundy"
>
{link.title}
</Link>
)}

View File

@@ -25,6 +25,14 @@
margin: 0;
}
.secondaryNavigationLink {
color: var(--Base-Text-High-contrast);
font-weight: var(--typography-Body-Bold-fontWeight);
font-family: var(--typography-Body-Bold-fontFamily);
margin: 0;
text-decoration: none;
}
@media screen and (min-width: 767px) {
.secondaryNavigation {
margin-top: var(--Spacing-x4);

View File

@@ -4,8 +4,8 @@ import FooterDetails from "./Details"
import FooterNavigation from "./Navigation"
export default async function Footer() {
const languages = await serverClient().contentstack.languageSwitcher.get()
const footerData = await serverClient().contentstack.base.footer()
const languages = await serverClient().contentstack.languageSwitcher.get()
if (!footerData || !languages) {
return <FooterDetails />

View File

@@ -1,28 +0,0 @@
fragment MainLinks on Footer {
main_links {
open_in_new_tab
link {
href
title
}
pageConnection {
edges {
node {
__typename
... on AccountPage {
title
url
}
... on LoyaltyPage {
title
url
}
... on ContentPage {
title
url
}
}
}
}
}
}

View File

@@ -1,22 +0,0 @@
#import "../../Refs/LoyaltyPage/LoyaltyPage.graphql"
#import "../../Refs/MyPages/AccountPage.graphql"
#import "../../Refs/ContentPage/ContentPage.graphql"
fragment MainLinksRef on Footer {
__typename
main_links {
pageConnection {
edges {
node {
__typename
...LoyaltyPageRef
...ContentPageRef
...AccountPageRef
}
}
}
}
system {
...System
}
}

View File

@@ -1,24 +0,0 @@
#import "../../Refs/LoyaltyPage/LoyaltyPage.graphql"
#import "../../Refs/MyPages/AccountPage.graphql"
#import "../../Refs/ContentPage/ContentPage.graphql"
fragment SecondaryLinksRef on Footer {
__typename
secondary_links {
links {
pageConnection {
edges {
node {
__typename
...LoyaltyPageRef
...ContentPageRef
...AccountPageRef
}
}
}
}
}
system {
...System
}
}

View File

@@ -1,31 +0,0 @@
fragment SecondaryLinks on Footer {
secondary_links {
title
links {
open_in_new_tab
pageConnection {
edges {
node {
__typename
... on AccountPage {
title
url
}
... on LoyaltyPage {
title
url
}
... on ContentPage {
title
url
}
}
}
}
link {
href
title
}
}
}
}

View File

@@ -1,28 +0,0 @@
fragment TertiaryLinks on Footer {
tertiary_links {
open_in_new_tab
link {
href
title
}
pageConnection {
edges {
node {
__typename
... on AccountPage {
title
url
}
... on LoyaltyPage {
title
url
}
... on ContentPage {
title
url
}
}
}
}
}
}

View File

@@ -1,21 +1,74 @@
#import "../Fragments/Footer/AppDownloads.graphql"
#import "../Fragments/Footer/MainLinks.graphql"
#import "../Fragments/Footer/SecondaryLinks.graphql"
#import "../Fragments/Footer/SocialMedia.graphql"
#import "../Fragments/Footer/TertiaryLinks.graphql"
#import "../Fragments/Footer/Refs/MainLinks.graphql"
#import "../Fragments/Footer/Refs/SecondaryLinks.graphql"
#import "../Fragments/Footer/Refs/TertiaryLinks.graphql"
#import "../Fragments/Refs/System.graphql"
#import "../Fragments/PageLink/AccountPageLink.graphql"
#import "../Fragments/PageLink/ContentPageLink.graphql"
#import "../Fragments/PageLink/HotelPageLink.graphql"
#import "../Fragments/PageLink/LoyaltyPageLink.graphql"
#import "../Fragments/Refs/ContentPage/ContentPage.graphql"
#import "../Fragments/Refs/HotelPage/HotelPage.graphql"
#import "../Fragments/Refs/LoyaltyPage/LoyaltyPage.graphql"
#import "../Fragments/Refs/MyPages/AccountPage.graphql"
#import "../Fragments/Footer/AppDownloads.graphql"
#import "../Fragments/Footer/SocialMedia.graphql"
query GetFooter($locale: String!) {
all_footer(limit: 1, locale: $locale) {
items {
...MainLinks
...SecondaryLinks
main_links {
open_in_new_tab
link {
href
title
}
pageConnection {
edges {
node {
...ContentPageLink
...HotelPageLink
...LoyaltyPageLink
}
}
}
}
secondary_links {
title
links {
open_in_new_tab
pageConnection {
edges {
node {
...ContentPageLink
...HotelPageLink
...LoyaltyPageLink
}
}
}
link {
href
title
}
}
}
tertiary_links {
open_in_new_tab
link {
href
title
}
pageConnection {
edges {
node {
...ContentPageLink
...HotelPageLink
...LoyaltyPageLink
}
}
}
}
...AppDownloads
...SocialMedia
...TertiaryLinks
}
}
}
@@ -23,9 +76,41 @@ query GetFooter($locale: String!) {
query GetFooterRef($locale: String!) {
all_footer(limit: 1, locale: $locale) {
items {
...MainLinksRef
...SecondaryLinksRef
...TertiaryLinksRef
main_links {
pageConnection {
edges {
node {
...ContentPageRef
...HotelPageRef
...LoyaltyPageRef
}
}
}
}
secondary_links {
links {
pageConnection {
edges {
node {
...ContentPageRef
...HotelPageRef
...LoyaltyPageRef
}
}
}
}
}
tertiary_links {
pageConnection {
edges {
node {
...ContentPageRef
...HotelPageRef
...LoyaltyPageRef
}
}
}
}
system {
...System
}

View File

@@ -280,100 +280,155 @@ const validateExternalLink = z
const validateInternalLink = z
.object({
edges: z.array(
z.object({
node: z.object({
title: z.string().optional(),
url: z.string().optional(),
}),
})
),
edges: z
.array(
z.object({
node: z.object({
system: z.object({
uid: z.string(),
locale: z.nativeEnum(Lang),
}),
url: z.string(),
title: z.string(),
web: z
.object({
original_url: z.string(),
})
.optional(),
}),
})
)
.max(1),
})
.transform((data) => {
const node = data.edges[0]?.node
if (!node) {
return null
}
const url = node.url
const originalUrl = node.web?.original_url
const lang = node.system.locale
return {
url: originalUrl || removeMultipleSlashes(`/${lang}/${url}`),
title: node.title,
}
})
.optional()
export const validateLinkItem = z.object({
open_in_new_tab: z.boolean(),
link: validateExternalLink,
pageConnection: validateInternalLink,
})
export const validateLinkItem = z
.object({
open_in_new_tab: z.boolean(),
link: validateExternalLink,
pageConnection: validateInternalLink,
})
.transform((data) => {
return {
url: data.pageConnection?.url ?? data.link?.href ?? "",
title: data.pageConnection?.title ?? data.link?.title,
openInNewTab: data.open_in_new_tab,
isExternal: !!data.link?.href,
}
})
export const validateFooterConfigSchema = z.object({
all_footer: z.object({
items: z.array(
z.object({
main_links: z.array(validateLinkItem),
app_downloads: z.object({
title: z.string(),
links: z.array(
z.object({
type: z.string(),
href: validateExternalLink,
})
),
}),
secondary_links: z.array(
z.object({
export const validateFooterConfigSchema = z
.object({
all_footer: z.object({
items: z.array(
z.object({
main_links: z.array(validateLinkItem),
app_downloads: z.object({
title: z.string(),
links: z.array(validateLinkItem),
})
),
social_media: z.object({
links: z.array(
links: z.array(
z.object({
type: z.string(),
href: validateExternalLink,
})
),
}),
secondary_links: z.array(
z.object({
type: z.string(),
href: validateExternalLink,
title: z.string(),
links: z.array(validateLinkItem),
})
),
}),
tertiary_links: z.array(validateLinkItem),
})
),
}),
})
social_media: z.object({
links: z.array(
z.object({
type: z.string(),
href: validateExternalLink,
})
),
}),
tertiary_links: z.array(validateLinkItem),
})
),
}),
})
.transform((data) => {
const {
main_links,
app_downloads,
secondary_links,
social_media,
tertiary_links,
} = data.all_footer.items[0]
return {
mainLinks: main_links,
appDownloads: app_downloads,
secondaryLinks: secondary_links,
socialMedia: social_media,
tertiaryLinks: tertiary_links,
}
})
const pageConnectionRefs = z.object({
edges: z.array(
z.object({
node: z.object({
__typename: z.nativeEnum(PageLinkEnum),
system: z.object({
content_type_uid: z.string(),
uid: z.string(),
edges: z
.array(
z.object({
node: z.object({
system: z.object({
content_type_uid: z.string(),
uid: z.string(),
}),
}),
}),
})
),
})
)
.max(1),
})
export const validateFooterRefConfigSchema = z.object({
all_footer: z.object({
items: z.array(
z.object({
main_links: z.array(
z.object({
pageConnection: pageConnectionRefs,
})
),
secondary_links: z.array(
z.object({
links: z.array(
z.object({
pageConnection: pageConnectionRefs,
})
),
})
),
tertiary_links: z.array(
z.object({
pageConnection: pageConnectionRefs,
})
),
system: z.object({
content_type_uid: z.string(),
uid: z.string(),
}),
})
),
items: z
.array(
z.object({
main_links: z.array(
z.object({
pageConnection: pageConnectionRefs,
})
),
secondary_links: z.array(
z.object({
links: z.array(
z.object({
pageConnection: pageConnectionRefs,
})
),
})
),
tertiary_links: z.array(
z.object({
pageConnection: pageConnectionRefs,
})
),
system: z.object({
content_type_uid: z.string(),
uid: z.string(),
}),
})
)
.length(1),
}),
})

View File

@@ -37,11 +37,7 @@ import {
validateFooterConfigSchema,
validateFooterRefConfigSchema,
} from "./output"
import {
getConnections,
getFooterConnections,
transformPageConnectionLinks,
} from "./utils"
import { getConnections, getFooterConnections } from "./utils"
import type {
FooterDataRaw,
@@ -658,28 +654,7 @@ export const baseQueryRouter = router({
"contentstack.footer success",
JSON.stringify({ query: { lang } })
)
const validatedFooterData = validatedFooterConfig.data.all_footer.items[0]
const mainLinks = transformPageConnectionLinks(
validatedFooterData.main_links
)
const secondaryLinks = validatedFooterData.secondary_links.map(
(section) => ({
title: section.title,
links: transformPageConnectionLinks(section.links),
})
)
const tertiaryLinks = transformPageConnectionLinks(
validatedFooterData.tertiary_links
)
return {
mainLinks: mainLinks,
appDownloads: validatedFooterData.app_downloads,
secondaryLinks: secondaryLinks,
socialMedia: validatedFooterData.social_media,
tertiaryLinks: tertiaryLinks,
}
return validatedFooterConfig.data
}),
})

View File

@@ -69,27 +69,3 @@ export function getFooterConnections(refs: FooterRefDataRaw) {
return connections
}
export function transformPageConnectionLinks(links: FooterLinkItem[]) {
if (!links) return []
return links.flatMap((link) => {
if (link.pageConnection?.edges.length) {
return link.pageConnection.edges.map((edge) => ({
title: edge.node.title || "",
url: edge.node.url || "",
openInNewTab: link.open_in_new_tab,
isExternal: false,
}))
} else if (link.link) {
return [
{
title: link.link.title,
url: link.link.href,
openInNewTab: link.open_in_new_tab,
isExternal: true,
},
]
}
return []
})
}

View File

@@ -8,5 +8,4 @@ import {
export type FooterRefDataRaw = z.infer<typeof validateFooterRefConfigSchema>
export type FooterDataRaw = z.infer<typeof validateFooterConfigSchema>
export type FooterData = FooterDataRaw["all_footer"]["items"][0]
export type FooterLinkItem = z.infer<typeof validateLinkItem>

View File

@@ -3,7 +3,7 @@ import type { LanguageSwitcherData } from "@/types/requests/languageSwitcher"
export type FooterLink = {
isExternal: boolean
openInNewTab: boolean
title: string
title: string | undefined
url: string
}
export type FooterMainNavProps = {

View File

@@ -1,4 +1,4 @@
import { LanguageSwitcherData } from "@/types/requests/languageSwitcher"
import type { LanguageSwitcherData } from "@/types/requests/languageSwitcher"
export interface LanguageSwitcherProps {
type: "mobileHeader" | "desktopHeader" | "footer"