Merged in feat/LOY-400-create-spend-points-modal (pull request #3131)
Feat/LOY-400 create spend points modal * feat(LOY-400): Added custom button to my pages overview and skeleton file to custom modal for my points. * feat(LOY-400): Added custom button to my pages overview and components for custom modal for my points. * feat(LOY-400): Changed some style and infogridcardover * feat(LOY-400):Removed custom card components and changed in infoCard: Added imagePosition top, added optional height prop. In Card: Changed Text-wrap styling, added min-width styling to buttons, added optional Icon prop, added optional height prop * feat(LOY-400):Added linkList, LinkListItem component and messageBanner component. Added granola illustration. * feat(LOY-400): Removed background in several illustrations. Added component for illustration. Fixed LinkedList and styling for UsePointsButton. * feat(LOY-400): Added modal to PointsToSpendCard and fixed UsePointsButton. * fix(LOY-400):added some styling * feat(LOY-400): Linked Modal to contentstack and fetch the data in cards with UsePointsModal for now * feat(LOY-400): changed link to aria-component, cleaned up a bit * feat(LOY-400): Changed height for larger modals in mobile, fixed zod schema for no illustration input, cleaned up * fix(LOY-400): fixed graphql after rebase * fix(LOY-400): mini fix * fix(LOY-400): fixed pr-comments * fix(LOY-400): fixed some PR-comments * fix(LOY-400): fixed a PR-comment * feat(LOY-400): added size prop to ilustration in LinkListItem to be able to use illustrations in IllustrationByIconName * fix(LOY-400): fixed pr-comments * Merged in feat/LOY-402-pre-ticked-book-reward-night-in-booking-flow (pull request #3210) Feat/LOY-402 pre ticked book reward night in booking flow * feat(LOY-402): Changed UsePointsModal structure to handle button actions in card. * feat(LOY-402): added functionality for book now button * feat(LOY-400): pr comment fix * feat(LOY-402): transformed the contentstack data * fix(LOY-402): fixed pr comments Approved-by: Chuma Mcphoy (We Ahead) Approved-by: Anton Gunnarsson Approved-by: Matilda Landström * Merged in feat/LOY-404-add-tracking-for-spend-points-modal (pull request #3229) Feat/LOY-404 add tracking for spend points modal * feat(LOY-402): Changed UsePointsModal structure to handle button actions in card. * feat(LOY-402): added functionality for book now button * feat(LOY-400): pr comment fix * feat(LOY-402): transformed the contentstack data * feat(LOY-404): added tracking * fix(LOY-404): fix for session storage removal of bookNowFromPointsModal * feat(LOY-404): added consts * fix(LOY-404): moved foxusWidget const * fix(LOY-404): moved BOOKING_WIDGET_STATE const * fix(LOY-404):fix Approved-by: Matilda Landström * fix(LOY-400): some fixes * feat(LOY-400): created linkList storybook Approved-by: Chuma Mcphoy (We Ahead) Approved-by: Matilda Landström
This commit is contained in:
117
packages/trpc/lib/graphql/Query/UsePointsModal.graphql.ts
Normal file
117
packages/trpc/lib/graphql/Query/UsePointsModal.graphql.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import { gql } from "graphql-tag"
|
||||
|
||||
import { AccountPageRef } from "../Fragments/AccountPage/Ref.graphql"
|
||||
import { CampaignOverviewPageRef } from "../Fragments/CampaignOverviewPage/Ref.graphql"
|
||||
import { CampaignPageRef } from "../Fragments/CampaignPage/Ref.graphql"
|
||||
import { CollectionPageRef } from "../Fragments/CollectionPage/Ref.graphql"
|
||||
import { ContentPageRef } from "../Fragments/ContentPage/Ref.graphql"
|
||||
import { DestinationCityPageRef } from "../Fragments/DestinationCityPage/Ref.graphql"
|
||||
import { DestinationCountryPageRef } from "../Fragments/DestinationCountryPage/Ref.graphql"
|
||||
import { DestinationOverviewPageRef } from "../Fragments/DestinationOverviewPage/Ref.graphql"
|
||||
import { HotelPageRef } from "../Fragments/HotelPage/Ref.graphql"
|
||||
import { LoyaltyPageRef } from "../Fragments/LoyaltyPage/Ref.graphql"
|
||||
import { AccountPageLink } from "../Fragments/PageLink/AccountPageLink.graphql"
|
||||
import { CampaignOverviewPageLink } from "../Fragments/PageLink/CampaignOverviewPageLink.graphql"
|
||||
import { CampaignPageLink } from "../Fragments/PageLink/CampaignPageLink.graphql"
|
||||
import { CollectionPageLink } from "../Fragments/PageLink/CollectionPageLink.graphql"
|
||||
import { ContentPageLink } from "../Fragments/PageLink/ContentPageLink.graphql"
|
||||
import { DestinationCityPageLink } from "../Fragments/PageLink/DestinationCityPageLink.graphql"
|
||||
import { DestinationCountryPageLink } from "../Fragments/PageLink/DestinationCountryPageLink.graphql"
|
||||
import { DestinationOverviewPageLink } from "../Fragments/PageLink/DestinationOverviewPageLink.graphql"
|
||||
import { HotelPageLink } from "../Fragments/PageLink/HotelPageLink.graphql"
|
||||
import { LoyaltyPageLink } from "../Fragments/PageLink/LoyaltyPageLink.graphql"
|
||||
import { PromoCampaignPageLink } from "../Fragments/PageLink/PromoCampaignPageLink.graphql"
|
||||
import { StartPageLink } from "../Fragments/PageLink/StartPageLink.graphql"
|
||||
import { PromoCampaignPageRef } from "../Fragments/PromoCampaignPage/Ref.graphql"
|
||||
import { StartPageRef } from "../Fragments/StartPage/Ref.graphql"
|
||||
|
||||
export const GetUsePointsModal = gql`
|
||||
query GetUsePointsModal($locale: String!) {
|
||||
all_usepointsmodal(locale: $locale) {
|
||||
items {
|
||||
image
|
||||
link_group {
|
||||
link_text
|
||||
illustration
|
||||
illustration_size
|
||||
is_contentstack_link
|
||||
external_link {
|
||||
href
|
||||
}
|
||||
linkConnection {
|
||||
edges {
|
||||
node {
|
||||
__typename
|
||||
...AccountPageLink
|
||||
...CampaignOverviewPageLink
|
||||
...CampaignPageLink
|
||||
...CollectionPageLink
|
||||
...ContentPageLink
|
||||
...DestinationCityPageLink
|
||||
...DestinationCountryPageLink
|
||||
...DestinationOverviewPageLink
|
||||
...HotelPageLink
|
||||
...LoyaltyPageLink
|
||||
...StartPageLink
|
||||
...PromoCampaignPageLink
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
${AccountPageLink}
|
||||
${CampaignOverviewPageLink}
|
||||
${CampaignPageLink}
|
||||
${CollectionPageLink}
|
||||
${ContentPageLink}
|
||||
${DestinationCityPageLink}
|
||||
${DestinationCountryPageLink}
|
||||
${DestinationOverviewPageLink}
|
||||
${HotelPageLink}
|
||||
${LoyaltyPageLink}
|
||||
${StartPageLink}
|
||||
${PromoCampaignPageLink}
|
||||
`
|
||||
export const GetUsePointsModalRefs = gql`
|
||||
query GetUsePointsModalRefs($locale: String!) {
|
||||
all_usepointsmodal(locale: $locale) {
|
||||
items {
|
||||
link_group {
|
||||
linkConnection {
|
||||
edges {
|
||||
node {
|
||||
__typename
|
||||
...AccountPageRef
|
||||
...CampaignOverviewPageRef
|
||||
...CampaignPageRef
|
||||
...CollectionPageRef
|
||||
...ContentPageRef
|
||||
...DestinationCityPageRef
|
||||
...DestinationCountryPageRef
|
||||
...DestinationOverviewPageRef
|
||||
...HotelPageRef
|
||||
...LoyaltyPageRef
|
||||
...StartPageRef
|
||||
...PromoCampaignPageRef
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
${AccountPageRef}
|
||||
${CampaignOverviewPageRef}
|
||||
${CampaignPageRef}
|
||||
${CollectionPageRef}
|
||||
${ContentPageRef}
|
||||
${DestinationCityPageRef}
|
||||
${DestinationCountryPageRef}
|
||||
${DestinationOverviewPageRef}
|
||||
${HotelPageRef}
|
||||
${LoyaltyPageRef}
|
||||
${StartPageRef}
|
||||
${PromoCampaignPageRef}
|
||||
`
|
||||
@@ -0,0 +1,4 @@
|
||||
import { mergeRouters } from "../../.."
|
||||
import { usePointsModalQueryRouter } from "./query"
|
||||
|
||||
export const usePointsModalRouter = mergeRouters(usePointsModalQueryRouter)
|
||||
@@ -0,0 +1,84 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { transformedImageVaultAssetSchema } from "@scandic-hotels/common/utils/imageVault"
|
||||
import { IconName } from "@scandic-hotels/design-system/Icons/iconName"
|
||||
|
||||
import { linkConnectionRefs } from "../schemas/linkConnection"
|
||||
import { linkUnionSchema, transformPageLink } from "../schemas/pageLinks"
|
||||
|
||||
export type UsePointsModalData = z.output<typeof usePointsModalSchema>
|
||||
export type UsePointsModalRefsData = z.output<typeof usePointsModalRefsSchema>
|
||||
|
||||
export const linkConnectionSchema = z
|
||||
.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: linkUnionSchema,
|
||||
})
|
||||
),
|
||||
})
|
||||
.transform((data) => {
|
||||
if (data.edges.length) {
|
||||
const linkNode = data.edges[0].node
|
||||
if (linkNode) {
|
||||
const link = transformPageLink(linkNode)
|
||||
if (link && link.url) {
|
||||
return link.url
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
const usePointsModalItemsSchema = z.object({
|
||||
image: transformedImageVaultAssetSchema,
|
||||
link_group: z
|
||||
.array(
|
||||
z.object({
|
||||
link_text: z.string().default(""),
|
||||
is_contentstack_link: z.boolean(),
|
||||
illustration: z.nativeEnum(IconName).nullish(),
|
||||
illustration_size: z
|
||||
.enum(["small", "medium", "large"])
|
||||
.nullish()
|
||||
.default("large"),
|
||||
external_link: z
|
||||
.object({
|
||||
href: z.string().default(""),
|
||||
})
|
||||
.optional(),
|
||||
linkConnection: linkConnectionSchema,
|
||||
})
|
||||
)
|
||||
.transform((links) =>
|
||||
links.map((link) => ({
|
||||
text: link.link_text || "",
|
||||
isExternal: !link.is_contentstack_link,
|
||||
href: link.is_contentstack_link
|
||||
? link.linkConnection || ""
|
||||
: link.external_link?.href || "",
|
||||
illustration: link.illustration
|
||||
? {
|
||||
illustration: link.illustration,
|
||||
size: link.illustration_size || "large",
|
||||
}
|
||||
: undefined,
|
||||
}))
|
||||
),
|
||||
})
|
||||
|
||||
export const usePointsModalSchema = z.object({
|
||||
all_usepointsmodal: z.object({
|
||||
items: z.array(usePointsModalItemsSchema),
|
||||
}),
|
||||
})
|
||||
|
||||
export const usePointsModalRefsSchema = z.object({
|
||||
all_usepointsmodal: z.object({
|
||||
items: z.array(
|
||||
z.object({
|
||||
link_group: z.array(linkConnectionRefs),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,90 @@
|
||||
import { createCounter } from "@scandic-hotels/common/telemetry"
|
||||
|
||||
import { router } from "../../.."
|
||||
import { notFound } from "../../../errors"
|
||||
import {
|
||||
GetUsePointsModal,
|
||||
GetUsePointsModalRefs,
|
||||
} from "../../../graphql/Query/UsePointsModal.graphql"
|
||||
import { request } from "../../../graphql/request"
|
||||
import { contentstackBaseProcedure } from "../../../procedures"
|
||||
import {
|
||||
type UsePointsModalData,
|
||||
type UsePointsModalRefsData,
|
||||
usePointsModalRefsSchema,
|
||||
usePointsModalSchema,
|
||||
} from "./output"
|
||||
|
||||
export const usePointsModalQueryRouter = router({
|
||||
get: contentstackBaseProcedure.query(async ({ ctx }) => {
|
||||
const { lang, uid } = ctx
|
||||
|
||||
const getRefsCounter = createCounter(
|
||||
"trpc.contentstack",
|
||||
"usePointsModal.get.refs"
|
||||
)
|
||||
const metricsRefs = getRefsCounter.init({
|
||||
lang,
|
||||
uid,
|
||||
})
|
||||
|
||||
metricsRefs.start()
|
||||
const refsResponse = await request<UsePointsModalRefsData>(
|
||||
GetUsePointsModalRefs,
|
||||
{ locale: lang },
|
||||
{
|
||||
key: `contentstack:usePointsModal:${lang}:refs`,
|
||||
ttl: "max",
|
||||
}
|
||||
)
|
||||
if (!refsResponse.data) {
|
||||
const notFoundError = notFound(refsResponse)
|
||||
metricsRefs.noDataError()
|
||||
throw notFoundError
|
||||
}
|
||||
|
||||
const validatedRefsData = usePointsModalRefsSchema.safeParse(
|
||||
refsResponse.data
|
||||
)
|
||||
|
||||
if (!validatedRefsData.success) {
|
||||
metricsRefs.validationError(validatedRefsData.error)
|
||||
return null
|
||||
}
|
||||
|
||||
metricsRefs.success()
|
||||
|
||||
const getCounter = createCounter("trpc.contentstack", "usePointsModal.get")
|
||||
|
||||
const metrics = getCounter.init({
|
||||
lang,
|
||||
uid,
|
||||
})
|
||||
metrics.start()
|
||||
|
||||
const response = await request<UsePointsModalData>(
|
||||
GetUsePointsModal,
|
||||
{ locale: lang },
|
||||
{
|
||||
key: `contentstack:usePointsModal:${lang}`,
|
||||
ttl: "max",
|
||||
}
|
||||
)
|
||||
|
||||
if (!response.data) {
|
||||
const notFoundError = notFound(response)
|
||||
metrics.noDataError()
|
||||
throw notFoundError
|
||||
}
|
||||
|
||||
const validatedResponse = usePointsModalSchema.safeParse(response.data)
|
||||
|
||||
if (!validatedResponse.success) {
|
||||
metrics.validationError(validatedResponse.error)
|
||||
return null
|
||||
}
|
||||
|
||||
metrics.success()
|
||||
return validatedResponse.data
|
||||
}),
|
||||
})
|
||||
@@ -20,6 +20,7 @@ import { profilingConsentRouter } from "./profilingConsent"
|
||||
import { promoCampaignPageRouter } from "./promoCampaignPage"
|
||||
import { rewardRouter } from "./reward"
|
||||
import { startPageRouter } from "./startPage"
|
||||
import { usePointsModalRouter } from "./UsePointsModal"
|
||||
|
||||
export const contentstackRouter = router({
|
||||
accountPage: accountPageRouter,
|
||||
@@ -43,4 +44,5 @@ export const contentstackRouter = router({
|
||||
partner: partnerRouter,
|
||||
promoCampaignPage: promoCampaignPageRouter,
|
||||
profilingConsent: profilingConsentRouter,
|
||||
usePointsModal: usePointsModalRouter,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user