feat(SW-217): Split up Card to two (Card and TeaserCard)

This commit is contained in:
Pontus Dreij
2024-09-26 11:07:03 +02:00
parent 6a85cfd19c
commit bb93bdf69c
11 changed files with 200 additions and 59 deletions

View File

@@ -1,10 +1,11 @@
import SectionContainer from "@/components/Section/Container"
import SectionHeader from "@/components/Section/Header"
import Card from "@/components/TempDesignSystem/Card"
import ContentCard from "@/components/TempDesignSystem/ContentCard"
import Grids from "@/components/TempDesignSystem/Grids"
import LoyaltyCard from "@/components/TempDesignSystem/LoyaltyCard"
import TeaserCard from "../TempDesignSystem/TeaserCard"
import type { CardsGridProps } from "@/types/components/blocks/cardsGrid"
import { CardsGridEnum } from "@/types/enums/cardsGrid"
@@ -22,37 +23,38 @@ export default function CardsGrid({
<Grids.Stackable>
{cards_grid.cards.map((card) => {
switch (card.__typename) {
case CardsGridEnum.cards.Card: {
return card.isContentCard ? (
<ContentCard
case CardsGridEnum.cards.Card:
return (
<Card
theme={cards_grid.theme ?? "one"}
key={card.system.uid}
scriptedTopTitle={card.scripted_top_title}
heading={card.heading}
bodyText={card.body_text}
secondaryButton={card.secondaryButton}
primaryButton={card.primaryButton}
/>
)
case CardsGridEnum.cards.TeaserCard:
return (
<TeaserCard
key={card.system.uid}
title={card.heading}
description={card.body_text}
backgroundImage={card.backgroundImage}
primaryButton={card.primaryButton}
secondaryButton={card.secondaryButton}
sidePeekButton={card.sidePeekButton}
image={card.image}
style="default"
title={card.heading}
/>
) : (
<Card
key={card.system.uid}
bodyText={card.body_text}
heading={card.heading}
primaryButton={card.primaryButton}
secondaryButton={card.secondaryButton}
scriptedTopTitle={card.scripted_top_title}
theme={cards_grid.theme || "one"}
/>
)
}
case CardsGridEnum.cards.LoyaltyCard:
return (
<LoyaltyCard
key={card.system.uid}
bodyText={card.body_text}
heading={card.heading}
image={card.image}
heading={card.heading}
bodyText={card.body_text}
link={card.link}
/>
)

View File

@@ -7,32 +7,32 @@ import Link from "@/components/TempDesignSystem/Link"
import Body from "@/components/TempDesignSystem/Text/Body"
import Subtitle from "../Text/Subtitle"
import { contentCardVariants } from "./variants"
import { teaserCardVariants } from "./variants"
import styles from "./contentCard.module.css"
import styles from "./teaserCard.module.css"
import type { ContentCardProps } from "@/types/components/contentCard"
import type { TeaserCardProps } from "@/types/components/teaserCard"
export default function ContentCard({
export default function TeaserCard({
title,
description,
primaryButton,
secondaryButton,
sidePeekButton,
backgroundImage,
image,
style = "default",
alwaysStack = false,
className,
}: ContentCardProps) {
const cardClasses = contentCardVariants({ style, alwaysStack, className })
}: TeaserCardProps) {
const cardClasses = teaserCardVariants({ style, alwaysStack, className })
return (
<div className={cardClasses}>
{backgroundImage && (
<article className={cardClasses}>
{image && (
<div className={styles.imageContainer}>
<Image
src={backgroundImage.url}
alt={backgroundImage.meta?.alt || ""}
src={image.url}
alt={image.meta?.alt || ""}
className={styles.backgroundImage}
width={399}
height={201}
@@ -70,6 +70,7 @@ export default function ContentCard({
<Link
href={primaryButton.href}
target={primaryButton.openInNewTab ? "_blank" : undefined}
color="none"
>
{primaryButton.title}
</Link>
@@ -93,6 +94,6 @@ export default function ContentCard({
</div>
)}
</div>
</div>
</article>
)
}

View File

@@ -1,8 +1,8 @@
import { cva } from "class-variance-authority"
import styles from "./contentCard.module.css"
import styles from "./teaserCard.module.css"
export const contentCardVariants = cva(styles.card, {
export const teaserCardVariants = cva(styles.card, {
variants: {
style: {
default: styles.default,

View File

@@ -9,9 +9,7 @@ fragment CardBlock on Card {
body_text
has_primary_button
has_secondary_button
has_sidepeek_button
heading
is_content_card
scripted_top_title
title
primary_button {
@@ -52,9 +50,6 @@ fragment CardBlock on Card {
}
}
}
sidepeek_button {
call_to_action_text
}
system {
...System
}

View File

@@ -1,8 +1,10 @@
#import "./Card.graphql"
#import "./LoyaltyCard.graphql"
#import "./TeaserCard.graphql"
#import "./Refs/Card.graphql"
#import "./Refs/LoyaltyCard.graphql"
#import "./Refs/TeaserCard.graphql"
fragment CardsGrid_ContentPage on ContentPageBlocksCardsGrid {
cards_grid {
layout
@@ -15,6 +17,7 @@ fragment CardsGrid_ContentPage on ContentPageBlocksCardsGrid {
__typename
...CardBlock
...LoyaltyCardBlock
...TeaserCardBlock
}
}
}
@@ -29,6 +32,7 @@ fragment CardsGrid_ContentPageRefs on ContentPageBlocksCardsGrid {
__typename
...CardBlockRef
...LoyaltyCardBlockRef
...TeaserCardBlockRef
}
}
}

View File

@@ -0,0 +1,36 @@
#import "../../AccountPage/Ref.graphql"
#import "../../ContentPage/Ref.graphql"
#import "../../LoyaltyPage/Ref.graphql"
#import "../../HotelPage/Ref.graphql"
fragment TeaserCardBlockRef on TeaserCard {
secondary_button {
linkConnection {
edges {
node {
__typename
...AccountPageRef
...ContentPageRef
...LoyaltyPageRef
...HotelPageRef
}
}
}
}
primary_button {
linkConnection {
edges {
node {
__typename
...AccountPageRef
...ContentPageRef
...LoyaltyPageRef
...HotelPageRef
}
}
}
}
system {
...System
}
}

View File

@@ -0,0 +1,61 @@
#import "../System.graphql"
#import "../PageLink/AccountPageLink.graphql"
#import "../PageLink/ContentPageLink.graphql"
#import "../PageLink/LoyaltyPageLink.graphql"
#import "../PageLink/HotelPageLink.graphql"
fragment TeaserCardBlock on TeaserCard {
heading
body_text
image
title
has_primary_button
has_secondary_button
has_sidepeek_button
primary_button {
is_contentstack_link
cta_text
open_in_new_tab
external_link {
title
href
}
linkConnection {
edges {
node {
__typename
...LoyaltyPageLink
...ContentPageLink
...AccountPageLink
}
}
}
}
secondary_button {
is_contentstack_link
cta_text
open_in_new_tab
external_link {
title
href
}
linkConnection {
edges {
node {
__typename
...LoyaltyPageLink
...ContentPageLink
...AccountPageLink
...HotelPageLink
}
}
}
}
sidepeek_button {
call_to_action_text
}
system {
...System
}
}

View File

@@ -15,17 +15,10 @@ export const cardBlockSchema = z.object({
body_text: z.string().optional().default(""),
has_primary_button: z.boolean().default(false),
has_secondary_button: z.boolean().default(false),
has_sidepeek_button: z.boolean().optional().default(false),
heading: z.string().optional().default(""),
is_content_card: z.boolean().optional().default(false),
primary_button: buttonSchema,
scripted_top_title: z.string().optional(),
secondary_button: buttonSchema,
sidepeek_button: z
.object({
call_to_action_text: z.string().optional(),
})
.optional(),
system: systemSchema,
title: z.string().optional(),
})
@@ -36,23 +29,53 @@ export function transformCardBlock(card: typeof cardBlockSchema._type) {
backgroundImage: card.background_image,
body_text: card.body_text,
heading: card.heading,
isContentCard: card.is_content_card,
primaryButton: card.has_primary_button ? card.primary_button : undefined,
scripted_top_title: card.scripted_top_title,
secondaryButton: card.has_secondary_button
? card.secondary_button
: undefined,
sidePeekButton:
card.has_sidepeek_button && card.sidepeek_button?.call_to_action_text
? {
title: card.sidepeek_button.call_to_action_text,
}
: undefined,
system: card.system,
title: card.title,
}
}
export const teaserCardBlockSchema = z.object({
__typename: z.literal(CardsGridEnum.cards.TeaserCard),
heading: z.string().default(""),
body_text: z.string().default(""),
image: tempImageVaultAssetSchema,
primary_button: buttonSchema,
secondary_button: buttonSchema,
has_primary_button: z.boolean().default(false),
has_secondary_button: z.boolean().default(false),
has_sidepeek_button: z.boolean().optional().default(false),
side_peek_button: z
.object({
title: z.string().optional().default(""),
})
.optional(),
system: systemSchema,
})
export function transformTeaserCardBlock(
card: typeof teaserCardBlockSchema._type
) {
return {
__typename: card.__typename,
body_text: card.body_text,
heading: card.heading,
primaryButton: card.has_primary_button ? card.primary_button : undefined,
secondaryButton: card.has_secondary_button
? card.secondary_button
: undefined,
sidePeekButton: card.has_sidepeek_button
? card.side_peek_button
: undefined,
image: card.image,
system: card.system,
}
}
const loyaltyCardBlockSchema = z.object({
__typename: z.literal(CardsGridEnum.cards.LoyaltyCard),
body_text: z.string().optional(),
@@ -77,6 +100,7 @@ export const cardsGridSchema = z.object({
node: z.discriminatedUnion("__typename", [
cardBlockSchema,
loyaltyCardBlockSchema,
teaserCardBlockSchema,
]),
})
),
@@ -95,6 +119,8 @@ export const cardsGridSchema = z.object({
cards: data.cardConnection.edges.map((card) => {
if (card.node.__typename === CardsGridEnum.cards.Card) {
return transformCardBlock(card.node)
} else if (card.node.__typename === CardsGridEnum.cards.TeaserCard) {
return transformTeaserCardBlock(card.node)
} else {
return {
__typename: card.node.__typename,
@@ -118,7 +144,11 @@ export const cardBlockRefsSchema = z.object({
system: systemSchema,
})
export function transformCardBlockRefs(card: typeof cardBlockRefsSchema._type) {
export function transformCardBlockRefs(
card:
| typeof cardBlockRefsSchema._type
| typeof teaserCardBlockRefsSchema._type
) {
const cards = [card.system]
if (card.primary_button) {
cards.push(card.primary_button)
@@ -135,6 +165,13 @@ const loyaltyCardBlockRefsSchema = z.object({
system: systemSchema,
})
export const teaserCardBlockRefsSchema = z.object({
__typename: z.literal(CardsGridEnum.cards.TeaserCard),
primary_button: linkConnectionRefsSchema,
secondary_button: linkConnectionRefsSchema,
system: systemSchema,
})
export const cardGridRefsSchema = z.object({
cards_grid: z
.object({
@@ -144,6 +181,7 @@ export const cardGridRefsSchema = z.object({
node: z.discriminatedUnion("__typename", [
cardBlockRefsSchema,
loyaltyCardBlockRefsSchema,
teaserCardBlockRefsSchema,
]),
})
),
@@ -152,7 +190,10 @@ export const cardGridRefsSchema = z.object({
.transform((data) => {
return data.cardConnection.edges
.map(({ node }) => {
if (node.__typename === CardsGridEnum.cards.Card) {
if (
node.__typename === CardsGridEnum.cards.Card ||
node.__typename === CardsGridEnum.cards.TeaserCard
) {
return transformCardBlockRefs(node)
} else {
const loyaltyCards = [node.system]

View File

@@ -1,6 +1,6 @@
import { VariantProps } from "class-variance-authority"
import { contentCardVariants } from "@/components/TempDesignSystem/ContentCard/variants"
import { teaserCardVariants } from "@/components/TempDesignSystem/TeaserCard/variants"
import { ImageVaultAsset } from "@/types/components/imageVault"
import type { CardProps } from "@/components/TempDesignSystem/Card/card"
@@ -9,13 +9,13 @@ interface SidePeekButton {
title: string
}
export interface ContentCardProps
extends VariantProps<typeof contentCardVariants> {
export interface TeaserCardProps
extends VariantProps<typeof teaserCardVariants> {
title: string
description: string
primaryButton?: CardProps["primaryButton"]
secondaryButton?: CardProps["secondaryButton"]
sidePeekButton?: SidePeekButton
backgroundImage?: ImageVaultAsset
image?: ImageVaultAsset
className?: string
}

View File

@@ -2,5 +2,6 @@ export namespace CardsGridEnum {
export const enum cards {
Card = "Card",
LoyaltyCard = "LoyaltyCard",
TeaserCard = "TeaserCard",
}
}