Merged in feat/SW-1452-city-page-filter-2 (pull request #1392)
feat(SW-1452): Added filtering and sorting to destination city pages * feat(SW-1452): Added filtering and sorting to destination city pages * feat(SW-1452): Added temporary component for country pages to avoid Context issues Approved-by: Matilda Landström
This commit is contained in:
5
server/routers/contentstack/metadata/input.ts
Normal file
5
server/routers/contentstack/metadata/input.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { z } from "zod"
|
||||
|
||||
export const getMetadataInput = z.object({
|
||||
subpage: z.string().optional(),
|
||||
})
|
||||
@@ -2,6 +2,7 @@ import { z } from "zod"
|
||||
|
||||
import { attributesSchema as hotelAttributesSchema } from "../../hotels/schemas/hotel"
|
||||
import { tempImageVaultAssetSchema } from "../schemas/imageVault"
|
||||
import { systemSchema } from "../schemas/system"
|
||||
import { getDescription, getImage, getTitle } from "./utils"
|
||||
|
||||
import type { Metadata } from "next"
|
||||
@@ -61,6 +62,17 @@ export const rawMetadataSchema = z.object({
|
||||
})
|
||||
.optional()
|
||||
.nullable(),
|
||||
destination_settings: z
|
||||
.object({
|
||||
city_denmark: z.string().optional().nullable(),
|
||||
city_finland: z.string().optional().nullable(),
|
||||
city_germany: z.string().optional().nullable(),
|
||||
city_poland: z.string().optional().nullable(),
|
||||
city_norway: z.string().optional().nullable(),
|
||||
city_sweden: z.string().optional().nullable(),
|
||||
})
|
||||
.optional()
|
||||
.nullable(),
|
||||
heading: z.string().optional().nullable(),
|
||||
preamble: z.string().optional().nullable(),
|
||||
header: z
|
||||
@@ -77,6 +89,10 @@ export const rawMetadataSchema = z.object({
|
||||
.pick({ name: true, address: true, hotelContent: true, gallery: true })
|
||||
.optional()
|
||||
.nullable(),
|
||||
cityName: z.string().optional().nullable(),
|
||||
cityFilter: z.string().optional().nullable(),
|
||||
cityFilterType: z.enum(["facility", "surroundings"]).optional().nullable(),
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export const metadataSchema = rawMetadataSchema.transform(async (data) => {
|
||||
|
||||
@@ -16,8 +16,9 @@ import { contentStackUidWithServiceProcedure, router } from "@/server/trpc"
|
||||
import { generateTag } from "@/utils/generateTag"
|
||||
|
||||
import { getHotel } from "../../hotels/query"
|
||||
import { getMetadataInput } from "./input"
|
||||
import { metadataSchema } from "./output"
|
||||
import { affix } from "./utils"
|
||||
import { affix, getCityData } from "./utils"
|
||||
|
||||
import { PageContentTypeEnum } from "@/types/requests/contentType"
|
||||
import type { RawMetadataSchema } from "@/types/trpc/routers/contentstack/metadata"
|
||||
@@ -117,76 +118,85 @@ async function getTransformedMetadata(data: unknown) {
|
||||
}
|
||||
|
||||
export const metadataQueryRouter = router({
|
||||
get: contentStackUidWithServiceProcedure.query(async ({ ctx }) => {
|
||||
const variables = {
|
||||
lang: ctx.lang,
|
||||
uid: ctx.uid,
|
||||
}
|
||||
get: contentStackUidWithServiceProcedure
|
||||
.input(getMetadataInput)
|
||||
.query(async ({ ctx, input }) => {
|
||||
const variables = {
|
||||
lang: ctx.lang,
|
||||
uid: ctx.uid,
|
||||
}
|
||||
|
||||
switch (ctx.contentType) {
|
||||
case PageContentTypeEnum.accountPage:
|
||||
const accountPageResponse = await fetchMetadata<{
|
||||
account_page: RawMetadataSchema
|
||||
}>(GetAccountPageMetadata, variables)
|
||||
return getTransformedMetadata(accountPageResponse.account_page)
|
||||
case PageContentTypeEnum.collectionPage:
|
||||
const collectionPageResponse = await fetchMetadata<{
|
||||
collection_page: RawMetadataSchema
|
||||
}>(GetCollectionPageMetadata, variables)
|
||||
return getTransformedMetadata(collectionPageResponse.collection_page)
|
||||
case PageContentTypeEnum.contentPage:
|
||||
const contentPageResponse = await fetchMetadata<{
|
||||
content_page: RawMetadataSchema
|
||||
}>(GetContentPageMetadata, variables)
|
||||
return getTransformedMetadata(contentPageResponse.content_page)
|
||||
case PageContentTypeEnum.destinationOverviewPage:
|
||||
const destinationOverviewPageResponse = await fetchMetadata<{
|
||||
destination_overview_page: RawMetadataSchema
|
||||
}>(GetDestinationOverviewPageMetadata, variables)
|
||||
return getTransformedMetadata(
|
||||
destinationOverviewPageResponse.destination_overview_page
|
||||
)
|
||||
case PageContentTypeEnum.destinationCountryPage:
|
||||
const destinationCountryPageResponse = await fetchMetadata<{
|
||||
destination_country_page: RawMetadataSchema
|
||||
}>(GetDestinationCountryPageMetadata, variables)
|
||||
return getTransformedMetadata(
|
||||
destinationCountryPageResponse.destination_country_page
|
||||
)
|
||||
case PageContentTypeEnum.destinationCityPage:
|
||||
const destinationCityPageResponse = await fetchMetadata<{
|
||||
destination_city_page: RawMetadataSchema
|
||||
}>(GetDestinationCityPageMetadata, variables)
|
||||
return getTransformedMetadata(
|
||||
destinationCityPageResponse.destination_city_page
|
||||
)
|
||||
case PageContentTypeEnum.loyaltyPage:
|
||||
const loyaltyPageResponse = await fetchMetadata<{
|
||||
loyalty_page: RawMetadataSchema
|
||||
}>(GetLoyaltyPageMetadata, variables)
|
||||
return getTransformedMetadata(loyaltyPageResponse.loyalty_page)
|
||||
case PageContentTypeEnum.hotelPage:
|
||||
const hotelPageResponse = await fetchMetadata<{
|
||||
hotel_page: RawMetadataSchema
|
||||
}>(GetHotelPageMetadata, variables)
|
||||
const hotelPageData = hotelPageResponse.hotel_page
|
||||
const hotelData = hotelPageData.hotel_page_id
|
||||
? await getHotel(
|
||||
{
|
||||
hotelId: hotelPageData.hotel_page_id,
|
||||
isCardOnlyPayment: false,
|
||||
language: ctx.lang,
|
||||
},
|
||||
ctx.serviceToken
|
||||
)
|
||||
: null
|
||||
switch (ctx.contentType) {
|
||||
case PageContentTypeEnum.accountPage:
|
||||
const accountPageResponse = await fetchMetadata<{
|
||||
account_page: RawMetadataSchema
|
||||
}>(GetAccountPageMetadata, variables)
|
||||
return getTransformedMetadata(accountPageResponse.account_page)
|
||||
case PageContentTypeEnum.collectionPage:
|
||||
const collectionPageResponse = await fetchMetadata<{
|
||||
collection_page: RawMetadataSchema
|
||||
}>(GetCollectionPageMetadata, variables)
|
||||
return getTransformedMetadata(collectionPageResponse.collection_page)
|
||||
case PageContentTypeEnum.contentPage:
|
||||
const contentPageResponse = await fetchMetadata<{
|
||||
content_page: RawMetadataSchema
|
||||
}>(GetContentPageMetadata, variables)
|
||||
return getTransformedMetadata(contentPageResponse.content_page)
|
||||
case PageContentTypeEnum.destinationOverviewPage:
|
||||
const destinationOverviewPageResponse = await fetchMetadata<{
|
||||
destination_overview_page: RawMetadataSchema
|
||||
}>(GetDestinationOverviewPageMetadata, variables)
|
||||
return getTransformedMetadata(
|
||||
destinationOverviewPageResponse.destination_overview_page
|
||||
)
|
||||
case PageContentTypeEnum.destinationCountryPage:
|
||||
const destinationCountryPageResponse = await fetchMetadata<{
|
||||
destination_country_page: RawMetadataSchema
|
||||
}>(GetDestinationCountryPageMetadata, variables)
|
||||
return getTransformedMetadata(
|
||||
destinationCountryPageResponse.destination_country_page
|
||||
)
|
||||
case PageContentTypeEnum.destinationCityPage:
|
||||
const destinationCityPageResponse = await fetchMetadata<{
|
||||
destination_city_page: RawMetadataSchema
|
||||
}>(GetDestinationCityPageMetadata, variables)
|
||||
const cityData = await getCityData(
|
||||
destinationCityPageResponse.destination_city_page,
|
||||
input,
|
||||
ctx.serviceToken,
|
||||
ctx.lang
|
||||
)
|
||||
return getTransformedMetadata({
|
||||
...destinationCityPageResponse.destination_city_page,
|
||||
...cityData,
|
||||
})
|
||||
case PageContentTypeEnum.loyaltyPage:
|
||||
const loyaltyPageResponse = await fetchMetadata<{
|
||||
loyalty_page: RawMetadataSchema
|
||||
}>(GetLoyaltyPageMetadata, variables)
|
||||
return getTransformedMetadata(loyaltyPageResponse.loyalty_page)
|
||||
case PageContentTypeEnum.hotelPage:
|
||||
const hotelPageResponse = await fetchMetadata<{
|
||||
hotel_page: RawMetadataSchema
|
||||
}>(GetHotelPageMetadata, variables)
|
||||
const hotelPageData = hotelPageResponse.hotel_page
|
||||
const hotelData = hotelPageData.hotel_page_id
|
||||
? await getHotel(
|
||||
{
|
||||
hotelId: hotelPageData.hotel_page_id,
|
||||
isCardOnlyPayment: false,
|
||||
language: ctx.lang,
|
||||
},
|
||||
ctx.serviceToken
|
||||
)
|
||||
: null
|
||||
|
||||
return getTransformedMetadata({
|
||||
...hotelPageData,
|
||||
hotelData: hotelData?.hotel,
|
||||
})
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}),
|
||||
return getTransformedMetadata({
|
||||
...hotelPageData,
|
||||
hotelData: hotelData?.hotel,
|
||||
})
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
@@ -1,7 +1,19 @@
|
||||
import { getFiltersFromHotels } from "@/stores/hotel-data/helper"
|
||||
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import {
|
||||
getCityByCityIdentifier,
|
||||
getHotelIdsByCityIdentifier,
|
||||
getHotelsByHotelIds,
|
||||
} from "../../hotels/utils"
|
||||
|
||||
import { RTETypeEnum } from "@/types/rte/enums"
|
||||
import type { RawMetadataSchema } from "@/types/trpc/routers/contentstack/metadata"
|
||||
import type {
|
||||
MetadataInputSchema,
|
||||
RawMetadataSchema,
|
||||
} from "@/types/trpc/routers/contentstack/metadata"
|
||||
import type { Lang } from "@/constants/languages"
|
||||
|
||||
export const affix = "metadata"
|
||||
|
||||
@@ -75,6 +87,27 @@ export async function getTitle(data: RawMetadataSchema) {
|
||||
}
|
||||
)
|
||||
}
|
||||
if (data.system.content_type_uid === "destination_city_page") {
|
||||
if (data.cityName) {
|
||||
if (data.cityFilter) {
|
||||
if (data.cityFilterType === "facility") {
|
||||
return intl.formatMessage(
|
||||
{ id: "Hotels with {filter} in {cityName}" },
|
||||
{ cityName: data.cityName, filter: data.cityFilter }
|
||||
)
|
||||
} else if (data.cityFilterType === "surroundings") {
|
||||
return intl.formatMessage(
|
||||
{ id: "Hotels near {filter} in {cityName}" },
|
||||
{ cityName: data.cityName, filter: data.cityFilter }
|
||||
)
|
||||
}
|
||||
}
|
||||
return intl.formatMessage(
|
||||
{ id: "Hotels in {city}" },
|
||||
{ city: data.cityName }
|
||||
)
|
||||
}
|
||||
}
|
||||
if (data.web?.breadcrumbs?.title) {
|
||||
return data.web.breadcrumbs.title
|
||||
}
|
||||
@@ -149,3 +182,64 @@ export function getImage(data: RawMetadataSchema) {
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
export async function getCityData(
|
||||
data: RawMetadataSchema,
|
||||
input: MetadataInputSchema,
|
||||
serviceToken: string,
|
||||
lang: Lang
|
||||
) {
|
||||
const destinationSettings = data.destination_settings
|
||||
const cityFilter = input.subpage
|
||||
let cityIdentifier
|
||||
let cityData
|
||||
let filterType
|
||||
|
||||
if (destinationSettings) {
|
||||
const {
|
||||
city_sweden,
|
||||
city_norway,
|
||||
city_denmark,
|
||||
city_finland,
|
||||
city_germany,
|
||||
city_poland,
|
||||
} = destinationSettings
|
||||
const cities = [
|
||||
city_denmark,
|
||||
city_finland,
|
||||
city_germany,
|
||||
city_poland,
|
||||
city_norway,
|
||||
city_sweden,
|
||||
].filter((city): city is string => Boolean(city))
|
||||
|
||||
cityIdentifier = cities[0]
|
||||
if (cityIdentifier) {
|
||||
cityData = await getCityByCityIdentifier(cityIdentifier, serviceToken)
|
||||
const hotelIds = await getHotelIdsByCityIdentifier(
|
||||
cityIdentifier,
|
||||
serviceToken
|
||||
)
|
||||
|
||||
const hotels = await getHotelsByHotelIds(hotelIds, lang, serviceToken)
|
||||
|
||||
if (cityFilter) {
|
||||
const allFilters = getFiltersFromHotels(hotels)
|
||||
const facilityFilter = allFilters.facilityFilters.find(
|
||||
(f) => f.slug === cityFilter
|
||||
)
|
||||
const surroudingsFilter = allFilters.surroundingsFilters.find(
|
||||
(f) => f.slug === cityFilter
|
||||
)
|
||||
|
||||
if (facilityFilter) {
|
||||
filterType = "facility"
|
||||
} else if (surroudingsFilter) {
|
||||
filterType = "surroundings"
|
||||
}
|
||||
}
|
||||
}
|
||||
return { cityName: cityData?.name, cityFilter, cityFilterType: filterType }
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user