Merged in feat/sw-2863-move-contentstack-router-to-trpc-package (pull request #2389)
feat(SW-2863): Move contentstack router to trpc package * Add exports to packages and lint rule to prevent relative imports * Add env to trpc package * Add eslint to trpc package * Apply lint rules * Use direct imports from trpc package * Add lint-staged config to trpc * Move lang enum to common * Restructure trpc package folder structure * WIP first step * update internal imports in trpc * Fix most errors in scandic-web Just 100 left... * Move Props type out of trpc * Fix CategorizedFilters types * Move more schemas in hotel router * Fix deps * fix getNonContentstackUrls * Fix import error * Fix entry error handling * Fix generateMetadata metrics * Fix alertType enum * Fix duplicated types * lint:fix * Merge branch 'master' into feat/sw-2863-move-contentstack-router-to-trpc-package * Fix broken imports * Merge branch 'master' into feat/sw-2863-move-contentstack-router-to-trpc-package Approved-by: Linus Flood
This commit is contained in:
10
packages/trpc/lib/routers/hotels/schemas/hotel/address.ts
Normal file
10
packages/trpc/lib/routers/hotels/schemas/hotel/address.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator"
|
||||
|
||||
export const addressSchema = z.object({
|
||||
city: nullableStringValidator,
|
||||
country: nullableStringValidator,
|
||||
streetAddress: nullableStringValidator,
|
||||
zipCode: nullableStringValidator,
|
||||
})
|
||||
@@ -0,0 +1,13 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import {
|
||||
nullableStringEmailValidator,
|
||||
nullableStringValidator,
|
||||
} from "@scandic-hotels/common/utils/zod/stringValidator"
|
||||
|
||||
export const contactInformationSchema = z.object({
|
||||
email: nullableStringEmailValidator,
|
||||
faxNumber: nullableStringValidator,
|
||||
phoneNumber: nullableStringValidator,
|
||||
websiteUrl: nullableStringValidator,
|
||||
})
|
||||
24
packages/trpc/lib/routers/hotels/schemas/hotel/content.ts
Normal file
24
packages/trpc/lib/routers/hotels/schemas/hotel/content.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator"
|
||||
|
||||
import { imageSchema } from "../image"
|
||||
|
||||
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,
|
||||
texts: textsSchema,
|
||||
})
|
||||
@@ -0,0 +1,37 @@
|
||||
import slugify from "slugify"
|
||||
import { z } from "zod"
|
||||
|
||||
import { nullableArrayObjectValidator } from "@scandic-hotels/common/utils/zod/arrayValidator"
|
||||
import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator"
|
||||
|
||||
import { FacilityEnum } from "../../../../enums/facilities"
|
||||
|
||||
const rawDetailedFacilitySchema = z.object({
|
||||
filter: nullableStringValidator,
|
||||
icon: nullableStringValidator,
|
||||
id: z.nativeEnum(FacilityEnum),
|
||||
name: nullableStringValidator,
|
||||
public: z.boolean(),
|
||||
sortOrder: z.number(),
|
||||
})
|
||||
|
||||
function transformDetailedFacility(
|
||||
data: z.output<typeof rawDetailedFacilitySchema>
|
||||
) {
|
||||
return {
|
||||
...data,
|
||||
slug: slugify(data.name, { lower: true, strict: true }),
|
||||
}
|
||||
}
|
||||
|
||||
export const detailedFacilitySchema = rawDetailedFacilitySchema.transform(
|
||||
transformDetailedFacility
|
||||
)
|
||||
|
||||
export const detailedFacilitiesSchema = nullableArrayObjectValidator(
|
||||
rawDetailedFacilitySchema
|
||||
).transform((facilities) =>
|
||||
facilities
|
||||
.sort((a, b) => b.sortOrder - a.sortOrder)
|
||||
.map(transformDetailedFacility)
|
||||
)
|
||||
47
packages/trpc/lib/routers/hotels/schemas/hotel/facts.ts
Normal file
47
packages/trpc/lib/routers/hotels/schemas/hotel/facts.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { nullableStringValidator } from "@scandic-hotels/common/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: nullableStringValidator,
|
||||
})
|
||||
|
||||
const interiorSchema = z.object({
|
||||
numberOfBeds: z.number(),
|
||||
numberOfCribs: z.number(),
|
||||
numberOfFloors: z.number(),
|
||||
numberOfRooms: z.object({
|
||||
connected: z.number(),
|
||||
forAllergics: z.number(),
|
||||
forDisabled: z.number(),
|
||||
nonSmoking: z.number(),
|
||||
pet: z.number(),
|
||||
withExtraBeds: z.number(),
|
||||
total: z.number(),
|
||||
}),
|
||||
})
|
||||
|
||||
const receptionHoursSchema = z.object({
|
||||
alwaysOpen: z.boolean(),
|
||||
closingTime: nullableStringValidator,
|
||||
isClosed: z.boolean(),
|
||||
openingTime: nullableStringValidator,
|
||||
})
|
||||
|
||||
export const hotelFactsSchema = z.object({
|
||||
checkin: checkinSchema,
|
||||
ecoLabels: ecoLabelsSchema,
|
||||
interior: interiorSchema,
|
||||
receptionHours: receptionHoursSchema,
|
||||
yearBuilt: nullableStringValidator,
|
||||
})
|
||||
@@ -0,0 +1,62 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { nullableArrayObjectValidator } from "@scandic-hotels/common/utils/zod/arrayValidator"
|
||||
import { nullableNumberValidator } from "@scandic-hotels/common/utils/zod/numberValidator"
|
||||
import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator"
|
||||
|
||||
import { imageSchema } from "../image"
|
||||
|
||||
const healthFacilitiesOpenHoursSchema = z.object({
|
||||
alwaysOpen: z.boolean(),
|
||||
closingTime: nullableStringValidator,
|
||||
isClosed: z.boolean(),
|
||||
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)
|
||||
.nullish()
|
||||
.transform((arr) => (arr ? arr.filter(Boolean) : [])),
|
||||
texts: textsSchema,
|
||||
}),
|
||||
details: nullableArrayObjectValidator(detailsSchema),
|
||||
openingDetails: z.object({
|
||||
manualOpeningHours: nullableStringValidator,
|
||||
openingHours: z.object({
|
||||
ordinary: healthFacilitiesOpenHoursSchema,
|
||||
weekends: healthFacilitiesOpenHoursSchema,
|
||||
}),
|
||||
useManualOpeningHours: z
|
||||
.boolean()
|
||||
.nullish()
|
||||
.transform((b) => !!b),
|
||||
openingHoursType: nullableStringValidator,
|
||||
}),
|
||||
type: nullableStringValidator,
|
||||
})
|
||||
|
||||
export const healthFacilitiesSchema =
|
||||
nullableArrayObjectValidator(healthFacilitySchema)
|
||||
44
packages/trpc/lib/routers/hotels/schemas/hotel/include.ts
Normal file
44
packages/trpc/lib/routers/hotels/schemas/hotel/include.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { citySchema } from "../city"
|
||||
import {
|
||||
additionalDataSchema,
|
||||
transformAdditionalData,
|
||||
} from "./include/additionalData"
|
||||
import { nearbyHotelsSchema } from "./include/nearbyHotels"
|
||||
import { restaurantsSchema } from "./include/restaurants"
|
||||
import {
|
||||
roomCategoriesSchema,
|
||||
transformRoomCategories,
|
||||
} from "./include/roomCategories"
|
||||
|
||||
export const includeSchema = z
|
||||
.union([
|
||||
z.null(),
|
||||
z.undefined(),
|
||||
z.discriminatedUnion("type", [
|
||||
additionalDataSchema,
|
||||
citySchema,
|
||||
nearbyHotelsSchema,
|
||||
restaurantsSchema,
|
||||
roomCategoriesSchema,
|
||||
]),
|
||||
])
|
||||
.transform((data) => {
|
||||
switch (data?.type) {
|
||||
case "additionalData":
|
||||
return transformAdditionalData(data)
|
||||
case "cities":
|
||||
case "hotels":
|
||||
case "restaurants":
|
||||
return {
|
||||
...data.attributes,
|
||||
id: data.id,
|
||||
type: data.type,
|
||||
}
|
||||
case "roomcategories":
|
||||
return transformRoomCategories(data)
|
||||
default:
|
||||
return null
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,54 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { nullableArrayObjectValidator } from "@scandic-hotels/common/utils/zod/arrayValidator"
|
||||
import { nullableStringValidator } from "@scandic-hotels/common/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 additionalDataAttributesSchema = 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.merge(
|
||||
z.object({
|
||||
meetingOnlineLink: z.string().nullish(),
|
||||
})
|
||||
),
|
||||
name: nullableStringValidator,
|
||||
parkingImages: facilitySchema.nullish(),
|
||||
restaurantImages: facilitySchema.nullish(),
|
||||
restaurantsOverviewPage: restaurantsOverviewPageSchema,
|
||||
specialNeedGroups: nullableArrayObjectValidator(specialNeedGroupSchema),
|
||||
})
|
||||
|
||||
export const additionalDataSchema = z.object({
|
||||
attributes: additionalDataAttributesSchema,
|
||||
type: z.literal("additionalData"),
|
||||
})
|
||||
|
||||
export function transformAdditionalData(
|
||||
data: z.output<typeof additionalDataSchema>
|
||||
) {
|
||||
return {
|
||||
...data.attributes,
|
||||
id: data.attributes.id,
|
||||
type: data.type,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { z } from "zod"
|
||||
|
||||
export const displayWebPageSchema = z
|
||||
.object({
|
||||
healthGym: z.boolean().default(false),
|
||||
meetingRoom: z.boolean().default(false),
|
||||
parking: z.boolean().default(false),
|
||||
specialNeeds: z.boolean().default(false),
|
||||
})
|
||||
.nullish()
|
||||
.transform(
|
||||
(object) =>
|
||||
object ?? {
|
||||
healthGym: false,
|
||||
meetingRoom: false,
|
||||
parking: false,
|
||||
specialNeeds: false,
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,13 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator"
|
||||
|
||||
import { imageSchema } from "../../../image"
|
||||
|
||||
export const facilitySchema = z.object({
|
||||
headingText: nullableStringValidator,
|
||||
heroImages: z
|
||||
.array(imageSchema)
|
||||
.nullish()
|
||||
.transform((arr) => (arr ? arr.filter(Boolean) : [])),
|
||||
})
|
||||
@@ -0,0 +1,13 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { imageSchema } from "../../../image"
|
||||
|
||||
const imagesSchema = z
|
||||
.array(imageSchema)
|
||||
.nullish()
|
||||
.transform((arr) => (arr ? arr.filter(Boolean) : []))
|
||||
|
||||
export const gallerySchema = z.object({
|
||||
heroImages: imagesSchema,
|
||||
smallerImages: imagesSchema,
|
||||
})
|
||||
@@ -0,0 +1,10 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator"
|
||||
|
||||
export const restaurantsOverviewPageSchema = z.object({
|
||||
restaurantsContentDescriptionMedium: nullableStringValidator,
|
||||
restaurantsContentDescriptionShort: nullableStringValidator,
|
||||
restaurantsOverviewPageLink: nullableStringValidator,
|
||||
restaurantsOverviewPageLinkText: nullableStringValidator,
|
||||
})
|
||||
@@ -0,0 +1,14 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { nullableArrayObjectValidator } from "@scandic-hotels/common/utils/zod/arrayValidator"
|
||||
import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator"
|
||||
|
||||
const specialNeedSchema = z.object({
|
||||
details: nullableStringValidator,
|
||||
name: nullableStringValidator,
|
||||
})
|
||||
|
||||
export const specialNeedGroupSchema = z.object({
|
||||
name: nullableStringValidator,
|
||||
specialNeeds: nullableArrayObjectValidator(specialNeedSchema),
|
||||
})
|
||||
@@ -0,0 +1,23 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { attributesSchema } from "../../hotel"
|
||||
|
||||
export const nearbyHotelsSchema = z.object({
|
||||
attributes: z.lazy(() =>
|
||||
attributesSchema.pick({
|
||||
address: true,
|
||||
cityId: true,
|
||||
cityName: true,
|
||||
detailedFacilities: true,
|
||||
hotelContent: true,
|
||||
isActive: true,
|
||||
isPublished: true,
|
||||
location: true,
|
||||
name: true,
|
||||
operaId: true,
|
||||
ratings: true,
|
||||
})
|
||||
),
|
||||
id: z.string(),
|
||||
type: z.literal("hotels"),
|
||||
})
|
||||
@@ -0,0 +1,95 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||
import {
|
||||
nullableIntValidator,
|
||||
nullableNumberValidator,
|
||||
} from "@scandic-hotels/common/utils/zod/numberValidator"
|
||||
import {
|
||||
nullableStringUrlValidator,
|
||||
nullableStringValidator,
|
||||
} from "@scandic-hotels/common/utils/zod/stringValidator"
|
||||
|
||||
import { imageSchema } from "../../image"
|
||||
import { specialAlertsSchema } from "../specialAlerts"
|
||||
|
||||
const descriptionSchema = z.object({
|
||||
medium: nullableStringValidator,
|
||||
short: nullableStringValidator,
|
||||
})
|
||||
|
||||
const textSchema = z.object({
|
||||
descriptions: descriptionSchema,
|
||||
facilityInformation: nullableStringValidator,
|
||||
meetingDescription: descriptionSchema.optional(),
|
||||
surroundingInformation: nullableStringValidator,
|
||||
})
|
||||
|
||||
const contentSchema = z.object({
|
||||
images: z.array(imageSchema).default([]),
|
||||
texts: textSchema,
|
||||
})
|
||||
|
||||
const restaurantPriceSchema = z.object({
|
||||
amount: nullableNumberValidator,
|
||||
currency: z.nativeEnum(CurrencyEnum).default(CurrencyEnum.SEK),
|
||||
})
|
||||
|
||||
const externalBreakfastSchema = z.object({
|
||||
isAvailable: z.boolean().default(false),
|
||||
localPriceForExternalGuests: restaurantPriceSchema.optional(),
|
||||
requestedPriceForExternalGuests: restaurantPriceSchema.optional(),
|
||||
})
|
||||
|
||||
const menuItemSchema = z.object({
|
||||
name: nullableStringValidator,
|
||||
url: nullableStringUrlValidator,
|
||||
})
|
||||
|
||||
export const openingHoursDetailsSchema = z.object({
|
||||
alwaysOpen: z.boolean().default(false),
|
||||
closingTime: nullableStringValidator,
|
||||
isClosed: z.boolean().default(false),
|
||||
openingTime: nullableStringValidator,
|
||||
sortOrder: nullableIntValidator,
|
||||
})
|
||||
|
||||
export const openingHoursSchema = z.object({
|
||||
friday: openingHoursDetailsSchema.optional(),
|
||||
isActive: z.boolean().default(false),
|
||||
monday: openingHoursDetailsSchema.optional(),
|
||||
name: nullableStringValidator,
|
||||
saturday: openingHoursDetailsSchema.optional(),
|
||||
sunday: openingHoursDetailsSchema.optional(),
|
||||
thursday: openingHoursDetailsSchema.optional(),
|
||||
tuesday: openingHoursDetailsSchema.optional(),
|
||||
wednesday: openingHoursDetailsSchema.optional(),
|
||||
})
|
||||
|
||||
const openingDetailsSchema = z.object({
|
||||
alternateOpeningHours: openingHoursSchema.optional(),
|
||||
openingHours: openingHoursSchema,
|
||||
ordinary: openingHoursSchema.optional(),
|
||||
weekends: openingHoursSchema.optional(),
|
||||
})
|
||||
|
||||
export const restaurantsSchema = z.object({
|
||||
attributes: z.object({
|
||||
bookTableUrl: nullableStringValidator,
|
||||
content: contentSchema,
|
||||
email: z.string().email().optional(),
|
||||
externalBreakfast: externalBreakfastSchema,
|
||||
isPublished: z.boolean().default(false),
|
||||
menus: z.array(menuItemSchema).default([]),
|
||||
name: z.string().default(""),
|
||||
openingDetails: z.array(openingDetailsSchema).default([]),
|
||||
phoneNumber: z.string().optional(),
|
||||
restaurantPage: z.boolean().default(false),
|
||||
elevatorPitch: z.string().optional(),
|
||||
nameInUrl: z.string().optional(),
|
||||
mainBody: z.string().optional(),
|
||||
specialAlerts: specialAlertsSchema,
|
||||
}),
|
||||
id: z.string(),
|
||||
type: z.literal("restaurants"),
|
||||
})
|
||||
@@ -0,0 +1,107 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { nullableArrayObjectValidator } from "@scandic-hotels/common/utils/zod/arrayValidator"
|
||||
import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator"
|
||||
|
||||
import { imageSchema } from "../../image"
|
||||
|
||||
const minMaxSchema = z.object({
|
||||
max: z.number(),
|
||||
min: z.number(),
|
||||
})
|
||||
|
||||
const bedTypeSchema = z.object({
|
||||
description: nullableStringValidator,
|
||||
type: nullableStringValidator,
|
||||
widthRange: minMaxSchema,
|
||||
})
|
||||
|
||||
const occupancySchema = z.object({
|
||||
adults: z.number(),
|
||||
children: z.number(),
|
||||
total: z.number(),
|
||||
})
|
||||
|
||||
const roomContentSchema = z.object({
|
||||
images: z
|
||||
.array(imageSchema)
|
||||
.nullish()
|
||||
.transform((arr) => (arr ? arr.filter(Boolean) : [])),
|
||||
texts: z.object({
|
||||
descriptions: z.object({
|
||||
medium: nullableStringValidator,
|
||||
short: nullableStringValidator,
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
const roomTypesSchema = z.object({
|
||||
code: nullableStringValidator,
|
||||
description: nullableStringValidator,
|
||||
fixedExtraBed: bedTypeSchema.optional(),
|
||||
isLackingCribs: z.boolean(),
|
||||
isLackingExtraBeds: z.boolean(),
|
||||
mainBed: bedTypeSchema,
|
||||
name: nullableStringValidator,
|
||||
occupancy: occupancySchema,
|
||||
roomCount: z.number(),
|
||||
roomSize: minMaxSchema,
|
||||
})
|
||||
|
||||
const roomFacilitiesSchema = z.object({
|
||||
availableInAllRooms: z.boolean(),
|
||||
icon: z.string().optional(),
|
||||
isUniqueSellingPoint: z.boolean(),
|
||||
name: z.string(),
|
||||
sortOrder: z.number(),
|
||||
})
|
||||
|
||||
export const roomCategoriesSchema = z.object({
|
||||
attributes: z.object({
|
||||
content: roomContentSchema,
|
||||
name: nullableStringValidator,
|
||||
occupancy: minMaxSchema,
|
||||
roomFacilities: nullableArrayObjectValidator(roomFacilitiesSchema),
|
||||
roomSize: minMaxSchema,
|
||||
roomTypes: nullableArrayObjectValidator(roomTypesSchema),
|
||||
sortOrder: z.number(),
|
||||
}),
|
||||
id: z.string(),
|
||||
type: z.literal("roomcategories"),
|
||||
})
|
||||
|
||||
export function transformRoomCategories(
|
||||
data: z.output<typeof roomCategoriesSchema>
|
||||
) {
|
||||
return {
|
||||
descriptions: data.attributes.content.texts.descriptions,
|
||||
id: data.id,
|
||||
images: data.attributes.content.images,
|
||||
name: data.attributes.name,
|
||||
occupancy: data.attributes.occupancy,
|
||||
roomFacilities: data.attributes.roomFacilities,
|
||||
roomSize: data.attributes.roomSize,
|
||||
roomTypes: data.attributes.roomTypes.map((roomType) => {
|
||||
if (!roomType || roomType.fixedExtraBed?.type.toLowerCase() === "none") {
|
||||
return {
|
||||
...roomType,
|
||||
fixedExtraBed: undefined,
|
||||
}
|
||||
}
|
||||
|
||||
return roomType
|
||||
}),
|
||||
sortOrder: data.attributes.sortOrder,
|
||||
type: data.type,
|
||||
totalOccupancy:
|
||||
data.attributes.occupancy.min === data.attributes.occupancy.max
|
||||
? {
|
||||
max: data.attributes.occupancy.max,
|
||||
range: `${data.attributes.occupancy.max}`,
|
||||
}
|
||||
: {
|
||||
max: data.attributes.occupancy.max,
|
||||
range: `${data.attributes.occupancy.min}-${data.attributes.occupancy.max}`,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { z } from "zod"
|
||||
|
||||
export const locationSchema = z.object({
|
||||
distanceToCentre: z.number(),
|
||||
latitude: z.number(),
|
||||
longitude: z.number(),
|
||||
})
|
||||
@@ -0,0 +1,23 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator"
|
||||
|
||||
import type { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMethod"
|
||||
|
||||
export const merchantInformationSchema = z.object({
|
||||
alternatePaymentOptions: z
|
||||
.record(z.string(), z.boolean())
|
||||
.transform((val) => {
|
||||
return Object.entries(val)
|
||||
.filter(([_, enabled]) => enabled)
|
||||
.map(([key]) => key)
|
||||
.filter((key): key is PaymentMethodEnum => !!key)
|
||||
}),
|
||||
cards: z.record(z.string(), z.boolean()).transform((val) => {
|
||||
return Object.entries(val)
|
||||
.filter(([_, enabled]) => enabled)
|
||||
.map(([key]) => key)
|
||||
.filter((key): key is PaymentMethodEnum => !!key)
|
||||
}),
|
||||
webMerchantId: nullableStringValidator,
|
||||
})
|
||||
45
packages/trpc/lib/routers/hotels/schemas/hotel/parking.ts
Normal file
45
packages/trpc/lib/routers/hotels/schemas/hotel/parking.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { nullableArrayObjectValidator } from "@scandic-hotels/common/utils/zod/arrayValidator"
|
||||
import { nullableNumberValidator } from "@scandic-hotels/common/utils/zod/numberValidator"
|
||||
import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator"
|
||||
|
||||
const periodSchema = z.object({
|
||||
amount: nullableNumberValidator,
|
||||
endTime: nullableStringValidator,
|
||||
period: nullableStringValidator,
|
||||
startTime: nullableStringValidator,
|
||||
})
|
||||
|
||||
const currencySchema = z
|
||||
.object({
|
||||
currency: nullableStringValidator,
|
||||
ordinary: nullableArrayObjectValidator(periodSchema),
|
||||
range: z
|
||||
.object({
|
||||
min: nullableNumberValidator,
|
||||
max: nullableNumberValidator,
|
||||
})
|
||||
.nullish(),
|
||||
weekend: nullableArrayObjectValidator(periodSchema),
|
||||
})
|
||||
.nullish()
|
||||
|
||||
const pricingSchema = z.object({
|
||||
freeParking: z.boolean(),
|
||||
localCurrency: currencySchema,
|
||||
paymentType: nullableStringValidator,
|
||||
requestedCurrency: currencySchema,
|
||||
})
|
||||
|
||||
export const parkingSchema = z.object({
|
||||
address: nullableStringValidator,
|
||||
canMakeReservation: z.boolean(),
|
||||
distanceToHotel: nullableNumberValidator,
|
||||
externalParkingUrl: nullableStringValidator,
|
||||
name: nullableStringValidator,
|
||||
numberOfChargingSpaces: nullableNumberValidator,
|
||||
numberOfParkingSpots: nullableNumberValidator,
|
||||
pricing: pricingSchema,
|
||||
type: nullableStringValidator,
|
||||
})
|
||||
63
packages/trpc/lib/routers/hotels/schemas/hotel/poi.ts
Normal file
63
packages/trpc/lib/routers/hotels/schemas/hotel/poi.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { nullableNumberValidator } from "@scandic-hotels/common/utils/zod/numberValidator"
|
||||
import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator"
|
||||
|
||||
import { PointOfInterestGroupEnum } from "../../../../enums/pointOfInterest"
|
||||
import { locationSchema } from "./location"
|
||||
|
||||
export const pointOfInterestSchema = z
|
||||
.object({
|
||||
category: z.object({
|
||||
name: nullableStringValidator,
|
||||
}),
|
||||
distance: nullableNumberValidator,
|
||||
location: locationSchema,
|
||||
name: nullableStringValidator,
|
||||
})
|
||||
.transform((poi) => ({
|
||||
categoryName: poi.category.name,
|
||||
coordinates: {
|
||||
lat: poi.location.latitude,
|
||||
lng: poi.location.longitude,
|
||||
},
|
||||
distance: poi.distance,
|
||||
group: getPoiGroupByCategoryName(poi.category.name),
|
||||
name: poi.name,
|
||||
}))
|
||||
|
||||
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))
|
||||
)
|
||||
|
||||
function getPoiGroupByCategoryName(category: string | undefined) {
|
||||
if (!category) return PointOfInterestGroupEnum.LOCATION
|
||||
switch (category) {
|
||||
case "Airport":
|
||||
case "Bus terminal":
|
||||
case "Transportations":
|
||||
return PointOfInterestGroupEnum.PUBLIC_TRANSPORT
|
||||
case "Amusement park":
|
||||
case "Museum":
|
||||
case "Sports":
|
||||
case "Theatre":
|
||||
case "Tourist":
|
||||
case "Zoo":
|
||||
return PointOfInterestGroupEnum.ATTRACTIONS
|
||||
case "Nearby companies":
|
||||
case "Fair":
|
||||
return PointOfInterestGroupEnum.BUSINESS
|
||||
case "Parking / Garage":
|
||||
return PointOfInterestGroupEnum.PARKING
|
||||
case "Shopping":
|
||||
case "Restaurant":
|
||||
return PointOfInterestGroupEnum.SHOPPING_DINING
|
||||
case "Hospital":
|
||||
default:
|
||||
return PointOfInterestGroupEnum.LOCATION
|
||||
}
|
||||
}
|
||||
57
packages/trpc/lib/routers/hotels/schemas/hotel/rating.ts
Normal file
57
packages/trpc/lib/routers/hotels/schemas/hotel/rating.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { nullableArrayObjectValidator } from "@scandic-hotels/common/utils/zod/arrayValidator"
|
||||
import {
|
||||
nullableStringUrlValidator,
|
||||
nullableStringValidator,
|
||||
} from "@scandic-hotels/common/utils/zod/stringValidator"
|
||||
|
||||
const awardSchema = z.object({
|
||||
displayName: nullableStringValidator,
|
||||
images: z
|
||||
.object({
|
||||
large: nullableStringValidator,
|
||||
medium: nullableStringValidator,
|
||||
small: nullableStringValidator,
|
||||
})
|
||||
.nullish()
|
||||
.transform((obj) =>
|
||||
obj
|
||||
? obj
|
||||
: {
|
||||
small: "",
|
||||
medium: "",
|
||||
large: "",
|
||||
}
|
||||
),
|
||||
})
|
||||
|
||||
const reviewsSchema = z
|
||||
.object({
|
||||
widgetHtmlTagId: nullableStringValidator,
|
||||
widgetScriptEmbedUrlIframe: nullableStringValidator,
|
||||
widgetScriptEmbedUrlJavaScript: nullableStringValidator,
|
||||
})
|
||||
.nullish()
|
||||
.transform((obj) =>
|
||||
obj
|
||||
? obj
|
||||
: {
|
||||
widgetHtmlTagId: "",
|
||||
widgetScriptEmbedUrlIframe: "",
|
||||
widgetScriptEmbedUrlJavaScript: "",
|
||||
}
|
||||
)
|
||||
|
||||
export const ratingsSchema = z
|
||||
.object({
|
||||
tripAdvisor: z.object({
|
||||
awards: nullableArrayObjectValidator(awardSchema),
|
||||
numberOfReviews: z.number(),
|
||||
rating: z.number(),
|
||||
ratingImageUrl: nullableStringUrlValidator,
|
||||
reviews: reviewsSchema,
|
||||
webUrl: nullableStringUrlValidator,
|
||||
}),
|
||||
})
|
||||
.optional()
|
||||
@@ -0,0 +1,12 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator"
|
||||
|
||||
export const rewardNightSchema = z.object({
|
||||
campaign: z.object({
|
||||
end: nullableStringValidator,
|
||||
points: z.number(),
|
||||
start: nullableStringValidator,
|
||||
}),
|
||||
points: z.number(),
|
||||
})
|
||||
@@ -0,0 +1,8 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator"
|
||||
|
||||
export const socialMediaSchema = z.object({
|
||||
facebook: nullableStringValidator,
|
||||
instagram: nullableStringValidator,
|
||||
})
|
||||
@@ -0,0 +1,42 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { dt } from "@scandic-hotels/common/dt"
|
||||
import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator"
|
||||
|
||||
import { AlertTypeEnum } from "../../../../types/alertType"
|
||||
|
||||
const specialAlertSchema = z.object({
|
||||
description: nullableStringValidator,
|
||||
displayInBookingFlow: z.boolean().default(false),
|
||||
endDate: nullableStringValidator,
|
||||
startDate: nullableStringValidator,
|
||||
title: nullableStringValidator,
|
||||
type: nullableStringValidator,
|
||||
})
|
||||
|
||||
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) => {
|
||||
const hasText = alert.description || alert.title
|
||||
const hasDates = alert.startDate && alert.endDate
|
||||
if (!hasDates) {
|
||||
return hasText
|
||||
}
|
||||
const shouldShowNow = alert.startDate <= now && alert.endDate >= now
|
||||
return shouldShowNow && hasText
|
||||
})
|
||||
return filteredAlerts.map((alert, idx) => ({
|
||||
heading: alert.title || null,
|
||||
id: `alert-${alert.type}-${idx}`,
|
||||
name: alert.type,
|
||||
text: alert.description || null,
|
||||
type: AlertTypeEnum.Info,
|
||||
displayInBookingFlow: alert.displayInBookingFlow,
|
||||
endDate: alert.endDate,
|
||||
startDate: alert.startDate,
|
||||
}))
|
||||
})
|
||||
Reference in New Issue
Block a user