feat(SW-1012): Added possibility for multiple include params for hotels

This commit is contained in:
Erik Tiekstra
2024-11-26 11:07:47 +01:00
committed by Fredrik Thorsson
parent 92bbfcf533
commit 05006506f0
17 changed files with 218 additions and 57 deletions

View File

@@ -51,6 +51,10 @@ export const getHotelDataInputSchema = z.object({
isCardOnlyPayment: z.boolean().optional(),
})
export const getRestaurantsInputSchema = z.object({
hotelId: z.string(),
})
export type HotelDataInput = z.input<typeof getHotelDataInputSchema>
export const getBreakfastPackageInputSchema = z.object({

View File

@@ -4,15 +4,21 @@ import { ChildBedTypeEnum, type PaymentMethodEnum } from "@/constants/booking"
import { dt } from "@/lib/dt"
import { toLang } from "@/server/utils"
import { imageMetaDataSchema, imageSizesSchema } from "./schemas/image"
import {
imageMetaDataSchema,
imageSchema,
imageSizesSchema,
} from "./schemas/image"
import { restaurantSchema } from "./schemas/restaurants"
import { roomSchema } from "./schemas/room"
import { specialAlertsSchema } from "./schemas/specialAlerts"
import { getPoiGroupByCategoryName } from "./utils"
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
import { AlertTypeEnum } from "@/types/enums/alert"
import { CurrencyEnum } from "@/types/enums/currency"
import { FacilityEnum } from "@/types/enums/facilities"
import { PackageTypeEnum } from "@/types/enums/packages"
import { RestaurantData, RoomData } from "@/types/hotel"
const ratingsSchema = z
.object({
@@ -159,11 +165,6 @@ export const facilitySchema = z.object({
),
})
export const imageSchema = z.object({
metaData: imageMetaDataSchema,
imageSizes: imageSizesSchema,
})
export const gallerySchema = z.object({
heroImages: z.array(imageSchema),
smallerImages: z.array(imageSchema),
@@ -332,36 +333,6 @@ const socialMediaSchema = z.object({
facebook: z.string().optional(),
})
const specialAlertSchema = z.object({
type: z.string(),
title: z.string().optional(),
description: z.string().optional(),
displayInBookingFlow: z.boolean(),
startDate: z.string().optional(),
endDate: z.string().optional(),
})
const specialAlertsSchema = z
.array(specialAlertSchema)
.transform((data) => {
const now = dt().utc().format("YYYY-MM-DD")
const filteredAlerts = data.filter((alert) => {
const shouldShowNow =
alert.startDate && alert.endDate
? alert.startDate <= now && alert.endDate >= now
: true
const hasText = alert.description || alert.title
return shouldShowNow && hasText
})
return filteredAlerts.map((alert, idx) => ({
id: `alert-${alert.type}-${idx}`,
type: AlertTypeEnum.Info,
heading: alert.title || null,
text: alert.description || null,
}))
})
.default([])
const relationshipsSchema = z.object({
restaurants: z.object({
links: z.object({
@@ -487,6 +458,19 @@ export const hotelAttributesSchema = z.object({
specialNeedGroups: z.array(specialNeedGroupSchema),
})
const includedSchema = z
.array(z.union([roomSchema, restaurantSchema]))
.transform((data) => {
const rooms = data.filter((d) => d.type === "roomcategories") as RoomData[]
const restaurants = data.filter(
(d) => d.type === "restaurants"
) as RestaurantData[]
return {
rooms,
restaurants,
}
})
// NOTE: Find schema at: https://aks-test.scandichotels.com/hotel/swagger/v1/index.html
export const getHotelDataSchema = z.object({
data: z.object({
@@ -504,7 +488,7 @@ export const getHotelDataSchema = z.object({
}),
// NOTE: We can pass an "include" param to the hotel API to retrieve
// additional data for an individual hotel.
included: z.array(roomSchema).optional(),
included: includedSchema.optional(),
})
export const childrenSchema = z.object({

View File

@@ -51,6 +51,14 @@ const getHotelCounter = meter.createCounter("trpc.hotel.get")
const getHotelSuccessCounter = meter.createCounter("trpc.hotel.get-success")
const getHotelFailCounter = meter.createCounter("trpc.hotel.get-fail")
const getRestaurantsCounter = meter.createCounter("trpc.hotel.restaurants.get")
const getRestaurantsSuccessCounter = meter.createCounter(
"trpc.hotel.restaurants.get-success"
)
const getRestaurantsFailCounter = meter.createCounter(
"trpc.hotel.restaurants.get-fail"
)
const getPackagesCounter = meter.createCounter("trpc.hotel.packages.get")
const getPackagesSuccessCounter = meter.createCounter(
"trpc.hotel.packages.get-success"
@@ -101,12 +109,12 @@ export const getHotelData = cache(
async (input: HotelDataInput, serviceToken: string) => {
const { hotelId, language, isCardOnlyPayment } = input
const params: Record<string, string> = {
const params: Record<string, string | string[]> = {
hotelId,
language,
}
params.include = "RoomCategories" // "RoomCategories","NearbyHotels","Restaurants","City",
params.include = ["RoomCategories", "Restaurants"] // "RoomCategories","NearbyHotels","Restaurants","City",
getHotelCounter.add(1, {
hotelId,
@@ -780,7 +788,7 @@ export const hotelQueryRouter = router({
Authorization: `Bearer ${ctx.serviceToken}`,
},
},
params
searchParams
)
if (!apiResponse.ok) {

View File

@@ -13,3 +13,8 @@ export const imageMetaDataSchema = z.object({
altText_En: z.string(),
copyRight: z.string(),
})
export const imageSchema = z.object({
metaData: imageMetaDataSchema,
imageSizes: imageSizesSchema,
})

View File

@@ -0,0 +1,80 @@
import { z } from "zod"
import { imageSchema } from "./image"
import { specialAlertsSchema } from "./specialAlerts"
const restaurantPriceSchema = z.object({
currency: z.string(),
amount: z.number(),
})
const restaurantDaySchema = z.object({
sortOrder: z.number(),
alwaysOpen: z.boolean(),
isClosed: z.boolean(),
openingTime: z.string(),
closingTime: z.string(),
})
const restaurantOpeningHoursSchema = z.object({
isActive: z.boolean(),
name: z.string().optional(),
openingTime: z.string().optional(),
closingTime: z.string().optional(),
monday: restaurantDaySchema.optional(),
tuesday: restaurantDaySchema.optional(),
wednesday: restaurantDaySchema.optional(),
thursday: restaurantDaySchema.optional(),
friday: restaurantDaySchema.optional(),
saturday: restaurantDaySchema.optional(),
sunday: restaurantDaySchema.optional(),
})
const restaurantOpeningDetailSchema = z.object({
openingHours: restaurantOpeningHoursSchema,
alternateOpeningHours: restaurantOpeningHoursSchema.optional(),
})
export const restaurantSchema = z
.object({
attributes: z.object({
name: z.string().optional(),
isPublished: z.boolean(),
email: z.string().optional(),
phoneNumber: z.string().optional(),
externalBreakfast: z.object({
isAvailable: z.boolean(),
localPriceForExternalGuests: restaurantPriceSchema.optional(),
requestedPriceForExternalGuests: restaurantPriceSchema.optional(),
}),
menus: z
.array(
z.object({
name: z.string(),
url: z.string(),
})
)
.optional(),
openingDetails: z.array(restaurantOpeningDetailSchema),
content: z.object({
images: z.array(imageSchema),
texts: z.object({
descriptions: z.object({
short: z.string(),
medium: z.string(),
}),
}),
bookTableUrl: z.string().optional(),
specialAlerts: specialAlertsSchema,
}),
}),
id: z.string(),
type: z.literal("restaurants"),
})
.transform(({ attributes, id, type }) => ({ ...attributes, id, type }))
export const getRestaurantsSchema = z
.object({
data: z.array(restaurantSchema),
})
.transform(({ data }) => {
return data.filter((item) => !!item.isPublished)
})

View File

@@ -78,7 +78,7 @@ export const roomSchema = z
}),
}),
id: z.string(),
type: z.enum(["roomcategories"]),
type: z.literal("roomcategories"),
})
.transform((data) => {
return {

View File

@@ -0,0 +1,33 @@
import { dt } from "@/lib/dt"
import { AlertTypeEnum } from "@/types/enums/alert"
import { z } from "zod"
const specialAlertSchema = z.object({
type: z.string(),
title: z.string().optional(),
description: z.string().optional(),
displayInBookingFlow: z.boolean(),
startDate: z.string().optional(),
endDate: z.string().optional(),
})
export const specialAlertsSchema = z
.array(specialAlertSchema)
.transform((data) => {
const now = dt().utc().format("YYYY-MM-DD")
const filteredAlerts = data.filter((alert) => {
const shouldShowNow =
alert.startDate && alert.endDate
? alert.startDate <= now && alert.endDate >= now
: true
const hasText = alert.description || alert.title
return shouldShowNow && hasText
})
return filteredAlerts.map((alert, idx) => ({
id: `alert-${alert.type}-${idx}`,
type: AlertTypeEnum.Info,
heading: alert.title || null,
text: alert.description || null,
}))
})
.default([])