Merged in feat/sw-1493-revised-comparison-block (pull request #1236)

feat(SW-1493): Revised SAS comparison block

* Base of new TierDetails for SAS tier comparison

* Add backgrounds and content to TierDetails

* Implement new cms schema for SasTierComparison

* Override gap in jsontohtml styling to 0

* Add animations to comparison details

* Redesign again

* Update content model to new design

* Add border to bottom item in tier match list

* Wrap interpolate-size in @supports to be safe

* Merge branch 'master' into feat/sw-1493-revised-comparison-block


Approved-by: Joakim Jäderberg
This commit is contained in:
Anton Gunnarsson
2025-02-03 08:42:16 +00:00
parent f9d1736195
commit fc866c0e4d
28 changed files with 450 additions and 351 deletions

View File

@@ -1,163 +1,164 @@
"use client"
import { type Key, useState } from "react"
import Image from "next/image"
import JsonToHtml from "@/components/JsonToHtml"
import Link from "@/components/TempDesignSystem/Link"
import Title from "@/components/TempDesignSystem/Text/Title"
import { ArrowRightIcon, CompareArrowsIcon } from "../Icons"
import { ArrowRightIcon, ChevronDownIcon, CompareArrowsIcon } from "../Icons"
import SectionContainer from "../Section/Container"
import SectionHeader from "../Section/Header"
import Button from "../TempDesignSystem/Button"
import Select from "../TempDesignSystem/Select"
import Body from "../TempDesignSystem/Text/Body"
import Caption from "../TempDesignSystem/Text/Caption"
import Subtitle from "../TempDesignSystem/Text/Subtitle"
import Title from "../TempDesignSystem/Text/Title"
import styles from "./sas-tier-comparison.module.css"
import type { ReactNode } from "react"
import type { SasTierComparison } from "@/types/trpc/routers/contentstack/blocks"
type SasTierComparisonContent = SasTierComparison["sas_tier_comparison"]
type TierComparisonProps = {
content: SasTierComparisonContent
firstItem: boolean
}
const scandicSasTierMappings: [string[], string[]][] = [
[["L1", "L2", "L3"], ["Basic"]],
[["L4"], ["Silver"]],
[["L5"], ["Gold"]],
[
["L6", "L7"],
["Diamond", "Pandion"],
],
]
export function SasTierComparison({ content, firstItem }: TierComparisonProps) {
export function SasTierComparison({ content }: TierComparisonProps) {
const comparisonContent = content.sasTierComparison
const scandic = comparisonContent?.scandic_friends
const sas = comparisonContent?.sas_eb
const [activeScandicTierCode, setActiveScandicTierCode] = useState(
scandic?.tiers.at(0)?.tier_code ?? ""
)
const [activeSasTierCode, setActiveSasTierCode] = useState(
sas?.tiers.at(0)?.tier_code ?? ""
)
if (!scandic || !sas) return null
const onChangeScandic = (k: Key) => {
const key = k.toString()
setActiveScandicTierCode(k.toString())
const mapping = scandicSasTierMappings.find(([tierMapping]) =>
tierMapping.includes(key)
)
if (!mapping) return
const sasTierCode = mapping[1][0]
setActiveSasTierCode(sasTierCode)
}
const onChangeSas = (k: Key) => {
const key = k.toString()
setActiveSasTierCode(key)
const mapping = scandicSasTierMappings.find(([_, tierMapping]) =>
tierMapping.includes(key)
)
if (!mapping) return
const scandicTierCode = mapping[0][0]
setActiveScandicTierCode(scandicTierCode)
}
if (!comparisonContent) return null
return (
<SectionContainer className={styles.comparisonSection}>
<div className={styles.header}>
<SectionHeader title={comparisonContent.title} topTitle={firstItem} />
<Title level="h2">{comparisonContent.title}</Title>
{comparisonContent.preamble && (
<p className={styles.preamble}>{comparisonContent.preamble}</p>
)}
</div>
<div className={styles.comparisonCard}>
<div className={styles.comparisonContainer}>
<div className={styles.comparisonBrand}>
<Title level="h3" textTransform="regular">
{scandic.title}
</Title>
<Select
name="friends-level"
label={scandic.label}
aria-label={scandic.label}
items={scandic.tiers.map((tier) => ({
label: tier.tier_label,
value: tier.tier_code,
}))}
value={activeScandicTierCode}
onSelect={onChangeScandic}
/>
{scandic.read_more_link && (
<ReadMoreLink
href={scandic.read_more_link.href}
title={scandic.read_more_link.title}
/>
)}
</div>
<div className={styles.comparisonIcon}>
<CompareArrowsIcon width={24} height={24} />
</div>
<div className={styles.comparisonBrand}>
<Title level="h3" textTransform="regular">
{sas.title}
</Title>
<Select
name="eb-level"
label={sas.label}
aria-label={sas.label}
items={sas.tiers.map((tier) => ({
label: tier.tier_label,
value: tier.tier_code,
}))}
value={activeSasTierCode}
onSelect={onChangeSas}
/>
{sas.read_more_link && (
<ReadMoreLink
href={sas.read_more_link.href}
title={sas.read_more_link.title}
/>
)}
</div>
<div>
<div className={styles.columnHeaders}>
<Image
alt="Scandic logo"
height={46}
src="/_static/img/scandic-logotype.svg"
priority
width={215}
/>
<Image
alt="SAS logo"
height={46}
src="/_static/img/sas/sas-logotype.svg"
priority
width={215}
/>
<ColumnTitle>{comparisonContent.scandic_column_title}</ColumnTitle>
<ColumnTitle>{comparisonContent.sas_column_title}</ColumnTitle>
</div>
<div className={styles.tierMatchList}>
{comparisonContent.tier_matches.map((tierMatch, i) => (
<TierDetails key={i} tierMatch={tierMatch}>
<JsonToHtml
nodes={tierMatch.content.json?.children}
embeds={[]}
className={styles.htmlContent}
/>
</TierDetails>
))}
</div>
{comparisonContent.cta && (
<div className={styles.ctaContainer}>
<Button
asChild
intent="primary"
size="small"
theme="base"
className={styles.ctaLink}
>
<Link color="none" href={comparisonContent.cta.href}>
{comparisonContent.cta.title}
</Link>
</Button>
</div>
)}
</div>
{comparisonContent.cta?.href && (
<Button theme="primaryLight" asChild className={styles.ctaButton}>
<Link href={comparisonContent.cta.href} color="white">
{comparisonContent.cta.title}
</Link>
</Button>
)}
</SectionContainer>
)
}
function ReadMoreLink({ href, title }: { href: string; title: string }) {
type TierMatch = NonNullable<
SasTierComparisonContent["sasTierComparison"]
>["tier_matches"][number]
function TierDetails({
children,
tierMatch,
}: {
children: React.ReactNode
tierMatch: TierMatch
}) {
return (
<Link
href={href}
variant="underscored"
className={styles.link}
color="peach80"
>
{title}
<ArrowRightIcon color="peach80" />
<details className={styles.tierDetails} name="sas-scandic-tier-match">
<summary className={styles.tierSummary}>
<div className={styles.tierTitles}>
<Body className={styles.tierTitle}>
{tierMatch.scandic_friends_tier_name}
</Body>
<div className={styles.comparisonIcon}>
<CompareArrowsIcon width={16} height={16} />
</div>
<div
style={{
display: "flex",
alignItems: "center",
position: "relative",
}}
>
<Body className={styles.tierTitle}>
{tierMatch.sas_eb_tier_name}
</Body>
<div className={styles.iconWrapper}>
<ChevronDownIcon
className={styles.chevron}
color="burgundy"
width={20}
height={20}
/>
</div>
</div>
</div>
</summary>
<div className={styles.tierContent}>
<div className={styles.tierInfo}>
<div className={styles.tierTitle}>
<Subtitle color="burgundy">{tierMatch.title}</Subtitle>
</div>
<div>{children}</div>
</div>
{tierMatch.link?.href && (
<ReadMoreLink href={tierMatch.link.href}>
{tierMatch.link.title}
</ReadMoreLink>
)}
</div>
</details>
)
}
function ReadMoreLink({
href,
children,
}: {
href: string
children: ReactNode
}) {
return (
<Link href={href} className={styles.link} weight="bold" color="burgundy">
{children}
<ArrowRightIcon color="burgundy" />
</Link>
)
}
function ColumnTitle({ children }: { children?: ReactNode }) {
return (
<div className={styles.columnTitle}>
<Caption type="bold" asChild>
<span>{children}</span>
</Caption>
</div>
)
}