Merged in feat/LOY-419-highlight-promo-campaigns (pull request #3308)
feat(LOY-419): add promo campaigns to Campaign Overview Page * feat(LOY-419): add promo campaigns as top campaign and all campaigns * refactor(LOY-419) Approved-by: Chuma Mcphoy (We Ahead)
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
import { ContentEnum } from "@scandic-hotels/trpc/types/content"
|
||||||
|
|
||||||
import CampaignHotelListing from "@/components/Blocks/CampaignHotelListing"
|
import CampaignHotelListing from "@/components/Blocks/CampaignHotelListing"
|
||||||
import CampaignHero from "@/components/ContentType/CampaignPage/Hero"
|
import CampaignHero from "@/components/ContentType/CampaignPage/Hero"
|
||||||
@@ -13,10 +14,12 @@ interface TopCampaignProps {
|
|||||||
topCampaign: CampaignOverviewPageData["topCampaign"]
|
topCampaign: CampaignOverviewPageData["topCampaign"]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function TopCampaign({ topCampaign }: TopCampaignProps) {
|
export async function TopCampaign({ topCampaign }: TopCampaignProps) {
|
||||||
const lang = await getLang()
|
const lang = await getLang()
|
||||||
const intl = await getIntl()
|
const intl = await getIntl()
|
||||||
|
|
||||||
const { campaign, heading } = topCampaign
|
const { campaign, heading } = topCampaign
|
||||||
|
|
||||||
const buttonData = {
|
const buttonData = {
|
||||||
cta: intl.formatMessage({
|
cta: intl.formatMessage({
|
||||||
id: "campaign.exploreTheOffer",
|
id: "campaign.exploreTheOffer",
|
||||||
@@ -25,6 +28,41 @@ export default async function TopCampaign({ topCampaign }: TopCampaignProps) {
|
|||||||
url: `/${lang}${campaign.url}`,
|
url: `/${lang}${campaign.url}`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function CampaignContent() {
|
||||||
|
switch (campaign.typename) {
|
||||||
|
case ContentEnum.blocks.CampaignPage:
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<CampaignHero {...campaign.hero} button={buttonData} />
|
||||||
|
<CampaignHotelListing
|
||||||
|
heading={
|
||||||
|
campaign.hotel_listing.heading ||
|
||||||
|
intl.formatMessage({
|
||||||
|
id: "campaignPage.hotelsIncludedInOffer",
|
||||||
|
defaultMessage: "Hotels included in this offer",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
hotelIds={campaign.hotel_listing.hotelIds}
|
||||||
|
visibleCountMobile={3}
|
||||||
|
visibleCountDesktop={3}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
case ContentEnum.blocks.PromoCampaignPage:
|
||||||
|
if (!campaign.hero) return null
|
||||||
|
return (
|
||||||
|
<CampaignHero
|
||||||
|
{...campaign.hero}
|
||||||
|
button={buttonData}
|
||||||
|
rate_text={null}
|
||||||
|
campaign_text={null}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
default:
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={styles.topCampaign}>
|
<section className={styles.topCampaign}>
|
||||||
{heading ? (
|
{heading ? (
|
||||||
@@ -32,19 +70,7 @@ export default async function TopCampaign({ topCampaign }: TopCampaignProps) {
|
|||||||
<h2 className={styles.heading}>{heading}</h2>
|
<h2 className={styles.heading}>{heading}</h2>
|
||||||
</Typography>
|
</Typography>
|
||||||
) : null}
|
) : null}
|
||||||
<CampaignHero {...campaign.hero} button={buttonData} />
|
<CampaignContent />
|
||||||
<CampaignHotelListing
|
|
||||||
heading={
|
|
||||||
campaign.hotel_listing.heading ||
|
|
||||||
intl.formatMessage({
|
|
||||||
id: "campaignPage.hotelsIncludedInOffer",
|
|
||||||
defaultMessage: "Hotels included in this offer",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
hotelIds={campaign.hotel_listing.hotelIds}
|
|
||||||
visibleCountMobile={3}
|
|
||||||
visibleCountDesktop={3}
|
|
||||||
/>
|
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { TrackingSDK } from "@scandic-hotels/tracking/TrackingSDK"
|
|||||||
|
|
||||||
import { getCampaignOverviewPage } from "@/lib/trpc/memoizedRequests"
|
import { getCampaignOverviewPage } from "@/lib/trpc/memoizedRequests"
|
||||||
|
|
||||||
import TopCampaign from "@/components/ContentType/CampaignOverviewPage/TopCampaign"
|
import { TopCampaign } from "@/components/ContentType/CampaignOverviewPage/TopCampaign"
|
||||||
import LinkChips from "@/components/TempDesignSystem/LinkChips"
|
import LinkChips from "@/components/TempDesignSystem/LinkChips"
|
||||||
|
|
||||||
import Blocks from "./Blocks"
|
import Blocks from "./Blocks"
|
||||||
@@ -23,7 +23,6 @@ export default async function CampaignOverviewPage() {
|
|||||||
|
|
||||||
const { campaign_overview_page, tracking } = pageData
|
const { campaign_overview_page, tracking } = pageData
|
||||||
const { header, topCampaign, blocks } = campaign_overview_page
|
const { header, topCampaign, blocks } = campaign_overview_page
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Suspense fallback={<CampaignOverviewPageSkeleton />}>
|
<Suspense fallback={<CampaignOverviewPageSkeleton />}>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const config = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
theme: "Peach",
|
theme: "Burgundy",
|
||||||
},
|
},
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { gql } from "graphql-tag"
|
import { gql } from "graphql-tag"
|
||||||
|
|
||||||
import { CampaignPageRef } from "../CampaignPage/Ref.graphql"
|
import { CampaignPageRef } from "../CampaignPage/Ref.graphql"
|
||||||
|
import { PromoCampaignPageRef } from "../PromoCampaignPage/Ref.graphql"
|
||||||
|
|
||||||
export const AllCampaigns = gql`
|
export const AllCampaigns = gql`
|
||||||
fragment AllCampaigns on CampaignOverviewPageBlocksAllCampaigns {
|
fragment AllCampaigns on CampaignOverviewPageBlocksAllCampaigns {
|
||||||
@@ -21,6 +22,17 @@ export const AllCampaigns = gql`
|
|||||||
locale
|
locale
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
... on PromoCampaignPage {
|
||||||
|
url
|
||||||
|
card_content {
|
||||||
|
heading
|
||||||
|
image
|
||||||
|
text
|
||||||
|
}
|
||||||
|
system {
|
||||||
|
locale
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,10 +48,12 @@ export const AllCampaignsRefs = gql`
|
|||||||
node {
|
node {
|
||||||
__typename
|
__typename
|
||||||
...CampaignPageRef
|
...CampaignPageRef
|
||||||
|
...PromoCampaignPageRef
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
${CampaignPageRef}
|
${CampaignPageRef}
|
||||||
|
${PromoCampaignPageRef}
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -30,3 +30,23 @@ export const TopCampaignRef = gql`
|
|||||||
}
|
}
|
||||||
${System}
|
${System}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
export const TopPromoCampaign = gql`
|
||||||
|
fragment TopPromoCampaign on PromoCampaignPage {
|
||||||
|
url
|
||||||
|
promo_hero {
|
||||||
|
image
|
||||||
|
heading
|
||||||
|
benefits
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export const TopPromoCampaignRef = gql`
|
||||||
|
fragment TopPromoCampaignRef on PromoCampaignPage {
|
||||||
|
system {
|
||||||
|
...System
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${System}
|
||||||
|
`
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import {
|
|||||||
import {
|
import {
|
||||||
TopCampaign,
|
TopCampaign,
|
||||||
TopCampaignRef,
|
TopCampaignRef,
|
||||||
|
TopPromoCampaign,
|
||||||
|
TopPromoCampaignRef,
|
||||||
} from "../../Fragments/CampaignOverviewPage/TopCampaign.graphql"
|
} from "../../Fragments/CampaignOverviewPage/TopCampaign.graphql"
|
||||||
import { System } from "../../Fragments/System.graphql"
|
import { System } from "../../Fragments/System.graphql"
|
||||||
|
|
||||||
@@ -33,7 +35,9 @@ export const GetCampaignOverviewPage = gql`
|
|||||||
campaignConnection {
|
campaignConnection {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
|
__typename
|
||||||
...TopCampaign
|
...TopCampaign
|
||||||
|
...TopPromoCampaign
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,6 +61,7 @@ export const GetCampaignOverviewPage = gql`
|
|||||||
${System}
|
${System}
|
||||||
${NavigationLinks_CampaignOverviewPage}
|
${NavigationLinks_CampaignOverviewPage}
|
||||||
${TopCampaign}
|
${TopCampaign}
|
||||||
|
${TopPromoCampaign}
|
||||||
${AllCampaigns}
|
${AllCampaigns}
|
||||||
${CarouselCards_CampaignOverviewPage}
|
${CarouselCards_CampaignOverviewPage}
|
||||||
${HotelListing_CampaignOverviewPage}
|
${HotelListing_CampaignOverviewPage}
|
||||||
@@ -73,6 +78,7 @@ export const GetCampaignOverviewPageRefs = gql`
|
|||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
...TopCampaignRef
|
...TopCampaignRef
|
||||||
|
...TopPromoCampaignRef
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,6 +96,7 @@ export const GetCampaignOverviewPageRefs = gql`
|
|||||||
${System}
|
${System}
|
||||||
${NavigationLinksRef_CampaignOverviewPage}
|
${NavigationLinksRef_CampaignOverviewPage}
|
||||||
${TopCampaignRef}
|
${TopCampaignRef}
|
||||||
|
${TopPromoCampaignRef}
|
||||||
${CarouselCards_CampaignOverviewPageRefs}
|
${CarouselCards_CampaignOverviewPageRefs}
|
||||||
${AllCampaignsRefs}
|
${AllCampaignsRefs}
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { CampaignOverviewPageEnum } from "../../../types/campaignOverviewPageEnum"
|
import { CampaignOverviewPageEnum } from "../../../types/campaignOverviewPageEnum"
|
||||||
import { CampaignPageEnum } from "../../../types/campaignPage"
|
import { CampaignPageEnum } from "../../../types/campaignPage"
|
||||||
|
import { ContentEnum } from "../../../types/content"
|
||||||
import { discriminatedUnionArray } from "../../../utils/discriminatedUnion"
|
import { discriminatedUnionArray } from "../../../utils/discriminatedUnion"
|
||||||
import {
|
import {
|
||||||
campaignPageHotelListing,
|
campaignPageHotelListing,
|
||||||
heroSchema,
|
heroSchema,
|
||||||
includedHotelsSchema,
|
includedHotelsSchema,
|
||||||
} from "../campaignPage/output"
|
} from "../campaignPage/output"
|
||||||
|
import { promoHeroSchema } from "../promoCampaignPage/output"
|
||||||
import {
|
import {
|
||||||
allCampaignsRefsSchema,
|
allCampaignsRefsSchema,
|
||||||
allCampaignsSchema,
|
allCampaignsSchema,
|
||||||
@@ -43,28 +45,69 @@ export const campaignPageBlocksSchema = z.discriminatedUnion("__typename", [
|
|||||||
campaignPageHotelListing,
|
campaignPageHotelListing,
|
||||||
])
|
])
|
||||||
|
|
||||||
|
const topCampaign = z.object({
|
||||||
|
typename: z
|
||||||
|
.literal(ContentEnum.blocks.CampaignPage)
|
||||||
|
.optional()
|
||||||
|
.default(ContentEnum.blocks.CampaignPage),
|
||||||
|
hero: heroSchema,
|
||||||
|
included_hotels: includedHotelsSchema,
|
||||||
|
blocks: discriminatedUnionArray(campaignPageBlocksSchema.options),
|
||||||
|
url: z.string(),
|
||||||
|
})
|
||||||
|
|
||||||
const topCampaignSchema = z
|
const topCampaignSchema = z
|
||||||
.object({
|
.object({
|
||||||
hero: heroSchema,
|
__typename: z.literal(ContentEnum.blocks.CampaignPage),
|
||||||
included_hotels: includedHotelsSchema,
|
|
||||||
blocks: discriminatedUnionArray(campaignPageBlocksSchema.options),
|
|
||||||
url: z.string(),
|
|
||||||
})
|
})
|
||||||
.transform((data) => {
|
.merge(topCampaign)
|
||||||
const { blocks, included_hotels, ...rest } = data
|
|
||||||
const hotelListingBlock = blocks.find(
|
|
||||||
(block) =>
|
|
||||||
block.__typename === CampaignPageEnum.ContentStack.blocks.HotelListing
|
|
||||||
)
|
|
||||||
|
|
||||||
return {
|
export const transformTopCampaign = (data: z.infer<typeof topCampaign>) => {
|
||||||
...rest,
|
const { blocks, included_hotels, ...rest } = data
|
||||||
hotel_listing: {
|
const hotelListingBlock = blocks?.find(
|
||||||
heading: hotelListingBlock?.hotel_listing.heading || "",
|
(block) =>
|
||||||
hotelIds: included_hotels,
|
block.__typename === CampaignPageEnum.ContentStack.blocks.HotelListing
|
||||||
},
|
)
|
||||||
}
|
return {
|
||||||
|
...rest,
|
||||||
|
__typename: ContentEnum.blocks.CampaignPage,
|
||||||
|
hotel_listing: {
|
||||||
|
heading: hotelListingBlock?.hotel_listing.heading || "",
|
||||||
|
hotelIds: included_hotels,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const transformedTopCampaign =
|
||||||
|
topCampaignSchema.transform(transformTopCampaign)
|
||||||
|
|
||||||
|
const topPromoCampaign = z.object({
|
||||||
|
typename: z
|
||||||
|
.literal(ContentEnum.blocks.PromoCampaignPage)
|
||||||
|
.optional()
|
||||||
|
.default(ContentEnum.blocks.PromoCampaignPage),
|
||||||
|
promo_hero: promoHeroSchema.nullish(),
|
||||||
|
url: z.string(),
|
||||||
|
})
|
||||||
|
|
||||||
|
const topPromoCampaignSchema = z
|
||||||
|
.object({
|
||||||
|
__typename: z.literal(ContentEnum.blocks.PromoCampaignPage),
|
||||||
})
|
})
|
||||||
|
.merge(topPromoCampaign)
|
||||||
|
|
||||||
|
export const transformTopPromoCampaign = (
|
||||||
|
data: z.infer<typeof topPromoCampaign>
|
||||||
|
) => {
|
||||||
|
const { promo_hero, ...rest } = data
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
__typename: ContentEnum.blocks.PromoCampaignPage,
|
||||||
|
hero: promo_hero,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const transformedTopPromoCampaign = topPromoCampaignSchema.transform(
|
||||||
|
transformTopPromoCampaign
|
||||||
|
)
|
||||||
|
|
||||||
const campaignOverviewPageCarouselCards = z
|
const campaignOverviewPageCarouselCards = z
|
||||||
.object({
|
.object({
|
||||||
@@ -109,9 +152,23 @@ export const campaignOverviewPageSchema = z.object({
|
|||||||
heading: z.string().nullish(),
|
heading: z.string().nullish(),
|
||||||
campaignConnection: z.object({
|
campaignConnection: z.object({
|
||||||
edges: z.array(
|
edges: z.array(
|
||||||
z.object({
|
z
|
||||||
node: topCampaignSchema,
|
.object({
|
||||||
})
|
node: z.discriminatedUnion("__typename", [
|
||||||
|
topCampaignSchema,
|
||||||
|
topPromoCampaignSchema,
|
||||||
|
]),
|
||||||
|
})
|
||||||
|
.transform((data) => {
|
||||||
|
if (data.node.__typename === ContentEnum.blocks.CampaignPage) {
|
||||||
|
return {
|
||||||
|
node: transformTopCampaign(data.node),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
node: transformTopPromoCampaign(data.node),
|
||||||
|
}
|
||||||
|
})
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { transformedImageVaultAssetSchema } from "@scandic-hotels/common/utils/i
|
|||||||
import { removeMultipleSlashes } from "@scandic-hotels/common/utils/url"
|
import { removeMultipleSlashes } from "@scandic-hotels/common/utils/url"
|
||||||
|
|
||||||
import { BlocksEnums } from "../../../../types/blocksEnum"
|
import { BlocksEnums } from "../../../../types/blocksEnum"
|
||||||
import { campaignPageRefSchema } from "../pageLinks"
|
import { campaignPageRefSchema, promoCampaignPageRefSchema } from "../pageLinks"
|
||||||
|
|
||||||
export const campaignPageCardSchema = z.object({
|
export const campaignPageCardSchema = z.object({
|
||||||
image: transformedImageVaultAssetSchema,
|
image: transformedImageVaultAssetSchema,
|
||||||
@@ -72,7 +72,10 @@ export const allCampaignsRefsSchema = z.object({
|
|||||||
campaignsConnection: z.object({
|
campaignsConnection: z.object({
|
||||||
edges: z.array(
|
edges: z.array(
|
||||||
z.object({
|
z.object({
|
||||||
node: campaignPageRefSchema,
|
node: z.discriminatedUnion("__typename", [
|
||||||
|
campaignPageRefSchema,
|
||||||
|
promoCampaignPageRefSchema,
|
||||||
|
]),
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -3,19 +3,27 @@ import type { z } from "zod"
|
|||||||
import type {
|
import type {
|
||||||
campaignOverviewPageRefsSchema,
|
campaignOverviewPageRefsSchema,
|
||||||
campaignOverviewPageSchema,
|
campaignOverviewPageSchema,
|
||||||
|
transformedTopCampaign,
|
||||||
|
transformedTopPromoCampaign,
|
||||||
} from "../routers/contentstack/campaignOverviewPage/output"
|
} from "../routers/contentstack/campaignOverviewPage/output"
|
||||||
|
|
||||||
export interface GetCampaignOverviewPageData
|
export interface GetCampaignOverviewPageData extends z.input<
|
||||||
extends z.input<typeof campaignOverviewPageSchema> {}
|
typeof campaignOverviewPageSchema
|
||||||
export interface CampaignOverviewPage
|
> {}
|
||||||
extends z.output<typeof campaignOverviewPageSchema> {}
|
export interface CampaignOverviewPage extends z.output<
|
||||||
|
typeof campaignOverviewPageSchema
|
||||||
|
> {}
|
||||||
export type CampaignOverviewPageData =
|
export type CampaignOverviewPageData =
|
||||||
CampaignOverviewPage["campaign_overview_page"]
|
CampaignOverviewPage["campaign_overview_page"]
|
||||||
|
|
||||||
export interface GetCampaignOverviewPageRefsData
|
export type TopCampaign = z.output<typeof transformedTopCampaign>
|
||||||
extends z.input<typeof campaignOverviewPageRefsSchema> {}
|
export type TopPromoCampaign = z.output<typeof transformedTopPromoCampaign>
|
||||||
|
export interface GetCampaignOverviewPageRefsData extends z.input<
|
||||||
|
typeof campaignOverviewPageRefsSchema
|
||||||
|
> {}
|
||||||
|
|
||||||
export interface CampaignOverviewPageRefs
|
export interface CampaignOverviewPageRefs extends z.output<
|
||||||
extends z.output<typeof campaignOverviewPageRefsSchema> {}
|
typeof campaignOverviewPageRefsSchema
|
||||||
|
> {}
|
||||||
|
|
||||||
export type Block = CampaignOverviewPageData["blocks"][number]
|
export type Block = CampaignOverviewPageData["blocks"][number]
|
||||||
|
|||||||
Reference in New Issue
Block a user