Merged in fix/header-parallel-route (pull request #238)

Static pages sync

Approved-by: Michael Zetterberg
This commit is contained in:
Christel Westerberg
2024-06-18 09:43:01 +00:00
committed by Michael Zetterberg
67 changed files with 759 additions and 278 deletions

View File

@@ -12,13 +12,13 @@ export default function Contact({ sections, system: { locale } }: ContactNode) {
const visitingAddressMessage = getVisitingAddressMessage(locale)
return (
<section>
{sections.map((section) => {
{sections.map((section, idx) => {
switch (section.__typename) {
case Section.ContactBlockSectionsExtraInfo:
return <p>{section.extra_info.text}</p>
case Section.ContactBlockSectionsMailingAddress:
return (
<p>
<p key={`section-mail-${idx}`}>
{section.mailing_address.name}
<br />
{section.mailing_address.street}
@@ -30,7 +30,10 @@ export default function Contact({ sections, system: { locale } }: ContactNode) {
)
case Section.ContactBlockSectionsPhone:
return (
<div className={styles.highlightBlock}>
<div
className={styles.highlightBlock}
key={`section-phone-${idx}`}
>
<h3>{section.phone.title}</h3>
<div className={styles.phoneContainer}>
<svg
@@ -55,10 +58,14 @@ export default function Contact({ sections, system: { locale } }: ContactNode) {
</div>
)
case Section.ContactBlockSectionsTitle:
return <h2 className={styles.heading}>{section.title.text}</h2>
return (
<h2 className={styles.heading} key={`section-heading-${idx}`}>
{section.title.text}
</h2>
)
case Section.ContactBlockSectionsVisitingAddress:
return (
<p>
<p key={`section-visiting-address-${idx}`}>
{visitingAddressMessage}: {section.visiting_address.street}{" "}
</p>
)

View File

@@ -14,15 +14,15 @@ export default function Blocks({ blocks }: BlocksProps) {
return (
<section className={styles.wrapper}>
{blocks.map((block) => {
{blocks.map((block, idx) => {
const type = block.__typename
switch (type) {
case BlocksTypenameEnum.CurrentBlocksPageBlocksList:
return <List key={block.__typename} {...block} />
return <List key={`${block.__typename}-${idx}`} {...block} />
case BlocksTypenameEnum.CurrentBlocksPageBlocksPuffs:
return <Puffs key={block.__typename} {...block} />
return <Puffs key={`${block.__typename}-${idx}`} {...block} />
case BlocksTypenameEnum.CurrentBlocksPageBlocksText:
return <Text key={block.__typename} {...block} />
return <Text key={`${block.__typename}-${idx}`} {...block} />
default:
console.log(`Unknown type: (${type})`)
return null

View File

@@ -6,8 +6,10 @@ import Navigation from "./Navigation"
import styles from "./footer.module.css"
export default async function Footer() {
const footerData = await serverClient().contentstack.base.footer()
import { LangParams } from "@/types/params"
export default async function Footer({ lang }: LangParams) {
const footerData = await serverClient().contentstack.base.footer({ lang })
return (
<footer className={styles.container}>
<div className={styles.content}>

View File

@@ -12,7 +12,7 @@
sans-serif;
}
.languageSwitcher {
.toggle {
display: flex;
color: #fff;
padding: 3px 15px;

View File

@@ -0,0 +1,19 @@
import Desktop from "./Desktop"
import Mobile from "./Mobile"
import { LangParams } from "@/types/params"
import { LanguageSwitcherData } from "@/types/requests/languageSwitcher"
type LanguageSwitcherProps = LangParams & { urls: LanguageSwitcherData }
export default function LanguageSwitcher({
urls,
lang,
}: LanguageSwitcherProps) {
return (
<>
<Desktop currentLanguage={lang} urls={urls} />
<Mobile currentLanguage={lang} urls={urls} />
</>
)
}

View File

@@ -275,6 +275,7 @@
.logo {
width: 102.17px;
height: 100%;
padding-bottom: 4px;
}
.listWrapper {

View File

@@ -23,7 +23,9 @@ export default async function TopMenu({
</a>
<ul className={styles.list}>
<li className={styles.langSwitcher}>{languageSwitcher}</li>
{languageSwitcher ? (
<li className={styles.langSwitcher}>{languageSwitcher}</li>
) : null}
{links.map(({ link }, i) => (
<li key={link.href + i}>

View File

@@ -16,7 +16,9 @@ export default async function Header({
lang,
languageSwitcher,
}: LangParams & { languageSwitcher: React.ReactNode }) {
const data = await serverClient().contentstack.base.header()
const data = await serverClient().contentstack.base.header({
lang,
})
const session = await auth()
const homeHref = homeHrefs[env.NODE_ENV][lang]

View File

@@ -0,0 +1,131 @@
import { Lang } from "@/constants/languages"
type Texts = {
title: string
goToStartPage: {
question: string
link: string
linkText: string
}
goToDestinations: {
question: string
link: string
linkText: string
}
goToOffers: {
question: string
link: string
linkText: string
}
}
export const texts: Record<Lang, Texts> = {
en: {
title: "Sorry, page not found.",
goToStartPage: {
question: "Would you like to go back to the ",
link: "https://www.scandichotels.com/",
linkText: "startpage",
},
goToDestinations: {
question: "Or take a trip to our ",
link: "https://www.scandichotels.com/hotels",
linkText: "destinations",
},
goToOffers: {
question: " or latest ",
link: "https://www.scandichotels.com/weekend-packages-and-offers",
linkText: "offers",
},
},
sv: {
title: "Oj då, vi kunde inte hitta sidan du söker.",
goToStartPage: {
question: "Vill du gå tillbaka till ",
link: "https://www.scandichotels.se/",
linkText: "startsidan",
},
goToDestinations: {
question: "Eller resa till våra ",
link: "https://www.scandichotels.se/hotell",
linkText: "destinationer",
},
goToOffers: {
question: " eller se våra senaste ",
link: "https://www.scandichotels.se/erbjudanden-och-weekendpaket",
linkText: "erbjudanden",
},
},
de: {
title: "Tut uns leid, Seite nicht gefunden.",
goToStartPage: {
question: "Möchten Sie zurück zur ",
link: "https://www.scandichotels.de/",
linkText: "Startseite",
},
goToDestinations: {
question: "Oder machen Sie einen Ausflug zu unseren ",
link: "https://www.scandichotels.de/hotelsuche",
linkText: "Reisezielen",
},
goToOffers: {
question: " und aktuellen ",
link: "https://www.scandichotels.de/angebote-arrangements",
linkText: "Angeboten",
},
},
fi: {
title: "TValitettavasti sivua ei löydy.",
goToStartPage: {
question: "Haluaisitko mennä takaisin ",
link: "https://www.scandichotels.fi/",
linkText: "etusivulle",
},
goToDestinations: {
question: "Voit myös tutustu ",
link: "https://www.scandichotels.fi/hotellit",
linkText: "kohteisiimme",
},
goToOffers: {
question: " tai ajankohtaisiin ",
link: "https://www.scandichotels.fi/tarjoukset",
linkText: "tarjouksiimme",
},
},
no: {
title: "Oi da, vi fant ikke siden du lette etter...",
goToStartPage: {
question: "Vil du gå tilbake til ",
link: "https://www.scandichotels.no/",
linkText: "startsiden",
},
goToDestinations: {
question: "Eller ta en tur til våre ",
link: "https://www.scandichotels.no/hotell",
linkText: "destinasjoner",
},
goToOffers: {
question: " eller siste ",
link: "https://www.scandichotels.no/hotelltilbud",
linkText: "tilbud",
},
},
da: {
title: "Hov - siden kan ikke findes!",
goToStartPage: {
question: "Vil du gå tilbage til ",
link: "https://www.scandichotels.dk/",
linkText: "startsiden",
},
goToDestinations: {
question: "Eller tag en tur til vores ",
link: "https://www.scandichotels.dk/hoteller",
linkText: "destinationer",
},
goToOffers: {
question: " eller seneste ",
link: "https://www.scandichotels.dk/tilbud-og-hotelpakker",
linkText: "tilbud",
},
},
}

View File

@@ -0,0 +1,48 @@
import { texts } from "./Texts"
import styles from "./notFound.module.css"
import { LangParams } from "@/types/params"
export default function NotFound({ lang }: LangParams) {
const infoTexts = texts[lang]
return (
<div className={styles.container}>
<div className={styles.content}>
<h1 className={styles.header}>{infoTexts.title}</h1>
<div className={styles.pitch}>
<p className={styles.text}>
{infoTexts.goToStartPage.question}
<a
className={styles.link}
title={infoTexts.goToStartPage.linkText}
href={infoTexts.goToStartPage.link}
>
{infoTexts.goToStartPage.linkText}
</a>
?
</p>
<p className={styles.text}>
{infoTexts.goToDestinations.question}
<a
className={styles.link}
title={infoTexts.goToDestinations.linkText}
href={infoTexts.goToDestinations.link}
>
{infoTexts.goToDestinations.linkText}
</a>
{infoTexts.goToOffers.question}
<a
className={styles.link}
title={infoTexts.goToOffers.linkText}
href={infoTexts.goToOffers.link}
>
{infoTexts.goToOffers.linkText}
</a>
.
</p>
</div>
</div>
</div>
)
}

View File

@@ -0,0 +1,70 @@
.container {
margin-top: 0;
background: var(--Main-Grey-White);
position: relative;
border-top: 50px solid var(--Main-Grey-White);
background-clip: content-box;
}
.content {
position: relative;
text-align: center;
box-sizing: content-box;
max-width: 1200px;
margin: 0 auto;
padding: 70px 30px;
}
.header {
font-family:
brandon text,
Arial,
Helvetica,
sans-serif;
font-size: 32px;
line-height: 1;
margin: 0;
text-transform: uppercase;
font-weight: 400;
color: #483729;
}
.pitch {
margin-top: 32px;
margin-bottom: 16px;
}
.text {
font-family:
Helvetica Neue,
Roboto,
Helvetica,
Arial,
sans-serif;
font-weight: 300;
line-height: normal;
text-transform: none;
font-size: 20px;
color: #333;
}
.link {
color: #00838e;
text-decoration: none;
}
@media screen and (min-width: 740px) {
.content {
text-align: left;
}
}
@media screen and (min-width: 950px) {
.header {
font-size: 46px;
}
.text {
font-size: 24px;
}
}

View File

@@ -37,7 +37,10 @@ export default function BenefitCard({
</div>
<div className={styles.benefitComparison}>
{comparedValues.map((benefit, idx) => (
<div key={idx} className={styles.comparisonItem}>
<div
key={`${benefit.valueDetails}-${idx}`}
className={styles.comparisonItem}
>
<BenefitValue benefit={benefit} />
</div>
))}

View File

@@ -29,8 +29,9 @@ export default function BenefitList({ levels }: BenefitListProps) {
<BenefitCard
title={benefit.name}
description={benefit.description}
comparedValues={levelBenefits.map((benefit) => {
comparedValues={levelBenefits.map((benefit, idx) => {
return {
key: `${benefit.name}-${idx}`,
value: benefit.value,
unlocked: benefit.unlocked,
valueDetails: benefit.valueDetails,

View File

@@ -14,10 +14,15 @@ export function Blocks({ lang, blocks }: BlocksProps & LangParams) {
const firstItem = idx === 0
switch (block.__typename) {
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid:
return <CardsGrid cards_grid={block.cards_grid} />
return (
<CardsGrid
key={`${block.cards_grid.title}-${idx}`}
cards_grid={block.cards_grid}
/>
)
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksContent:
return (
<section>
<section key={`${block.__typename}-${idx}`}>
<JsonToHtml
nodes={block.content.content.json.children}
embeds={block.content.content.embedded_itemsConnection.edges}
@@ -39,6 +44,7 @@ export function Blocks({ lang, blocks }: BlocksProps & LangParams) {
<DynamicContentBlock
dynamicContent={dynamicContent}
firstItem={firstItem}
key={`${block.dynamic_content.title}-${idx}`}
/>
)
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksShortcuts:
@@ -49,6 +55,7 @@ export function Blocks({ lang, blocks }: BlocksProps & LangParams) {
return (
<Shortcuts
firstItem={firstItem}
key={`${block.shortcuts.title}-${idx}`}
shortcuts={shortcuts}
title={block.shortcuts.title}
subtitle={block.shortcuts.preamble}

View File

@@ -13,7 +13,7 @@ export function Blocks({ blocks }: BlocksProps) {
switch (block.__typename) {
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksContent:
return (
<section>
<section key={`${block.__typename}-${idx}`}>
<JsonToHtml
nodes={block.content.content.json.children}
embeds={block.content.content.embedded_itemsConnection.edges}
@@ -25,19 +25,26 @@ export function Blocks({ blocks }: BlocksProps) {
<DynamicContentBlock
dynamicContent={block.dynamic_content}
firstItem={firstItem}
key={`${block.dynamic_content.title}-${idx}`}
/>
)
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksShortcuts:
return (
<Shortcuts
firstItem={firstItem}
key={`${block.shortcuts.title}-${idx}`}
shortcuts={block.shortcuts.shortcuts}
subtitle={block.shortcuts.preamble}
title={block.shortcuts.title}
/>
)
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid:
return <CardsGrid cards_grid={block.cards_grid} />
return (
<CardsGrid
cards_grid={block.cards_grid}
key={`${block.cards_grid.title}-${idx}`}
/>
)
default:
return null
}

View File

@@ -1,3 +1,5 @@
import { login } from "@/constants/routes/handleAuth"
import { ScandicFriends } from "@/components/Levels"
import Button from "@/components/TempDesignSystem/Button"
import Link from "@/components/TempDesignSystem/Link"
@@ -11,11 +13,12 @@ import Contact from "./Contact"
import styles from "./joinLoyalty.module.css"
import type { JoinLoyaltyContactProps } from "@/types/components/loyalty/sidebar"
import { LangParams } from "@/types/params"
export default async function JoinLoyaltyContact({
block,
lang,
}: JoinLoyaltyContactProps) {
}: JoinLoyaltyContactProps & LangParams) {
const { formatMessage } = await getIntl()
return (
<section className={styles.container}>
@@ -28,11 +31,9 @@ export default async function JoinLoyaltyContact({
<Body textAlign="center">{block.preamble}</Body>
) : null}
<Button asChild className={styles.link} intent="primary">
<Link href="#">
{formatMessage({ id: "Join Scandic Friends" })}
</Link>
<Link href="#">{formatMessage({ id: "Join Scandic Friends" })}</Link>
</Button>
<Link href={`/${lang}/login`}>
<Link href={login[lang]}>
<Footnote textAlign="center" textTransform="bold">
{formatMessage({ id: "Already a friend?" })} <br />
{formatMessage({ id: "Click here to log in" })}

View File

@@ -6,15 +6,22 @@ import styles from "./sidebar.module.css"
import { SidebarTypenameEnum } from "@/types/components/loyalty/enums"
import { SidebarProps } from "@/types/components/loyalty/sidebar"
import { LangParams } from "@/types/params"
export default function SidebarLoyalty({ blocks, lang }: SidebarProps) {
export default function SidebarLoyalty({
blocks,
lang,
}: SidebarProps & LangParams) {
return (
<aside className={styles.aside}>
{blocks.map((block) => {
{blocks.map((block, idx) => {
switch (block.__typename) {
case SidebarTypenameEnum.LoyaltyPageSidebarContent:
return (
<section className={styles.content}>
<section
className={styles.content}
key={`${block.__typename}-${idx}`}
>
<JsonToHtml
embeds={block.content.content.embedded_itemsConnection.edges}
nodes={block.content.content.json.children}
@@ -26,6 +33,7 @@ export default function SidebarLoyalty({ blocks, lang }: SidebarProps) {
<JoinLoyaltyContact
block={block.join_loyalty_contact}
lang={lang}
key={`${block.join_loyalty_contact.title}-${idx}`}
/>
)
default:

View File

@@ -47,7 +47,7 @@ function DynamicComponent({ component, props }: AccountPageContentProps) {
}
export default function Content({ lang, content }: ContentProps) {
return content.map((item) => {
return content.map((item, idx) => {
switch (item.__typename) {
case ContentEntries.AccountPageContentDynamicContent:
const link = item.dynamic_content.link.linkConnection.edges.length
@@ -71,6 +71,7 @@ export default function Content({ lang, content }: ContentProps) {
}
return (
<DynamicComponent
key={`${item.dynamic_content.title}-${idx}`}
component={item.dynamic_content.component}
props={componentProps}
/>
@@ -78,6 +79,7 @@ export default function Content({ lang, content }: ContentProps) {
case ContentEntries.AccountPageContentShortcuts:
return (
<Shortcuts
key={`${item.shortcuts.title}-${idx}`}
shortcuts={item.shortcuts.shortcuts}
subtitle={item.shortcuts.preamble}
title={item.shortcuts.title}
@@ -85,7 +87,7 @@ export default function Content({ lang, content }: ContentProps) {
)
case ContentEntries.AccountPageContentTextContent:
return (
<section>
<section key={`${item.__typename}-${idx}`}>
<JsonToHtml
embeds={item.text_content.content.embedded_itemsConnection.edges}
nodes={item.text_content.content.json.children}

View File

@@ -48,7 +48,7 @@ function DynamicComponent({ component, props }: AccountPageContentProps) {
export default function Content({ lang, content }: ContentProps) {
return (
<>
{content.map((item) => {
{content.map((item, idx) => {
switch (item.__typename) {
case ContentEntries.AccountPageContentDynamicContent:
const link = item.dynamic_content.link.linkConnection.edges.length
@@ -70,6 +70,7 @@ export default function Content({ lang, content }: ContentProps) {
}
return (
<DynamicComponent
key={`${item.dynamic_content.title}-${idx}`}
component={item.dynamic_content.component}
props={componentProps}
/>
@@ -83,6 +84,7 @@ export default function Content({ lang, content }: ContentProps) {
})
return (
<Shortcuts
key={`${item.shortcuts.title}-${idx}`}
shortcuts={shortcuts}
subtitle={item.shortcuts.preamble}
title={item.shortcuts.title}
@@ -90,7 +92,7 @@ export default function Content({ lang, content }: ContentProps) {
)
case ContentEntries.AccountPageContentTextContent:
return (
<section>
<section key={`${item.__typename}-${idx}`}>
<JsonToHtml
embeds={
item.text_content.content.embedded_itemsConnection.edges

View File

@@ -49,13 +49,10 @@
line-height: var(--typography-Script-2-lineHeight);
letter-spacing: 0.48px;
padding: var(--Spacing-x1);
margin: 0;
transform: rotate(-3deg);
}
.divider {
border-bottom-color: var(--divider-color);
}
.heading {
color: var(--font-color);
}

View File

@@ -42,10 +42,7 @@ export default function Card({
>
{scriptedTopTitle ? (
<section className={styles.scriptContainer}>
<Title className={styles.scriptedTitle} level="h3">
{scriptedTopTitle}
</Title>
<Divider className={styles.divider} />
<h3 className={styles.scriptedTitle}>{scriptedTopTitle}</h3>
</section>
) : null}
<Title as="h5" className={styles.heading} level="h3">