feat(SW-66, SW-348): search functionality and ui

This commit is contained in:
Simon Emanuelsson
2024-08-28 10:47:57 +02:00
parent b9dbcf7d90
commit af850c90e7
437 changed files with 7663 additions and 9881 deletions
@@ -0,0 +1,126 @@
"use client"
import { notFound, useParams } from "next/navigation"
import { useIntl } from "react-intl"
import { Lang } from "@/constants/languages"
import { CheckIcon } from "@/components/Icons"
import {
BestFriend,
CloseFriend,
DearFriend,
GoodFriend,
LoyalFriend,
NewFriend,
TrueFriend,
} from "@/components/Levels"
import BiroScript from "@/components/TempDesignSystem/Text/BiroScript"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Title from "@/components/TempDesignSystem/Text/Title"
import levelsData from "@/data/loyaltyLevels"
import SectionWrapper from "../SectionWrapper"
import styles from "./loyaltyLevels.module.css"
import type { LoyaltyLevelsProps } from "@/types/components/blocks/dynamicContent"
import type { Level, LevelCardProps } from "@/types/components/overviewTable"
export default function LoyaltyLevels({
dynamic_content,
firstItem,
}: LoyaltyLevelsProps) {
const params = useParams()
const lang = params.lang as Lang
const { formatMessage } = useIntl()
const { levels } = levelsData[lang]
return (
<SectionWrapper dynamic_content={dynamic_content} firstItem={firstItem}>
<section className={styles.cardContainer}>
{levels.map((level: Level) => (
<LevelCard
key={level.level}
formatMessage={formatMessage}
lang={lang}
level={level}
/>
))}
</section>
</SectionWrapper>
)
}
function LevelCard({ formatMessage, lang, level }: LevelCardProps) {
let Level = null
switch (level.level) {
case 1:
Level = NewFriend
break
case 2:
Level = GoodFriend
break
case 3:
Level = CloseFriend
break
case 4:
Level = DearFriend
break
case 5:
Level = LoyalFriend
break
case 6:
Level = TrueFriend
break
case 7:
Level = BestFriend
break
default: {
const loyaltyLevel = level.level as never
console.error(`Unsupported loyalty level given: ${loyaltyLevel}`)
notFound()
}
}
const pointsString = `${level.requiredPoints.toLocaleString(lang)} ${formatMessage({ id: "points" })} `
return (
<article className={styles.card}>
<header>
<BiroScript
type="two"
color="primaryLightOnSurfaceAccent"
tilted="large"
>
{formatMessage({ id: "Level" })} {level.level}
</BiroScript>
<Level color="red" />
</header>
<Title textAlign="center" level="h5">
{pointsString}
{level.requiredNights ? (
<span className={styles.redText}>
{formatMessage({ id: "or" })} {level.requiredNights}{" "}
{formatMessage({ id: "nights" })}
</span>
) : null}
</Title>
<div className={styles.textContainer}>
{level.benefits.map((benefit) => (
<Caption
className={styles.levelText}
key={benefit.title}
textAlign="center"
color="textMediumContrast"
>
<CheckIcon
className={styles.checkIcon}
color="primaryLightOnSurfaceAccent"
/>
{benefit.title}
</Caption>
))}
</div>
</article>
)
}
@@ -0,0 +1,55 @@
.cardContainer {
display: grid;
gap: var(--Spacing-x2);
}
.link {
justify-self: center;
}
.card {
background-color: var(--Scandic-Brand-Pale-Peach);
border-radius: var(--Corner-radius-xLarge);
display: grid;
gap: var(--Spacing-x2);
min-height: 280px;
justify-items: center;
padding: var(--Spacing-x5) var(--Spacing-x1);
grid-template-rows: auto auto 1fr;
}
.textContainer {
align-content: flex-start;
display: flex;
gap: var(--Spacing-x-one-and-half);
width: 100%;
flex-wrap: wrap;
justify-content: center;
}
.redText {
color: var(--Base-Text-Accent);
}
.levelText {
margin: 0;
}
.checkIcon {
vertical-align: middle;
}
@media screen and (min-width: 1367px) {
.cardContainer {
display: grid;
grid-template-columns: repeat(12, 1fr);
}
.card:nth-of-type(-n + 3) {
grid-column: span 4;
}
.card:nth-of-type(n + 4) {
grid-column: span 3;
}
}