From bb93bdf69c3180b1e92fe530ec3650bc08b1bd91 Mon Sep 17 00:00:00 2001 From: Pontus Dreij Date: Thu, 26 Sep 2024 11:07:03 +0200 Subject: [PATCH] feat(SW-217): Split up Card to two (Card and TeaserCard) --- components/Blocks/CardsGrid.tsx | 40 +++++----- .../{ContentCard => TeaserCard}/index.tsx | 25 ++++--- .../teaserCard.module.css} | 0 .../{ContentCard => TeaserCard}/variants.ts | 4 +- lib/graphql/Fragments/Blocks/Card.graphql | 5 -- .../Fragments/Blocks/CardsGrid.graphql | 6 +- .../Fragments/Blocks/Refs/TeaserCard.graphql | 36 +++++++++ .../Fragments/Blocks/TeaserCard.graphql | 61 ++++++++++++++++ .../contentstack/schemas/blocks/cardsGrid.ts | 73 +++++++++++++++---- .../{contentCard.ts => teaserCard.ts} | 8 +- types/enums/cardsGrid.ts | 1 + 11 files changed, 200 insertions(+), 59 deletions(-) rename components/TempDesignSystem/{ContentCard => TeaserCard}/index.tsx (82%) rename components/TempDesignSystem/{ContentCard/contentCard.module.css => TeaserCard/teaserCard.module.css} (100%) rename components/TempDesignSystem/{ContentCard => TeaserCard}/variants.ts (75%) create mode 100644 lib/graphql/Fragments/Blocks/Refs/TeaserCard.graphql create mode 100644 lib/graphql/Fragments/Blocks/TeaserCard.graphql rename types/components/{contentCard.ts => teaserCard.ts} (67%) diff --git a/components/Blocks/CardsGrid.tsx b/components/Blocks/CardsGrid.tsx index 60e654c1a..839690de8 100644 --- a/components/Blocks/CardsGrid.tsx +++ b/components/Blocks/CardsGrid.tsx @@ -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({ {cards_grid.cards.map((card) => { switch (card.__typename) { - case CardsGridEnum.cards.Card: { - return card.isContentCard ? ( - + ) + case CardsGridEnum.cards.TeaserCard: + return ( + - ) : ( - ) - } case CardsGridEnum.cards.LoyaltyCard: return ( ) diff --git a/components/TempDesignSystem/ContentCard/index.tsx b/components/TempDesignSystem/TeaserCard/index.tsx similarity index 82% rename from components/TempDesignSystem/ContentCard/index.tsx rename to components/TempDesignSystem/TeaserCard/index.tsx index bdde9de6f..a51c04eed 100644 --- a/components/TempDesignSystem/ContentCard/index.tsx +++ b/components/TempDesignSystem/TeaserCard/index.tsx @@ -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 ( -
- {backgroundImage && ( +
+ {image && (
{backgroundImage.meta?.alt {primaryButton.title} @@ -93,6 +94,6 @@ export default function ContentCard({
)}
- + ) } diff --git a/components/TempDesignSystem/ContentCard/contentCard.module.css b/components/TempDesignSystem/TeaserCard/teaserCard.module.css similarity index 100% rename from components/TempDesignSystem/ContentCard/contentCard.module.css rename to components/TempDesignSystem/TeaserCard/teaserCard.module.css diff --git a/components/TempDesignSystem/ContentCard/variants.ts b/components/TempDesignSystem/TeaserCard/variants.ts similarity index 75% rename from components/TempDesignSystem/ContentCard/variants.ts rename to components/TempDesignSystem/TeaserCard/variants.ts index a9cc2b67f..b6ca7744d 100644 --- a/components/TempDesignSystem/ContentCard/variants.ts +++ b/components/TempDesignSystem/TeaserCard/variants.ts @@ -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, diff --git a/lib/graphql/Fragments/Blocks/Card.graphql b/lib/graphql/Fragments/Blocks/Card.graphql index 2adc5a75b..39aa63a49 100644 --- a/lib/graphql/Fragments/Blocks/Card.graphql +++ b/lib/graphql/Fragments/Blocks/Card.graphql @@ -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 } diff --git a/lib/graphql/Fragments/Blocks/CardsGrid.graphql b/lib/graphql/Fragments/Blocks/CardsGrid.graphql index 5697bba22..ce4eb3886 100644 --- a/lib/graphql/Fragments/Blocks/CardsGrid.graphql +++ b/lib/graphql/Fragments/Blocks/CardsGrid.graphql @@ -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 } } } diff --git a/lib/graphql/Fragments/Blocks/Refs/TeaserCard.graphql b/lib/graphql/Fragments/Blocks/Refs/TeaserCard.graphql new file mode 100644 index 000000000..c922f8adc --- /dev/null +++ b/lib/graphql/Fragments/Blocks/Refs/TeaserCard.graphql @@ -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 + } +} diff --git a/lib/graphql/Fragments/Blocks/TeaserCard.graphql b/lib/graphql/Fragments/Blocks/TeaserCard.graphql new file mode 100644 index 000000000..5b333797c --- /dev/null +++ b/lib/graphql/Fragments/Blocks/TeaserCard.graphql @@ -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 + } +} diff --git a/server/routers/contentstack/schemas/blocks/cardsGrid.ts b/server/routers/contentstack/schemas/blocks/cardsGrid.ts index d9c39bcc5..a73eac737 100644 --- a/server/routers/contentstack/schemas/blocks/cardsGrid.ts +++ b/server/routers/contentstack/schemas/blocks/cardsGrid.ts @@ -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] diff --git a/types/components/contentCard.ts b/types/components/teaserCard.ts similarity index 67% rename from types/components/contentCard.ts rename to types/components/teaserCard.ts index 8c904a2e3..4ca7f56f1 100644 --- a/types/components/contentCard.ts +++ b/types/components/teaserCard.ts @@ -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 { +export interface TeaserCardProps + extends VariantProps { title: string description: string primaryButton?: CardProps["primaryButton"] secondaryButton?: CardProps["secondaryButton"] sidePeekButton?: SidePeekButton - backgroundImage?: ImageVaultAsset + image?: ImageVaultAsset className?: string } diff --git a/types/enums/cardsGrid.ts b/types/enums/cardsGrid.ts index c6b6b2983..3bb96c684 100644 --- a/types/enums/cardsGrid.ts +++ b/types/enums/cardsGrid.ts @@ -2,5 +2,6 @@ export namespace CardsGridEnum { export const enum cards { Card = "Card", LoyaltyCard = "LoyaltyCard", + TeaserCard = "TeaserCard", } }