feat(SW-2264): Added campaign overview page
Approved-by: Matilda Landström
This commit is contained in:
@@ -0,0 +1,19 @@
|
|||||||
|
import { Suspense } from "react"
|
||||||
|
|
||||||
|
import Breadcrumbs from "@/components/Breadcrumbs"
|
||||||
|
import BreadcrumbsSkeleton from "@/components/TempDesignSystem/Breadcrumbs/BreadcrumbsSkeleton"
|
||||||
|
|
||||||
|
import type { BreadcrumbsProps } from "@/components/TempDesignSystem/Breadcrumbs/breadcrumbs"
|
||||||
|
|
||||||
|
export default function CampaignOverviewPageBreadcrumbs() {
|
||||||
|
const variants: Pick<BreadcrumbsProps, "color" | "size"> = {
|
||||||
|
color: "Surface/Secondary/Default",
|
||||||
|
size: "contentWidth",
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Suspense fallback={<BreadcrumbsSkeleton {...variants} />}>
|
||||||
|
<Breadcrumbs {...variants} />
|
||||||
|
</Suspense>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { notFound } from "next/navigation"
|
||||||
|
import { Suspense } from "react"
|
||||||
|
|
||||||
|
import { env } from "@/env/server"
|
||||||
|
|
||||||
|
import CampaignOverviewPage from "@/components/ContentType/CampaignOverviewPage"
|
||||||
|
import CampaignOverviewPageSkeleton from "@/components/ContentType/CampaignOverviewPage/CampaignOverviewPageSkeleton"
|
||||||
|
|
||||||
|
export { generateMetadata } from "@/utils/generateMetadata"
|
||||||
|
|
||||||
|
export default async function CampaignOverviewPagePage() {
|
||||||
|
if (!env.CAMPAIGN_PAGES_ENABLED) {
|
||||||
|
notFound()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Suspense fallback={<CampaignOverviewPageSkeleton />}>
|
||||||
|
<CampaignOverviewPage />
|
||||||
|
</Suspense>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import SkeletonShimmer from "@/components/SkeletonShimmer"
|
||||||
|
|
||||||
|
import styles from "./campaignOverviewPage.module.css"
|
||||||
|
|
||||||
|
export default function CampaignOverviewPageSkeleton() {
|
||||||
|
return (
|
||||||
|
<div className={styles.pageContainer}>
|
||||||
|
<h1>
|
||||||
|
<SkeletonShimmer width="50%" height="2rem" />
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
.pageContainer {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--Space-x5);
|
||||||
|
padding-bottom: var(--Space-x7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
background-color: var(--Base-Surface-Subtle-Normal);
|
||||||
|
padding-bottom: var(--Space-x4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerContent {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--Space-x3);
|
||||||
|
width: var(--max-width-content);
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerIntro {
|
||||||
|
display: grid;
|
||||||
|
max-width: var(--max-width-text-block);
|
||||||
|
gap: var(--Space-x3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading {
|
||||||
|
color: var(--Text-Heading);
|
||||||
|
text-wrap: balance;
|
||||||
|
hyphens: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainContent {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--Space-x6);
|
||||||
|
width: var(--max-width-content);
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.pageContainer {
|
||||||
|
gap: var(--Space-x9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerIntro {
|
||||||
|
gap: var(--Space-x3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 1367px) {
|
||||||
|
.mainContent {
|
||||||
|
gap: var(--Space-x9);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import { notFound } from "next/navigation"
|
||||||
|
import { Suspense } from "react"
|
||||||
|
|
||||||
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
|
||||||
|
import { getCampaignOverviewPage } from "@/lib/trpc/memoizedRequests"
|
||||||
|
|
||||||
|
import LinkChips from "@/components/TempDesignSystem/LinkChips"
|
||||||
|
|
||||||
|
import CampaignOverviewPageSkeleton from "./CampaignOverviewPageSkeleton"
|
||||||
|
|
||||||
|
import styles from "./campaignOverviewPage.module.css"
|
||||||
|
|
||||||
|
export default async function CampaignOverviewPage() {
|
||||||
|
const pageData = await getCampaignOverviewPage()
|
||||||
|
|
||||||
|
if (!pageData) {
|
||||||
|
notFound()
|
||||||
|
}
|
||||||
|
|
||||||
|
const { campaignOverviewPage } = pageData
|
||||||
|
const { header } = campaignOverviewPage
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Suspense fallback={<CampaignOverviewPageSkeleton />}>
|
||||||
|
<div className={styles.pageContainer}>
|
||||||
|
{header ? (
|
||||||
|
<header className={styles.header}>
|
||||||
|
<div className={styles.headerContent}>
|
||||||
|
<>
|
||||||
|
<div className={styles.headerIntro}>
|
||||||
|
<Typography variant="Title/lg">
|
||||||
|
<h1 className={styles.heading}>{header.heading}</h1>
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="Body/Lead text">
|
||||||
|
<p>{header.preamble}</p>
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
{header.navigation_links ? (
|
||||||
|
<LinkChips chips={header.navigation_links} />
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
<main className={styles.mainContent}>
|
||||||
|
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||||
|
{">>> MAIN CONTENT <<<"}
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</Suspense>
|
||||||
|
{/* <TrackingSDK pageData={tracking} /> */}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
.linkChip {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: var(--Spacing-x-half);
|
|
||||||
padding: var(--Spacing-x1) var(--Spacing-x-one-and-half);
|
|
||||||
border-radius: var(--Corner-radius-sm);
|
|
||||||
background-color: var(--Base-Button-Inverted-Fill-Normal);
|
|
||||||
transition: background-color 0.3s;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.linkChip:hover {
|
|
||||||
background-color: var(--Base-Button-Inverted-Fill-Hover-alt);
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export interface LinkChipProps {
|
|
||||||
url: string
|
|
||||||
title: string
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
import Link from "next/link"
|
|
||||||
|
|
||||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
|
||||||
|
|
||||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
|
||||||
|
|
||||||
import styles from "./chip.module.css"
|
|
||||||
|
|
||||||
import type { LinkChipProps } from "./chip"
|
|
||||||
|
|
||||||
export default function LinkChip({ url, title }: LinkChipProps) {
|
|
||||||
return (
|
|
||||||
<Caption type="bold" color="burgundy" asChild>
|
|
||||||
<Link href={url} className={styles.linkChip}>
|
|
||||||
{title}
|
|
||||||
<MaterialIcon icon="chevron_right" size={20} color="CurrentColor" />
|
|
||||||
</Link>
|
|
||||||
</Caption>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,15 @@
|
|||||||
import LinkChip from "./Chip"
|
"use client"
|
||||||
|
|
||||||
import styles from "./linkChips.module.css"
|
import { ChipLink } from "@scandic-hotels/design-system/ChipLink"
|
||||||
|
import { Chips } from "@scandic-hotels/design-system/Chips"
|
||||||
|
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||||
|
|
||||||
import type { LinkChipsProps } from "./linkChips"
|
interface LinkChipsProps {
|
||||||
|
chips: {
|
||||||
|
url: string
|
||||||
|
title: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
export default function LinkChips({ chips }: LinkChipsProps) {
|
export default function LinkChips({ chips }: LinkChipsProps) {
|
||||||
if (!chips.length) {
|
if (!chips.length) {
|
||||||
@@ -10,12 +17,13 @@ export default function LinkChips({ chips }: LinkChipsProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul className={styles.linkChips}>
|
<Chips>
|
||||||
{chips.map(({ url, title }) => (
|
{chips.map(({ title, url }) => (
|
||||||
<li key={`link-chip-${title}`}>
|
<ChipLink key={`${title}-${url}`} href={url}>
|
||||||
<LinkChip url={url} title={title} />
|
{title}
|
||||||
</li>
|
<MaterialIcon icon="chevron_right" size={20} color="CurrentColor" />
|
||||||
|
</ChipLink>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</Chips>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
.linkChips {
|
|
||||||
list-style: none;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: flex-start;
|
|
||||||
align-items: center;
|
|
||||||
gap: var(--Spacing-x1);
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
import type { LinkChipProps } from "./Chip/chip"
|
|
||||||
|
|
||||||
export interface LinkChipsProps {
|
|
||||||
chips: LinkChipProps[]
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
#import "../PageLink/AccountPageLink.graphql"
|
||||||
|
#import "../PageLink/CampaignOverviewPageLink.graphql"
|
||||||
|
#import "../PageLink/CampaignPageLink.graphql"
|
||||||
|
#import "../PageLink/CollectionPageLink.graphql"
|
||||||
|
#import "../PageLink/ContentPageLink.graphql"
|
||||||
|
#import "../PageLink/DestinationCityPageLink.graphql"
|
||||||
|
#import "../PageLink/DestinationCountryPageLink.graphql"
|
||||||
|
#import "../PageLink/DestinationOverviewPageLink.graphql"
|
||||||
|
#import "../PageLink/HotelPageLink.graphql"
|
||||||
|
#import "../PageLink/LoyaltyPageLink.graphql"
|
||||||
|
#import "../PageLink/StartPageLink.graphql"
|
||||||
|
|
||||||
|
#import "../AccountPage/Ref.graphql"
|
||||||
|
#import "../CampaignOverviewPage/Ref.graphql"
|
||||||
|
#import "../CampaignPage/Ref.graphql"
|
||||||
|
#import "../CollectionPage/Ref.graphql"
|
||||||
|
#import "../ContentPage/Ref.graphql"
|
||||||
|
#import "../DestinationCityPage/Ref.graphql"
|
||||||
|
#import "../DestinationCountryPage/Ref.graphql"
|
||||||
|
#import "../DestinationOverviewPage/Ref.graphql"
|
||||||
|
#import "../HotelPage/Ref.graphql"
|
||||||
|
#import "../LoyaltyPage/Ref.graphql"
|
||||||
|
#import "../StartPage/Ref.graphql"
|
||||||
|
|
||||||
|
fragment NavigationLinks_CampaignOverviewPage on CampaignOverviewPageHeader {
|
||||||
|
navigation_links {
|
||||||
|
title
|
||||||
|
linkConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
__typename
|
||||||
|
...AccountPageLink
|
||||||
|
...CampaignOverviewPageLink
|
||||||
|
...CampaignPageLink
|
||||||
|
...CollectionPageLink
|
||||||
|
...ContentPageLink
|
||||||
|
...DestinationCityPageLink
|
||||||
|
...DestinationCountryPageLink
|
||||||
|
...DestinationOverviewPageLink
|
||||||
|
...HotelPageLink
|
||||||
|
...LoyaltyPageLink
|
||||||
|
...StartPageLink
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment NavigationLinksRef_CampaignOverviewPage on CampaignOverviewPageHeader {
|
||||||
|
navigation_links {
|
||||||
|
linkConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
__typename
|
||||||
|
...AccountPageRef
|
||||||
|
...CampaignOverviewPageRef
|
||||||
|
...CampaignPageRef
|
||||||
|
...CollectionPageRef
|
||||||
|
...ContentPageRef
|
||||||
|
...DestinationCityPageRef
|
||||||
|
...DestinationCountryPageRef
|
||||||
|
...DestinationOverviewPageRef
|
||||||
|
...HotelPageRef
|
||||||
|
...LoyaltyPageRef
|
||||||
|
...StartPageRef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#import "../System.graphql"
|
||||||
|
|
||||||
|
fragment CampaignOverviewPageRef on CampaignOverviewPage {
|
||||||
|
system {
|
||||||
|
...System
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#import "../System.graphql"
|
||||||
|
|
||||||
|
fragment CampaignOverviewPageLink on CampaignOverviewPage {
|
||||||
|
title
|
||||||
|
url
|
||||||
|
system {
|
||||||
|
...System
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#import "../../Fragments/Breadcrumbs/Breadcrumbs.graphql"
|
||||||
|
#import "../../Fragments/System.graphql"
|
||||||
|
|
||||||
|
query GetCampaignOverviewPageBreadcrumbs($locale: String!, $uid: String!) {
|
||||||
|
campaign_overview_page(locale: $locale, uid: $uid) {
|
||||||
|
url
|
||||||
|
web {
|
||||||
|
breadcrumbs {
|
||||||
|
...Breadcrumbs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
system {
|
||||||
|
...System
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
query GetCampaignOverviewPageBreadcrumbsRefs($locale: String!, $uid: String!) {
|
||||||
|
campaign_overview_page(locale: $locale, uid: $uid) {
|
||||||
|
web {
|
||||||
|
breadcrumbs {
|
||||||
|
...BreadcrumbsRefs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
system {
|
||||||
|
...System
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
#import "../../Fragments/System.graphql"
|
||||||
|
|
||||||
|
#import "../../Fragments/CampaignOverviewPage/NavigationLinks.graphql"
|
||||||
|
|
||||||
|
query GetCampaignOverviewPage($locale: String!, $uid: String!) {
|
||||||
|
campaign_overview_page(uid: $uid, locale: $locale) {
|
||||||
|
title
|
||||||
|
header {
|
||||||
|
heading
|
||||||
|
preamble
|
||||||
|
...NavigationLinks_CampaignOverviewPage
|
||||||
|
}
|
||||||
|
system {
|
||||||
|
...System
|
||||||
|
created_at
|
||||||
|
updated_at
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trackingProps: campaign_overview_page(locale: "en", uid: $uid) {
|
||||||
|
url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
query GetCampaignOverviewPageRefs($locale: String!, $uid: String!) {
|
||||||
|
campaign_overview_page(locale: $locale, uid: $uid) {
|
||||||
|
header {
|
||||||
|
...NavigationLinksRef_CampaignOverviewPage
|
||||||
|
}
|
||||||
|
system {
|
||||||
|
...System
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
query GetDaDeEnUrlsCampaignOverviewPage($uid: String!) {
|
||||||
|
de: campaign_overview_page(locale: "de", uid: $uid) {
|
||||||
|
url
|
||||||
|
}
|
||||||
|
en: campaign_overview_page(locale: "en", uid: $uid) {
|
||||||
|
url
|
||||||
|
}
|
||||||
|
da: campaign_overview_page(locale: "da", uid: $uid) {
|
||||||
|
url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
query GetFiNoSvUrlsCampaignOverviewPage($uid: String!) {
|
||||||
|
fi: campaign_overview_page(locale: "fi", uid: $uid) {
|
||||||
|
url
|
||||||
|
}
|
||||||
|
no: campaign_overview_page(locale: "no", uid: $uid) {
|
||||||
|
url
|
||||||
|
}
|
||||||
|
sv: campaign_overview_page(locale: "sv", uid: $uid) {
|
||||||
|
url
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#import "../../Fragments/Metadata.graphql"
|
||||||
|
#import "../../Fragments/System.graphql"
|
||||||
|
|
||||||
|
query GetCampaignOverviewPageMetadata($locale: String!, $uid: String!) {
|
||||||
|
campaign_overview_page(locale: $locale, uid: $uid) {
|
||||||
|
web {
|
||||||
|
breadcrumbs {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
seo_metadata {
|
||||||
|
...Metadata
|
||||||
|
}
|
||||||
|
}
|
||||||
|
header {
|
||||||
|
heading
|
||||||
|
preamble
|
||||||
|
}
|
||||||
|
system {
|
||||||
|
...System
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,14 @@ query GetAccountPageSettings($uid: String!, $locale: String!) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query GetCampaignOverviewPageSettings($uid: String!, $locale: String!) {
|
||||||
|
page: campaign_overview_page(uid: $uid, locale: $locale) {
|
||||||
|
settings: page_settings {
|
||||||
|
...PageSettings
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
query GetCampaignPageSettings($uid: String!, $locale: String!) {
|
query GetCampaignPageSettings($uid: String!, $locale: String!) {
|
||||||
page: campaign_page(uid: $uid, locale: $locale) {
|
page: campaign_page(uid: $uid, locale: $locale) {
|
||||||
settings: page_settings {
|
settings: page_settings {
|
||||||
|
|||||||
@@ -92,4 +92,12 @@ query EntryByUrlBatch2($locale: String!, $url: String!) {
|
|||||||
}
|
}
|
||||||
total
|
total
|
||||||
}
|
}
|
||||||
|
all_campaign_overview_page(where: { url: $url }, locale: $locale) {
|
||||||
|
items {
|
||||||
|
system {
|
||||||
|
...System
|
||||||
|
}
|
||||||
|
}
|
||||||
|
total
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -422,3 +422,10 @@ export const getCampaignPage = cache(async function getMemoizedCampaignPage() {
|
|||||||
const caller = await serverClient()
|
const caller = await serverClient()
|
||||||
return caller.contentstack.campaignPage.get()
|
return caller.contentstack.campaignPage.get()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const getCampaignOverviewPage = cache(
|
||||||
|
async function getMemoizedCampaignOverviewPage() {
|
||||||
|
const caller = await serverClient()
|
||||||
|
return caller.contentstack.campaignOverviewPage.get()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ import {
|
|||||||
GetMyPagesBreadcrumbs,
|
GetMyPagesBreadcrumbs,
|
||||||
GetMyPagesBreadcrumbsRefs,
|
GetMyPagesBreadcrumbsRefs,
|
||||||
} from "@/lib/graphql/Query/Breadcrumbs/AccountPage.graphql"
|
} from "@/lib/graphql/Query/Breadcrumbs/AccountPage.graphql"
|
||||||
|
import {
|
||||||
|
GetCampaignOverviewPageBreadcrumbs,
|
||||||
|
GetCampaignOverviewPageBreadcrumbsRefs,
|
||||||
|
} from "@/lib/graphql/Query/Breadcrumbs/CampaignOverviewPage.graphql"
|
||||||
import {
|
import {
|
||||||
GetCampaignPageBreadcrumbs,
|
GetCampaignPageBreadcrumbs,
|
||||||
GetCampaignPageBreadcrumbsRefs,
|
GetCampaignPageBreadcrumbsRefs,
|
||||||
@@ -158,6 +162,17 @@ export const breadcrumbsQueryRouter = router({
|
|||||||
},
|
},
|
||||||
variables
|
variables
|
||||||
)
|
)
|
||||||
|
case PageContentTypeEnum.campaignOverviewPage:
|
||||||
|
return await getBreadcrumbs<{
|
||||||
|
campaign_overview_page: RawBreadcrumbsSchema
|
||||||
|
}>(
|
||||||
|
{
|
||||||
|
dataKey: "campaign_overview_page",
|
||||||
|
refQuery: GetCampaignOverviewPageBreadcrumbsRefs,
|
||||||
|
query: GetCampaignOverviewPageBreadcrumbs,
|
||||||
|
},
|
||||||
|
variables
|
||||||
|
)
|
||||||
case PageContentTypeEnum.campaignPage:
|
case PageContentTypeEnum.campaignPage:
|
||||||
return await getBreadcrumbs<{
|
return await getBreadcrumbs<{
|
||||||
campaign_page: RawBreadcrumbsSchema
|
campaign_page: RawBreadcrumbsSchema
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { mergeRouters } from "@scandic-hotels/trpc"
|
||||||
|
|
||||||
|
import { campaignOverviewPageQueryRouter } from "./query"
|
||||||
|
|
||||||
|
export const campaignOverviewPageRouter = mergeRouters(
|
||||||
|
campaignOverviewPageQueryRouter
|
||||||
|
)
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import { z } from "zod"
|
||||||
|
|
||||||
|
import {
|
||||||
|
linkAndTitleSchema,
|
||||||
|
linkConnectionRefs,
|
||||||
|
} from "@/server/routers/contentstack/schemas/linkConnection"
|
||||||
|
|
||||||
|
import { systemSchema } from "../schemas/system"
|
||||||
|
|
||||||
|
const navigationLinksSchema = z
|
||||||
|
.array(linkAndTitleSchema)
|
||||||
|
.nullable()
|
||||||
|
.transform((data) => {
|
||||||
|
if (!data) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
|
.filter((item) => !!item.link)
|
||||||
|
.map((item) => ({
|
||||||
|
url: item.link!.url,
|
||||||
|
title: item.title || item.link!.title,
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
|
export const campaignOverviewPageSchema = z.object({
|
||||||
|
campaign_overview_page: z.object({
|
||||||
|
title: z.string(),
|
||||||
|
header: z.object({
|
||||||
|
heading: z.string(),
|
||||||
|
preamble: z.string(),
|
||||||
|
navigation_links: navigationLinksSchema,
|
||||||
|
}),
|
||||||
|
system: systemSchema.merge(
|
||||||
|
z.object({
|
||||||
|
created_at: z.string(),
|
||||||
|
updated_at: z.string(),
|
||||||
|
})
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
trackingProps: z.object({
|
||||||
|
url: z.string(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
/** REFS */
|
||||||
|
|
||||||
|
const campaignOverviewPageHeaderRefs = z.object({
|
||||||
|
navigation_links: z.array(linkConnectionRefs),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const campaignOverviewPageRefsSchema = z.object({
|
||||||
|
campaign_overview_page: z.object({
|
||||||
|
header: campaignOverviewPageHeaderRefs,
|
||||||
|
system: systemSchema,
|
||||||
|
}),
|
||||||
|
})
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
import { createCounter } from "@scandic-hotels/common/telemetry"
|
||||||
|
import { router } from "@scandic-hotels/trpc"
|
||||||
|
import { notFound } from "@scandic-hotels/trpc/errors"
|
||||||
|
import { contentStackUidWithServiceProcedure } from "@scandic-hotels/trpc/procedures"
|
||||||
|
|
||||||
|
import {
|
||||||
|
GetCampaignOverviewPage,
|
||||||
|
GetCampaignOverviewPageRefs,
|
||||||
|
} from "@/lib/graphql/Query/CampaignOverviewPage/CampaignOverviewPage.graphql"
|
||||||
|
import { request } from "@/lib/graphql/request"
|
||||||
|
|
||||||
|
import { generateRefsResponseTag } from "@/utils/generateTag"
|
||||||
|
|
||||||
|
import {
|
||||||
|
campaignOverviewPageRefsSchema,
|
||||||
|
campaignOverviewPageSchema,
|
||||||
|
} from "./output"
|
||||||
|
import { generatePageTags } from "./utils"
|
||||||
|
|
||||||
|
import {
|
||||||
|
TrackingChannelEnum,
|
||||||
|
type TrackingSDKPageData,
|
||||||
|
} from "@/types/components/tracking"
|
||||||
|
import type {
|
||||||
|
GetCampaignOverviewPageData,
|
||||||
|
GetCampaignOverviewPageRefsData,
|
||||||
|
} from "@/types/trpc/routers/contentstack/campaignOverviewPage"
|
||||||
|
|
||||||
|
export const campaignOverviewPageQueryRouter = router({
|
||||||
|
get: contentStackUidWithServiceProcedure.query(async ({ ctx }) => {
|
||||||
|
const { lang, uid } = ctx
|
||||||
|
|
||||||
|
const getCampaignOverviewPageRefsCounter = createCounter(
|
||||||
|
"trpc.contentstack",
|
||||||
|
"campaignOverviewPage.get.refs"
|
||||||
|
)
|
||||||
|
const metricsGetCampaignOverviewPageRefs =
|
||||||
|
getCampaignOverviewPageRefsCounter.init({
|
||||||
|
lang,
|
||||||
|
uid,
|
||||||
|
})
|
||||||
|
|
||||||
|
metricsGetCampaignOverviewPageRefs.start()
|
||||||
|
|
||||||
|
const refsResponse = await request<GetCampaignOverviewPageRefsData>(
|
||||||
|
GetCampaignOverviewPageRefs,
|
||||||
|
{ locale: lang, uid },
|
||||||
|
{
|
||||||
|
key: generateRefsResponseTag(lang, uid),
|
||||||
|
ttl: "max",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!refsResponse.data) {
|
||||||
|
const notFoundError = notFound(refsResponse)
|
||||||
|
metricsGetCampaignOverviewPageRefs.noDataError()
|
||||||
|
throw notFoundError
|
||||||
|
}
|
||||||
|
|
||||||
|
const validatedRefsData = campaignOverviewPageRefsSchema.safeParse(
|
||||||
|
refsResponse.data
|
||||||
|
)
|
||||||
|
if (!validatedRefsData.success) {
|
||||||
|
metricsGetCampaignOverviewPageRefs.validationError(
|
||||||
|
validatedRefsData.error
|
||||||
|
)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
metricsGetCampaignOverviewPageRefs.success()
|
||||||
|
|
||||||
|
const tags = generatePageTags(validatedRefsData.data, lang)
|
||||||
|
|
||||||
|
const getCampaignOverviewPageCounter = createCounter(
|
||||||
|
"trpc.contentstack",
|
||||||
|
"campaignOverviewPage.get"
|
||||||
|
)
|
||||||
|
const metricsGetCampaignOverviewPage = getCampaignOverviewPageCounter.init({
|
||||||
|
lang,
|
||||||
|
uid,
|
||||||
|
})
|
||||||
|
|
||||||
|
metricsGetCampaignOverviewPage.start()
|
||||||
|
|
||||||
|
const response = await request<GetCampaignOverviewPageData>(
|
||||||
|
GetCampaignOverviewPage,
|
||||||
|
{
|
||||||
|
locale: lang,
|
||||||
|
uid,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: tags,
|
||||||
|
ttl: "max",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (!response.data) {
|
||||||
|
const notFoundError = notFound(response)
|
||||||
|
metricsGetCampaignOverviewPage.noDataError()
|
||||||
|
throw notFoundError
|
||||||
|
}
|
||||||
|
|
||||||
|
const validatedResponse = campaignOverviewPageSchema.safeParse(
|
||||||
|
response.data
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!validatedResponse.success) {
|
||||||
|
metricsGetCampaignOverviewPage.validationError(validatedResponse.error)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const campaignOverviewPage = validatedResponse.data.campaign_overview_page
|
||||||
|
|
||||||
|
metricsGetCampaignOverviewPage.success()
|
||||||
|
|
||||||
|
const system = campaignOverviewPage.system
|
||||||
|
const pageName = `campaign-overview-page`
|
||||||
|
|
||||||
|
const tracking: TrackingSDKPageData = {
|
||||||
|
pageId: system.uid,
|
||||||
|
domainLanguage: system.locale,
|
||||||
|
publishDate: system.updated_at,
|
||||||
|
createDate: system.created_at,
|
||||||
|
channel: TrackingChannelEnum["campaign-overview-page"],
|
||||||
|
pageType: "campaign-overview-page",
|
||||||
|
pageName,
|
||||||
|
siteSections: pageName,
|
||||||
|
siteVersion: "new-web",
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
campaignOverviewPage,
|
||||||
|
tracking,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
})
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { generateTag, generateTagsFromSystem } from "@/utils/generateTag"
|
||||||
|
|
||||||
|
import type { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
|
|
||||||
|
import type { System } from "@/types/requests/system"
|
||||||
|
import type { CampaignOverviewPageRefs } from "@/types/trpc/routers/contentstack/campaignOverviewPage"
|
||||||
|
|
||||||
|
export function generatePageTags(
|
||||||
|
validatedData: CampaignOverviewPageRefs,
|
||||||
|
lang: Lang
|
||||||
|
): string[] {
|
||||||
|
const connections = getConnections(validatedData)
|
||||||
|
return [
|
||||||
|
generateTagsFromSystem(lang, connections),
|
||||||
|
generateTag(lang, validatedData.campaign_overview_page.system.uid),
|
||||||
|
].flat()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getConnections({
|
||||||
|
campaign_overview_page,
|
||||||
|
}: CampaignOverviewPageRefs) {
|
||||||
|
const connections: System["system"][] = [campaign_overview_page.system]
|
||||||
|
|
||||||
|
if (campaign_overview_page.header.navigation_links) {
|
||||||
|
campaign_overview_page.header.navigation_links.forEach((link) => {
|
||||||
|
if (link.link) {
|
||||||
|
connections.push(link.link)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return connections
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import { router } from "@scandic-hotels/trpc"
|
|||||||
import { accountPageRouter } from "./accountPage"
|
import { accountPageRouter } from "./accountPage"
|
||||||
import { baseRouter } from "./base"
|
import { baseRouter } from "./base"
|
||||||
import { breadcrumbsRouter } from "./breadcrumbs"
|
import { breadcrumbsRouter } from "./breadcrumbs"
|
||||||
|
import { campaignOverviewPageRouter } from "./campaignOverviewPage"
|
||||||
import { campaignPageRouter } from "./campaignPage"
|
import { campaignPageRouter } from "./campaignPage"
|
||||||
import { collectionPageRouter } from "./collectionPage"
|
import { collectionPageRouter } from "./collectionPage"
|
||||||
import { contentPageRouter } from "./contentPage"
|
import { contentPageRouter } from "./contentPage"
|
||||||
@@ -26,6 +27,7 @@ export const contentstackRouter = router({
|
|||||||
hotelPage: hotelPageRouter,
|
hotelPage: hotelPageRouter,
|
||||||
languageSwitcher: languageSwitcherRouter,
|
languageSwitcher: languageSwitcherRouter,
|
||||||
loyaltyPage: loyaltyPageRouter,
|
loyaltyPage: loyaltyPageRouter,
|
||||||
|
campaignOverviewPage: campaignOverviewPageRouter,
|
||||||
campaignPage: campaignPageRouter,
|
campaignPage: campaignPageRouter,
|
||||||
collectionPage: collectionPageRouter,
|
collectionPage: collectionPageRouter,
|
||||||
contentPage: contentPageRouter,
|
contentPage: contentPageRouter,
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ import {
|
|||||||
GetDaDeEnUrlsAccountPage,
|
GetDaDeEnUrlsAccountPage,
|
||||||
GetFiNoSvUrlsAccountPage,
|
GetFiNoSvUrlsAccountPage,
|
||||||
} from "@/lib/graphql/Query/AccountPage/AccountPage.graphql"
|
} from "@/lib/graphql/Query/AccountPage/AccountPage.graphql"
|
||||||
|
import {
|
||||||
|
GetDaDeEnUrlsCampaignOverviewPage,
|
||||||
|
GetFiNoSvUrlsCampaignOverviewPage,
|
||||||
|
} from "@/lib/graphql/Query/CampaignOverviewPage/CampaignOverviewPage.graphql"
|
||||||
import {
|
import {
|
||||||
GetDaDeEnUrlsCampaignPage,
|
GetDaDeEnUrlsCampaignPage,
|
||||||
GetFiNoSvUrlsCampaignPage,
|
GetFiNoSvUrlsCampaignPage,
|
||||||
@@ -100,6 +104,10 @@ export async function getUrlsOfAllLanguages(
|
|||||||
daDeEnDocument = GetDaDeEnUrlsCurrentBlocksPage
|
daDeEnDocument = GetDaDeEnUrlsCurrentBlocksPage
|
||||||
fiNoSvDocument = GetFiNoSvUrlsCurrentBlocksPage
|
fiNoSvDocument = GetFiNoSvUrlsCurrentBlocksPage
|
||||||
break
|
break
|
||||||
|
case PageContentTypeEnum.campaignOverviewPage:
|
||||||
|
daDeEnDocument = GetDaDeEnUrlsCampaignOverviewPage
|
||||||
|
fiNoSvDocument = GetFiNoSvUrlsCampaignOverviewPage
|
||||||
|
break
|
||||||
case PageContentTypeEnum.campaignPage:
|
case PageContentTypeEnum.campaignPage:
|
||||||
daDeEnDocument = GetDaDeEnUrlsCampaignPage
|
daDeEnDocument = GetDaDeEnUrlsCampaignPage
|
||||||
fiNoSvDocument = GetFiNoSvUrlsCampaignPage
|
fiNoSvDocument = GetFiNoSvUrlsCampaignPage
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { contentStackUidWithServiceProcedure } from "@scandic-hotels/trpc/proced
|
|||||||
|
|
||||||
import { env } from "@/env/server"
|
import { env } from "@/env/server"
|
||||||
import { GetAccountPageMetadata } from "@/lib/graphql/Query/AccountPage/Metadata.graphql"
|
import { GetAccountPageMetadata } from "@/lib/graphql/Query/AccountPage/Metadata.graphql"
|
||||||
|
import { GetCampaignOverviewPageMetadata } from "@/lib/graphql/Query/CampaignOverviewPage/Metadata.graphql"
|
||||||
import { GetCampaignPageMetadata } from "@/lib/graphql/Query/CampaignPage/Metadata.graphql"
|
import { GetCampaignPageMetadata } from "@/lib/graphql/Query/CampaignPage/Metadata.graphql"
|
||||||
import { GetCollectionPageMetadata } from "@/lib/graphql/Query/CollectionPage/Metadata.graphql"
|
import { GetCollectionPageMetadata } from "@/lib/graphql/Query/CollectionPage/Metadata.graphql"
|
||||||
import { GetContentPageMetadata } from "@/lib/graphql/Query/ContentPage/Metadata.graphql"
|
import { GetContentPageMetadata } from "@/lib/graphql/Query/ContentPage/Metadata.graphql"
|
||||||
@@ -131,6 +132,14 @@ export const metadataQueryRouter = router({
|
|||||||
accountPageResponse.account_page
|
accountPageResponse.account_page
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
|
case PageContentTypeEnum.campaignOverviewPage:
|
||||||
|
const campaignOverviewPageResponse = await fetchMetadata<{
|
||||||
|
campaign_overview_page: RawMetadataSchema
|
||||||
|
}>(GetCampaignOverviewPageMetadata, variables)
|
||||||
|
metadata = await getTransformedMetadata(
|
||||||
|
campaignOverviewPageResponse.campaign_overview_page
|
||||||
|
)
|
||||||
|
break
|
||||||
case PageContentTypeEnum.campaignPage:
|
case PageContentTypeEnum.campaignPage:
|
||||||
const campaignPageResponse = await fetchMetadata<{
|
const campaignPageResponse = await fetchMetadata<{
|
||||||
campaign_page: RawMetadataSchema
|
campaign_page: RawMetadataSchema
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { contentstackBaseProcedure } from "@scandic-hotels/trpc/procedures"
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
GetAccountPageSettings,
|
GetAccountPageSettings,
|
||||||
|
GetCampaignOverviewPageSettings,
|
||||||
GetCampaignPageSettings,
|
GetCampaignPageSettings,
|
||||||
GetCollectionPageSettings,
|
GetCollectionPageSettings,
|
||||||
GetContentPageSettings,
|
GetContentPageSettings,
|
||||||
@@ -77,6 +78,7 @@ export const pageSettingsQueryRouter = router({
|
|||||||
|
|
||||||
const graphqlQueriesForContentType: Record<PageContentTypeEnum, any> = {
|
const graphqlQueriesForContentType: Record<PageContentTypeEnum, any> = {
|
||||||
[PageContentTypeEnum.accountPage]: GetAccountPageSettings,
|
[PageContentTypeEnum.accountPage]: GetAccountPageSettings,
|
||||||
|
[PageContentTypeEnum.campaignOverviewPage]: GetCampaignOverviewPageSettings,
|
||||||
[PageContentTypeEnum.campaignPage]: GetCampaignPageSettings,
|
[PageContentTypeEnum.campaignPage]: GetCampaignPageSettings,
|
||||||
[PageContentTypeEnum.collectionPage]: GetCollectionPageSettings,
|
[PageContentTypeEnum.collectionPage]: GetCollectionPageSettings,
|
||||||
[PageContentTypeEnum.contentPage]: GetContentPageSettings,
|
[PageContentTypeEnum.contentPage]: GetContentPageSettings,
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
accountPageSchema,
|
accountPageSchema,
|
||||||
|
campaignOverviewPageSchema,
|
||||||
|
campaignPageSchema,
|
||||||
collectionPageSchema,
|
collectionPageSchema,
|
||||||
contentPageSchema,
|
contentPageSchema,
|
||||||
destinationCityPageSchema,
|
destinationCityPageSchema,
|
||||||
@@ -20,6 +22,8 @@ export const contentEmbedsSchema = z
|
|||||||
imageContainerSchema,
|
imageContainerSchema,
|
||||||
sysAssetSchema,
|
sysAssetSchema,
|
||||||
accountPageSchema,
|
accountPageSchema,
|
||||||
|
campaignOverviewPageSchema,
|
||||||
|
campaignPageSchema,
|
||||||
collectionPageSchema,
|
collectionPageSchema,
|
||||||
contentPageSchema,
|
contentPageSchema,
|
||||||
destinationCityPageSchema,
|
destinationCityPageSchema,
|
||||||
|
|||||||
@@ -32,6 +32,18 @@ export const extendedPageLinkSchema = pageLinkSchema.merge(
|
|||||||
.default({ original_url: "" }),
|
.default({ original_url: "" }),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const campaignOverviewPageSchema = z
|
||||||
|
.object({
|
||||||
|
__typename: z.literal(ContentEnum.blocks.CampaignOverviewPage),
|
||||||
|
})
|
||||||
|
.merge(extendedPageLinkSchema)
|
||||||
|
|
||||||
|
export const campaignOverviewPageRefSchema = z.object({
|
||||||
|
__typename: z.literal(ContentEnum.blocks.CampaignOverviewPage),
|
||||||
|
system: systemSchema,
|
||||||
|
})
|
||||||
|
|
||||||
export const collectionPageSchema = z
|
export const collectionPageSchema = z
|
||||||
.object({
|
.object({
|
||||||
__typename: z.literal(ContentEnum.blocks.CollectionPage),
|
__typename: z.literal(ContentEnum.blocks.CollectionPage),
|
||||||
@@ -133,6 +145,7 @@ export const startPageRefSchema = z.object({
|
|||||||
|
|
||||||
export const linkUnionSchema = z.discriminatedUnion("__typename", [
|
export const linkUnionSchema = z.discriminatedUnion("__typename", [
|
||||||
accountPageSchema,
|
accountPageSchema,
|
||||||
|
campaignOverviewPageSchema,
|
||||||
campaignPageSchema,
|
campaignPageSchema,
|
||||||
collectionPageSchema,
|
collectionPageSchema,
|
||||||
contentPageSchema,
|
contentPageSchema,
|
||||||
@@ -146,6 +159,7 @@ export const linkUnionSchema = z.discriminatedUnion("__typename", [
|
|||||||
|
|
||||||
type Data =
|
type Data =
|
||||||
| z.output<typeof accountPageSchema>
|
| z.output<typeof accountPageSchema>
|
||||||
|
| z.output<typeof campaignOverviewPageSchema>
|
||||||
| z.output<typeof campaignPageSchema>
|
| z.output<typeof campaignPageSchema>
|
||||||
| z.output<typeof collectionPageSchema>
|
| z.output<typeof collectionPageSchema>
|
||||||
| z.output<typeof contentPageSchema>
|
| z.output<typeof contentPageSchema>
|
||||||
@@ -161,6 +175,7 @@ export function transformPageLink(data: Data) {
|
|||||||
if (data && "__typename" in data) {
|
if (data && "__typename" in data) {
|
||||||
switch (data.__typename) {
|
switch (data.__typename) {
|
||||||
case ContentEnum.blocks.AccountPage:
|
case ContentEnum.blocks.AccountPage:
|
||||||
|
case ContentEnum.blocks.CampaignOverviewPage:
|
||||||
case ContentEnum.blocks.CampaignPage:
|
case ContentEnum.blocks.CampaignPage:
|
||||||
case ContentEnum.blocks.DestinationCityPage:
|
case ContentEnum.blocks.DestinationCityPage:
|
||||||
case ContentEnum.blocks.DestinationCountryPage:
|
case ContentEnum.blocks.DestinationCountryPage:
|
||||||
@@ -173,7 +188,6 @@ export function transformPageLink(data: Data) {
|
|||||||
title: data.title,
|
title: data.title,
|
||||||
url: removeMultipleSlashes(`/${data.system.locale}/${data.url}`),
|
url: removeMultipleSlashes(`/${data.system.locale}/${data.url}`),
|
||||||
}
|
}
|
||||||
|
|
||||||
case ContentEnum.blocks.CollectionPage:
|
case ContentEnum.blocks.CollectionPage:
|
||||||
case ContentEnum.blocks.ContentPage:
|
case ContentEnum.blocks.ContentPage:
|
||||||
case ContentEnum.blocks.LoyaltyPage:
|
case ContentEnum.blocks.LoyaltyPage:
|
||||||
@@ -195,6 +209,7 @@ export function transformPageLink(data: Data) {
|
|||||||
|
|
||||||
export const linkRefsUnionSchema = z.discriminatedUnion("__typename", [
|
export const linkRefsUnionSchema = z.discriminatedUnion("__typename", [
|
||||||
accountPageRefSchema,
|
accountPageRefSchema,
|
||||||
|
campaignOverviewPageRefSchema,
|
||||||
campaignPageRefSchema,
|
campaignPageRefSchema,
|
||||||
collectionPageRefSchema,
|
collectionPageRefSchema,
|
||||||
contentPageRefSchema,
|
contentPageRefSchema,
|
||||||
@@ -208,6 +223,7 @@ export const linkRefsUnionSchema = z.discriminatedUnion("__typename", [
|
|||||||
|
|
||||||
type RefData =
|
type RefData =
|
||||||
| z.output<typeof accountPageRefSchema>
|
| z.output<typeof accountPageRefSchema>
|
||||||
|
| z.output<typeof campaignOverviewPageRefSchema>
|
||||||
| z.output<typeof campaignPageRefSchema>
|
| z.output<typeof campaignPageRefSchema>
|
||||||
| z.output<typeof collectionPageRefSchema>
|
| z.output<typeof collectionPageRefSchema>
|
||||||
| z.output<typeof contentPageRefSchema>
|
| z.output<typeof contentPageRefSchema>
|
||||||
@@ -223,6 +239,7 @@ export function transformPageLinkRef(data: RefData) {
|
|||||||
if (data && "__typename" in data) {
|
if (data && "__typename" in data) {
|
||||||
switch (data.__typename) {
|
switch (data.__typename) {
|
||||||
case ContentEnum.blocks.AccountPage:
|
case ContentEnum.blocks.AccountPage:
|
||||||
|
case ContentEnum.blocks.CampaignOverviewPage:
|
||||||
case ContentEnum.blocks.CampaignPage:
|
case ContentEnum.blocks.CampaignPage:
|
||||||
case ContentEnum.blocks.CollectionPage:
|
case ContentEnum.blocks.CollectionPage:
|
||||||
case ContentEnum.blocks.ContentPage:
|
case ContentEnum.blocks.ContentPage:
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export enum TrackingChannelEnum {
|
|||||||
"hotelreservation" = "hotelreservation",
|
"hotelreservation" = "hotelreservation",
|
||||||
"collection-page" = "collection-page",
|
"collection-page" = "collection-page",
|
||||||
"campaign-page" = "campaign-page",
|
"campaign-page" = "campaign-page",
|
||||||
|
"campaign-overview-page" = "campaign-overview-page",
|
||||||
"hotels" = "hotels",
|
"hotels" = "hotels",
|
||||||
"homepage" = "homepage",
|
"homepage" = "homepage",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
export namespace ContentEnum {
|
export namespace ContentEnum {
|
||||||
export const enum blocks {
|
export const enum blocks {
|
||||||
AccountPage = "AccountPage",
|
AccountPage = "AccountPage",
|
||||||
|
CampaignOverviewPage = "CampaignOverviewPage",
|
||||||
CampaignPage = "CampaignPage",
|
CampaignPage = "CampaignPage",
|
||||||
CollectionPage = "CollectionPage",
|
CollectionPage = "CollectionPage",
|
||||||
ContentPage = "ContentPage",
|
ContentPage = "ContentPage",
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ export type StatusParams = {
|
|||||||
export type ContentTypeParams = {
|
export type ContentTypeParams = {
|
||||||
contentType:
|
contentType:
|
||||||
| PageContentTypeEnum.loyaltyPage
|
| PageContentTypeEnum.loyaltyPage
|
||||||
|
| PageContentTypeEnum.campaignOverviewPage
|
||||||
|
| PageContentTypeEnum.campaignPage
|
||||||
| PageContentTypeEnum.contentPage
|
| PageContentTypeEnum.contentPage
|
||||||
| PageContentTypeEnum.hotelPage
|
| PageContentTypeEnum.hotelPage
|
||||||
| PageContentTypeEnum.collectionPage
|
| PageContentTypeEnum.collectionPage
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
export enum PageContentTypeEnum {
|
export enum PageContentTypeEnum {
|
||||||
accountPage = "account_page",
|
accountPage = "account_page",
|
||||||
|
campaignOverviewPage = "campaign_overview_page",
|
||||||
campaignPage = "campaign_page",
|
campaignPage = "campaign_page",
|
||||||
collectionPage = "collection_page",
|
collectionPage = "collection_page",
|
||||||
contentPage = "content_page",
|
contentPage = "content_page",
|
||||||
currentBlocksPage = "current_blocks_page",
|
currentBlocksPage = "current_blocks_page",
|
||||||
destinationOverviewPage = "destination_overview_page",
|
|
||||||
destinationCountryPage = "destination_country_page",
|
|
||||||
destinationCityPage = "destination_city_page",
|
destinationCityPage = "destination_city_page",
|
||||||
|
destinationCountryPage = "destination_country_page",
|
||||||
|
destinationOverviewPage = "destination_overview_page",
|
||||||
hotelPage = "hotel_page",
|
hotelPage = "hotel_page",
|
||||||
loyaltyPage = "loyalty_page",
|
loyaltyPage = "loyalty_page",
|
||||||
startPage = "start_page",
|
startPage = "start_page",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ const entryResolveSchema = z.object({
|
|||||||
|
|
||||||
export const validateEntryResolveSchema = z.object({
|
export const validateEntryResolveSchema = z.object({
|
||||||
all_account_page: entryResolveSchema,
|
all_account_page: entryResolveSchema,
|
||||||
|
all_campaign_overview_page: entryResolveSchema,
|
||||||
all_campaign_page: entryResolveSchema,
|
all_campaign_page: entryResolveSchema,
|
||||||
all_collection_page: entryResolveSchema,
|
all_collection_page: entryResolveSchema,
|
||||||
all_content_page: entryResolveSchema,
|
all_content_page: entryResolveSchema,
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import type { z } from "zod"
|
||||||
|
|
||||||
|
import type {
|
||||||
|
campaignOverviewPageRefsSchema,
|
||||||
|
campaignOverviewPageSchema,
|
||||||
|
} from "@/server/routers/contentstack/campaignOverviewPage/output"
|
||||||
|
|
||||||
|
export interface GetCampaignOverviewPageData
|
||||||
|
extends z.input<typeof campaignOverviewPageSchema> {}
|
||||||
|
export interface CampaignOverviewPage
|
||||||
|
extends z.output<typeof campaignOverviewPageSchema> {}
|
||||||
|
export type CampaignOverviewPageData =
|
||||||
|
CampaignOverviewPage["campaign_overview_page"]
|
||||||
|
|
||||||
|
export interface GetCampaignOverviewPageRefsData
|
||||||
|
extends z.input<typeof campaignOverviewPageRefsSchema> {}
|
||||||
|
|
||||||
|
export interface CampaignOverviewPageRefs
|
||||||
|
extends z.output<typeof campaignOverviewPageRefsSchema> {}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Button } from '@scandic-hotels/design-system/Button'
|
import { Button } from '@scandic-hotels/design-system/Button'
|
||||||
import { Chips } from '@scandic-hotels/design-system/Chips'
|
|
||||||
import { ChipButton } from '@scandic-hotels/design-system/ChipButton'
|
import { ChipButton } from '@scandic-hotels/design-system/ChipButton'
|
||||||
import { ChipLink } from '@scandic-hotels/design-system/ChipLink'
|
import { ChipLink } from '@scandic-hotels/design-system/ChipLink'
|
||||||
|
import { Chips } from '@scandic-hotels/design-system/Chips'
|
||||||
import { Typography } from '@scandic-hotels/design-system/Typography'
|
import { Typography } from '@scandic-hotels/design-system/Typography'
|
||||||
|
|
||||||
import styles from './header.module.css'
|
import styles from './header.module.css'
|
||||||
@@ -10,8 +10,6 @@ import type { PressEvent } from 'react-aria-components'
|
|||||||
|
|
||||||
export function Header() {
|
export function Header() {
|
||||||
const onPress = (e: PressEvent) => alert(e.target.innerHTML)
|
const onPress = (e: PressEvent) => alert(e.target.innerHTML)
|
||||||
const onClick = (e: React.MouseEvent<HTMLAnchorElement>) =>
|
|
||||||
alert(`Link to: ${e.currentTarget.href}`)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className={styles.header}>
|
<header className={styles.header}>
|
||||||
@@ -42,27 +40,27 @@ export function Header() {
|
|||||||
<div className={styles.chips}>
|
<div className={styles.chips}>
|
||||||
<Chips>
|
<Chips>
|
||||||
<ChipButton onPress={onPress}>Restaurants and bars</ChipButton>
|
<ChipButton onPress={onPress}>Restaurants and bars</ChipButton>
|
||||||
<ChipLink onClick={onClick} href="/kristianshavn">
|
<ChipLink onPress={onPress} href="/kristianshavn">
|
||||||
Kristianshavn
|
Kristianshavn
|
||||||
</ChipLink>
|
</ChipLink>
|
||||||
<ChipButton onPress={onPress}>Tivoli Gardens</ChipButton>
|
<ChipButton onPress={onPress}>Tivoli Gardens</ChipButton>
|
||||||
<ChipLink onClick={onClick} href="/copenhagen">
|
<ChipLink onPress={onPress} href="/copenhagen">
|
||||||
See all Copenhagen
|
See all Copenhagen
|
||||||
</ChipLink>
|
</ChipLink>
|
||||||
<ChipButton onPress={onPress}>See all Copenhagen</ChipButton>
|
<ChipButton onPress={onPress}>See all Copenhagen</ChipButton>
|
||||||
<ChipLink onClick={onClick} href="/copenhagen">
|
<ChipLink onPress={onPress} href="/copenhagen">
|
||||||
See all Copenhagen
|
See all Copenhagen
|
||||||
</ChipLink>
|
</ChipLink>
|
||||||
<ChipButton onPress={onPress}>See all Copenhagen</ChipButton>
|
<ChipButton onPress={onPress}>See all Copenhagen</ChipButton>
|
||||||
<ChipLink onClick={onClick} href="/copenhagen">
|
<ChipLink onPress={onPress} href="/copenhagen">
|
||||||
See all Copenhagen
|
See all Copenhagen
|
||||||
</ChipLink>
|
</ChipLink>
|
||||||
<ChipButton onPress={onPress}>See all Copenhagen</ChipButton>
|
<ChipButton onPress={onPress}>See all Copenhagen</ChipButton>
|
||||||
<ChipLink onClick={onClick} href="/copenhagen">
|
<ChipLink onPress={onPress} href="/copenhagen">
|
||||||
See all Copenhagen
|
See all Copenhagen
|
||||||
</ChipLink>
|
</ChipLink>
|
||||||
<ChipButton onPress={onPress}>See all Copenhagen</ChipButton>
|
<ChipButton onPress={onPress}>See all Copenhagen</ChipButton>
|
||||||
<ChipLink onClick={onClick} href="/copenhagen">
|
<ChipLink onPress={onPress} href="/copenhagen">
|
||||||
See all Copenhagen
|
See all Copenhagen
|
||||||
</ChipLink>
|
</ChipLink>
|
||||||
</Chips>
|
</Chips>
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
background-color: var(--Surface-Primary-Hover);
|
background-color: var(--Surface-Primary-Hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.Outlined:focus,
|
|
||||||
.Outlined:active {
|
.Outlined:active {
|
||||||
border-color: var(--Border-Interactive-Selected);
|
border-color: var(--Border-Interactive-Selected);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import type { Meta, StoryObj } from '@storybook/react'
|
import type { Meta, StoryObj } from '@storybook/react'
|
||||||
|
|
||||||
import { ChipLink } from './ChipLink.tsx'
|
|
||||||
import { MaterialIcon } from '../Icons/MaterialIcon'
|
import { MaterialIcon } from '../Icons/MaterialIcon'
|
||||||
|
import { ChipLink } from './ChipLink.tsx'
|
||||||
|
|
||||||
const meta: Meta<typeof ChipLink> = {
|
const meta: Meta<typeof ChipLink> = {
|
||||||
title: 'Components/Chip/ChipLInk 🚧',
|
title: 'Components/Chip/ChipLink',
|
||||||
component: ChipLink,
|
component: ChipLink,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ type Story = StoryObj<typeof ChipLink>
|
|||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
args: {
|
args: {
|
||||||
href: '/',
|
href: '/',
|
||||||
onClick: (e) => e.preventDefault(),
|
onPress: (e) => console.log(e),
|
||||||
children: (
|
children: (
|
||||||
<>
|
<>
|
||||||
Link Chip
|
Link Chip
|
||||||
|
|||||||
@@ -1,19 +1,24 @@
|
|||||||
|
import { cx } from 'class-variance-authority'
|
||||||
import { Typography } from '../Typography'
|
import { Typography } from '../Typography'
|
||||||
|
|
||||||
import styles from './chip-link.module.css'
|
import styles from './chip-link.module.css'
|
||||||
|
|
||||||
import type { PropsWithChildren } from 'react'
|
import type { PropsWithChildren } from 'react'
|
||||||
|
import {
|
||||||
|
Link as LinkRAC,
|
||||||
|
LinkProps as LinkRACProps,
|
||||||
|
} from 'react-aria-components'
|
||||||
|
|
||||||
export function ChipLink({
|
export function ChipLink({
|
||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: PropsWithChildren<React.AnchorHTMLAttributes<HTMLAnchorElement>>) {
|
}: PropsWithChildren<LinkRACProps>) {
|
||||||
return (
|
return (
|
||||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||||
<a {...props} className={[styles.chip, className].join(' ')}>
|
<LinkRAC {...props} className={cx(styles.chip, className)}>
|
||||||
{children}
|
{children}
|
||||||
</a>
|
</LinkRAC>
|
||||||
</Typography>
|
</Typography>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
.chip {
|
.chip {
|
||||||
background-color: var(--Component-Button-Inverted-Fill-Default);
|
background-color: var(--Component-Button-Inverted-Fill-Default);
|
||||||
border-color: var(--Component-Button-Inverted-Border-Default);
|
border: 1px solid var(--Component-Button-Inverted-Border-Default);
|
||||||
border-style: solid;
|
|
||||||
border-width: 1px;
|
|
||||||
border-radius: var(--Corner-radius-sm);
|
border-radius: var(--Corner-radius-sm);
|
||||||
padding: var(--Space-x1) var(--Space-x15);
|
padding: var(--Space-x1) var(--Space-x15);
|
||||||
color: var(--Text-Interactive-Default);
|
color: var(--Text-Interactive-Default);
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
gap: var(--Space-x05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.chip:hover {
|
.chip:hover {
|
||||||
/* TODO: change to proper Component-variable once it is available */
|
background-color: var(--Surface-Primary-Hover-Accent);
|
||||||
background-color: var(--Scandic-Peach-10);
|
}
|
||||||
/* TODO: change to proper Component-variable once it is available */
|
|
||||||
color: var(--Scandic-Red-100);
|
.chip:focus {
|
||||||
|
outline-offset: 4px;
|
||||||
|
outline-color: var(--Border-Interactive-Focus);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user