feat: adjust select rate ui to latest design

This commit is contained in:
Simon Emanuelsson
2025-02-17 15:10:48 +01:00
parent 2c72957dc6
commit 4c23700d52
76 changed files with 819 additions and 654 deletions

View File

@@ -18,7 +18,7 @@ import { cache } from "@/utils/cache"
import { getHotelPageUrl } from "../contentstack/hotelPage/utils"
import { getVerifiedUser, parsedUser } from "../user/query"
import { additionalDataSchema } from "./schemas/additionalData"
import { additionalDataSchema } from "./schemas/hotel/include/additionalData"
import { meetingRoomsSchema } from "./schemas/meetingRoom"
import {
ancillaryPackageInputSchema,
@@ -510,8 +510,8 @@ export const hotelQueryRouter = router({
adults: adultCount,
...(childArray &&
childArray.length > 0 && {
children: childArray.join(","),
}),
children: childArray.join(","),
}),
...(bookingCode && { bookingCode }),
language: apiLang,
}
@@ -754,9 +754,9 @@ export const hotelQueryRouter = router({
type: matchingRoom.mainBed.type,
extraBed: matchingRoom.fixedExtraBed
? {
type: matchingRoom.fixedExtraBed.type,
description: matchingRoom.fixedExtraBed.description,
}
type: matchingRoom.fixedExtraBed.type,
description: matchingRoom.fixedExtraBed.description,
}
: undefined,
}
}
@@ -855,7 +855,7 @@ export const hotelQueryRouter = router({
}),
}),
rates: router({
get: publicProcedure.input(ratesInputSchema).query(async ({}) => {
get: publicProcedure.input(ratesInputSchema).query(async () => {
// TODO: Do a real API call when the endpoint is ready
// const { hotelId } = input
@@ -1112,9 +1112,9 @@ export const hotelQueryRouter = router({
return hotelData
? {
...hotelData,
url,
}
...hotelData,
url,
}
: null
})
)

View File

@@ -1,78 +0,0 @@
import { z } from "zod"
import { imageSchema } from "./image"
const specialNeedSchema = z.object({
name: z.string(),
details: z.string(),
})
const specialNeedGroupSchema = z.object({
name: z.string(),
specialNeeds: z.array(specialNeedSchema),
})
export const gallerySchema = z.object({
heroImages: z.array(imageSchema),
smallerImages: z.array(imageSchema),
})
export const facilitySchema = z.object({
headingText: z.string().default(""),
heroImages: z.array(imageSchema),
})
export const restaurantsOverviewPageSchema = z.object({
restaurantsOverviewPageLinkText: z.string().optional(),
restaurantsOverviewPageLink: z.string().optional(),
restaurantsContentDescriptionShort: z.string().optional(),
restaurantsContentDescriptionMedium: z.string().optional(),
})
export const extraPageSchema = z.object({
elevatorPitch: z.string().default(""),
mainBody: z.string().optional(),
nameInUrl: z.string().optional(),
})
export const accessibilitySchema = z.object({
headingText: z.string().default(""),
heroImages: z.array(imageSchema),
})
export const additionalDataSchema = z.object({
attributes: z.object({
name: z.string(),
id: z.string(),
displayWebPage: z.object({
healthGym: z.boolean(),
meetingRoom: z.boolean(),
parking: z.boolean(),
specialNeeds: z.boolean(),
}),
specialNeedGroups: z.array(specialNeedGroupSchema),
gallery: gallerySchema.optional(),
conferencesAndMeetings: facilitySchema.optional(),
healthAndWellness: facilitySchema.optional(),
restaurantImages: facilitySchema.optional(),
parkingImages: facilitySchema.optional(),
restaurantsOverviewPage: restaurantsOverviewPageSchema,
meetingRooms: extraPageSchema,
healthAndFitness: extraPageSchema,
hotelParking: extraPageSchema,
hotelSpecialNeeds: extraPageSchema,
hotelRoomElevatorPitchText: z.string().optional(),
accessibility: accessibilitySchema.optional(),
}),
type: z.literal("additionalData"),
})
export function transformAdditionalData(
data: z.output<typeof additionalDataSchema>
) {
return {
...data.attributes,
id: data.attributes.id,
type: data.type,
}
}

View File

@@ -1,14 +1,21 @@
import { z } from "zod"
import {
nullableArrayObjectValidator,
nullableArrayStringValidator,
} from "@/utils/zod/arrayValidator"
import { nullableNumberValidator } from "@/utils/zod/numberValidator"
import { nullableStringValidator } from "@/utils/zod/stringValidator"
import { addressSchema } from "./hotel/address"
import { contactInformationSchema } from "./hotel/contactInformation"
import { hotelContentSchema } from "./hotel/content"
import { detailedFacilitiesSchema } from "./hotel/detailedFacility"
import { hotelFactsSchema } from "./hotel/facts"
import { gallerySchema } from "./hotel/gallery"
import { healthFacilitySchema } from "./hotel/healthFacilities"
import { healthFacilitiesSchema } from "./hotel/healthFacilities"
import { displayWebPageSchema } from "./hotel/include/additionalData/displayWebPage"
import { facilitySchema } from "./hotel/include/additionalData/facility"
import { gallerySchema } from "./hotel/include/additionalData/gallery"
import { includeSchema } from "./hotel/include/include"
import { locationSchema } from "./hotel/location"
import { merchantInformationSchema } from "./hotel/merchantInformation"
@@ -18,41 +25,41 @@ import { ratingsSchema } from "./hotel/rating"
import { rewardNightSchema } from "./hotel/rewardNight"
import { socialMediaSchema } from "./hotel/socialMedia"
import { specialAlertsSchema } from "./hotel/specialAlerts"
import { specialNeedGroupSchema } from "./hotel/specialNeedGroups"
import { facilitySchema } from "./additionalData"
import { imageSchema } from "./image"
export const attributesSchema = z.object({
id: z.string().optional(),
address: addressSchema,
cityId: z.string(),
cityName: z.string(),
conferencesAndMeetings: facilitySchema.optional(),
cityId: nullableStringValidator,
cityName: nullableStringValidator,
conferencesAndMeetings: facilitySchema.nullish(),
contactInformation: contactInformationSchema,
countryCode: nullableStringValidator,
detailedFacilities: detailedFacilitiesSchema,
gallery: gallerySchema.optional(),
galleryImages: z.array(imageSchema).optional(),
healthAndWellness: facilitySchema.optional(),
healthFacilities: z.array(healthFacilitySchema),
displayWebPage: displayWebPageSchema,
gallery: gallerySchema.nullish(),
galleryImages: z
.array(imageSchema)
.nullish()
.transform((arr) => (arr ? arr.filter(Boolean) : [])),
healthAndWellness: facilitySchema.nullish(),
healthFacilities: healthFacilitiesSchema,
hotelContent: hotelContentSchema,
hotelFacts: hotelFactsSchema,
hotelRoomElevatorPitchText: z.string().optional(),
hotelType: z.string().optional(),
hotelType: nullableStringValidator,
isActive: z.boolean(),
isPublished: z.boolean(),
keywords: z.array(z.string()),
keywords: nullableArrayStringValidator,
location: locationSchema,
merchantInformationData: merchantInformationSchema,
name: z.string(),
operaId: z.string(),
parking: z.array(parkingSchema),
name: nullableStringValidator,
operaId: nullableStringValidator,
parking: nullableArrayObjectValidator(parkingSchema),
pointsOfInterest: pointOfInterestsSchema,
ratings: ratingsSchema,
restaurantImages: facilitySchema.nullish(),
rewardNight: rewardNightSchema,
restaurantImages: facilitySchema.optional(),
socialMedia: socialMediaSchema,
specialAlerts: specialAlertsSchema,
specialNeedGroups: z.array(specialNeedGroupSchema),
vat: nullableNumberValidator,
})

View File

@@ -1,8 +1,10 @@
import { z } from "zod"
import { nullableStringValidator } from "@/utils/zod/stringValidator"
export const addressSchema = z.object({
city: z.string(),
country: z.string(),
streetAddress: z.string(),
zipCode: z.string(),
city: nullableStringValidator,
country: nullableStringValidator,
streetAddress: nullableStringValidator,
zipCode: nullableStringValidator,
})

View File

@@ -1,8 +1,13 @@
import { z } from "zod"
import {
nullableStringEmailValidator,
nullableStringValidator,
} from "@/utils/zod/stringValidator"
export const contactInformationSchema = z.object({
email: z.string(),
faxNumber: z.string().optional(),
phoneNumber: z.string(),
websiteUrl: z.string(),
email: nullableStringEmailValidator,
faxNumber: nullableStringValidator,
phoneNumber: nullableStringValidator,
websiteUrl: nullableStringValidator,
})

View File

@@ -1,40 +1,26 @@
import { z } from "zod"
import { nullableStringValidator } from "@/utils/zod/stringValidator"
import { imageSchema } from "../image"
import { restaurantsOverviewPageSchema } from "./include/additionalData/restaurantsOverviewPage"
const descriptionSchema = z
.object({
medium: nullableStringValidator,
short: nullableStringValidator,
})
.nullish()
const textsSchema = z.object({
descriptions: descriptionSchema,
facilityInformation: nullableStringValidator,
meetingDescription: descriptionSchema,
surroundingInformation: nullableStringValidator,
})
export const hotelContentSchema = z.object({
images: imageSchema.default({
metaData: {
altText: "default image",
altText_En: "default image",
copyRight: "default image",
title: "default image",
},
imageSizes: {
large: "https://placehold.co/1280x720",
medium: "https://placehold.co/1280x720",
small: "https://placehold.co/1280x720",
tiny: "https://placehold.co/1280x720",
},
}),
restaurantsOverviewPage: z.object({
restaurantsContentDescriptionMedium: z.string().optional(),
restaurantsContentDescriptionShort: z.string().optional(),
restaurantsOverviewPageLink: z.string().optional(),
restaurantsOverviewPageLinkText: z.string().optional(),
}),
texts: z.object({
descriptions: z.object({
medium: z.string(),
short: z.string(),
}),
facilityInformation: z.string().optional(),
meetingDescription: z
.object({
medium: z.string().optional(),
short: z.string().optional(),
})
.optional(),
surroundingInformation: z.string(),
}),
images: imageSchema,
restaurantsOverviewPage: restaurantsOverviewPageSchema,
texts: textsSchema,
})

View File

@@ -1,16 +1,21 @@
import { z } from "zod"
const detailedFacilitySchema = z.object({
filter: z.string().optional(),
icon: z.string().optional(),
id: z.number(),
name: z.string(),
import { nullableArrayObjectValidator } from "@/utils/zod/arrayValidator"
import { nullableStringValidator } from "@/utils/zod/stringValidator"
import { FacilityEnum } from "@/types/enums/facilities"
export const detailedFacilitySchema = z.object({
filter: nullableStringValidator,
icon: nullableStringValidator,
id: z.nativeEnum(FacilityEnum),
name: nullableStringValidator,
public: z.boolean(),
sortOrder: z.number(),
})
export const detailedFacilitiesSchema = z
.array(detailedFacilitySchema)
.transform((facilities) =>
facilities.sort((a, b) => b.sortOrder - a.sortOrder)
)
export const detailedFacilitiesSchema = nullableArrayObjectValidator(
detailedFacilitySchema
).transform((facilities) =>
facilities.sort((a, b) => b.sortOrder - a.sortOrder)
)

View File

@@ -1,50 +1,19 @@
import { z } from "zod"
import { nullableStringValidator } from "@/utils/zod/stringValidator"
export const checkinSchema = z.object({
checkInTime: nullableStringValidator,
checkOutTime: nullableStringValidator,
onlineCheckout: z.boolean(),
onlineCheckOutAvailableFrom: nullableStringValidator,
})
const ecoLabelsSchema = z.object({
euEcoLabel: z.boolean(),
greenGlobeLabel: z.boolean(),
nordicEcoLabel: z.boolean(),
svanenEcoLabelCertificateNumber: z.string().optional(),
})
export const checkinSchema = z.object({
checkInTime: z.string(),
checkOutTime: z.string(),
onlineCheckout: z.boolean(),
onlineCheckOutAvailableFrom: z.string().nullable().optional(),
})
const hotelFacilityDetailSchema = z
.object({
description: z.string(),
heading: z.string(),
})
.optional()
/** Possibly more values */
const hotelFacilityDetailsSchema = z.object({
breakfast: hotelFacilityDetailSchema,
checkout: hotelFacilityDetailSchema,
gym: hotelFacilityDetailSchema,
internet: hotelFacilityDetailSchema,
laundry: hotelFacilityDetailSchema,
luggage: hotelFacilityDetailSchema,
shop: hotelFacilityDetailSchema,
telephone: hotelFacilityDetailSchema,
})
const hotelInformationSchema = z
.object({
description: z.string(),
heading: z.string(),
link: z.string().optional(),
})
.optional()
const hotelInformationsSchema = z.object({
accessibility: hotelInformationSchema,
safety: hotelInformationSchema,
sustainability: hotelInformationSchema,
svanenEcoLabelCertificateNumber: nullableStringValidator,
})
const interiorSchema = z.object({
@@ -53,7 +22,7 @@ const interiorSchema = z.object({
numberOfFloors: z.number(),
numberOfRooms: z.object({
connected: z.number(),
forAllergics: z.number().optional(),
forAllergics: z.number(),
forDisabled: z.number(),
nonSmoking: z.number(),
pet: z.number(),
@@ -64,17 +33,15 @@ const interiorSchema = z.object({
const receptionHoursSchema = z.object({
alwaysOpen: z.boolean(),
closingTime: nullableStringValidator,
isClosed: z.boolean(),
openingTime: z.string().optional(),
closingTime: z.string().optional(),
openingTime: nullableStringValidator,
})
export const hotelFactsSchema = z.object({
checkin: checkinSchema,
ecoLabels: ecoLabelsSchema,
hotelFacilityDetail: hotelFacilityDetailsSchema.default({}),
hotelInformation: hotelInformationsSchema.default({}),
interior: interiorSchema,
receptionHours: receptionHoursSchema,
yearBuilt: z.string(),
yearBuilt: nullableStringValidator,
})

View File

@@ -1,8 +0,0 @@
import { z } from "zod"
import { imageSchema } from "../image"
export const gallerySchema = z.object({
heroImages: z.array(imageSchema),
smallerImages: z.array(imageSchema),
})

View File

@@ -1,41 +1,61 @@
import { z } from "zod"
import { nullableArrayObjectValidator } from "@/utils/zod/arrayValidator"
import { nullableNumberValidator } from "@/utils/zod/numberValidator"
import { nullableStringValidator } from "@/utils/zod/stringValidator"
import { imageSchema } from "../image"
const healthFacilitiesOpenHoursSchema = z.object({
alwaysOpen: z.boolean(),
closingTime: z.string().optional(),
closingTime: nullableStringValidator,
isClosed: z.boolean(),
openingTime: z.string().optional(),
sortOrder: z.number().optional(),
openingTime: nullableStringValidator,
sortOrder: nullableNumberValidator,
})
const descriptionSchema = z
.object({
medium: nullableStringValidator,
short: nullableStringValidator,
})
.nullish()
const detailsSchema = z.object({
name: nullableStringValidator,
type: nullableStringValidator,
value: nullableStringValidator,
})
const textsSchema = z.object({
descriptions: descriptionSchema,
facilityInformation: nullableStringValidator,
meetingDescription: descriptionSchema,
surroundingInformation: nullableStringValidator,
})
export const healthFacilitySchema = z.object({
content: z.object({
images: z.array(imageSchema),
texts: z.object({
descriptions: z.object({
short: z.string(),
medium: z.string(),
}),
facilityInformation: z.string().optional(),
surroundingInformation: z.string().optional(),
}),
images: z
.array(imageSchema)
.nullish()
.transform((arr) => (arr ? arr.filter(Boolean) : [])),
texts: textsSchema,
}),
details: z.array(
z.object({
name: z.string(),
type: z.string(),
value: z.string().optional(),
})
),
details: nullableArrayObjectValidator(detailsSchema),
openingDetails: z.object({
manualOpeningHours: z.string().optional(),
manualOpeningHours: nullableStringValidator,
openingHours: z.object({
ordinary: healthFacilitiesOpenHoursSchema,
weekends: healthFacilitiesOpenHoursSchema,
}),
useManualOpeningHours: z.boolean(),
useManualOpeningHours: z
.boolean()
.nullish()
.transform((b) => !!b),
}),
type: z.string(),
type: nullableStringValidator,
})
export const healthFacilitiesSchema =
nullableArrayObjectValidator(healthFacilitySchema)

View File

@@ -0,0 +1,48 @@
import { z } from "zod"
import { nullableArrayObjectValidator } from "@/utils/zod/arrayValidator"
import { nullableStringValidator } from "@/utils/zod/stringValidator"
import { displayWebPageSchema } from "./additionalData/displayWebPage"
import { facilitySchema } from "./additionalData/facility"
import { gallerySchema } from "./additionalData/gallery"
import { restaurantsOverviewPageSchema } from "./additionalData/restaurantsOverviewPage"
import { specialNeedGroupSchema } from "./additionalData/specialNeedGroups"
export const extraPageSchema = z.object({
elevatorPitch: nullableStringValidator,
mainBody: nullableStringValidator,
nameInUrl: nullableStringValidator,
})
export const additionalDataSchema = z.object({
attributes: z.object({
accessibility: facilitySchema.nullish(),
conferencesAndMeetings: facilitySchema.nullish(),
displayWebPage: displayWebPageSchema,
gallery: gallerySchema.nullish(),
healthAndFitness: extraPageSchema,
healthAndWellness: facilitySchema.nullish(),
hotelParking: extraPageSchema,
hotelRoomElevatorPitchText: nullableStringValidator,
hotelSpecialNeeds: extraPageSchema,
id: nullableStringValidator,
meetingRooms: extraPageSchema,
name: nullableStringValidator,
parkingImages: facilitySchema.nullish(),
restaurantImages: facilitySchema.nullish(),
restaurantsOverviewPage: restaurantsOverviewPageSchema,
specialNeedGroups: nullableArrayObjectValidator(specialNeedGroupSchema),
}),
type: z.literal("additionalData"),
})
export function transformAdditionalData(
data: z.output<typeof additionalDataSchema>
) {
return {
...data.attributes,
id: data.attributes.id,
type: data.type,
}
}

View File

@@ -0,0 +1,8 @@
import { z } from "zod"
export const displayWebPageSchema = z.object({
healthGym: z.boolean(),
meetingRoom: z.boolean(),
parking: z.boolean(),
specialNeeds: z.boolean(),
})

View File

@@ -0,0 +1,13 @@
import { z } from "zod"
import { imageSchema } from "@/server/routers/hotels/schemas/image"
import { nullableStringValidator } from "@/utils/zod/stringValidator"
export const facilitySchema = z.object({
headingText: nullableStringValidator,
heroImages: z
.array(imageSchema)
.nullish()
.transform((arr) => (arr ? arr.filter(Boolean) : [])),
})

View File

@@ -0,0 +1,13 @@
import { z } from "zod"
import { imageSchema } from "@/server/routers/hotels/schemas/image"
const imagesSchema = z
.array(imageSchema)
.nullish()
.transform((arr) => (arr ? arr.filter(Boolean) : []))
export const gallerySchema = z.object({
heroImages: imagesSchema,
smallerImages: imagesSchema,
})

View File

@@ -0,0 +1,10 @@
import { z } from "zod"
import { nullableStringValidator } from "@/utils/zod/stringValidator"
export const restaurantsOverviewPageSchema = z.object({
restaurantsContentDescriptionMedium: nullableStringValidator,
restaurantsContentDescriptionShort: nullableStringValidator,
restaurantsOverviewPageLink: nullableStringValidator,
restaurantsOverviewPageLinkText: nullableStringValidator,
})

View File

@@ -0,0 +1,14 @@
import { z } from "zod"
import { nullableArrayObjectValidator } from "@/utils/zod/arrayValidator"
import { nullableStringValidator } from "@/utils/zod/stringValidator"
const specialNeedSchema = z.object({
details: nullableStringValidator,
name: nullableStringValidator,
})
export const specialNeedGroupSchema = z.object({
name: nullableStringValidator,
specialNeeds: nullableArrayObjectValidator(specialNeedSchema),
})

View File

@@ -8,10 +8,7 @@ import {
transformRoomCategories,
} from "@/server/routers/hotels/schemas/hotel/include/roomCategories"
import {
additionalDataSchema,
transformAdditionalData,
} from "../../additionalData"
import { additionalDataSchema, transformAdditionalData } from "./additionalData"
export const includeSchema = z
.discriminatedUnion("type", [

View File

@@ -1,6 +1,9 @@
import { z } from "zod"
import { imageMetaDataSchema, imageSizesSchema } from "../../image"
import { imageSchema } from "@/server/routers/hotels/schemas/image"
import { nullableArrayObjectValidator } from "@/utils/zod/arrayValidator"
import { nullableStringValidator } from "@/utils/zod/stringValidator"
const minMaxSchema = z.object({
max: z.number(),
@@ -8,8 +11,8 @@ const minMaxSchema = z.object({
})
const bedTypeSchema = z.object({
description: z.string().default(""),
type: z.string(),
description: nullableStringValidator,
type: nullableStringValidator,
widthRange: minMaxSchema,
})
@@ -20,28 +23,26 @@ const occupancySchema = z.object({
})
const roomContentSchema = z.object({
images: z.array(
z.object({
imageSizes: imageSizesSchema,
metaData: imageMetaDataSchema,
})
),
images: z
.array(imageSchema)
.nullish()
.transform((arr) => (arr ? arr.filter(Boolean) : [])),
texts: z.object({
descriptions: z.object({
medium: z.string().optional(),
short: z.string().optional(),
medium: nullableStringValidator,
short: nullableStringValidator,
}),
}),
})
const roomTypesSchema = z.object({
code: z.string(),
description: z.string(),
code: nullableStringValidator,
description: nullableStringValidator,
fixedExtraBed: bedTypeSchema,
isLackingCribs: z.boolean(),
isLackingExtraBeds: z.boolean(),
mainBed: bedTypeSchema,
name: z.string(),
name: nullableStringValidator,
occupancy: occupancySchema,
roomCount: z.number(),
roomSize: minMaxSchema,
@@ -58,11 +59,11 @@ const roomFacilitiesSchema = z.object({
export const roomCategoriesSchema = z.object({
attributes: z.object({
content: roomContentSchema,
name: z.string(),
name: nullableStringValidator,
occupancy: minMaxSchema,
roomFacilities: z.array(roomFacilitiesSchema),
roomFacilities: nullableArrayObjectValidator(roomFacilitiesSchema),
roomSize: minMaxSchema,
roomTypes: z.array(roomTypesSchema),
roomTypes: nullableArrayObjectValidator(roomTypesSchema),
sortOrder: z.number(),
}),
id: z.string(),

View File

@@ -1,5 +1,7 @@
import { z } from "zod"
import { nullableStringValidator } from "@/utils/zod/stringValidator"
import type { PaymentMethodEnum } from "@/constants/booking"
export const merchantInformationSchema = z.object({
@@ -17,5 +19,5 @@ export const merchantInformationSchema = z.object({
.map(([key]) => key)
.filter((key): key is PaymentMethodEnum => !!key)
}),
webMerchantId: z.string().optional(),
webMerchantId: nullableStringValidator,
})

View File

@@ -1,41 +1,45 @@
import { z } from "zod"
import { nullableArrayObjectValidator } from "@/utils/zod/arrayValidator"
import { nullableNumberValidator } from "@/utils/zod/numberValidator"
import { nullableStringValidator } from "@/utils/zod/stringValidator"
const periodSchema = z.object({
amount: z.number().optional(),
endTime: z.string().optional(),
period: z.string().optional(),
startTime: z.string().optional(),
amount: nullableNumberValidator,
endTime: nullableStringValidator,
period: nullableStringValidator,
startTime: nullableStringValidator,
})
const currencySchema = z
.object({
currency: z.string().optional(),
ordinary: z.array(periodSchema).optional(),
currency: nullableStringValidator,
ordinary: nullableArrayObjectValidator(periodSchema),
range: z
.object({
min: z.number().optional(),
max: z.number().optional(),
min: nullableNumberValidator,
max: nullableNumberValidator,
})
.optional(),
weekend: z.array(periodSchema).optional(),
.nullish(),
weekend: nullableArrayObjectValidator(periodSchema),
})
.optional()
.nullish()
const pricingSchema = z.object({
freeParking: z.boolean(),
localCurrency: currencySchema,
paymentType: z.string().optional(),
paymentType: nullableStringValidator,
requestedCurrency: currencySchema,
})
export const parkingSchema = z.object({
address: z.string().optional(),
address: nullableStringValidator,
canMakeReservation: z.boolean(),
distanceToHotel: z.number().optional(),
externalParkingUrl: z.string().optional(),
name: z.string().optional(),
numberOfChargingSpaces: z.number().optional(),
numberOfParkingSpots: z.number().optional(),
distanceToHotel: nullableNumberValidator,
externalParkingUrl: nullableStringValidator,
name: nullableStringValidator,
numberOfChargingSpaces: nullableNumberValidator,
numberOfParkingSpots: nullableNumberValidator,
pricing: pricingSchema,
type: z.string().optional(),
type: nullableStringValidator,
})

View File

@@ -1,24 +1,25 @@
import { z } from "zod"
import { nullableNumberValidator } from "@/utils/zod/numberValidator"
import { nullableStringValidator } from "@/utils/zod/stringValidator"
import { getPoiGroupByCategoryName } from "../../utils"
import { locationSchema } from "./location"
export const pointOfInterestSchema = z
.object({
category: z.object({
name: z.string().optional(),
group: z.string().optional(),
name: nullableStringValidator,
}),
distance: z.number().optional(),
isHighlighted: z.boolean().optional(),
location: locationSchema.optional(),
name: z.string().optional(),
distance: nullableNumberValidator,
location: locationSchema,
name: nullableStringValidator,
})
.transform((poi) => ({
categoryName: poi.category.name,
coordinates: {
lat: poi.location?.latitude ?? 0,
lng: poi.location?.longitude ?? 0,
lat: poi.location.latitude,
lng: poi.location.longitude,
},
distance: poi.distance,
group: getPoiGroupByCategoryName(poi.category.name),
@@ -27,6 +28,8 @@ export const pointOfInterestSchema = z
export const pointOfInterestsSchema = z
.array(pointOfInterestSchema)
.nullish()
.transform((arr) => (arr ? arr.filter(Boolean) : []))
.transform((pois) =>
pois.sort((a, b) => (a.distance ?? 0) - (b.distance ?? 0))
)

View File

@@ -1,31 +1,57 @@
import { z } from "zod"
import { nullableArrayObjectValidator } from "@/utils/zod/arrayValidator"
import {
nullableStringUrlValidator,
nullableStringValidator,
} from "@/utils/zod/stringValidator"
const awardSchema = z.object({
displayName: z.string(),
images: z.object({
large: z.string(),
medium: z.string(),
small: z.string(),
}),
displayName: nullableStringValidator,
images: z
.object({
large: nullableStringValidator,
medium: nullableStringValidator,
small: nullableStringValidator,
})
.nullish()
.transform((obj) =>
obj
? obj
: {
small: "",
medium: "",
large: "",
}
),
})
const reviewsSchema = z
.object({
widgetHtmlTagId: z.string(),
widgetScriptEmbedUrlIframe: z.string(),
widgetScriptEmbedUrlJavaScript: z.string(),
widgetHtmlTagId: nullableStringValidator,
widgetScriptEmbedUrlIframe: nullableStringValidator,
widgetScriptEmbedUrlJavaScript: nullableStringValidator,
})
.optional()
.nullish()
.transform((obj) =>
obj
? obj
: {
widgetHtmlTagId: "",
widgetScriptEmbedUrlIframe: "",
widgetScriptEmbedUrlJavaScript: "",
}
)
export const ratingsSchema = z
.object({
tripAdvisor: z.object({
awards: z.array(awardSchema),
awards: nullableArrayObjectValidator(awardSchema),
numberOfReviews: z.number(),
rating: z.number(),
ratingImageUrl: z.string(),
ratingImageUrl: nullableStringUrlValidator,
reviews: reviewsSchema,
webUrl: z.string(),
webUrl: nullableStringUrlValidator,
}),
})
.optional()

View File

@@ -1,10 +1,12 @@
import { z } from "zod"
import { nullableStringValidator } from "@/utils/zod/stringValidator"
export const rewardNightSchema = z.object({
campaign: z.object({
end: z.string(),
end: nullableStringValidator,
points: z.number(),
start: z.string(),
start: nullableStringValidator,
}),
points: z.number(),
})

View File

@@ -1,6 +1,8 @@
import { z } from "zod"
import { nullableStringValidator } from "@/utils/zod/stringValidator"
export const socialMediaSchema = z.object({
facebook: z.string().optional(),
instagram: z.string().optional(),
facebook: nullableStringValidator,
instagram: nullableStringValidator,
})

View File

@@ -17,6 +17,8 @@ const specialAlertSchema = z.object({
export const specialAlertsSchema = z
.array(specialAlertSchema)
.nullish()
.transform((arr) => (arr ? arr.filter(Boolean) : []))
.transform((data) => {
const now = dt().utc().format("YYYY-MM-DD")
const filteredAlerts = data.filter((alert) => {
@@ -35,4 +37,3 @@ export const specialAlertsSchema = z
displayInBookingFlow: alert.displayInBookingFlow,
}))
})
.default([])

View File

@@ -1,11 +0,0 @@
import { z } from "zod"
const specialNeedSchema = z.object({
details: z.string(),
name: z.string(),
})
export const specialNeedGroupSchema = z.object({
name: z.string(),
specialNeeds: z.array(specialNeedSchema),
})

View File

@@ -1,25 +1,27 @@
import { z } from "zod"
import { nullableStringValidator } from "@/utils/zod/stringValidator"
export const imageSizesSchema = z.object({
large: z.string(),
medium: z.string(),
small: z.string(),
tiny: z.string(),
large: nullableStringValidator,
medium: nullableStringValidator,
small: nullableStringValidator,
tiny: nullableStringValidator,
})
export const imageMetaDataSchema = z.object({
altText: z.string(),
altText_En: z.string(),
copyRight: z.string(),
title: z.string(),
altText: nullableStringValidator,
altText_En: nullableStringValidator,
copyRight: nullableStringValidator,
title: nullableStringValidator,
})
const DEFAULT_IMAGE_OBJ = {
metaData: {
title: "Default image",
altText: "Default image",
altText_En: "Default image",
copyRight: "Default image",
title: "Default image",
},
imageSizes: {
tiny: "https://placehold.co/1280x720",
@@ -31,11 +33,10 @@ const DEFAULT_IMAGE_OBJ = {
export const imageSchema = z
.object({
metaData: imageMetaDataSchema,
imageSizes: imageSizesSchema,
metaData: imageMetaDataSchema,
})
.default(DEFAULT_IMAGE_OBJ)
.nullable()
.nullish()
.transform((val) => {
if (!val) {
return DEFAULT_IMAGE_OBJ

View File

@@ -17,7 +17,6 @@ import {
} from "./output"
import { getHotel } from "./query"
import type { Country } from "@/types/enums/country"
import { PointOfInterestGroupEnum } from "@/types/enums/pointOfInterest"
import type { RequestOptionsWithOutBody } from "@/types/fetch"
import type { HotelDataWithUrl } from "@/types/hotel"