Merged in feat/language-switcher-revalidation (pull request #42)
Feat/language switcher revalidation Approved-by: Christel Westerberg Approved-by: Arvid Norlin
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import AdobeScript from "@/components/Current/AdobeScript"
|
||||
import Script from "next/script"
|
||||
|
||||
import type { Metadata } from "next"
|
||||
import type { LangParams, LayoutArgs } from "@/types/params"
|
||||
import AdobeScript from "../AdobeScript"
|
||||
|
||||
export const metadata: Metadata = {
|
||||
description: "New web",
|
||||
|
||||
@@ -4,7 +4,8 @@ import { request } from "@/lib/request"
|
||||
import { GetCurrentBlockPage } from "@/lib/graphql/Query/CurrentBlockPage.graphql"
|
||||
|
||||
import ContentPage from "@/components/Current/ContentPage"
|
||||
import Tracking from "../../Tracking"
|
||||
import Header from "@/components/Current/Header"
|
||||
import Tracking from "@/components/Current/Tracking"
|
||||
|
||||
import type { PageArgs, LangParams, UriParams } from "@/types/params"
|
||||
import type { GetCurrentBlockPageData } from "@/types/requests/currentBlockPage"
|
||||
@@ -23,6 +24,9 @@ export default async function CurrentContentPage({
|
||||
{
|
||||
locale: params.lang,
|
||||
url: searchParams.uri,
|
||||
},
|
||||
{
|
||||
tags: [`${searchParams.uri}-${params.lang}`]
|
||||
}
|
||||
)
|
||||
|
||||
@@ -43,11 +47,8 @@ export default async function CurrentContentPage({
|
||||
|
||||
return (
|
||||
<>
|
||||
<ContentPage
|
||||
data={response.data}
|
||||
uri={searchParams.uri}
|
||||
lang={params.lang}
|
||||
/>
|
||||
<Header lang={params.lang} uid={pageData.system.uid} />
|
||||
<ContentPage data={response.data} />
|
||||
<Tracking pageData={trackingData} />
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* eslint-disable @next/next/no-css-tags */
|
||||
|
||||
import AdobeScript from "@/components/Current/AdobeScript"
|
||||
import Footer from "@/components/Current/Footer"
|
||||
import LangPopup from "@/components/Current/LangPopup"
|
||||
import Script from "next/script"
|
||||
import SkipToMainContent from "@/components/SkipToMainContent"
|
||||
import AdobeScript from "../AdobeScript"
|
||||
|
||||
import type { Metadata } from "next"
|
||||
import type { LangParams, LayoutArgs } from "@/types/params"
|
||||
@@ -21,8 +21,8 @@ export default function RootLayout({
|
||||
return (
|
||||
<html lang={params.lang}>
|
||||
<head>
|
||||
<link rel="stylesheet" href="/Static/css/core.css"/>
|
||||
<link rel="stylesheet" href="/Static/css/scandic.css"/>
|
||||
<link rel="stylesheet" href="/Static/css/core.css" />
|
||||
<link rel="stylesheet" href="/Static/css/scandic.css" />
|
||||
<Script
|
||||
data-cookieconsent="ignore"
|
||||
src="/Static/dist/js/cookie-bot.js?1705409331007"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import InitLivePreview from "@/components/Current/LivePreview"
|
||||
|
||||
import type { Metadata } from "next"
|
||||
import type { LangParams, LayoutArgs } from "@/types/params"
|
||||
import InitLivePreview from "@/components/Current/LivePreview"
|
||||
|
||||
export const metadata: Metadata = {
|
||||
description: "New web",
|
||||
|
||||
@@ -30,13 +30,7 @@ export default async function CurrentPreviewPage({
|
||||
throw new Error("Not found")
|
||||
}
|
||||
|
||||
return (
|
||||
<ContentPage
|
||||
data={response.data}
|
||||
uri={searchParams.uri}
|
||||
lang={params.lang}
|
||||
/>
|
||||
)
|
||||
return <ContentPage data={response.data} />
|
||||
} catch (error) {
|
||||
// TODO: throw 500
|
||||
console.error(error)
|
||||
|
||||
45
app/api/revalidate/route.ts
Normal file
45
app/api/revalidate/route.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { env } from "@/env/server"
|
||||
import { revalidateTag } from 'next/cache'
|
||||
|
||||
import type { NextRequest } from 'next/server'
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const secret = request.nextUrl.searchParams.get("secret") ?? ""
|
||||
const tag = request.nextUrl.searchParams.get("tag") ?? ""
|
||||
|
||||
if (secret !== env.REVALIDATE_SECRET) {
|
||||
return Response.json(
|
||||
{
|
||||
message: 'Invalid secret',
|
||||
now: Date.now(),
|
||||
revalidated: false,
|
||||
},
|
||||
{
|
||||
status: 401,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (!tag) {
|
||||
return Response.json(
|
||||
{
|
||||
message: 'Missing tag param',
|
||||
now: Date.now(),
|
||||
revalidated: false,
|
||||
},
|
||||
{
|
||||
status: 400,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
revalidateTag(tag)
|
||||
|
||||
return Response.json({ revalidated: true, now: Date.now() })
|
||||
} catch (error) {
|
||||
console.info("Failed to revalidate tag")
|
||||
console.error(error)
|
||||
return Response.json({ revalidated: false, now: Date.now() }, { status: 500 })
|
||||
}
|
||||
}
|
||||
42
components/Current/Aside/Puff/index.tsx
Normal file
42
components/Current/Aside/Puff/index.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import { renderOptions } from "./renderOptions"
|
||||
|
||||
import Image from "@/components/Image"
|
||||
import JsonToHtml from "@/components/JsonToHtml"
|
||||
|
||||
import styles from "./puff.module.css"
|
||||
|
||||
import type { PuffProps } from "@/types/components/current/asides/puff"
|
||||
|
||||
export default function Puff({
|
||||
imageConnection,
|
||||
link,
|
||||
text,
|
||||
title,
|
||||
}: PuffProps) {
|
||||
return (
|
||||
<a className={styles.link} href={link.href}>
|
||||
<article>
|
||||
{imageConnection.edges.map((image) => (
|
||||
<Image
|
||||
alt={image.node.title}
|
||||
className={styles.image}
|
||||
height={image.node.dimension.height}
|
||||
key={image.node.system.uid}
|
||||
src={image.node.url}
|
||||
width={image.node.dimension.width}
|
||||
/>
|
||||
))}
|
||||
<section className={styles.content}>
|
||||
<header>
|
||||
<h3 className={styles.heading}>{title}</h3>
|
||||
</header>
|
||||
<JsonToHtml
|
||||
embeds={[]}
|
||||
nodes={text.json.children}
|
||||
renderOptions={renderOptions}
|
||||
/>
|
||||
</section>
|
||||
</article>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
import { renderOptions } from "./renderOptions"
|
||||
|
||||
import JsonToHtml from "@/components/JsonToHtml"
|
||||
import Link from "next/link"
|
||||
|
||||
import styles from "./puff.module.css"
|
||||
|
||||
import type { PuffProps } from "@/types/components/current/asides/puff"
|
||||
import Image from "@/components/Image"
|
||||
|
||||
export default function Puff({
|
||||
imageConnection,
|
||||
is_internal,
|
||||
link,
|
||||
pageConnection,
|
||||
text,
|
||||
title,
|
||||
}: PuffProps) {
|
||||
if (is_internal) {
|
||||
const page = pageConnection.edges[0]
|
||||
if (!page?.node?.url) {
|
||||
return null
|
||||
}
|
||||
return (
|
||||
<Link className={styles.link} href={page.node.url}>
|
||||
<PuffContent
|
||||
imageConnection={imageConnection}
|
||||
text={text}
|
||||
title={title}
|
||||
/>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<a className={styles.link} href={link.href} target="_blank">
|
||||
<PuffContent
|
||||
imageConnection={imageConnection}
|
||||
text={text}
|
||||
title={title}
|
||||
/>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
function PuffContent({
|
||||
imageConnection,
|
||||
text,
|
||||
title,
|
||||
}: Pick<PuffProps, "imageConnection" | "text" | "title">) {
|
||||
return (
|
||||
<article>
|
||||
{imageConnection.edges.map((image) => (
|
||||
<Image
|
||||
alt={image.node.title}
|
||||
className={styles.image}
|
||||
height={image.node.dimension.height}
|
||||
key={image.node.system.uid}
|
||||
src={image.node.url}
|
||||
width={image.node.dimension.width}
|
||||
/>
|
||||
))}
|
||||
<section className={styles.content}>
|
||||
<header>
|
||||
<h3 className={styles.heading}>{title}</h3>
|
||||
</header>
|
||||
<JsonToHtml
|
||||
embeds={text.embedded_itemsConnection.edges}
|
||||
nodes={text.json.children}
|
||||
renderOptions={renderOptions}
|
||||
/>
|
||||
</section>
|
||||
</article>
|
||||
)
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import Puff from "./Puff"
|
||||
|
||||
import type { PuffsProps } from "@/types/components/current/asides/puffs"
|
||||
|
||||
export default function Puffs({ puffs }: PuffsProps) {
|
||||
if (!puffs.length) {
|
||||
return null
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{puffs.map((puff) => (
|
||||
<Puff key={puff.node.system.uid} {...puff.node} />
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import Puffs from "./Puffs"
|
||||
import Puff from "./Puff"
|
||||
import Contacts from "./Contacts"
|
||||
|
||||
import { AsideTypenameEnum } from "@/types/requests/utils/typename"
|
||||
@@ -25,9 +25,9 @@ export default function Aside({ blocks }: AsideProps) {
|
||||
)
|
||||
case AsideTypenameEnum.CurrentBlocksPageAsidePuff:
|
||||
return (
|
||||
<Puffs
|
||||
<Puff
|
||||
key={`block-${idx}`}
|
||||
puffs={block.puff.puffConnection.edges}
|
||||
{...block.puff}
|
||||
/>
|
||||
)
|
||||
default:
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import Link from "next/link"
|
||||
import { cva } from "class-variance-authority"
|
||||
import { BlockListItemsEnum } from "@/types/requests/blocks/list"
|
||||
|
||||
@@ -63,27 +62,6 @@ export default function ListItem({ listItem }: { listItem: ListItem }) {
|
||||
)}
|
||||
</li>
|
||||
)
|
||||
case BlockListItemsEnum.CurrentBlocksPageBlocksListBlockListItemsListItemInternalLink:
|
||||
const link = listItem.list_item_internal_link.pageConnection.edges[0]
|
||||
const linkUrlWithLocale = `/${link.node.system.locale}${link.node.url}`
|
||||
return (
|
||||
<li
|
||||
key={link.node.system.uid}
|
||||
className={listItemStyle({
|
||||
type: listItem.list_item_internal_link.list_item_style,
|
||||
})}
|
||||
>
|
||||
<Link href={linkUrlWithLocale} className={styles.link}>
|
||||
{listItem.list_item_internal_link.link_text}
|
||||
</Link>
|
||||
{listItem.list_item_internal_link.subtitle && (
|
||||
<span>
|
||||
<br />
|
||||
{listItem.list_item_internal_link.subtitle}
|
||||
</span>
|
||||
)}
|
||||
</li>
|
||||
)
|
||||
|
||||
default:
|
||||
return null
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import type { ListProps } from "@/types/requests/blocks/list"
|
||||
import ListItem from "./ListItem"
|
||||
|
||||
import styles from "./list.module.css"
|
||||
import ListItem from "./ListItem"
|
||||
|
||||
import type { ListProps } from "@/types/requests/blocks/list"
|
||||
|
||||
export default function List({ list }: ListProps) {
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
{list.title ? <h2 className={styles.title}>{list.title}</h2> : null}
|
||||
<ul className={styles.ul}>
|
||||
{list.list_items.map((item, i) => (
|
||||
<ListItem listItem={item} key={`list-item-${i}`} />
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
.title {
|
||||
color: #483729;
|
||||
font-family: BrandonText-Bold, Arial, Helvetica, sans-serif;
|
||||
font-size: 1.375rem;
|
||||
line-height: 1.1em;
|
||||
text-transform: uppercase;
|
||||
font-weight: 400;
|
||||
color: #483729;
|
||||
line-height: 1.1em;
|
||||
margin-bottom: 1rem;
|
||||
margin-top: 2rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.title:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.ul {
|
||||
@@ -64,4 +69,4 @@
|
||||
.title {
|
||||
font-size: 1.625rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
padding-bottom: 50px;
|
||||
background: #f3f2f1;
|
||||
display: block;
|
||||
}
|
||||
padding-bottom: 50px;
|
||||
width: 100%;
|
||||
z-index: 10;
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import Aside from "@/components/Current/Aside"
|
||||
import Blocks from "@/components/Current/Blocks"
|
||||
import Header from "@/components/Current/Header"
|
||||
import Hero from "@/components/Current/Hero"
|
||||
import Preamble from "@/components/Current/Preamble"
|
||||
import Section from "@/components/Current/Section"
|
||||
@@ -10,15 +9,14 @@ import styles from "./contentPage.module.css"
|
||||
|
||||
import type { ContentPageProps } from "@/types/components/current/contentPage"
|
||||
|
||||
export default function ContentPage({ data, lang, uri }: ContentPageProps) {
|
||||
export default function ContentPage({ data }: ContentPageProps) {
|
||||
const page = data.all_current_blocks_page.items[0]
|
||||
const images = page.hero?.imagesConnection
|
||||
const breadcrumbs = page.breadcrumbs.parentsConnection
|
||||
const parent = breadcrumbs.edges.at(-1)
|
||||
const breadcrumbs = page.breadcrumbs.parents
|
||||
const parent = breadcrumbs.at(-1)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header lang={lang} pathname={uri} />
|
||||
{images?.totalCount ? <Hero images={images.edges} /> : null}
|
||||
<main className={styles.wrapper} id="maincontent" role="main">
|
||||
<input
|
||||
|
||||
@@ -1,49 +1,24 @@
|
||||
import {
|
||||
FooterNavigationProps,
|
||||
FooterNavigationItemProps,
|
||||
} from "@/types/components/current/footer"
|
||||
import Link from "next/link"
|
||||
import type { FooterNavigationProps } from "@/types/components/current/footer"
|
||||
|
||||
function NavigationItem({ linkObject, lang }: FooterNavigationItemProps) {
|
||||
if (linkObject.__typename === "FooterNavigationLinksInternalLink") {
|
||||
const href = `/${lang}${linkObject.internal_link.pageConnection.edges[0].node.url}`
|
||||
return (
|
||||
<li>
|
||||
<Link href={href}>{linkObject.internal_link.link_text}</Link>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<li>
|
||||
<a href={linkObject.external_link.link.href}>
|
||||
{linkObject.external_link.link.title}
|
||||
</a>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
export default function Navigation({
|
||||
linkGroups,
|
||||
lang,
|
||||
}: FooterNavigationProps) {
|
||||
export default function Navigation({ linkGroups }: FooterNavigationProps) {
|
||||
return (
|
||||
<ul className="l-footer-sections global-footer__content__sections">
|
||||
{linkGroups.map((group) => {
|
||||
return (
|
||||
<li className="global-footer-section" key={group.title}>
|
||||
<div className="link-list">
|
||||
<h3 className="link-list-header">{group.title}</h3>
|
||||
<ul className="list-footer-pages">
|
||||
{group.links.map((link, idx) => {
|
||||
return (
|
||||
<NavigationItem key={idx} linkObject={link} lang={lang} />
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
{linkGroups.map((group) => (
|
||||
<li className="global-footer-section" key={group.title}>
|
||||
<div className="link-list">
|
||||
<h3 className="link-list-header">{group.title}</h3>
|
||||
<ul className="list-footer-pages">
|
||||
{group.links.map(link => (
|
||||
<li key={link.href}>
|
||||
<a href={link.href}>
|
||||
{link.title}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,9 +9,15 @@ import type { GetFooterData } from "@/types/requests/footer"
|
||||
import type { LangParams } from "@/types/params"
|
||||
|
||||
export default async function Footer({ lang }: LangParams) {
|
||||
const response = await request<GetFooterData>(GetFooter, {
|
||||
locale: lang,
|
||||
})
|
||||
const response = await request<GetFooterData>(
|
||||
GetFooter,
|
||||
{
|
||||
locale: lang,
|
||||
},
|
||||
{
|
||||
tags: [`footer-${lang}`]
|
||||
}
|
||||
)
|
||||
|
||||
const footerData = response.data.all_footer.items[0]
|
||||
return (
|
||||
@@ -40,7 +46,7 @@ export default async function Footer({ lang }: LangParams) {
|
||||
data-js-collapsible="global-footer"
|
||||
className="collapsible-global-footer"
|
||||
>
|
||||
<Navigation lang={lang} linkGroups={footerData.navigation} />
|
||||
<Navigation linkGroups={footerData.navigation} />
|
||||
|
||||
<div className="global-footer__content__bottom">
|
||||
<p className="newFooterTitle">
|
||||
|
||||
@@ -1,198 +0,0 @@
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
import {
|
||||
currentAboutLinks,
|
||||
currentSponsoringLinks,
|
||||
currentWifiLinks,
|
||||
} from "@/constants/current/links"
|
||||
|
||||
import Desktop from "./LanguageSwitcher/Desktop"
|
||||
import Mobile from "./LanguageSwitcher/Mobile"
|
||||
|
||||
import type { LanguageSwitcherLink } from "@/types/components/current/languageSwitcher"
|
||||
import type { HeaderProps } from "@/types/components/current/header"
|
||||
|
||||
const paths: Record<string, LanguageSwitcherLink[]> = {
|
||||
"/kundeservice/sporgsmal-og-svar/om-scandics-website": currentAboutLinks,
|
||||
"/oplev-scandic/wifi": currentWifiLinks,
|
||||
"/sponsorering": currentSponsoringLinks,
|
||||
}
|
||||
|
||||
const currentLanguage = "Dansk"
|
||||
|
||||
export default function DaHeader({ pathname }: HeaderProps) {
|
||||
const links = paths?.[pathname] ?? null
|
||||
return (
|
||||
<header className="header" role="banner">
|
||||
<div className="offline-banner hidden">
|
||||
Du er offline. Noget indhold på siden kan være forældet.
|
||||
<button type="button" className="reload">
|
||||
Opdatér siden
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="l-section main-header navigation-bar"
|
||||
data-js="main-nav-bar"
|
||||
>
|
||||
<div className="navigation-bar__top navigation-bar__top--ghostwhite-light">
|
||||
<div className="l-section__inner">
|
||||
<a
|
||||
href="https://www.scandichotels.dk"
|
||||
className="scandic-main-page-link"
|
||||
>
|
||||
Back to scandichotels.dk
|
||||
</a>
|
||||
|
||||
<ul className="nav-secondary navbar-login">
|
||||
<li className="nav-secondary__item hidden-xxsmall hidden-xsmall hidden-small">
|
||||
{links ? (
|
||||
<Desktop currentLanguage={currentLanguage} links={links} />
|
||||
) : null}
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.dk/hotelreservation/hent-booking"
|
||||
>
|
||||
Vis/Afbestil booking
|
||||
</a>
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.dk/job-hos-scandic/ledige-stillinger"
|
||||
>
|
||||
Arbejd med os
|
||||
</a>
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.dk/forretningsrejse"
|
||||
>
|
||||
Forretningsrejse
|
||||
</a>
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.dk/scandic-friends"
|
||||
>
|
||||
Om Scandic Friends
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div className="navigation-bar__main">
|
||||
<div
|
||||
className="l-section__inner l-section__inner--small-no-padding"
|
||||
itemScope
|
||||
itemType="http://schema.org/Organization"
|
||||
>
|
||||
<meta itemProp="name" content="Scandic" />
|
||||
<button
|
||||
type="button"
|
||||
className="navigation-bar__main__expander"
|
||||
data-js="main-nav-toggler"
|
||||
data-target="#main-menu"
|
||||
aria-pressed="false"
|
||||
>
|
||||
<span className="icon-bars"></span>
|
||||
<span className="hidden--accessible">Menu</span>
|
||||
</button>
|
||||
|
||||
<a
|
||||
id="scandic-logo"
|
||||
className="navigation-bar__main__logo hidden-medium "
|
||||
href="https://www.scandichotels.dk"
|
||||
itemProp="url"
|
||||
>
|
||||
<span className="hidden--accessible">
|
||||
Back to scandichotels.dk
|
||||
</span>
|
||||
<img
|
||||
src="/Static/img/scandic-logotype.svg"
|
||||
data-js="scandiclogoimg"
|
||||
alt="Scandic Hotels logo"
|
||||
height="22"
|
||||
data-nosvgsrc="/Static/img/scandic-logotype.png"
|
||||
itemProp="logo"
|
||||
/>
|
||||
</a>
|
||||
|
||||
<nav>
|
||||
<ul
|
||||
id="main-menu"
|
||||
className="nav-primary is-collapsed"
|
||||
data-collapsable="main-menu"
|
||||
>
|
||||
<li
|
||||
className="nav-primary__item nav-primary__item--primary hidden-large hidden-small hidden-xsmall hidden-xxsmall"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<a
|
||||
className="navigation-bar__main__logo"
|
||||
href="https://www.scandichotels.dk"
|
||||
>
|
||||
<img
|
||||
src="/Static/img/scandic-logotype.svg"
|
||||
data-js="scandiclogoimg"
|
||||
alt="Scandic Hotels logo"
|
||||
height="22"
|
||||
data-nosvgsrc="/Static/img/scandic-logotype.png"
|
||||
/>
|
||||
<span className="hidden--accessible">
|
||||
Back to scandichotels.dk
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.dk/hoteller">
|
||||
Hoteller & destinationer
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.dk/rejseguide">
|
||||
Rejseguide
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.dk/mode-konference-event">
|
||||
Møde, konference & event
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.dk/oplev-scandic">
|
||||
Oplev Scandic
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.dk/tilbud-og-hotelpakker">
|
||||
Tilbud
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li className="nav-primary__item nav-primary__item--secondary hidden-medium hidden-large ">
|
||||
<a href="https://www.scandichotels.dk/scandic-friends">
|
||||
Om Scandic Friends
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--secondary hidden-medium hidden-large ">
|
||||
<a href="https://www.scandichotels.dk/forretningsrejse">
|
||||
Forretningsrejse
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li className="nav-primary__item hidden-medium hidden-large">
|
||||
{links ? (
|
||||
<Mobile currentLanguage={currentLanguage} links={links} />
|
||||
) : null}
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
import {
|
||||
currentAboutLinks,
|
||||
currentSponsoringLinks,
|
||||
currentWifiLinks,
|
||||
} from "@/constants/current/links"
|
||||
|
||||
import Desktop from "./LanguageSwitcher/Desktop"
|
||||
import Mobile from "./LanguageSwitcher/Mobile"
|
||||
|
||||
import type { HeaderProps } from "@/types/components/current/header"
|
||||
import type { LanguageSwitcherLink } from "@/types/components/current/languageSwitcher"
|
||||
|
||||
const paths: Record<string, LanguageSwitcherLink[]> = {
|
||||
"/kundenbetreuung/haufig-gestellte-fragen/nutzung-der-internetseite":
|
||||
currentAboutLinks,
|
||||
"/scandic-entdecken/wlan": currentWifiLinks,
|
||||
"/sponsoring": currentSponsoringLinks,
|
||||
}
|
||||
|
||||
const currentLanguage = "Deutsch"
|
||||
|
||||
export default function DeHeader({ pathname }: HeaderProps) {
|
||||
const links = paths?.[pathname] ?? null
|
||||
|
||||
return (
|
||||
<header className="header" role="banner">
|
||||
<div className="offline-banner hidden">
|
||||
Sie sind offline. Manche Inhalte könnten nicht aktuell sein.
|
||||
<button type="button" className="reload">
|
||||
Neu laden
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="l-section main-header navigation-bar"
|
||||
data-js="main-nav-bar"
|
||||
>
|
||||
<div className="navigation-bar__top navigation-bar__top--ghostwhite-light">
|
||||
<div className="l-section__inner">
|
||||
<a
|
||||
href="https://www.scandichotels.de"
|
||||
className="scandic-main-page-link"
|
||||
>
|
||||
Back to scandichotels.de
|
||||
</a>
|
||||
<ul className="nav-secondary navbar-login">
|
||||
<li className="nav-secondary__item hidden-xxsmall hidden-xsmall hidden-small">
|
||||
{links ? (
|
||||
<Desktop currentLanguage={currentLanguage} links={links} />
|
||||
) : null}
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.de/hotelreservation/get-booking"
|
||||
>
|
||||
Buchung ansehen/ändern
|
||||
</a>
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.de/karriere-bei-scandic-hotels"
|
||||
>
|
||||
Karriere bei Scandic
|
||||
</a>
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.de/geschaftsreisen"
|
||||
>
|
||||
Firmenkunden
|
||||
</a>
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.de/scandic-friends"
|
||||
>
|
||||
Über Scandic Friends
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="navigation-bar__main">
|
||||
<div
|
||||
className="l-section__inner l-section__inner--small-no-padding"
|
||||
itemScope={undefined}
|
||||
itemType="http://schema.org/Organization"
|
||||
>
|
||||
<meta itemProp="name" content="Scandic" />
|
||||
<button
|
||||
type="button"
|
||||
className="navigation-bar__main__expander"
|
||||
data-js="main-nav-toggler"
|
||||
data-target="#main-menu"
|
||||
aria-pressed="false"
|
||||
>
|
||||
<span className="icon-bars"></span>
|
||||
<span className="hidden--accessible">Menu</span>
|
||||
</button>
|
||||
<a
|
||||
id="scandic-logo"
|
||||
className="navigation-bar__main__logo hidden-medium "
|
||||
href="https://www.scandichotels.de"
|
||||
itemProp="url"
|
||||
>
|
||||
<span className="hidden--accessible">
|
||||
Back to scandichotels.de
|
||||
</span>
|
||||
<img
|
||||
src="/Static/img/scandic-logotype.svg"
|
||||
data-js="scandiclogoimg"
|
||||
alt="Scandic Hotels logo"
|
||||
height="22"
|
||||
data-nosvgsrc="/Static/img/scandic-logotype.png"
|
||||
itemProp="logo"
|
||||
/>
|
||||
</a>
|
||||
<ul
|
||||
id="navbar-header-design"
|
||||
className="hidden hidden-medium hidden-large nav-primary__header"
|
||||
>
|
||||
<li className="nav-primary__scandicfriendslogo">
|
||||
<img
|
||||
src="/Static/img/icons/scandic-friends/icon-scandic-friends.svg"
|
||||
width="35"
|
||||
height="35"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<nav>
|
||||
<ul
|
||||
id="main-menu"
|
||||
className="nav-primary is-collapsed"
|
||||
data-collapsable="main-menu"
|
||||
>
|
||||
<li
|
||||
className="nav-primary__item nav-primary__item--primary hidden-large hidden-small hidden-xsmall hidden-xxsmall"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<a
|
||||
className="navigation-bar__main__logo"
|
||||
href="https://www.scandichotels.de"
|
||||
>
|
||||
<img
|
||||
src="/Static/img/scandic-logotype.svg"
|
||||
data-js="scandiclogoimg"
|
||||
alt="Scandic Hotels logo"
|
||||
height="22"
|
||||
data-nosvgsrc="/Static/img/scandic-logotype.png"
|
||||
/>
|
||||
<span className="hidden--accessible">
|
||||
Back to scandichotels.de
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.de/hotelsuche">
|
||||
Hotels & Reiseziele
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.de/reisemagazin">
|
||||
Reisemagazin
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.de/tagungen-und-events">
|
||||
Tagungen & Events
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.de/scandic-entdecken">
|
||||
Scandic entdecken
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.de/angebote-arrangements">
|
||||
Angebote
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--secondary hidden-medium hidden-large ">
|
||||
<a href="https://www.scandichotels.de/scandic-friends">
|
||||
Über Scandic Friends
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--secondary hidden-medium hidden-large ">
|
||||
<a href="https://www.scandichotels.de/geschaftsreisen">
|
||||
Geschäftsreisen
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item hidden-medium hidden-large">
|
||||
{links ? (
|
||||
<Mobile currentLanguage={currentLanguage} links={links} />
|
||||
) : null}
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
@@ -1,196 +0,0 @@
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
import {
|
||||
currentAboutLinks,
|
||||
currentSponsoringLinks,
|
||||
currentWifiLinks,
|
||||
} from "@/constants/current/links"
|
||||
|
||||
import Desktop from "./LanguageSwitcher/Desktop"
|
||||
import Mobile from "./LanguageSwitcher/Mobile"
|
||||
|
||||
import type { LanguageSwitcherLink } from "@/types/components/current/languageSwitcher"
|
||||
import type { HeaderProps } from "@/types/components/current/header"
|
||||
|
||||
const paths: Record<string, LanguageSwitcherLink[]> = {
|
||||
"/customer-service/frequently-asked-questions/using-the-website":
|
||||
currentAboutLinks,
|
||||
"/explore-scandic/wifi": currentWifiLinks,
|
||||
"/sponsoring": currentSponsoringLinks,
|
||||
}
|
||||
|
||||
const currentLanguage = "English"
|
||||
|
||||
export default function EnHeader({ pathname }: HeaderProps) {
|
||||
const links = paths?.[pathname] ?? null
|
||||
return (
|
||||
<header className="header" role="banner">
|
||||
<div className="offline-banner hidden">
|
||||
You are offline, some content may be out of date.
|
||||
<button type="button" className="reload">
|
||||
Reload
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="l-section main-header navigation-bar"
|
||||
data-js="main-nav-bar"
|
||||
>
|
||||
<div className="navigation-bar__top navigation-bar__top--ghostwhite-light">
|
||||
<div className="l-section__inner">
|
||||
<a
|
||||
href="https://www.scandichotels.com"
|
||||
className="scandic-main-page-link"
|
||||
>
|
||||
Back to scandichotels.com
|
||||
</a>
|
||||
|
||||
<ul className="nav-secondary navbar-login">
|
||||
<li className="nav-secondary__item hidden-xxsmall hidden-xsmall hidden-small">
|
||||
{links ? (
|
||||
<Desktop currentLanguage={currentLanguage} links={links} />
|
||||
) : null}
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="/hotelreservation/get-booking"
|
||||
>
|
||||
View/Cancel booking
|
||||
</a>
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a className="nav-secondary__item__link" href="/work-with-us">
|
||||
Work with us
|
||||
</a>
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="/corporate-travel"
|
||||
>
|
||||
Corporate Travel
|
||||
</a>
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="/scandic-friends"
|
||||
>
|
||||
About Scandic Friends
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div className="navigation-bar__main">
|
||||
<div
|
||||
className="l-section__inner l-section__inner--small-no-padding"
|
||||
itemScope
|
||||
itemType="http://schema.org/Organization"
|
||||
>
|
||||
<meta itemProp="name" content="Scandic" />
|
||||
<button
|
||||
type="button"
|
||||
className="navigation-bar__main__expander"
|
||||
data-js="main-nav-toggler"
|
||||
data-target="#main-menu"
|
||||
aria-pressed="false"
|
||||
>
|
||||
<span className="icon-bars"></span>
|
||||
<span className="hidden--accessible">Menu</span>
|
||||
</button>
|
||||
|
||||
<a
|
||||
id="scandic-logo"
|
||||
className="navigation-bar__main__logo hidden-medium "
|
||||
href="https://www.scandichotels.com"
|
||||
itemProp="url"
|
||||
>
|
||||
<span className="hidden--accessible">
|
||||
Back to scandichotels.com
|
||||
</span>
|
||||
<img
|
||||
src="/Static/img/scandic-logotype.svg"
|
||||
data-js="scandiclogoimg"
|
||||
alt="Scandic Hotels logo"
|
||||
height="22"
|
||||
data-nosvgsrc="/Static/img/scandic-logotype.png"
|
||||
itemProp="logo"
|
||||
/>
|
||||
</a>
|
||||
|
||||
<nav>
|
||||
<ul
|
||||
id="main-menu"
|
||||
className="nav-primary is-collapsed"
|
||||
data-collapsable="main-menu"
|
||||
>
|
||||
<li
|
||||
className="nav-primary__item nav-primary__item--primary hidden-large hidden-small hidden-xsmall hidden-xxsmall"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<a
|
||||
className="navigation-bar__main__logo"
|
||||
href="https://www.scandichotels.com"
|
||||
>
|
||||
<img
|
||||
src="/Static/img/scandic-logotype.svg"
|
||||
data-js="scandiclogoimg"
|
||||
alt="Scandic Hotels logo"
|
||||
height="22"
|
||||
data-nosvgsrc="/Static/img/scandic-logotype.png"
|
||||
/>
|
||||
<span className="hidden--accessible">
|
||||
Back to scandichotels.com
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.com/hotels">
|
||||
Hotels & Destinations
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.com/travel-guides">
|
||||
Travel guides
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.com/conferences-meetings">
|
||||
Conferences & Meetings
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.com/explore-scandic">
|
||||
Explore Scandic
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.com/weekend-packages-and-offers">
|
||||
Offers
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li className="nav-primary__item nav-primary__item--secondary hidden-medium hidden-large ">
|
||||
<a href="https://www.scandichotels.com/scandic-friends">
|
||||
About Scandic Friends
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--secondary hidden-medium hidden-large ">
|
||||
<a href="https://www.scandichotels.com/corporate-travel">
|
||||
Corporate Travel
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li className="nav-primary__item hidden-medium hidden-large">
|
||||
{links ? (
|
||||
<Mobile currentLanguage={currentLanguage} links={links} />
|
||||
) : null}
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
import {
|
||||
currentAboutLinks,
|
||||
currentSponsoringLinks,
|
||||
currentWifiLinks,
|
||||
} from "@/constants/current/links"
|
||||
|
||||
import Desktop from "./LanguageSwitcher/Desktop"
|
||||
import Mobile from "./LanguageSwitcher/Mobile"
|
||||
|
||||
import type { LanguageSwitcherLink } from "@/types/components/current/languageSwitcher"
|
||||
import type { HeaderProps } from "@/types/components/current/header"
|
||||
|
||||
const paths: Record<string, LanguageSwitcherLink[]> = {
|
||||
"/asiakaspalvelu/usein-kysytyt-kysymykset/tietoja-internetsivuista":
|
||||
currentAboutLinks,
|
||||
"/koe-scandic/maksuton-internetyhteys": currentSponsoringLinks,
|
||||
"/scandic-entdecken/wlan": currentWifiLinks,
|
||||
}
|
||||
|
||||
const currentLanguage = "Suomi"
|
||||
|
||||
export default function FiHeader({ pathname }: HeaderProps) {
|
||||
const links = paths?.[pathname] ?? null
|
||||
return (
|
||||
<header className="header" role="banner">
|
||||
<div className="offline-banner hidden">
|
||||
Ei yhteyttä verkkoon. Osa sisällöstä saattaa olla vanhentunut.
|
||||
<button type="button" className="reload">
|
||||
Lataa uudelleen
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="l-section main-header navigation-bar"
|
||||
data-js="main-nav-bar"
|
||||
>
|
||||
<div className="navigation-bar__top navigation-bar__top--ghostwhite-light">
|
||||
<div className="l-section__inner">
|
||||
<a
|
||||
href="https://www.scandichotels.fi"
|
||||
className="scandic-main-page-link"
|
||||
>
|
||||
Back to scandichotels.fi
|
||||
</a>
|
||||
|
||||
<ul className="nav-secondary navbar-login">
|
||||
<li className="nav-secondary__item hidden-xxsmall hidden-xsmall hidden-small">
|
||||
{links ? (
|
||||
<Desktop currentLanguage={currentLanguage} links={links} />
|
||||
) : null}
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.fi/varaa-hotelli/hae-varaus"
|
||||
>
|
||||
Varaukseni
|
||||
</a>
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.fi/tyo/avoimet-tyopaikat"
|
||||
>
|
||||
Työpaikat
|
||||
</a>
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.fi/yrityksille"
|
||||
>
|
||||
Yrityksille
|
||||
</a>
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.fi/scandic-friends"
|
||||
>
|
||||
Scandic Friends
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div className="navigation-bar__main">
|
||||
<div
|
||||
className="l-section__inner l-section__inner--small-no-padding"
|
||||
itemScope
|
||||
itemType="http://schema.org/Organization"
|
||||
>
|
||||
<meta itemProp="name" content="Scandic" />
|
||||
<button
|
||||
type="button"
|
||||
className="navigation-bar__main__expander"
|
||||
data-js="main-nav-toggler"
|
||||
data-target="#main-menu"
|
||||
aria-pressed="false"
|
||||
>
|
||||
<span className="icon-bars"></span>
|
||||
<span className="hidden--accessible">Menu</span>
|
||||
</button>
|
||||
|
||||
<a
|
||||
id="scandic-logo"
|
||||
className="navigation-bar__main__logo hidden-medium "
|
||||
href="https://www.scandichotels.fi"
|
||||
itemProp="url"
|
||||
>
|
||||
<span className="hidden--accessible">
|
||||
Back to scandichotels.fi
|
||||
</span>
|
||||
<img
|
||||
src="/Static/img/scandic-logotype.svg"
|
||||
data-js="scandiclogoimg"
|
||||
alt="Scandic Hotels logo"
|
||||
height="22"
|
||||
data-nosvgsrc="/Static/img/scandic-logotype.png"
|
||||
itemProp="logo"
|
||||
/>
|
||||
</a>
|
||||
<nav>
|
||||
<ul
|
||||
id="main-menu"
|
||||
className="nav-primary is-collapsed"
|
||||
data-collapsable="main-menu"
|
||||
>
|
||||
<li
|
||||
className="nav-primary__item nav-primary__item--primary hidden-large hidden-small hidden-xsmall hidden-xxsmall"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<a
|
||||
className="navigation-bar__main__logo"
|
||||
href="https://www.scandichotels.fi"
|
||||
>
|
||||
<img
|
||||
src="/Static/img/scandic-logotype.svg"
|
||||
data-js="scandiclogoimg"
|
||||
alt="Scandic Hotels logo"
|
||||
height="22"
|
||||
data-nosvgsrc="/Static/img/scandic-logotype.png"
|
||||
/>
|
||||
<span className="hidden--accessible">
|
||||
Back to scandichotels.fi
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.fi/hotellit">
|
||||
Hotellit ja kohteet
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.fi/matkavinkit">
|
||||
Matkavinkit
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.fi/kokoukset-ja-juhlatilat">
|
||||
Kokoukset ja juhlatilat
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.fi/koe-scandic">
|
||||
Koe Scandic
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.fi/tarjoukset">
|
||||
Tarjoukset
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li className="nav-primary__item nav-primary__item--secondary hidden-medium hidden-large ">
|
||||
<a href="https://www.scandichotels.fi/scandic-friends">
|
||||
Scandic Friends
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--secondary hidden-medium hidden-large ">
|
||||
<a href="https://www.scandichotels.fi/yrityksille">
|
||||
Yrityksille
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li className="nav-primary__item hidden-medium hidden-large">
|
||||
{links ? (
|
||||
<Mobile currentLanguage={currentLanguage} links={links} />
|
||||
) : null}
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
import type { LanguageSwitcherProps } from "@/types/components/current/languageSwitcher"
|
||||
|
||||
export default function Desktop({
|
||||
currentLanguage,
|
||||
links,
|
||||
}: LanguageSwitcherProps) {
|
||||
return (
|
||||
<div className="dropdown-container navbar-language-selector ">
|
||||
<button
|
||||
className="navbar-language-selector__toggler"
|
||||
data-js="dropdown-toggler"
|
||||
aria-pressed="false"
|
||||
>
|
||||
<svg
|
||||
focusable="false"
|
||||
className="icon icon--xs icon--white"
|
||||
viewBox="0 0 32 32"
|
||||
>
|
||||
<use xlinkHref="/Static/img/icons/sprites.svg#icon-globe"></use>
|
||||
</svg>
|
||||
{currentLanguage}
|
||||
<span className="hidden--accessible">Choose language</span>
|
||||
<span className="caret"></span>
|
||||
</button>
|
||||
<ul className="dropdown-menu">
|
||||
{links.map((link) => (
|
||||
<li
|
||||
className={currentLanguage === link.title ? "active" : undefined}
|
||||
key={link.href}
|
||||
>
|
||||
<a href={link.href}>{link.title}</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
.dropdown {
|
||||
background-clip: padding-box;
|
||||
background-color: #fff;
|
||||
border: 1px solid rgba(0, 0, 0, .15);
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
|
||||
display: none;
|
||||
float: left;
|
||||
font-size: 1rem;
|
||||
left: 0;
|
||||
list-style: none;
|
||||
margin: 2px 0 0;
|
||||
min-width: 160px;
|
||||
padding: 5px 0;
|
||||
position: absolute;
|
||||
text-align: left;
|
||||
top: 100%;
|
||||
z-index: 11;
|
||||
}
|
||||
|
||||
.dropdown.isOpen {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.link {
|
||||
clear: both;
|
||||
color: grey;
|
||||
display: block;
|
||||
font-weight: 400;
|
||||
padding: 3px 20px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
background-color: #f5f5f5;
|
||||
color: #737373;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.active>.link {
|
||||
background-color: #00838e;
|
||||
color: #fff;
|
||||
outline: 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
83
components/Current/Header/LanguageSwitcher/Desktop/index.tsx
Normal file
83
components/Current/Header/LanguageSwitcher/Desktop/index.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
"use client"
|
||||
import { useCallback, useEffect, useRef, useState } from "react"
|
||||
|
||||
import { languages } from "@/constants/languages"
|
||||
|
||||
import styles from "./desktop.module.css"
|
||||
|
||||
import type { LanguageSwitcherProps } from "@/types/components/current/languageSwitcher"
|
||||
|
||||
export default function Desktop({
|
||||
currentLanguage,
|
||||
urls,
|
||||
}: LanguageSwitcherProps) {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const divRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
function toggleOpen() {
|
||||
setIsOpen(prevIsOpen => !prevIsOpen)
|
||||
}
|
||||
|
||||
const close = useCallback(() => {
|
||||
setIsOpen(false)
|
||||
}, [setIsOpen])
|
||||
|
||||
useEffect(() => {
|
||||
function handleClickOutside(evt: Event) {
|
||||
const target = evt.target as HTMLElement
|
||||
if (divRef.current && target && !divRef.current.contains(target)) {
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
if (divRef.current) {
|
||||
document.addEventListener('click', handleClickOutside, false)
|
||||
}
|
||||
return () => {
|
||||
document.removeEventListener('click', handleClickOutside, false)
|
||||
}
|
||||
}, [close])
|
||||
|
||||
return (
|
||||
<div className="dropdown-container navbar-language-selector " ref={divRef}>
|
||||
<button
|
||||
aria-pressed="false"
|
||||
className="navbar-language-selector__toggler"
|
||||
data-js="dropdown-toggler"
|
||||
onClick={toggleOpen}
|
||||
>
|
||||
<svg
|
||||
focusable="false"
|
||||
className="icon icon--xs icon--white"
|
||||
viewBox="0 0 32 32"
|
||||
>
|
||||
<use xlinkHref="/Static/img/icons/sprites.svg#icon-globe"></use>
|
||||
</svg>
|
||||
{currentLanguage}
|
||||
<span className="hidden--accessible">Choose language</span>
|
||||
<span className="caret"></span>
|
||||
</button>
|
||||
<ul className={`${styles.dropdown} ${isOpen ? styles.isOpen : ""}`}>
|
||||
<li className={currentLanguage === languages.en ? styles.active : undefined}>
|
||||
<a className={styles.link} href={urls.en?.url}>{languages.en}</a>
|
||||
</li>
|
||||
<li className={currentLanguage === languages.sv ? styles.active : undefined}>
|
||||
<a className={styles.link} href={urls.sv?.url}>{languages.sv}</a>
|
||||
</li>
|
||||
<li className={currentLanguage === languages.no ? styles.active : undefined}>
|
||||
<a className={styles.link} href={urls.no?.url}>{languages.no}</a>
|
||||
</li>
|
||||
{/* When we have 6 languages in Contenstack, danish url should come from urls.da?.url */}
|
||||
<li className={currentLanguage === languages.da ? styles.active : undefined}>
|
||||
<a className={styles.link} href="https://www.scandichotels.dk/">{languages.da}</a>
|
||||
</li>
|
||||
<li className={currentLanguage === languages.fi ? styles.active : undefined}>
|
||||
<a className={styles.link} href={urls.fi?.url}>{languages.fi}</a>
|
||||
</li>
|
||||
<li className={currentLanguage === languages.de ? styles.active : undefined}>
|
||||
<a className={styles.link} href={urls.de?.url}>{languages.de}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import type { LanguageSwitcherProps } from "@/types/components/current/languageSwitcher"
|
||||
|
||||
export default function Mobile({
|
||||
currentLanguage,
|
||||
links,
|
||||
}: LanguageSwitcherProps) {
|
||||
return (
|
||||
<div className="navbar-language-selector">
|
||||
<button
|
||||
className="navbar-language-selector__toggler "
|
||||
data-js="collapsible-toggler"
|
||||
data-target="language-menu"
|
||||
aria-pressed="false"
|
||||
>
|
||||
{currentLanguage}{" "}
|
||||
<span className="navbar-language-selector__toggler__arrow"></span>
|
||||
<span className="hidden--accessible">Choose language</span>
|
||||
</button>
|
||||
<ul className="is-collapsed" data-collapsable="language-menu">
|
||||
{links.map((link) => (
|
||||
<li
|
||||
className={`navbar-language-selector__item ${currentLanguage === link.title ? "is-active" : ""}`}
|
||||
key={link.href}
|
||||
>
|
||||
<a href={link.href}>{link.title}</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
56
components/Current/Header/LanguageSwitcher/Mobile/index.tsx
Normal file
56
components/Current/Header/LanguageSwitcher/Mobile/index.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
"use client"
|
||||
import { useState } from "react"
|
||||
|
||||
import { languages } from "@/constants/languages"
|
||||
|
||||
import styles from "./mobile.module.css"
|
||||
|
||||
import type { LanguageSwitcherProps } from "@/types/components/current/languageSwitcher"
|
||||
|
||||
export default function Mobile({
|
||||
currentLanguage,
|
||||
urls,
|
||||
}: LanguageSwitcherProps) {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
|
||||
function toggleOpen() {
|
||||
setIsOpen(prevIsOpen => !prevIsOpen)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="navbar-language-selector">
|
||||
<button
|
||||
aria-pressed="false"
|
||||
className="navbar-language-selector__toggler "
|
||||
data-js="collapsible-toggler"
|
||||
data-target="language-menu"
|
||||
onClick={toggleOpen}
|
||||
>
|
||||
{currentLanguage}{" "}
|
||||
<span className={`${styles.arrow} ${isOpen ? styles.open : ""}`}></span>
|
||||
<span className="hidden--accessible">Choose language</span>
|
||||
</button>
|
||||
<ul className={`${styles.dropdown} ${isOpen ? styles.isOpen : ""}`} data-collapsable="language-menu">
|
||||
<li className={`navbar-language-selector__item ${currentLanguage === languages.en ? "is-active" : ""}`}>
|
||||
<a href={urls.en?.url}>{languages.en}</a>
|
||||
</li>
|
||||
<li className={`navbar-language-selector__item ${currentLanguage === languages.sv ? "is-active" : ""}`}>
|
||||
<a href={urls.sv?.url}>{languages.sv}</a>
|
||||
</li>
|
||||
<li className={`navbar-language-selector__item ${currentLanguage === languages.no ? "is-active" : ""}`}>
|
||||
<a href={urls.no?.url}>{languages.no}</a>
|
||||
</li>
|
||||
{/* When we have 6 languages in Contenstack, danish url should come from urls.da?.url */}
|
||||
<li className={`navbar-language-selector__item ${currentLanguage === languages.da ? "is-active" : ""}`}>
|
||||
<a href="https://www.scandichotels.dk/">{languages.da}</a>
|
||||
</li>
|
||||
<li className={`navbar-language-selector__item ${currentLanguage === languages.fi ? "is-active" : ""}`}>
|
||||
<a href={urls.fi?.url}>{languages.fi}</a>
|
||||
</li>
|
||||
<li className={`navbar-language-selector__item ${currentLanguage === languages.de ? "is-active" : ""}`}>
|
||||
<a href={urls.de?.url}>{languages.de}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
.dropdown {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dropdown.isOpen {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
background-image: url("/Static/img/icons/arrows/arrow-down-grey.png");
|
||||
background-position: 50%;
|
||||
background-repeat: no-repeat;
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.arrow.open {
|
||||
background-image: url("/Static/img/icons/arrows/arrow-up-grey.png");
|
||||
}
|
||||
|
||||
.link {
|
||||
color: grey;
|
||||
display: block;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
color: #7f7369;
|
||||
text-decoration: none;
|
||||
}
|
||||
107
components/Current/Header/MainMenu/index.tsx
Normal file
107
components/Current/Header/MainMenu/index.tsx
Normal file
@@ -0,0 +1,107 @@
|
||||
"use client"
|
||||
import { useState } from "react"
|
||||
|
||||
import Image from "@/components/Image"
|
||||
import Mobile from "../LanguageSwitcher/Mobile"
|
||||
|
||||
import styles from "./mainMenu.module.css"
|
||||
|
||||
import type { MainMenuProps } from "@/types/components/current/header/mainMenu"
|
||||
|
||||
export default function MainMenu({
|
||||
currentLanguage,
|
||||
frontpageLinkText,
|
||||
homeHref,
|
||||
links,
|
||||
logo,
|
||||
topMenuMobileLinks,
|
||||
urls,
|
||||
}: MainMenuProps) {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
|
||||
function toogleIsOpen() {
|
||||
setIsOpen(prevIsOpen => !prevIsOpen)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.mainMenu}>
|
||||
<div
|
||||
className={styles.container}
|
||||
itemScope
|
||||
itemType="http://schema.org/Organization"
|
||||
>
|
||||
<meta itemProp="name" content="Scandic" />
|
||||
<button
|
||||
aria-pressed="false"
|
||||
className={`${styles.expanderBtn} ${isOpen ? styles.expanded : ""}`}
|
||||
data-js="main-nav-toggler"
|
||||
data-target="#main-menu"
|
||||
onClick={toogleIsOpen}
|
||||
type="button"
|
||||
>
|
||||
<span className={styles.iconBars}></span>
|
||||
<span className={styles.hiddenAccessible}>Menu</span>
|
||||
</button>
|
||||
|
||||
<a
|
||||
className={styles.logoLink}
|
||||
href={homeHref}
|
||||
id="scandic-logo"
|
||||
itemProp="url"
|
||||
>
|
||||
<span className={styles.hiddenAccessible}>
|
||||
{frontpageLinkText}
|
||||
</span>
|
||||
<Image
|
||||
alt="Scandic Hotels logo"
|
||||
className={styles.logo}
|
||||
data-js="scandiclogoimg"
|
||||
data-nosvgsrc="/Static/img/scandic-logotype.png"
|
||||
itemProp="logo"
|
||||
height={22}
|
||||
src={logo.url}
|
||||
width={logo.dimension.width}
|
||||
/>
|
||||
</a>
|
||||
|
||||
<nav>
|
||||
<ul
|
||||
className={`${styles.list} ${isOpen ? styles.isOpen : ""}`}
|
||||
data-collapsable="main-menu"
|
||||
id="main-menu"
|
||||
>
|
||||
{links.map(link => (
|
||||
<li
|
||||
className={styles.li}
|
||||
key={link.href}
|
||||
>
|
||||
<a
|
||||
className={styles.link}
|
||||
href={link.href}
|
||||
>
|
||||
{link.title}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
|
||||
<ul className={styles.mobileList}>
|
||||
{topMenuMobileLinks.map(({ link }) => (
|
||||
<li className={styles.mobileLi} key={link.href}>
|
||||
<a className={styles.mobileLink} href={link.href}>
|
||||
{link.title}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
{urls ? (
|
||||
<li className={styles.mobileLi}>
|
||||
<Mobile currentLanguage={currentLanguage} urls={urls} />
|
||||
</li>
|
||||
) : null}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
225
components/Current/Header/MainMenu/mainMenu.module.css
Normal file
225
components/Current/Header/MainMenu/mainMenu.module.css
Normal file
@@ -0,0 +1,225 @@
|
||||
.mainMenu {
|
||||
background-color: #fff;
|
||||
background-image: none;
|
||||
box-shadow: 0 0 7px rgba(0, 0, 0, .75);
|
||||
max-height: 100%;
|
||||
overflow: visible;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
.container {
|
||||
box-sizing: content-box;
|
||||
display: grid;
|
||||
/** Third column is Book button */
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
height: 100%;
|
||||
margin: 0 auto;
|
||||
max-width: 1200px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.expanderBtn {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
justify-self: flex-start;
|
||||
left: 0;
|
||||
padding: 0.75rem 0.5rem 1rem;
|
||||
transition: .3s;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.iconBars,
|
||||
.iconBars::after,
|
||||
.iconBars::before {
|
||||
background: #757575;
|
||||
border-radius: 0.1428571429rem;
|
||||
display: inline-block;
|
||||
height: 0.2857142857rem;
|
||||
position: relative;
|
||||
transition: .3s;
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.iconBars::after,
|
||||
.iconBars::before {
|
||||
content: "";
|
||||
left: 0;
|
||||
position: absolute;
|
||||
transform-origin: 0.1428571429rem center;
|
||||
}
|
||||
|
||||
.iconBars::after {
|
||||
top: -0.5rem;
|
||||
}
|
||||
|
||||
.iconBars::before {
|
||||
top: 0.5rem;
|
||||
}
|
||||
|
||||
.expanded .iconBars {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.expanded .iconBars::after,
|
||||
.expanded .iconBars::before {
|
||||
top: 0;
|
||||
transform-origin: 50% 50%;
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.expanded .iconBars::after {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.expanded .iconBars::before {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.hiddenAccessible {
|
||||
display: block;
|
||||
height: 1px;
|
||||
left: -100000em;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: auto;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
.logoLink {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.list {
|
||||
background-color: #fff;
|
||||
border-top: 1px solid #e3e0db;
|
||||
display: none;
|
||||
list-style: none;
|
||||
overflow-y: visible;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.list.isOpen {
|
||||
display: block;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 100%;
|
||||
}
|
||||
|
||||
.li {
|
||||
border-bottom: none;
|
||||
display: block;
|
||||
line-height: 17px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #000;
|
||||
display: block;
|
||||
font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
|
||||
font-size: .875rem;
|
||||
font-weight: 700;
|
||||
padding-bottom: 20px;
|
||||
padding-top: 20px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
color: #7f7369;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.mobileList {
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.mobileLi {
|
||||
display: block;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mobileLink {
|
||||
color: #000;
|
||||
display: block;
|
||||
font-family: Helvetica;
|
||||
font-size: .875rem;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 950px) {
|
||||
.logoLink {
|
||||
width: 5rem;
|
||||
}
|
||||
|
||||
.li {
|
||||
background-color: #f3f2f1;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 950px) {
|
||||
.mainMenu {
|
||||
background-color: hsla(0, 0%, 100%, .95);
|
||||
position: relative;
|
||||
z-index: unset;
|
||||
}
|
||||
|
||||
.container {
|
||||
gap: 30px;
|
||||
grid-template-columns: minmax(100px, auto) 1fr;
|
||||
padding: 0px 30px;
|
||||
}
|
||||
|
||||
.expanderBtn {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.logo {
|
||||
max-width: none;
|
||||
min-width: 98px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.list {
|
||||
border-top: none;
|
||||
display: block;
|
||||
padding-bottom: 0;
|
||||
padding-top: 0;
|
||||
position: static;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.list.isOpen {
|
||||
position: static;
|
||||
}
|
||||
|
||||
.li {
|
||||
display: table-cell;
|
||||
float: none;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.link {
|
||||
background-image: none;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
font-weight: 700;
|
||||
line-height: 1.15;
|
||||
padding: 30px 15px;
|
||||
}
|
||||
|
||||
.mobileList {
|
||||
display: none;
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
.mobileLi {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
import {
|
||||
currentAboutLinks,
|
||||
currentSponsoringLinks,
|
||||
currentWifiLinks,
|
||||
} from "@/constants/current/links"
|
||||
|
||||
import Desktop from "./LanguageSwitcher/Desktop"
|
||||
import Mobile from "./LanguageSwitcher/Mobile"
|
||||
|
||||
import type { LanguageSwitcherLink } from "@/types/components/current/languageSwitcher"
|
||||
import type { HeaderProps } from "@/types/components/current/header"
|
||||
|
||||
const paths: Record<string, LanguageSwitcherLink[]> = {
|
||||
"/kundeservice/sporsmal-og-svar/bruk-av-nettsiden": currentAboutLinks,
|
||||
"/utforsk-scandic/wifi": currentWifiLinks,
|
||||
"/vi-sponser": currentSponsoringLinks,
|
||||
}
|
||||
|
||||
const currentLanguage = "Norsk"
|
||||
|
||||
export default function NoHeader({ pathname }: HeaderProps) {
|
||||
const links = paths?.[pathname] ?? null
|
||||
|
||||
return (
|
||||
<header className="header" role="banner">
|
||||
<div className="offline-banner hidden">
|
||||
Du er offline. Noe innhold kan være utdatert.
|
||||
<button type="button" className="reload">
|
||||
Last inn på nytt
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="l-section main-header navigation-bar"
|
||||
data-js="main-nav-bar"
|
||||
>
|
||||
<div className="navigation-bar__top navigation-bar__top--ghostwhite-light">
|
||||
<div className="l-section__inner">
|
||||
<a
|
||||
href="https://www.scandichotels.no"
|
||||
className="scandic-main-page-link"
|
||||
>
|
||||
Tilbake til scandichotels.no
|
||||
</a>
|
||||
<ul className="nav-secondary navbar-login">
|
||||
<li className="nav-secondary__item hidden-xxsmall hidden-xsmall hidden-small">
|
||||
{links ? (
|
||||
<Desktop currentLanguage={currentLanguage} links={links} />
|
||||
) : null}
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.no/hotelreservation/get-booking"
|
||||
>
|
||||
Vis/Avbestill din booking
|
||||
</a>
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.no/jobb-hos-oss/ledige-stillinger"
|
||||
>
|
||||
Jobb hos oss
|
||||
</a>
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.no/for-bedrifter"
|
||||
>
|
||||
For bedrifter
|
||||
</a>
|
||||
</li>
|
||||
<li className=" hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.no/scandic-friends"
|
||||
>
|
||||
Om Scandic Friends
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div className="navigation-bar__main">
|
||||
<div
|
||||
className="l-section__inner l-section__inner--small-no-padding"
|
||||
itemScope={undefined}
|
||||
itemType="http://schema.org/Organization"
|
||||
>
|
||||
<meta itemProp="name" content="Scandic" />
|
||||
<button
|
||||
type="button"
|
||||
className="navigation-bar__main__expander"
|
||||
data-js="main-nav-toggler"
|
||||
data-target="#main-menu"
|
||||
aria-pressed="false"
|
||||
>
|
||||
<span className="icon-bars"></span>
|
||||
<span className="hidden--accessible">Menu</span>
|
||||
</button>
|
||||
<a
|
||||
id="scandic-logo"
|
||||
className="navigation-bar__main__logo hidden-medium "
|
||||
href="https://www.scandichotels.no"
|
||||
itemProp="url"
|
||||
>
|
||||
<span className="hidden--accessible">
|
||||
Tilbake til scandichotels.no
|
||||
</span>
|
||||
<img
|
||||
src="/Static/img/scandic-logotype.svg"
|
||||
data-js="scandiclogoimg"
|
||||
alt="Scandic Hotels logo"
|
||||
height="22"
|
||||
data-nosvgsrc="/Static/img/scandic-logotype.png"
|
||||
itemProp="logo"
|
||||
/>
|
||||
</a>
|
||||
<ul
|
||||
id="navbar-header-design"
|
||||
className="hidden hidden-medium hidden-large nav-primary__header"
|
||||
>
|
||||
<li className="nav-primary__scandicfriendslogo">
|
||||
<img
|
||||
src="/Static/img/icons/scandic-friends/icon-scandic-friends.svg"
|
||||
width="35"
|
||||
height="35"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
<nav>
|
||||
<ul
|
||||
id="main-menu"
|
||||
className="nav-primary is-collapsed"
|
||||
data-collapsable="main-menu"
|
||||
>
|
||||
<li
|
||||
className="nav-primary__item nav-primary__item--primary hidden-large hidden-small hidden-xsmall hidden-xxsmall"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<a
|
||||
className="navigation-bar__main__logo"
|
||||
href="https://www.scandichotels.no"
|
||||
>
|
||||
<img
|
||||
src="/Static/img/scandic-logotype.svg"
|
||||
data-js="scandiclogoimg"
|
||||
alt="Scandic Hotels logo"
|
||||
height="22"
|
||||
data-nosvgsrc="/Static/img/scandic-logotype.png"
|
||||
/>
|
||||
<span className="hidden--accessible">
|
||||
Tilbake til scandichotels.no
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.no/hotell">
|
||||
Hoteller og destinasjoner
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.no/reiseguider">
|
||||
Reiseguider
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.no/moter-og-konferanser">
|
||||
Møter og konferanser
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.no/utforsk-scandic">
|
||||
Utforsk Scandic
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.no/hotelltilbud">Tilbud</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--secondary hidden-medium hidden-large ">
|
||||
<a href="https://www.scandichotels.no/scandic-friends">
|
||||
Om Scandic Friends
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--secondary hidden-medium hidden-large ">
|
||||
<a href="https://www.scandichotels.no/for-bedrifter">
|
||||
For bedrifter
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item hidden-medium hidden-large">
|
||||
{links ? (
|
||||
<Mobile currentLanguage={currentLanguage} links={links} />
|
||||
) : null}
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
23
components/Current/Header/OfflineBanner/banner.module.css
Normal file
23
components/Current/Header/OfflineBanner/banner.module.css
Normal file
@@ -0,0 +1,23 @@
|
||||
.banner {
|
||||
align-items: center;
|
||||
background: #606060;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 10px;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.reloadBtn {
|
||||
color: #fff;
|
||||
background-color: #00838e;
|
||||
border: 0;
|
||||
border-radius: 18px;
|
||||
outline: 0 none;
|
||||
padding: 5px 15px;
|
||||
}
|
||||
10
components/Current/Header/OfflineBanner/index.tsx
Normal file
10
components/Current/Header/OfflineBanner/index.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import styles from "./banner.module.css"
|
||||
|
||||
export default function OfflineBanner() {
|
||||
return (
|
||||
<div className={`${styles.banner} ${styles.hidden}`}>
|
||||
You are offline, some content may be out of date.
|
||||
<button className={styles.reloadBtn} type="button">Reload</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
import {
|
||||
currentAboutLinks,
|
||||
currentSponsoringLinks,
|
||||
currentWifiLinks,
|
||||
} from "@/constants/current/links"
|
||||
|
||||
import Desktop from "./LanguageSwitcher/Desktop"
|
||||
import Mobile from "./LanguageSwitcher/Mobile"
|
||||
|
||||
import type { LanguageSwitcherLink } from "@/types/components/current/languageSwitcher"
|
||||
import type { HeaderProps } from "@/types/components/current/header"
|
||||
|
||||
const paths: Record<string, LanguageSwitcherLink[]> = {
|
||||
"/kundservice/fragor-och-svar/om-scandics-webbplats": currentAboutLinks,
|
||||
"/utforska-scandic/wi-fi": currentWifiLinks,
|
||||
"/vi-sponsrar": currentSponsoringLinks,
|
||||
}
|
||||
|
||||
const currentLanguage = "Svenska"
|
||||
|
||||
export default function SvHeader({ pathname }: HeaderProps) {
|
||||
const links = paths?.[pathname] ?? null
|
||||
return (
|
||||
<header className="header" role="banner">
|
||||
<div className="offline-banner hidden">
|
||||
Du är offline. Sidan kan visa gammalt innehåll.
|
||||
<button type="button" className="reload">
|
||||
Ladda om
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="l-section main-header navigation-bar"
|
||||
data-js="main-nav-bar"
|
||||
>
|
||||
<div className="navigation-bar__top navigation-bar__top--ghostwhite-light">
|
||||
<div className="l-section__inner">
|
||||
<a
|
||||
href="https://www.scandichotels.se"
|
||||
className="scandic-main-page-link"
|
||||
>
|
||||
Tillbaka till scandichotels.se
|
||||
</a>
|
||||
|
||||
<ul className="nav-secondary navbar-login">
|
||||
<li className="nav-secondary__item hidden-xxsmall hidden-xsmall hidden-small">
|
||||
{links ? (
|
||||
<Desktop currentLanguage={currentLanguage} links={links} />
|
||||
) : null}
|
||||
</li>
|
||||
<li className="hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.se/hotelreservation/hitta-bokning"
|
||||
>
|
||||
Visa bokning / Avboka
|
||||
</a>
|
||||
</li>
|
||||
<li className="hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.se/jobba-hos-oss/lediga-tjanster"
|
||||
>
|
||||
Jobba hos oss
|
||||
</a>
|
||||
</li>
|
||||
<li className="hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.se/for-foretag"
|
||||
>
|
||||
Företag
|
||||
</a>
|
||||
</li>
|
||||
<li className="hidden-xxsmall hidden-xsmall hidden-small nav-secondary__item">
|
||||
<a
|
||||
className="nav-secondary__item__link"
|
||||
href="https://www.scandichotels.se/scandic-friends"
|
||||
>
|
||||
Om Scandic Friends
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div className="navigation-bar__main">
|
||||
<div
|
||||
className="l-section__inner l-section__inner--small-no-padding"
|
||||
itemScope
|
||||
itemType="http://schema.org/Organization"
|
||||
>
|
||||
<meta itemProp="name" content="Scandic" />
|
||||
<button
|
||||
type="button"
|
||||
className="navigation-bar__main__expander"
|
||||
data-js="main-nav-toggler"
|
||||
data-target="#main-menu"
|
||||
aria-pressed="false"
|
||||
>
|
||||
<span className="icon-bars"></span>
|
||||
<span className="hidden--accessible">Menu</span>
|
||||
</button>
|
||||
|
||||
<a
|
||||
id="scandic-logo"
|
||||
className="navigation-bar__main__logo hidden-medium "
|
||||
href="https://www.scandichotels.se"
|
||||
itemProp="url"
|
||||
>
|
||||
<span className="hidden--accessible">
|
||||
Tillbaka till scandichotels.se
|
||||
</span>
|
||||
<img
|
||||
src="/Static/img/scandic-logotype.svg"
|
||||
data-js="scandiclogoimg"
|
||||
alt="Scandic Hotels logo"
|
||||
height="22"
|
||||
data-nosvgsrc="/Static/img/scandic-logotype.png"
|
||||
itemProp="logo"
|
||||
/>
|
||||
</a>
|
||||
|
||||
<nav>
|
||||
<ul
|
||||
id="main-menu"
|
||||
className="nav-primary is-collapsed"
|
||||
data-collapsable="main-menu"
|
||||
>
|
||||
<li
|
||||
className="nav-primary__item nav-primary__item--primary hidden-large hidden-small hidden-xsmall hidden-xxsmall"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<a
|
||||
className="navigation-bar__main__logo"
|
||||
href="https://www.scandichotels.se"
|
||||
>
|
||||
<img
|
||||
src="/Static/img/scandic-logotype.svg"
|
||||
data-js="scandiclogoimg"
|
||||
alt="Scandic Hotels logo"
|
||||
height="22"
|
||||
data-nosvgsrc="/Static/img/scandic-logotype.png"
|
||||
/>
|
||||
<span className="hidden--accessible">
|
||||
Tillbaka till scandichotels.se
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.se/hotell">
|
||||
Hotell & destinationer
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.se/reseguide">
|
||||
Reseguider
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.se/konferens-mote">
|
||||
Konferens & möten
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.se/utforska-scandic">
|
||||
Utforska Scandic
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--primary ">
|
||||
<a href="https://www.scandichotels.se/erbjudanden-och-weekendpaket">
|
||||
Erbjudanden
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li className="nav-primary__item nav-primary__item--secondary hidden-medium hidden-large ">
|
||||
<a href="https://www.scandichotels.se/scandic-friends">
|
||||
Om Scandic Friends
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-primary__item nav-primary__item--secondary hidden-medium hidden-large ">
|
||||
<a href="https://www.scandichotels.se/for-foretag">
|
||||
För företag
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li className="nav-primary__item hidden-medium hidden-large">
|
||||
{links ? (
|
||||
<Mobile currentLanguage={currentLanguage} links={links} />
|
||||
) : null}
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
39
components/Current/Header/TopMenu/index.tsx
Normal file
39
components/Current/Header/TopMenu/index.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import Desktop from "../LanguageSwitcher/Desktop"
|
||||
|
||||
import styles from "./topMenu.module.css"
|
||||
|
||||
import type { TopMenuProps } from "@/types/components/current/header/topMenu"
|
||||
|
||||
export default function TopMenu({ currentLanguage, frontpageLinkText, homeHref, links, urls }: TopMenuProps) {
|
||||
return (
|
||||
<div className={styles.topMenu}>
|
||||
<div className={styles.container}>
|
||||
<a
|
||||
className={styles.homeLink}
|
||||
href={homeHref}
|
||||
>
|
||||
{frontpageLinkText}
|
||||
</a>
|
||||
|
||||
<ul className={styles.list}>
|
||||
{urls ? (
|
||||
<li className="nav-secondary__item hidden-xxsmall hidden-xsmall hidden-small">
|
||||
<Desktop currentLanguage={currentLanguage} urls={urls} />
|
||||
</li>
|
||||
) : null}
|
||||
|
||||
{links.map(({ link }) => (
|
||||
<li key={link.href}>
|
||||
<a
|
||||
className={styles.link}
|
||||
href={link.href}
|
||||
>
|
||||
{link.title}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
51
components/Current/Header/TopMenu/topMenu.module.css
Normal file
51
components/Current/Header/TopMenu/topMenu.module.css
Normal file
@@ -0,0 +1,51 @@
|
||||
.topMenu {
|
||||
background-color: #8d3a7c;
|
||||
color: #fff;
|
||||
display: none;
|
||||
font-size: .8125rem;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.container {
|
||||
box-sizing: content-box;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin: 0 auto;
|
||||
max-width: 1200px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.homeLink {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.list {
|
||||
display: flex;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||
padding: 3px 10px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 740px) {
|
||||
.container {
|
||||
padding: 0 30px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 950px) {
|
||||
.topMenu {
|
||||
background-color: #3d3835;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.link {
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
}
|
||||
9
components/Current/Header/header.module.css
Normal file
9
components/Current/Header/header.module.css
Normal file
@@ -0,0 +1,9 @@
|
||||
.header {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 950px) {
|
||||
.header {
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,77 @@
|
||||
import { langEnum } from "@/types/lang"
|
||||
import { languages } from "@/constants/languages"
|
||||
import { batchRequest } from "@/lib/batchRequest"
|
||||
import { request } from "@/lib/request"
|
||||
import { GetHeader } from "@/lib/graphql/Query/Header.graphql"
|
||||
import { GetDaDeEnUrls, GetFiNoSvUrls } from "@/lib/graphql/Query/LanguageSwitcher.graphql"
|
||||
import { homeHrefs } from "@/constants/homeHrefs"
|
||||
import { env } from "@/env/server"
|
||||
|
||||
import Da from "./Da"
|
||||
import De from "./De"
|
||||
import En from "./En"
|
||||
import Fi from "./Fi"
|
||||
import No from "./No"
|
||||
import Sv from "./Sv"
|
||||
import MainMenu from "./MainMenu"
|
||||
import OfflineBanner from "./OfflineBanner"
|
||||
import TopMenu from "./TopMenu"
|
||||
|
||||
import styles from "./header.module.css"
|
||||
|
||||
import type { HeaderProps } from "@/types/components/current/header"
|
||||
import { LangParams } from "@/types/params"
|
||||
import type { HeaderQueryData } from "@/types/requests/header"
|
||||
import type { HeaderProps } from "@/types/components/current/header"
|
||||
import type { LanguageSwitcherQueryData } from "@/types/requests/languageSwitcher"
|
||||
|
||||
export default function Header({ lang, pathname }: LangParams & HeaderProps) {
|
||||
switch (lang) {
|
||||
case langEnum.sv:
|
||||
return <Sv pathname={pathname} />
|
||||
case langEnum.fi:
|
||||
return <Fi pathname={pathname} />
|
||||
case langEnum.en:
|
||||
return <En pathname={pathname} />
|
||||
case langEnum.da:
|
||||
return <Da pathname={pathname} />
|
||||
case langEnum.de:
|
||||
return <De pathname={pathname} />
|
||||
case langEnum.no:
|
||||
return <No pathname={pathname} />
|
||||
default:
|
||||
export default async function Header({ lang, uid }: LangParams & HeaderProps) {
|
||||
try {
|
||||
const variables = {
|
||||
locale: lang,
|
||||
uid,
|
||||
}
|
||||
|
||||
const { data } = await request<HeaderQueryData>(GetHeader, { locale: lang }, { tags: [`header-${lang}`] })
|
||||
const { data: urls } = await batchRequest<LanguageSwitcherQueryData>([
|
||||
{
|
||||
document: GetDaDeEnUrls,
|
||||
tags: [`DA-DE-EN-${uid}`],
|
||||
variables,
|
||||
},
|
||||
{
|
||||
document: GetFiNoSvUrls,
|
||||
tags: [`FI-NO-SV-${uid}`],
|
||||
variables,
|
||||
},
|
||||
])
|
||||
|
||||
if (!data.all_header.items.length) {
|
||||
return null
|
||||
}
|
||||
|
||||
const currentLanguage = languages[lang]
|
||||
const homeHref = homeHrefs[env.NODE_ENV][lang]
|
||||
const { frontpage_link_text, logoConnection, menu, top_menu } = data.all_header.items[0]
|
||||
const logo = logoConnection.edges?.[0]?.node
|
||||
const topMenuMobileLinks = top_menu.links.filter(link => link.show_on_mobile)
|
||||
.sort((a, b) => a.sort_order_mobile < b.sort_order_mobile ? 1 : -1)
|
||||
|
||||
return (
|
||||
<header className={styles.header} role="banner">
|
||||
<OfflineBanner />
|
||||
<TopMenu
|
||||
currentLanguage={currentLanguage}
|
||||
frontpageLinkText={frontpage_link_text}
|
||||
homeHref={homeHref}
|
||||
links={top_menu.links}
|
||||
urls={urls}
|
||||
/>
|
||||
<MainMenu
|
||||
currentLanguage={currentLanguage}
|
||||
frontpageLinkText={frontpage_link_text}
|
||||
homeHref={homeHref}
|
||||
links={menu.links}
|
||||
logo={logo}
|
||||
topMenuMobileLinks={topMenuMobileLinks}
|
||||
urls={urls}
|
||||
/>
|
||||
</header>
|
||||
)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import Link from "next/link"
|
||||
|
||||
import styles from "./breadcrumbs.module.css"
|
||||
|
||||
import type { BreadcrumbsProps } from "@/types/components/current/breadcrumbs"
|
||||
@@ -14,20 +12,20 @@ export default function Breadcrumbs({
|
||||
<ul className={styles.list}>
|
||||
{parent ? (
|
||||
<li className={styles.parent}>
|
||||
<Link href={parent.node.url}>
|
||||
{parent.node.breadcrumbs?.title ?? parent.node.title}
|
||||
</Link>
|
||||
<a href={parent.href}>
|
||||
{parent.title}
|
||||
</a>
|
||||
</li>
|
||||
) : null}
|
||||
{breadcrumbs.edges.map((breadcrumb) => (
|
||||
{breadcrumbs.map((breadcrumb) => (
|
||||
<li
|
||||
className={styles.li}
|
||||
itemProp="breadcrumb"
|
||||
key={breadcrumb.node.title}
|
||||
key={breadcrumb.href}
|
||||
>
|
||||
<Link className={styles.link} href={breadcrumb.node.url}>
|
||||
{breadcrumb.node.breadcrumbs?.title ?? breadcrumb.node.title}
|
||||
</Link>
|
||||
<a className={styles.link} href={breadcrumb.href}>
|
||||
{breadcrumb.title}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
<li className={styles.currentPage}>
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import Link from "next/link"
|
||||
|
||||
import type { SubnavMobileProps } from "@/types/components/current/subnavMobile"
|
||||
|
||||
export default async function SubnavMobile({
|
||||
@@ -13,16 +11,16 @@ export default async function SubnavMobile({
|
||||
<ul className="breadcrumb-list hidden-small hidden-medium hidden-large">
|
||||
{parent ? (
|
||||
<li className="breadcrumb-list__parent hidden-medium hidden-large">
|
||||
<Link href={parent.node.url}>
|
||||
{parent.node.breadcrumbs?.title ?? parent.node.title}
|
||||
</Link>
|
||||
<a href={parent.href}>
|
||||
{parent.title}
|
||||
</a>
|
||||
</li>
|
||||
) : null}
|
||||
{breadcrumbs.edges.map((breadcrumb) => (
|
||||
<li className="breadcrumb-list__body" key={breadcrumb.node.url}>
|
||||
<Link href={breadcrumb.node.url}>
|
||||
{breadcrumb.node.breadcrumbs?.title ?? breadcrumb.node.title}
|
||||
</Link>
|
||||
{breadcrumbs.map((breadcrumb) => (
|
||||
<li className="breadcrumb-list__body" key={breadcrumb.href}>
|
||||
<a href={breadcrumb.href}>
|
||||
{breadcrumb.title}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
<li className="breadcrumb-list__body">
|
||||
|
||||
@@ -263,8 +263,9 @@ export const renderOptions: RenderOptions = {
|
||||
}
|
||||
} else {
|
||||
const props = extractPossibleAttributes(node.attrs)
|
||||
const href = node.attrs?.locale ? `/${node.attrs.locale}${node.attrs.href}` : node.attrs.href
|
||||
return (
|
||||
<Link {...props} href={node.attrs.href} key={node.uid}>
|
||||
<Link {...props} href={href} key={node.uid}>
|
||||
{next(node.children, embeds, fullRenderOptions)}
|
||||
</Link>
|
||||
)
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
export const currentAboutLinks = [
|
||||
{
|
||||
href: "https://www.scandichotels.com/customer-service/frequently-asked-questions/using-the-website",
|
||||
title: "English",
|
||||
},
|
||||
{
|
||||
href: "https://www.scandichotels.se/kundservice/fragor-och-svar/om-scandics-webbplats",
|
||||
title: "Svenska",
|
||||
},
|
||||
{
|
||||
href: "https://www.scandichotels.no/kundeservice/sporsmal-og-svar/bruk-av-nettsiden",
|
||||
title: "Norsk",
|
||||
},
|
||||
{
|
||||
href: "https://www.scandichotels.dk/kundeservice/sporgsmal-og-svar/om-scandics-website",
|
||||
title: "Dansk",
|
||||
},
|
||||
{
|
||||
href: "https://www.scandichotels.fi/asiakaspalvelu/usein-kysytyt-kysymykset/tietoja-internetsivuista",
|
||||
title: "Suomi",
|
||||
},
|
||||
{
|
||||
href: "https://www.scandichotels.de/kundenbetreuung/haufig-gestellte-fragen/nutzung-der-internetseite",
|
||||
title: "Deutsch",
|
||||
},
|
||||
]
|
||||
|
||||
export const currentSponsoringLinks = [
|
||||
{
|
||||
href: "https://www.scandichotels.com/sponsoring",
|
||||
title: "English",
|
||||
},
|
||||
{
|
||||
href: "https://www.scandichotels.se/vi-sponsrar",
|
||||
title: "Svenska",
|
||||
},
|
||||
{
|
||||
href: "https://www.scandichotels.no/vi-sponser",
|
||||
title: "Norsk",
|
||||
},
|
||||
{
|
||||
href: "https://www.scandichotels.dk/sponsorering",
|
||||
title: "Dansk",
|
||||
},
|
||||
{
|
||||
href: "https://www.scandichotels.fi/sponsorointi",
|
||||
title: "Suomi",
|
||||
},
|
||||
{
|
||||
href: "https://www.scandichotels.de/sponsoring",
|
||||
title: "Deutsch",
|
||||
},
|
||||
]
|
||||
|
||||
export const currentWifiLinks = [
|
||||
{
|
||||
href: "https://www.scandichotels.com/explore-scandic/wifi",
|
||||
title: "English",
|
||||
},
|
||||
{
|
||||
href: "https://www.scandichotels.se/utforska-scandic/wi-fi",
|
||||
title: "Svenska",
|
||||
},
|
||||
{
|
||||
href: "https://www.scandichotels.no/utforsk-scandic/wifi",
|
||||
title: "Norsk",
|
||||
},
|
||||
{
|
||||
href: "https://www.scandichotels.dk/oplev-scandic/wifi",
|
||||
title: "Dansk",
|
||||
},
|
||||
{
|
||||
href: "https://www.scandichotels.fi/koe-scandic/maksuton-internetyhteys",
|
||||
title: "Suomi",
|
||||
},
|
||||
{
|
||||
href: "https://www.scandichotels.de/scandic-entdecken/wlan",
|
||||
title: "Deutsch",
|
||||
},
|
||||
]
|
||||
27
constants/homeHrefs.ts
Normal file
27
constants/homeHrefs.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
export const homeHrefs = {
|
||||
development: {
|
||||
da: "https://stage.scandichotels.dk",
|
||||
de: "https://stage.scandichotels.de",
|
||||
en: "https://stage.scandichotels.com",
|
||||
fi: "https://stage.scandichotels.fi",
|
||||
no: "https://stage.scandichotels.no",
|
||||
sv: "https://stage.scandichotels.se",
|
||||
},
|
||||
production: {
|
||||
da: "https://www.scandichotels.dk",
|
||||
de: "https://www.scandichotels.de",
|
||||
en: "https://www.scandichotels.com",
|
||||
fi: "https://www.scandichotels.fi",
|
||||
no: "https://www.scandichotels.no",
|
||||
sv: "https://www.scandichotels.se",
|
||||
},
|
||||
test: {
|
||||
da: "https://test2.scandichotels.dk",
|
||||
de: "https://test2.scandichotels.de",
|
||||
en: "https://test2.scandichotels.com",
|
||||
fi: "https://test2.scandichotels.fi",
|
||||
no: "https://test2.scandichotels.no",
|
||||
sv: "https://test2.scandichotels.se",
|
||||
},
|
||||
}
|
||||
8
constants/languages.ts
Normal file
8
constants/languages.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export const languages = {
|
||||
da: "Dansk",
|
||||
de: "Deutsch",
|
||||
en: "English",
|
||||
fi: "Suomi",
|
||||
no: "Norsk",
|
||||
sv: "Svenska",
|
||||
}
|
||||
2
env/server.ts
vendored
2
env/server.ts
vendored
@@ -11,6 +11,7 @@ export const env = createEnv({
|
||||
CMS_PREVIEW_TOKEN: z.string(),
|
||||
NODE_ENV: z.enum(["development", "test", "production"]),
|
||||
PRINT_QUERY: z.boolean().default(false),
|
||||
REVALIDATE_SECRET: z.string(),
|
||||
},
|
||||
emptyStringAsUndefined: true,
|
||||
runtimeEnv: {
|
||||
@@ -22,5 +23,6 @@ export const env = createEnv({
|
||||
CMS_PREVIEW_TOKEN: process.env.CMS_PREVIEW_TOKEN,
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
PRINT_QUERY: process.env.PRINT_QUERY,
|
||||
REVALIDATE_SECRET: process.env.REVALIDATE_SECRET,
|
||||
},
|
||||
})
|
||||
|
||||
28
lib/batchRequest.ts
Normal file
28
lib/batchRequest.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import "server-only"
|
||||
import { request } from "./request"
|
||||
|
||||
import type { Data } from "@/types/request"
|
||||
import type { BatchRequestDocument } from "graphql-request"
|
||||
|
||||
export async function batchRequest<T>(queries: (BatchRequestDocument & NextFetchRequestConfig)[]): Promise<Data<T>> {
|
||||
try {
|
||||
const response = await Promise.allSettled(
|
||||
queries.map(query => request<T>(query.document, query.variables, { tags: query.tags }))
|
||||
)
|
||||
|
||||
let data = {} as T
|
||||
const reasons = []
|
||||
response.forEach(res => {
|
||||
if (res.status === "fulfilled") {
|
||||
data = Object.assign({}, data, res.value.data)
|
||||
} else {
|
||||
reasons.push(res.reason)
|
||||
}
|
||||
})
|
||||
|
||||
return { data }
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
throw new Error("Something went wrong")
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,6 @@
|
||||
|
||||
fragment PuffAside on CurrentBlocksPageAsidePuff {
|
||||
puff {
|
||||
puffConnection {
|
||||
totalCount
|
||||
edges {
|
||||
node {
|
||||
...Puff
|
||||
}
|
||||
}
|
||||
}
|
||||
...Puff
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#import "../PageLinks.graphql"
|
||||
|
||||
fragment ListItem on CurrentBlocksPageBlocksListBlockListItemsListItem {
|
||||
list_item {
|
||||
list_item_style
|
||||
@@ -19,30 +17,12 @@ fragment ListItemExternalLink on CurrentBlocksPageBlocksListBlockListItemsListIt
|
||||
}
|
||||
}
|
||||
|
||||
fragment ListItemInternalLink on CurrentBlocksPageBlocksListBlockListItemsListItemInternalLink {
|
||||
list_item_internal_link {
|
||||
link_text
|
||||
list_item_style
|
||||
subtitle
|
||||
pageConnection {
|
||||
totalCount
|
||||
edges {
|
||||
node {
|
||||
__typename
|
||||
...CurrentBlocksPageLink
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fragment ListBlock on CurrentBlocksPageBlocksList {
|
||||
list {
|
||||
list_items {
|
||||
__typename
|
||||
...ListItem
|
||||
...ListItemExternalLink
|
||||
...ListItemInternalLink
|
||||
}
|
||||
title
|
||||
}
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
|
||||
fragment PuffBlock on CurrentBlocksPageBlocksPuffs {
|
||||
puffs {
|
||||
# We have to manually add a limit since Contentstack handles its complexity calculation in a certain way
|
||||
puffsConnection(limit: 9) {
|
||||
totalCount
|
||||
edges {
|
||||
node {
|
||||
puffs {
|
||||
... on CurrentBlocksPageBlocksPuffsBlockPuffsPuff {
|
||||
puff {
|
||||
...Puff
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#import "../Image.graphql"
|
||||
#import "../PageLinks.graphql"
|
||||
|
||||
fragment TextBlock on CurrentBlocksPageBlocksText {
|
||||
text {
|
||||
@@ -9,7 +8,6 @@ fragment TextBlock on CurrentBlocksPageBlocksText {
|
||||
edges {
|
||||
node {
|
||||
__typename
|
||||
...CurrentBlocksPageLink
|
||||
...Image
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
fragment Breadcrumbs on CurrentBlocksPage {
|
||||
breadcrumbs {
|
||||
title
|
||||
parentsConnection {
|
||||
edges {
|
||||
node {
|
||||
... on CurrentBlocksPage {
|
||||
breadcrumbs {
|
||||
title
|
||||
}
|
||||
title
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
parents {
|
||||
href
|
||||
title
|
||||
}
|
||||
title
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#import "../Image.graphql"
|
||||
|
||||
fragment Logo on Footer {
|
||||
logoConnection {
|
||||
edges {
|
||||
node {
|
||||
title
|
||||
url
|
||||
...Image
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,9 @@
|
||||
#import "../PageLinks.graphql"
|
||||
|
||||
fragment Navigation on Footer {
|
||||
navigation {
|
||||
links {
|
||||
... on FooterNavigationLinksInternalLink {
|
||||
__typename
|
||||
internal_link {
|
||||
link_text
|
||||
pageConnection {
|
||||
edges {
|
||||
node {
|
||||
__typename
|
||||
...CurrentBlocksPageLink
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
... on FooterNavigationLinksExternalLink {
|
||||
__typename
|
||||
external_link {
|
||||
link {
|
||||
href
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
href
|
||||
title
|
||||
}
|
||||
|
||||
title
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#import "./Image.graphql"
|
||||
#import "./PageLinks.graphql"
|
||||
|
||||
fragment Hero on Hero {
|
||||
imagesConnection {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
fragment CurrentBlocksPageLink on CurrentBlocksPage {
|
||||
system {
|
||||
uid
|
||||
locale
|
||||
uid
|
||||
}
|
||||
title
|
||||
url
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#import "./Image.graphql"
|
||||
#import "./PageLinks.graphql"
|
||||
|
||||
fragment Preamble on CurrentBlocksPage {
|
||||
preamble {
|
||||
@@ -9,7 +8,6 @@ fragment Preamble on CurrentBlocksPage {
|
||||
edges {
|
||||
node {
|
||||
__typename
|
||||
...CurrentBlocksPageLink
|
||||
...Image
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#import "./Image.graphql"
|
||||
#import "./PageLinks.graphql"
|
||||
|
||||
fragment Puff on Puff {
|
||||
imageConnection {
|
||||
@@ -9,33 +8,12 @@ fragment Puff on Puff {
|
||||
}
|
||||
}
|
||||
}
|
||||
is_internal
|
||||
link {
|
||||
href
|
||||
title
|
||||
}
|
||||
pageConnection {
|
||||
edges {
|
||||
node {
|
||||
__typename
|
||||
...CurrentBlocksPageLink
|
||||
}
|
||||
}
|
||||
}
|
||||
system {
|
||||
uid
|
||||
}
|
||||
text {
|
||||
json
|
||||
embedded_itemsConnection {
|
||||
totalCount
|
||||
edges {
|
||||
node {
|
||||
__typename
|
||||
...Image
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
title
|
||||
}
|
||||
|
||||
@@ -27,13 +27,13 @@ query GetCurrentBlockPage($locale: String!, $url: String!) {
|
||||
...Hero
|
||||
}
|
||||
...Preamble
|
||||
title
|
||||
url
|
||||
system {
|
||||
uid
|
||||
created_at
|
||||
uid
|
||||
updated_at
|
||||
}
|
||||
title
|
||||
url
|
||||
}
|
||||
total
|
||||
}
|
||||
|
||||
32
lib/graphql/Query/Header.graphql
Normal file
32
lib/graphql/Query/Header.graphql
Normal file
@@ -0,0 +1,32 @@
|
||||
#import "../Fragments/Image.graphql"
|
||||
|
||||
query GetHeader($locale: String!) {
|
||||
all_header(limit: 1, locale: $locale) {
|
||||
items {
|
||||
frontpage_link_text
|
||||
logoConnection {
|
||||
edges {
|
||||
node {
|
||||
...Image
|
||||
}
|
||||
}
|
||||
}
|
||||
menu {
|
||||
links {
|
||||
href
|
||||
title
|
||||
}
|
||||
}
|
||||
top_menu {
|
||||
links {
|
||||
link {
|
||||
href
|
||||
title
|
||||
}
|
||||
show_on_mobile
|
||||
sort_order_mobile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
lib/graphql/Query/LanguageSwitcher.graphql
Normal file
21
lib/graphql/Query/LanguageSwitcher.graphql
Normal file
@@ -0,0 +1,21 @@
|
||||
query GetDaDeEnUrls($uid: String!) {
|
||||
de: current_blocks_page(uid: $uid, locale: "de") {
|
||||
url: original_url
|
||||
}
|
||||
en: current_blocks_page(uid: $uid, locale: "en") {
|
||||
url: original_url
|
||||
}
|
||||
}
|
||||
|
||||
query GetFiNoSvUrls($uid: String!) {
|
||||
fi: current_blocks_page(uid: $uid, locale: "fi") {
|
||||
url: original_url
|
||||
}
|
||||
no: current_blocks_page(uid: $uid, locale: "no") {
|
||||
url: original_url
|
||||
}
|
||||
sv: current_blocks_page(uid: $uid, locale: "sv") {
|
||||
url: original_url
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,31 @@
|
||||
import "server-only"
|
||||
import { request as graphqlRequest } from "graphql-request"
|
||||
import { GraphQLClient } from "graphql-request"
|
||||
import { env } from "@/env/server"
|
||||
import { cache } from "react"
|
||||
|
||||
import type { Data } from "@/types/request"
|
||||
import type { DocumentNode } from "graphql"
|
||||
|
||||
const client = new GraphQLClient(env.CMS_URL, {
|
||||
fetch: cache(async function (url: URL | RequestInfo, params: RequestInit | undefined) {
|
||||
return fetch(url, params)
|
||||
}),
|
||||
})
|
||||
|
||||
export async function request<T>(
|
||||
query: string | DocumentNode,
|
||||
variables?: {}
|
||||
variables?: {},
|
||||
next?: NextFetchRequestConfig
|
||||
): Promise<Data<T>> {
|
||||
try {
|
||||
if (env.PRINT_QUERY) {
|
||||
const graphqlRawRequest = (await import("graphql-request")).rawRequest
|
||||
const print = (await import("graphql/language/printer")).print
|
||||
|
||||
const rawResponse = await graphqlRawRequest<T>(
|
||||
env.CMS_URL,
|
||||
if (next) {
|
||||
client.requestConfig.next = next
|
||||
}
|
||||
|
||||
if (env.PRINT_QUERY) {
|
||||
const print = (await import("graphql/language/printer")).print
|
||||
const rawResponse = await client.rawRequest<T>(
|
||||
print(query as DocumentNode),
|
||||
variables,
|
||||
{
|
||||
@@ -40,13 +50,12 @@ export async function request<T>(
|
||||
}
|
||||
}
|
||||
|
||||
const response = await graphqlRequest<T>({
|
||||
const response = await client.request<T>({
|
||||
document: query,
|
||||
requestHeaders: {
|
||||
access_token: env.CMS_ACCESS_TOKEN,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
url: env.CMS_URL,
|
||||
variables,
|
||||
})
|
||||
|
||||
|
||||
@@ -25,8 +25,14 @@ const nextConfig = {
|
||||
loader: "graphql-tag/loader",
|
||||
})
|
||||
|
||||
return config
|
||||
return config;
|
||||
},
|
||||
}
|
||||
|
||||
logging: {
|
||||
fetches: {
|
||||
fullUrl: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="27 7.7 85 18.3" style="enable-background:new 27 7.7 85 18.3;" xml:space="preserve">
|
||||
viewBox="27 7.7 85 19" style="enable-background:new 27 7.7 85 19;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
@@ -2,7 +2,7 @@
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 85 18.3" enable-background="new 0 0 85 18.3" xml:space="preserve">
|
||||
viewBox="0 0 85 19" enable-background="new 0 0 85 19" xml:space="preserve">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="#CD0921" d="M24.8,17.9c-1.2,0.3-2.4,0.4-3.6,0.4c-4.3,0-7.1-2-7.1-6.7
|
||||
c0-4.5,2.9-6.4,7-6.4c1.2,0,2.4,0.1,3.6,0.3v2.2c-0.9-0.1-1.6-0.2-2.4-0.2c-3.3,0-4.9,1-4.9,4.3c0,3.1,1.5,4.2,4.9,4.2
|
||||
c0.9,0,1.6-0.1,2.4-0.2V17.9z"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
@@ -1,8 +1,7 @@
|
||||
import type { Breadcrumb } from "@/types/requests/currentBlockPage"
|
||||
import type { Edges, Node } from "@/types/requests/utils/edges"
|
||||
|
||||
export type BreadcrumbsProps = {
|
||||
breadcrumbs: Edges<Breadcrumb>
|
||||
parent?: Node<Breadcrumb>
|
||||
breadcrumbs: Breadcrumb[]
|
||||
parent?: Breadcrumb
|
||||
title: string
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import type { Lang } from "@/types/lang"
|
||||
import type { GetCurrentBlockPageData } from "@/types/requests/currentBlockPage"
|
||||
|
||||
export type ContentPageProps = {
|
||||
data: GetCurrentBlockPageData
|
||||
uri: string
|
||||
lang: Lang
|
||||
}
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
import { Lang } from "@/types/lang"
|
||||
import {
|
||||
ExternalLink,
|
||||
InternalLink,
|
||||
NavigationItem,
|
||||
} from "@/types/requests/footer"
|
||||
import type { NavigationItem } from "@/types/requests/footer"
|
||||
|
||||
export type FooterNavigationProps = {
|
||||
linkGroups: NavigationItem[]
|
||||
lang: Lang
|
||||
}
|
||||
|
||||
export type FooterNavigationItemProps = {
|
||||
linkObject: InternalLink | ExternalLink
|
||||
lang: Lang
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export type HeaderProps = {
|
||||
pathname: string
|
||||
uid: string
|
||||
}
|
||||
|
||||
13
types/components/current/header/mainMenu.ts
Normal file
13
types/components/current/header/mainMenu.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { HeaderLink, TopMenuHeaderLink } from "@/types/requests/header"
|
||||
import type { Image } from "@/types/image"
|
||||
import type { LanguageSwitcherQueryData } from "@/types/requests/languageSwitcher"
|
||||
|
||||
export type MainMenuProps = {
|
||||
currentLanguage: string
|
||||
frontpageLinkText: string
|
||||
homeHref: string
|
||||
links: HeaderLink[]
|
||||
logo: Image
|
||||
topMenuMobileLinks: TopMenuHeaderLink[]
|
||||
urls: LanguageSwitcherQueryData
|
||||
}
|
||||
10
types/components/current/header/topMenu.ts
Normal file
10
types/components/current/header/topMenu.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import type { LanguageSwitcherQueryData } from "@/types/requests/languageSwitcher"
|
||||
import type { TopMenuHeaderLink } from "@/types/requests/header"
|
||||
|
||||
export type TopMenuProps = {
|
||||
currentLanguage: string
|
||||
frontpageLinkText: string
|
||||
homeHref: string
|
||||
links: TopMenuHeaderLink[]
|
||||
urls: LanguageSwitcherQueryData
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { LanguageSwitcherQueryData } from "@/types/requests/languageSwitcher"
|
||||
|
||||
export type LanguageSwitcherLink = {
|
||||
href: string
|
||||
title: string
|
||||
@@ -5,5 +7,5 @@ export type LanguageSwitcherLink = {
|
||||
|
||||
export type LanguageSwitcherProps = {
|
||||
currentLanguage: string
|
||||
links: LanguageSwitcherLink[]
|
||||
urls: LanguageSwitcherQueryData
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import type { Breadcrumb } from "@/types/requests/currentBlockPage"
|
||||
import type { Edges, Node } from "@/types/requests/utils/edges"
|
||||
|
||||
export type SubnavMobileProps = {
|
||||
breadcrumbs: Edges<Breadcrumb>
|
||||
parent?: Node<Breadcrumb>
|
||||
breadcrumbs: Breadcrumb[]
|
||||
parent?: Breadcrumb
|
||||
title: string
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import type { Puff } from "../puff"
|
||||
import type { Edges } from "../utils/edges"
|
||||
|
||||
export type PuffAside = {
|
||||
puff: {
|
||||
puffConnection: Edges<Puff>
|
||||
}
|
||||
puff: Puff
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import type { Edges } from "../utils/edges"
|
||||
import type { PageLink } from "../utils/pageLink"
|
||||
import type { Typename } from "../utils/typename"
|
||||
|
||||
enum ListItemStyleEnum {
|
||||
@@ -12,7 +10,6 @@ type ListItemStyle = keyof typeof ListItemStyleEnum
|
||||
export enum BlockListItemsEnum {
|
||||
CurrentBlocksPageBlocksListBlockListItemsListItem = "CurrentBlocksPageBlocksListBlockListItemsListItem",
|
||||
CurrentBlocksPageBlocksListBlockListItemsListItemExternalLink = "CurrentBlocksPageBlocksListBlockListItemsListItemExternalLink",
|
||||
CurrentBlocksPageBlocksListBlockListItemsListItemInternalLink = "CurrentBlocksPageBlocksListBlockListItemsListItemInternalLink",
|
||||
}
|
||||
|
||||
type ExternalLinkListItem = Typename<
|
||||
@@ -29,18 +26,6 @@ type ExternalLinkListItem = Typename<
|
||||
BlockListItemsEnum.CurrentBlocksPageBlocksListBlockListItemsListItemExternalLink
|
||||
>
|
||||
|
||||
type InternalLinkListItem = Typename<
|
||||
{
|
||||
list_item_internal_link: {
|
||||
link_text?: string
|
||||
list_item_style: ListItemStyle
|
||||
subtitle?: string
|
||||
pageConnection: Edges<PageLink>
|
||||
}
|
||||
},
|
||||
BlockListItemsEnum.CurrentBlocksPageBlocksListBlockListItemsListItemInternalLink
|
||||
>
|
||||
|
||||
type RegularListItem = Typename<
|
||||
{
|
||||
list_item: {
|
||||
@@ -54,7 +39,6 @@ type RegularListItem = Typename<
|
||||
|
||||
export type ListItem =
|
||||
| ExternalLinkListItem
|
||||
| InternalLinkListItem
|
||||
| RegularListItem
|
||||
|
||||
export type List = {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import type { Edges } from "../utils/edges"
|
||||
import type { Puff } from "../puff"
|
||||
|
||||
export type PuffBlock = {
|
||||
puffs: {
|
||||
puffsConnection: Edges<Puff>
|
||||
puffs: {
|
||||
puff: Puff
|
||||
}[]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,6 @@ import type {
|
||||
Typename,
|
||||
PagesTypenameEnum,
|
||||
} from "./utils/typename"
|
||||
import type { EmbedEnum } from "./utils/embeds"
|
||||
import type { Edges } from "./utils/edges"
|
||||
|
||||
export type Asides =
|
||||
| Typename<Contact, AsideTypenameEnum.CurrentBlocksPageAsideContact>
|
||||
@@ -25,22 +23,13 @@ export type Blocks =
|
||||
| Typename<PuffBlock, BlocksTypenameEnum.CurrentBlocksPageBlocksPuffs>
|
||||
| Typename<Text, BlocksTypenameEnum.CurrentBlocksPageBlocksText>
|
||||
|
||||
interface SharedBreadcrumb {
|
||||
breadcrumbs: {
|
||||
title?: string
|
||||
} | null
|
||||
export type Breadcrumb = {
|
||||
href: string
|
||||
title: string
|
||||
url: string
|
||||
}
|
||||
|
||||
export interface CurrentBlocksPageBreadcrumb extends SharedBreadcrumb {
|
||||
__typename: EmbedEnum.CurrentBlocksPage
|
||||
}
|
||||
|
||||
export type Breadcrumb = CurrentBlocksPageBreadcrumb
|
||||
|
||||
export type Breadcrumbs = {
|
||||
parentsConnection: Edges<Breadcrumb>
|
||||
parents: Breadcrumb[]
|
||||
title: string
|
||||
}
|
||||
|
||||
@@ -51,13 +40,13 @@ export type BlockPage = {
|
||||
breadcrumbs: Breadcrumbs
|
||||
hero: Hero
|
||||
preamble: Preamble
|
||||
title: string
|
||||
url: string
|
||||
system: {
|
||||
uid: string
|
||||
created_at: string
|
||||
uid: string
|
||||
updated_at: string
|
||||
}
|
||||
title: string
|
||||
url: string
|
||||
}
|
||||
|
||||
export type GetCurrentBlockPageData = {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { SysAsset } from "./utils/asset"
|
||||
import type { PageLinkType } from "./utils/pageLink"
|
||||
|
||||
export type Embeds = PageLinkType | SysAsset
|
||||
export type Embeds = SysAsset
|
||||
|
||||
@@ -1,33 +1,19 @@
|
||||
import type { AllRequestResponse } from "./utils/all"
|
||||
import type { Edges } from "./utils/edges"
|
||||
import type { Image } from "../image"
|
||||
import type { PageLink } from "./utils/pageLink"
|
||||
|
||||
type AppDownload = {
|
||||
href: string
|
||||
imageConnection: Edges<Image>
|
||||
}
|
||||
|
||||
export type InternalLink = {
|
||||
__typename: "FooterNavigationLinksInternalLink"
|
||||
internal_link: {
|
||||
link_text: string
|
||||
pageConnection: Edges<PageLink>
|
||||
}
|
||||
}
|
||||
|
||||
export type ExternalLink = {
|
||||
__typename: "FooterNavigationLinksExternalLink"
|
||||
external_link: {
|
||||
link: {
|
||||
href: string
|
||||
title: string
|
||||
}
|
||||
}
|
||||
export type Link = {
|
||||
href: string
|
||||
title: string
|
||||
}
|
||||
|
||||
export type NavigationItem = {
|
||||
links: (ExternalLink | InternalLink)[]
|
||||
links: Link[]
|
||||
title: string
|
||||
}
|
||||
|
||||
|
||||
35
types/requests/header.ts
Normal file
35
types/requests/header.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import type { Edges } from "./utils/edges"
|
||||
import type { Image } from "../image"
|
||||
|
||||
export type HeaderLink = {
|
||||
href: string
|
||||
title: string
|
||||
}
|
||||
|
||||
export type TopMenuHeaderLink = {
|
||||
link: {
|
||||
href: string
|
||||
title: string
|
||||
}
|
||||
show_on_mobile: boolean
|
||||
sort_order_mobile: number
|
||||
}
|
||||
|
||||
export type HeaderLinks = {
|
||||
links: HeaderLink[]
|
||||
}
|
||||
|
||||
export type TopMenuHeaderLinks = {
|
||||
links: TopMenuHeaderLink[]
|
||||
}
|
||||
|
||||
export type HeaderQueryData = {
|
||||
all_header: {
|
||||
items: {
|
||||
frontpage_link_text: string
|
||||
logoConnection: Edges<Image>
|
||||
menu: HeaderLinks
|
||||
top_menu: TopMenuHeaderLinks
|
||||
}[]
|
||||
}
|
||||
}
|
||||
11
types/requests/languageSwitcher.ts
Normal file
11
types/requests/languageSwitcher.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
type LanguageResult = {
|
||||
url: string
|
||||
}
|
||||
|
||||
export type LanguageSwitcherQueryData = {
|
||||
de: LanguageResult | undefined
|
||||
en: LanguageResult | undefined
|
||||
fi: LanguageResult | undefined
|
||||
no: LanguageResult | undefined
|
||||
sv: LanguageResult | undefined
|
||||
}
|
||||
@@ -1,22 +1,14 @@
|
||||
import type { Image } from "../image"
|
||||
import type { Edges } from "./utils/edges"
|
||||
import type { Embeds } from "./embeds"
|
||||
import type { PageLink } from "./utils/pageLink"
|
||||
import type { RTEDocument } from "../rte/node"
|
||||
|
||||
export type Puff = {
|
||||
imageConnection: Edges<Image>
|
||||
is_internal: boolean
|
||||
link: {
|
||||
href: string
|
||||
title: string
|
||||
}
|
||||
pageConnection: Edges<PageLink>
|
||||
system: {
|
||||
uid: string
|
||||
}
|
||||
text: {
|
||||
embedded_itemsConnection: Edges<Embeds>
|
||||
json: RTEDocument
|
||||
}
|
||||
title: string
|
||||
|
||||
@@ -7,7 +7,6 @@ export type AsideTypename = keyof typeof AsideTypenameEnum
|
||||
|
||||
export enum BlocksTypenameEnum {
|
||||
CurrentBlocksPageBlocksList = "CurrentBlocksPageBlocksList",
|
||||
CurrentBlocksPageBlocksPreamble = "CurrentBlocksPageBlocksPreamble",
|
||||
CurrentBlocksPageBlocksPuffs = "CurrentBlocksPageBlocksPuffs",
|
||||
CurrentBlocksPageBlocksText = "CurrentBlocksPageBlocksText",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user