!prevIsOpen) + } + + return ( +
+
+ + + + + + {frontpageLinkText} + + Scandic Hotels logo + + + +
+
+ ) +} diff --git a/components/Current/Header/MainMenu/mainMenu.module.css b/components/Current/Header/MainMenu/mainMenu.module.css new file mode 100644 index 000000000..ed56b3ef0 --- /dev/null +++ b/components/Current/Header/MainMenu/mainMenu.module.css @@ -0,0 +1,219 @@ +.mainMenu { + background-color: #fff; + background-image: none; + position: fixed; + top: 0; + max-height: 100%; + width: 100%; + z-index: 99999; + overflow: visible; +} + +.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; + } + + .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; + } +} \ No newline at end of file diff --git a/components/Current/Header/OfflineBanner/banner.module.css b/components/Current/Header/OfflineBanner/banner.module.css new file mode 100644 index 000000000..b6ecf284e --- /dev/null +++ b/components/Current/Header/OfflineBanner/banner.module.css @@ -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; +} \ No newline at end of file diff --git a/components/Current/Header/OfflineBanner/index.tsx b/components/Current/Header/OfflineBanner/index.tsx new file mode 100644 index 000000000..1b98d40a9 --- /dev/null +++ b/components/Current/Header/OfflineBanner/index.tsx @@ -0,0 +1,10 @@ +import styles from "./banner.module.css" + +export default function OfflineBanner() { + return ( +
+ You are offline, some content may be out of date. + +
+ ) +} diff --git a/components/Current/Header/TopMenu/index.tsx b/components/Current/Header/TopMenu/index.tsx new file mode 100644 index 000000000..479662dba --- /dev/null +++ b/components/Current/Header/TopMenu/index.tsx @@ -0,0 +1,41 @@ +// import Desktop from "../LanguageSwitcher/Desktop" +import Link from "next/link" + +import styles from "./topMenu.module.css" + +import type { TopMenuProps } from "@/types/components/current/header/topMenu" + +/** + * Desktop is commented out as it relates to + * LanguageSwitcher and will be handled in another task + */ +export default function TopMenu({ frontpageLinkText, homeHref, links }: TopMenuProps) { + return ( +
+
+ + {frontpageLinkText} + + +
    + {/*
  • + {links ? : null} +
  • */} + {links.map(({ link }) => ( +
  • + + {link.title} + +
  • + ))} +
+
+
+ ) +} diff --git a/components/Current/Header/TopMenu/topMenu.module.css b/components/Current/Header/TopMenu/topMenu.module.css new file mode 100644 index 000000000..161b00ac5 --- /dev/null +++ b/components/Current/Header/TopMenu/topMenu.module.css @@ -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; + } +} \ No newline at end of file diff --git a/components/Current/Header/header.module.css b/components/Current/Header/header.module.css new file mode 100644 index 000000000..36b5ca688 --- /dev/null +++ b/components/Current/Header/header.module.css @@ -0,0 +1,3 @@ +.header { + display: grid; +} \ No newline at end of file diff --git a/components/Current/Header/index.tsx b/components/Current/Header/index.tsx index 52c480605..c24d3a3d6 100644 --- a/components/Current/Header/index.tsx +++ b/components/Current/Header/index.tsx @@ -1,30 +1,47 @@ -import { langEnum } from "@/types/lang" +import { request } from "@/lib/request" +import { GetHeader } from "@/lib/graphql/Query/Header.graphql" -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" -export default function Header({ lang, pathname }: LangParams & HeaderProps) { - switch (lang) { - case langEnum.sv: - return - case langEnum.fi: - return - case langEnum.en: - return - case langEnum.da: - return - case langEnum.de: - return - case langEnum.no: - return - default: +export default async function Header({ lang }: LangParams) { + try { + const { data } = await request(GetHeader, { locale: lang }) + if (!data.all_header.items.length) { return null + } + + const homeHref = `https://www.scandichotels.com/${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 ( +
+ + + +
+ ) + } catch (error) { + console.error(error) + return null } } diff --git a/components/Current/Preamble/Breadcrumbs/index.tsx b/components/Current/Preamble/Breadcrumbs/index.tsx index 631482046..2d629d75e 100644 --- a/components/Current/Preamble/Breadcrumbs/index.tsx +++ b/components/Current/Preamble/Breadcrumbs/index.tsx @@ -14,7 +14,7 @@ export default function Breadcrumbs({
    {parent ? (
  • - + {parent.node.breadcrumbs?.title ?? parent.node.title}
  • @@ -25,7 +25,7 @@ export default function Breadcrumbs({ itemProp="breadcrumb" key={breadcrumb.node.title} > - + {breadcrumb.node.breadcrumbs?.title ?? breadcrumb.node.title} diff --git a/components/Current/SubnavMobile.tsx b/components/Current/SubnavMobile.tsx index 4dac85716..c9d7a508b 100644 --- a/components/Current/SubnavMobile.tsx +++ b/components/Current/SubnavMobile.tsx @@ -13,14 +13,14 @@ export default async function SubnavMobile({
      {parent ? (
    • - + {parent.node.breadcrumbs?.title ?? parent.node.title}
    • ) : null} {breadcrumbs.edges.map((breadcrumb) => (
    • - + {breadcrumb.node.breadcrumbs?.title ?? breadcrumb.node.title}
    • diff --git a/app/[lang]/Tracking.tsx b/components/Current/Tracking.tsx similarity index 100% rename from app/[lang]/Tracking.tsx rename to components/Current/Tracking.tsx diff --git a/components/JsonToHtml/renderOptions.tsx b/components/JsonToHtml/renderOptions.tsx index c2061923b..3529017cd 100644 --- a/components/JsonToHtml/renderOptions.tsx +++ b/components/JsonToHtml/renderOptions.tsx @@ -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 ( - + {next(node.children, embeds, fullRenderOptions)} ) diff --git a/lib/graphql/Fragments/Breadcrumbs.graphql b/lib/graphql/Fragments/Breadcrumbs.graphql index 2be6fd10e..f8ebafec2 100644 --- a/lib/graphql/Fragments/Breadcrumbs.graphql +++ b/lib/graphql/Fragments/Breadcrumbs.graphql @@ -1,3 +1,5 @@ +#import "./PageLinks.graphql" + fragment Breadcrumbs on CurrentBlocksPage { breadcrumbs { title @@ -8,8 +10,7 @@ fragment Breadcrumbs on CurrentBlocksPage { breadcrumbs { title } - title - url + ...CurrentBlocksPageLink } } } diff --git a/lib/graphql/Fragments/Footer/Logo.graphql b/lib/graphql/Fragments/Footer/Logo.graphql index 730d13a1b..d2ce3cbe6 100644 --- a/lib/graphql/Fragments/Footer/Logo.graphql +++ b/lib/graphql/Fragments/Footer/Logo.graphql @@ -1,9 +1,10 @@ +#import "../Image.graphql" + fragment Logo on Footer { logoConnection { edges { node { - title - url + ...Image } } } diff --git a/lib/graphql/Fragments/PageLinks.graphql b/lib/graphql/Fragments/PageLinks.graphql index abc9c3920..1b82b2a59 100644 --- a/lib/graphql/Fragments/PageLinks.graphql +++ b/lib/graphql/Fragments/PageLinks.graphql @@ -1,7 +1,7 @@ fragment CurrentBlocksPageLink on CurrentBlocksPage { system { - uid locale + uid } title url diff --git a/lib/graphql/Query/Header.graphql b/lib/graphql/Query/Header.graphql new file mode 100644 index 000000000..e546f88af --- /dev/null +++ b/lib/graphql/Query/Header.graphql @@ -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 + } + } + } + } +} diff --git a/next.config.js b/next.config.js index 526ce8d5e..ef9e4137e 100644 --- a/next.config.js +++ b/next.config.js @@ -25,8 +25,14 @@ const nextConfig = { loader: "graphql-tag/loader", }) - return config + return config; }, -} + + logging: { + fetches: { + fullUrl: true, + }, + }, +}; export default nextConfig diff --git a/public/Static/img/scandic-logotype-white.svg b/public/Static/img/scandic-logotype-white.svg index e8837b33d..c253c69fa 100644 --- a/public/Static/img/scandic-logotype-white.svg +++ b/public/Static/img/scandic-logotype-white.svg @@ -2,7 +2,7 @@ + viewBox="27 7.7 85 19" style="enable-background:new 27 7.7 85 19;" xml:space="preserve"> diff --git a/public/Static/img/scandic-logotype.svg b/public/Static/img/scandic-logotype.svg index 0ed8677d8..e19f2974a 100644 --- a/public/Static/img/scandic-logotype.svg +++ b/public/Static/img/scandic-logotype.svg @@ -2,7 +2,7 @@ + viewBox="0 0 85 19" enable-background="new 0 0 85 19" xml:space="preserve"> diff --git a/types/components/current/contentPage.ts b/types/components/current/contentPage.ts index 73f029864..91a5253d6 100644 --- a/types/components/current/contentPage.ts +++ b/types/components/current/contentPage.ts @@ -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 } diff --git a/types/components/current/header/mainMenu.ts b/types/components/current/header/mainMenu.ts new file mode 100644 index 000000000..5784692ee --- /dev/null +++ b/types/components/current/header/mainMenu.ts @@ -0,0 +1,10 @@ +import type { HeaderLink, TopMenuHeaderLink } from "@/types/requests/header" +import type { Image } from "@/types/image" + +export type MainMenuProps = { + frontpageLinkText: string + homeHref: string + links: HeaderLink[] + logo: Image + topMenuMobileLinks: TopMenuHeaderLink[] +} diff --git a/types/components/current/header/topMenu.ts b/types/components/current/header/topMenu.ts new file mode 100644 index 000000000..bda691693 --- /dev/null +++ b/types/components/current/header/topMenu.ts @@ -0,0 +1,7 @@ +import type { TopMenuHeaderLink } from "@/types/requests/header" + +export type TopMenuProps = { + frontpageLinkText: string + homeHref: string + links: TopMenuHeaderLink[] +} diff --git a/types/requests/currentBlockPage.ts b/types/requests/currentBlockPage.ts index 52a096880..88daa6f0a 100644 --- a/types/requests/currentBlockPage.ts +++ b/types/requests/currentBlockPage.ts @@ -29,6 +29,10 @@ interface SharedBreadcrumb { breadcrumbs: { title?: string } | null + system: { + locale: string + uid: string + } title: string url: string } diff --git a/types/requests/header.ts b/types/requests/header.ts new file mode 100644 index 000000000..242687213 --- /dev/null +++ b/types/requests/header.ts @@ -0,0 +1,37 @@ +import type { Edges } from "./utils/edges" +import type { Image } from "../image" + +export type HeaderLink = { + link: { + 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 + menu: HeaderLinks + top_menu: TopMenuHeaderLinks + }[] + } +}