diff --git a/apps/scandic-web/components/ContentCard/contentCard.ts b/apps/scandic-web/components/ContentCard/contentCard.ts deleted file mode 100644 index 915349aad..000000000 --- a/apps/scandic-web/components/ContentCard/contentCard.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { ImageVaultAsset } from "@scandic-hotels/trpc/types/imageVault" - -export interface ContentCardProps { - link?: { - href: string - openInNewTab?: boolean - isExternal?: boolean - } - heading: string - image: ImageVaultAsset - bodyText: string - promoText?: string - className?: string -} diff --git a/apps/scandic-web/components/ContentCard/index.tsx b/apps/scandic-web/components/ContentCard/index.tsx index 4494115c8..8c6dd5ec0 100644 --- a/apps/scandic-web/components/ContentCard/index.tsx +++ b/apps/scandic-web/components/ContentCard/index.tsx @@ -6,7 +6,20 @@ import Subtitle from "@scandic-hotels/design-system/Subtitle" import styles from "./contentCard.module.css" -import type { ContentCardProps } from "./contentCard" +import type { ImageVaultAsset } from "@scandic-hotels/trpc/types/imageVault" + +interface ContentCardProps { + link?: { + href: string + openInNewTab?: boolean + isExternal?: boolean + } + heading: string + image: ImageVaultAsset + bodyText: string + promoText?: string + className?: string +} export default function ContentCard({ heading, diff --git a/apps/scandic-web/components/ContentType/CampaignPage/Hero/hero.module.css b/apps/scandic-web/components/ContentType/CampaignPage/Hero/hero.module.css index 441094b21..20b22f7fc 100644 --- a/apps/scandic-web/components/ContentType/CampaignPage/Hero/hero.module.css +++ b/apps/scandic-web/components/ContentType/CampaignPage/Hero/hero.module.css @@ -69,6 +69,7 @@ border-radius: 0; margin: 0; align-content: center; + padding: var(--Space-x7) var(--Space-x3); } .hero { @@ -76,11 +77,18 @@ display: grid; grid-template-columns: repeat(3, 1fr); overflow: hidden; + min-height: 478px; + height: 100%; + + &.hotelPage { + min-height: 310px; + } } .imageContainer { grid-column: span 2; position: relative; border-radius: 0; + height: 100%; } } diff --git a/apps/scandic-web/components/ContentType/CampaignPage/Hero/index.tsx b/apps/scandic-web/components/ContentType/CampaignPage/Hero/index.tsx index 1feecc0f9..c111bcb1a 100644 --- a/apps/scandic-web/components/ContentType/CampaignPage/Hero/index.tsx +++ b/apps/scandic-web/components/ContentType/CampaignPage/Hero/index.tsx @@ -1,4 +1,6 @@ /* eslint-disable formatjs/no-literal-string-in-jsx */ +import { cx, type VariantProps } from "class-variance-authority" + import ButtonLink from "@scandic-hotels/design-system/ButtonLink" import { Divider } from "@scandic-hotels/design-system/Divider" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" @@ -9,7 +11,14 @@ import { variants } from "./variants" import styles from "./hero.module.css" -import type { HeroProps } from "@/components/ContentType/CampaignPage/Hero/types" +import type { Hero } from "@scandic-hotels/trpc/types/campaignPage" + +interface HeroProps + extends React.HTMLAttributes, + VariantProps, + Omit { + pageType?: "campaign" | "overview" | "hotelPage" +} export default async function CampaignHero({ image, @@ -18,12 +27,17 @@ export default async function CampaignHero({ rate_text, button, theme, + pageType = "campaign", }: HeroProps) { const classNames = variants({ theme, }) + + const visibleBenefits = + pageType === "campaign" ? benefits : benefits.slice(0, 3) + return ( -
+
{image ? (
-

{heading}

+

{heading}

- {benefits?.length ? ( + {visibleBenefits?.length ? (
    - {benefits.map((benefit) => ( + {visibleBenefits.map((benefit) => (
  • , - VariantProps, - Omit {} diff --git a/apps/scandic-web/components/ContentType/HotelPage/Campaigns/CampaignCardList/campaignCardList.module.css b/apps/scandic-web/components/ContentType/HotelPage/Campaigns/CampaignCardList/campaignCardList.module.css new file mode 100644 index 000000000..da9bd005d --- /dev/null +++ b/apps/scandic-web/components/ContentType/HotelPage/Campaigns/CampaignCardList/campaignCardList.module.css @@ -0,0 +1,17 @@ +.list { + list-style: none; + display: grid; + gap: var(--Space-x4) var(--Space-x1); +} + +@media screen and (min-width: 768px) { + .list { + grid-template-columns: repeat(2, 1fr); + } +} + +@media screen and (min-width: 1024px) { + .list { + grid-template-columns: repeat(3, 1fr); + } +} diff --git a/apps/scandic-web/components/ContentType/HotelPage/Campaigns/CampaignCardList/index.tsx b/apps/scandic-web/components/ContentType/HotelPage/Campaigns/CampaignCardList/index.tsx new file mode 100644 index 000000000..3fe792b33 --- /dev/null +++ b/apps/scandic-web/components/ContentType/HotelPage/Campaigns/CampaignCardList/index.tsx @@ -0,0 +1,34 @@ +"use client" + +import { cx } from "class-variance-authority" + +import ContentCard from "@/components/ContentCard" + +import styles from "./campaignCardList.module.css" + +import type { Campaigns } from "@scandic-hotels/trpc/types/campaignPage" + +interface CampaignCardListProps { + campaigns: Campaigns + className?: string +} + +export default function CampaignCardList({ + campaigns, + className, +}: CampaignCardListProps) { + return ( +
      + {campaigns.map(({ id, url, card_content }) => ( +
    • + +
    • + ))} +
    + ) +} diff --git a/apps/scandic-web/components/ContentType/HotelPage/Campaigns/campaigns.module.css b/apps/scandic-web/components/ContentType/HotelPage/Campaigns/campaigns.module.css new file mode 100644 index 000000000..da5f62451 --- /dev/null +++ b/apps/scandic-web/components/ContentType/HotelPage/Campaigns/campaigns.module.css @@ -0,0 +1,35 @@ +.campaignsSection { + display: grid; + gap: var(--Space-x3); + scroll-margin-top: var(--hotel-page-scroll-margin-top); +} + +.intro { + display: grid; + gap: var(--Space-x15); + max-width: var(--max-width-text-block); +} + +.campaigns { + display: grid; + gap: var(--Space-x7); +} + +.heading { + color: var(--Text-Heading); +} + +@media screen and (max-width: 767px) { + .cardList { + display: none; + } +} + +@media screen and (min-width: 768px) { + .campaignsSection { + gap: var(--Space-x5); + } + .carousel { + display: none; + } +} diff --git a/apps/scandic-web/components/ContentType/HotelPage/Campaigns/index.tsx b/apps/scandic-web/components/ContentType/HotelPage/Campaigns/index.tsx new file mode 100644 index 000000000..94bbe4ee4 --- /dev/null +++ b/apps/scandic-web/components/ContentType/HotelPage/Campaigns/index.tsx @@ -0,0 +1,88 @@ +import { Typography } from "@scandic-hotels/design-system/Typography" + +import { Carousel } from "@/components/Carousel" +import { CarouselContent } from "@/components/Carousel/CarouselContent" +import { CarouselDots } from "@/components/Carousel/CarouselDots" +import { CarouselItem } from "@/components/Carousel/CarouselItem" +import { + CarouselNext, + CarouselPrevious, +} from "@/components/Carousel/CarouselNavigation" +import ContentCard from "@/components/ContentCard" +import CampaignHero from "@/components/ContentType/CampaignPage/Hero" +import CampaignCardList from "@/components/ContentType/HotelPage/Campaigns/CampaignCardList" +import { getIntl } from "@/i18n" + +import styles from "./campaigns.module.css" + +import type { Campaigns } from "@scandic-hotels/trpc/types/campaignPage" + +import { HotelHashValues } from "@/types/enums/hotelPage" + +interface HotelCampaignsProps { + heading?: string + preamble?: string + campaigns: Campaigns +} + +export default async function HotelCampaigns({ + heading, + preamble, + campaigns, +}: HotelCampaignsProps) { + const intl = await getIntl() + + const [topCampaign, ...campaignCards] = campaigns + + return ( +
    +
    + +

    + {heading || intl.formatMessage({ defaultMessage: "Offers" })} +

    +
    + {preamble ? ( + +

    {preamble}

    +
    + ) : null} +
    +
    + + {campaignCards.length ? ( +
    + + + + {campaignCards.map(({ id, url, card_content }) => ( + + + + ))} + + + + + +
    + ) : null} +
    +
    + ) +} diff --git a/apps/scandic-web/components/ContentType/HotelPage/index.tsx b/apps/scandic-web/components/ContentType/HotelPage/index.tsx index 32e465fe3..4c43e1f9b 100644 --- a/apps/scandic-web/components/ContentType/HotelPage/index.tsx +++ b/apps/scandic-web/components/ContentType/HotelPage/index.tsx @@ -12,6 +12,7 @@ import { import AccordionSection from "@/components/Blocks/Accordion" import Breadcrumbs from "@/components/Breadcrumbs" +import HotelCampaigns from "@/components/ContentType/HotelPage/Campaigns" import Alert from "@/components/TempDesignSystem/Alert" import BreadcrumbsSkeleton from "@/components/TempDesignSystem/Breadcrumbs/BreadcrumbsSkeleton" import TrackingSDK from "@/components/TrackingSDK" @@ -84,6 +85,7 @@ export default async function HotelPage({ hotelId }: HotelPageProps) { faq, content: { spaPage, activitiesCards }, sectionHeadings, + campaignsBlock, } = hotelPageData const { hotel, restaurants, roomCategories, additionalData } = hotelData const { @@ -120,12 +122,13 @@ export default async function HotelPage({ hotelId }: HotelPageProps) { const pageSections = getPageSectionsData( intl, { - hasWellness: healthFacilities.length > 0, - hasRestaurants: restaurants.length > 0, - hasMeetingRooms: !!(meetingRoomsData && meetingRoomsData.length > 0), hasActivities: activitiesCards.length > 0, hasFAQ: !!(faq && faq.accordions.length > 0), + hasMeetingRooms: !!(meetingRoomsData && meetingRoomsData.length > 0), + hasOffers: !!(campaignsBlock && campaignsBlock.campaigns.length > 0), + hasRestaurants: restaurants.length > 0, hasRooms: roomCategories.length > 0, + hasWellness: healthFacilities.length > 0, }, sectionHeadings ) @@ -223,6 +226,14 @@ export default async function HotelPage({ hotelId }: HotelPageProps) { {faq && faq.accordions.length > 0 && ( )} + + {campaignsBlock ? ( + + ) : null}