diff --git a/components/Loyalty/Blocks/DynamicContent/OverviewTable/BenefitCard/benefitCard.module.css b/components/Loyalty/Blocks/DynamicContent/OverviewTable/BenefitCard/benefitCard.module.css new file mode 100644 index 000000000..cd6e21f5a --- /dev/null +++ b/components/Loyalty/Blocks/DynamicContent/OverviewTable/BenefitCard/benefitCard.module.css @@ -0,0 +1,78 @@ +.benefitCard { + background-color: var(--Main-Grey-White); + border: 1px solid var(--Base-Border-Subtle); + border-radius: var(--Corner-radius-Small); + color: var(--Main-Brand-Burgundy); + padding: 0 var(--Spacing-x2); + z-index: 2; + grid-column: 1/3; +} + +.benefitValueContainer { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--Spacing-x-one-and-half); +} + +.benefitValue { + background-color: var(--Main-Brand-Burgundy); + border-radius: var(--Corner-radius-Medium); + color: var(--Base-Surface-Primary-Hover-alt, #fff); + font-size: var(--typography-Footnote-Regular-fontSize); + padding: var(--Spacing-x-half) var(--Spacing-x1); +} + +.benefitValueDetails { + font-size: var(--typography-Footnote-Regular-fontSize); + text-align: center; +} + +.benefitCardHeader { + display: grid; + grid-template-columns: 1fr auto; +} + +.benefitCardDescription { + line-height: 150%; +} + +.benefitInfo { + border-bottom: 1px solid var(--Base-Border-Subtle); + padding: var(--Spacing-x-one-and-half) 0; +} + +.benefitComparison { + display: grid; + grid-template-columns: 1fr 1fr; +} + +.comparisonItem { + display: flex; + justify-content: center; + align-items: center; + padding: var(--Spacing-x-one-and-half); +} + +.details[open] .chevron { + transform: rotate(180deg); +} + +.chevron { + display: flex; + align-items: center; +} + +.summary::-webkit-details-marker { + display: none; +} + +.summary { + list-style: none; +} + +@media screen and (min-width: 950px) { + .benefitComparison { + grid-template-columns: 1fr 1fr 1fr; + } +} diff --git a/components/Loyalty/Blocks/DynamicContent/OverviewTable/BenefitCard.tsx b/components/Loyalty/Blocks/DynamicContent/OverviewTable/BenefitCard/index.tsx similarity index 97% rename from components/Loyalty/Blocks/DynamicContent/OverviewTable/BenefitCard.tsx rename to components/Loyalty/Blocks/DynamicContent/OverviewTable/BenefitCard/index.tsx index 17e1b90a7..0097f2562 100644 --- a/components/Loyalty/Blocks/DynamicContent/OverviewTable/BenefitCard.tsx +++ b/components/Loyalty/Blocks/DynamicContent/OverviewTable/BenefitCard/index.tsx @@ -3,7 +3,7 @@ import { ChevronDown, Minus } from "react-feather" import CheckCircle from "@/components/Icons/CheckCircle" import Title from "@/components/Title" -import styles from "./overviewTable.module.css" +import styles from "./benefitCard.module.css" import { BenefitCardProps, diff --git a/components/Loyalty/Blocks/DynamicContent/OverviewTable/BenefitList/benefitList.module.css b/components/Loyalty/Blocks/DynamicContent/OverviewTable/BenefitList/benefitList.module.css new file mode 100644 index 000000000..e8f910fe8 --- /dev/null +++ b/components/Loyalty/Blocks/DynamicContent/OverviewTable/BenefitList/benefitList.module.css @@ -0,0 +1,49 @@ +.benefitCardWrapper { + position: relative; + display: grid; + grid-template-columns: 1fr 1fr; + grid-column: 1/3; + padding: var(--Spacing-x2); + padding-top: 0; +} + +.firstColumn { + background-color: var(--Main-Brand-PalePeach); + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 50%; + z-index: 1; +} + +.secondColumn { + background-color: var(--Base-Background-Normal); + position: absolute; + position: absolute; + top: 0; + bottom: 0; + margin-bottom: calc(var(--Spacing-x2) * -1); + left: 50%; + right: 0; + z-index: 1; + border-top-left-radius: var(--Corner-radius-Medium); +} + +@media screen and (min-width: 950px) { + .benefitCardWrapper { + grid-column: 1/4; + } + + .firstColumn { + width: calc((100%) / 3); + right: calc(100% / 3 * 2); + margin-left: 0; + } + + .secondColumn { + width: calc(100% / 3); + left: calc(100% / 3); + right: calc(100% / 3); + } +} diff --git a/components/Loyalty/Blocks/DynamicContent/OverviewTable/BenefitList/index.tsx b/components/Loyalty/Blocks/DynamicContent/OverviewTable/BenefitList/index.tsx new file mode 100644 index 000000000..d5f6a6a22 --- /dev/null +++ b/components/Loyalty/Blocks/DynamicContent/OverviewTable/BenefitList/index.tsx @@ -0,0 +1,43 @@ +import BenefitCard from "../BenefitCard" + +import styles from "./benefitList.module.css" + +import { + BenefitListProps, + ComparisonLevel, +} from "@/types/components/loyalty/blocks" + +export default function BenefitList({ levels }: BenefitListProps) { + const highestTier = levels.reduce( + (acc: ComparisonLevel | null, level: ComparisonLevel) => { + if (!acc) { + return level + } + return level.tier > acc.tier ? level : acc + }, + null + ) + + return highestTier?.benefits + .filter((benefit) => benefit.unlocked) + .map((benefit, idx) => { + const levelBenefits = levels.map((level) => level.benefits[idx]) + return ( +
+
+
+ { + return { + value: benefit.value, + unlocked: benefit.unlocked, + valueDetails: benefit.valueDetails, + } + })} + /> +
+ ) + }) +} diff --git a/components/Loyalty/Blocks/DynamicContent/OverviewTable/LevelSummary/index.tsx b/components/Loyalty/Blocks/DynamicContent/OverviewTable/LevelSummary/index.tsx new file mode 100644 index 000000000..b270da342 --- /dev/null +++ b/components/Loyalty/Blocks/DynamicContent/OverviewTable/LevelSummary/index.tsx @@ -0,0 +1,15 @@ +import Image from "@/components/Image" + +import styles from "./levelSummary.module.css" + +import { LevelSummaryProps } from "@/types/components/loyalty/blocks" + +export default function LevelSummary({ level }: LevelSummaryProps) { + return ( +
+ {level.name} + {level.requirement} +

{level.description}

+
+ ) +} diff --git a/components/Loyalty/Blocks/DynamicContent/OverviewTable/LevelSummary/levelSummary.module.css b/components/Loyalty/Blocks/DynamicContent/OverviewTable/LevelSummary/levelSummary.module.css new file mode 100644 index 000000000..ea7a4938f --- /dev/null +++ b/components/Loyalty/Blocks/DynamicContent/OverviewTable/LevelSummary/levelSummary.module.css @@ -0,0 +1,20 @@ +.levelSummary { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--Spacing-x2); +} + +.levelRequirements { + background-color: var(--Main-Brand-Burgundy); + border-radius: var(--Corner-radius-Medium); + color: #f7e1d5; + padding: var(--Spacing-x-half) var(--Spacing-x1); +} + +.levelSummaryText { + color: var(--Main-Brand-Burgundy); + font-size: var(--typography-Footnote-Regular-fontSize); + line-height: var(--typography-Body-Regular-lineHeight); + margin: 0; +} diff --git a/components/Loyalty/Blocks/DynamicContent/OverviewTable/Title/index.tsx b/components/Loyalty/Blocks/DynamicContent/OverviewTable/Title/index.tsx new file mode 100644 index 000000000..c22192ef2 --- /dev/null +++ b/components/Loyalty/Blocks/DynamicContent/OverviewTable/Title/index.tsx @@ -0,0 +1,20 @@ +import { Fragment } from "react" + +import Title from "@/components/Title" + +import styles from "./overviewTableTitle.module.css" + +import { OverviewTableTitleProps } from "@/types/components/loyalty/blocks" + +export default function OverviewTableTitle({ texts }: OverviewTableTitleProps) { + return ( + + {texts.map(({ text, highlight }, idx) => ( + <Fragment key={idx}> + <span className={highlight ? styles.highlight : ""}>{text}</span> + {idx < texts.length - 1 && " "} + </Fragment> + ))} + + ) +} diff --git a/components/Loyalty/Blocks/DynamicContent/OverviewTable/Title/overviewTableTitle.module.css b/components/Loyalty/Blocks/DynamicContent/OverviewTable/Title/overviewTableTitle.module.css new file mode 100644 index 000000000..50ab7016d --- /dev/null +++ b/components/Loyalty/Blocks/DynamicContent/OverviewTable/Title/overviewTableTitle.module.css @@ -0,0 +1,3 @@ +.highlight { + color: var(--Base-Text-Primary-Accent); +} diff --git a/components/Loyalty/Blocks/DynamicContent/OverviewTable/index.tsx b/components/Loyalty/Blocks/DynamicContent/OverviewTable/index.tsx index 8a34e5605..9ce98a557 100644 --- a/components/Loyalty/Blocks/DynamicContent/OverviewTable/index.tsx +++ b/components/Loyalty/Blocks/DynamicContent/OverviewTable/index.tsx @@ -1,25 +1,21 @@ "use client" -import { Dispatch, Fragment, SetStateAction, useState } from "react" +import { Dispatch, SetStateAction, useState } from "react" import { type Key } from "react-aria-components" import { Lang } from "@/constants/languages" import { _ } from "@/lib/translation" -import Image from "@/components/Image" import Select from "@/components/TempDesignSystem/Form/Select" -import Title from "@/components/Title" import levelsData from "./data/EN.json" -import BenefitCard from "./BenefitCard" +import BenefitList from "./BenefitList" +import LevelSummary from "./LevelSummary" +import OverviewTableTitle from "./Title" import styles from "./overviewTable.module.css" -import { - ComparisonLevel, - LevelSummaryProps, - OverviewTableTitleProps, -} from "@/types/components/loyalty/blocks" +import { ComparisonLevel } from "@/types/components/loyalty/blocks" // These should ultimately be fetched from Contentstack const titleTranslations = { @@ -50,60 +46,12 @@ const titleTranslations = { ], } -function OverviewTableTitle({ texts }: OverviewTableTitleProps) { - return ( - - {texts.map(({ text, highlight }, idx) => ( - <Fragment key={idx}> - <span className={highlight ? styles.highlight : ""}>{text}</span> - {idx < texts.length - 1 && " "} - </Fragment> - ))} - - ) -} - function getLevelByTier(tier: number) { return levelsData.levels.find( (level) => level.tier === tier ) as ComparisonLevel } -function createComparison(levels: ComparisonLevel[]) { - const highestTier = levels.reduce( - (acc: ComparisonLevel | null, level: ComparisonLevel) => { - if (!acc) { - return level - } - return level.tier > acc.tier ? level : acc - }, - null - ) - - return highestTier?.benefits - .filter((benefit) => benefit.unlocked) - .map((benefit, idx) => { - const levelBenefits = levels.map((level) => level.benefits[idx]) - return ( -
-
-
- { - return { - value: benefit.value, - unlocked: benefit.unlocked, - valueDetails: benefit.valueDetails, - } - })} - /> -
- ) - }) -} - export default function OverviewTable() { const [selectedLevelA, setSelectedLevelA] = useState(getLevelByTier(1)) const [selectedLevelB, setSelectedLevelB] = useState(getLevelByTier(2)) @@ -173,7 +121,7 @@ export default function OverviewTable() { />
- {createComparison([selectedLevelA, selectedLevelB])} +
@@ -226,19 +174,11 @@ export default function OverviewTable() { />
- {createComparison([selectedLevelA, selectedLevelB, selectedLevelC])} +
) } - -function LevelSummary({ level }: LevelSummaryProps) { - return ( -
- {level.name} - {level.requirement} -

{level.description}

-
- ) -} diff --git a/components/Loyalty/Blocks/DynamicContent/OverviewTable/overviewTable.module.css b/components/Loyalty/Blocks/DynamicContent/OverviewTable/overviewTable.module.css index 1d269dbda..841f03130 100644 --- a/components/Loyalty/Blocks/DynamicContent/OverviewTable/overviewTable.module.css +++ b/components/Loyalty/Blocks/DynamicContent/OverviewTable/overviewTable.module.css @@ -18,10 +18,6 @@ gap: var(--Spacing-x3); } -.highlight { - color: var(--Base-Text-Primary-Accent); -} - .preamble { color: var(--Base-Text-Primary-High-contrast); font-size: var(--typography-Body-Regular-fontSize); @@ -34,17 +30,10 @@ position: relative; } -.mobileColumns { - display: flex; - flex-direction: column; - display: none; - margin: 0 calc(var(--Spacing-x2) * -1); - position: relative; -} - .mobileColumns { display: grid; grid-template-columns: 1fr 1fr; + margin: 0 calc(var(--Spacing-x2) * -1); padding-top: var(--Spacing-x2); position: relative; } @@ -74,7 +63,6 @@ } .columnHeader:nth-child(2):has(+ .columnHeader) { - /* margin: 0; */ padding-left: var(--Spacing-x1); padding-right: var(--Spacing-x1); } @@ -83,160 +71,6 @@ padding-left: var(--Spacing-x1); } -.selectContainer { - position: relative; - width: 100%; -} - -.selectLabel { - color: var(--Base-Text-UI-Placeholder); - position: absolute; - top: 7px; - left: var(--Spacing-x2); -} - -.select { - appearance: none; - border: 1px solid var(--Base-Input-Controls-Border-Normal, #b8a79a); - border-radius: var(--Corner-radius-Medium); - padding: var(--Spacing-x2); - width: 100%; -} - -.selectChevron { - display: flex; - align-items: center; - position: absolute; - right: var(--Spacing-x2); - bottom: var(--Spacing-x2); -} - -.firstColumn { - background-color: var(--Main-Brand-PalePeach); - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 50%; - z-index: 1; -} - -.secondColumn { - background-color: var(--Base-Background-Normal); - position: absolute; - position: absolute; - top: 0; - bottom: 0; - margin-bottom: calc(var(--Spacing-x2) * -1); - left: 50%; - right: 0; - z-index: 1; - border-top-left-radius: var(--Corner-radius-Medium); -} - -.levelSummary { - display: flex; - flex-direction: column; - align-items: center; - gap: var(--Spacing-x2); -} - -.levelRequirements { - background-color: var(--Main-Brand-Burgundy); - border-radius: var(--Corner-radius-Medium); - color: #f7e1d5; - padding: var(--Spacing-x-half) var(--Spacing-x1); -} - -.levelSummaryText { - color: var(--Main-Brand-Burgundy); - font-size: var(--typography-Footnote-Regular-fontSize); - line-height: var(--typography-Body-Regular-lineHeight); - margin: 0; -} - -.benefitCardWrapper { - position: relative; - display: grid; - grid-template-columns: 1fr 1fr; - grid-column: 1/3; - padding: var(--Spacing-x2); - padding-top: 0; -} - -.benefitCard { - background-color: var(--Main-Grey-White); - border: 1px solid var(--Base-Border-Subtle); - border-radius: var(--Corner-radius-Small); - color: var(--Main-Brand-Burgundy); - padding: 0 var(--Spacing-x2); - z-index: 2; - grid-column: 1/3; -} - -.details[open] .chevron { - transform: rotate(180deg); -} - -.chevron { - display: flex; - align-items: center; -} - -.summary::-webkit-details-marker { - display: none; -} - -.summary { - list-style: none; -} - -.benefitCardHeader { - display: grid; - grid-template-columns: 1fr auto; -} - -.benefitCardDescription { - line-height: 150%; -} - -.benefitInfo { - border-bottom: 1px solid var(--Base-Border-Subtle); - padding: var(--Spacing-x-one-and-half) 0; -} - -.benefitComparison { - display: grid; - grid-template-columns: 1fr 1fr; -} - -.comparisonItem { - display: flex; - justify-content: center; - align-items: center; - padding: var(--Spacing-x-one-and-half); -} - -.benefitValueContainer { - display: flex; - flex-direction: column; - align-items: center; - gap: var(--Spacing-x-one-and-half); -} - -.benefitValue { - background-color: var(--Main-Brand-Burgundy); - border-radius: var(--Corner-radius-Medium); - color: var(--Base-Surface-Primary-Hover-alt, #fff); - font-size: var(--typography-Footnote-Regular-fontSize); - padding: var(--Spacing-x-half) var(--Spacing-x1); -} - -.benefitValueDetails { - font-size: var(--typography-Footnote-Regular-fontSize); - text-align: center; -} - @media screen and (min-width: 950px) { .container { margin: 0 calc(var(--Spacing-x3) * -1); @@ -245,24 +79,6 @@ display: none; } - .firstColumn { - width: calc((100%) / 3); - right: calc(100% / 3 * 2); - margin-left: 0; - } - - .secondColumn { - width: calc(100% / 3); - left: calc(100% / 3); - right: calc(100% / 3); - } - - .thirdColumn { - width: calc(100% / 3); - left: calc(100% / 3 * 2); - right: 0; - } - .columnHeaderContainer { grid-template-columns: 1fr 1fr 1fr; } @@ -275,11 +91,4 @@ grid-template-columns: 1fr 1fr 1fr; margin: 0 calc(var(--Spacing-x2) * -1); } - - .benefitCardWrapper { - grid-column: 1/4; - } - .benefitComparison { - grid-template-columns: 1fr 1fr 1fr; - } } diff --git a/types/components/loyalty/blocks.ts b/types/components/loyalty/blocks.ts index 43abec1a3..1c63cc0e8 100644 --- a/types/components/loyalty/blocks.ts +++ b/types/components/loyalty/blocks.ts @@ -86,3 +86,7 @@ type BenefitValueInformation = { export type BenefitValueProps = { benefit: BenefitValueInformation } + +export type BenefitListProps = { + levels: ComparisonLevel[] +}