feat(SW-1652): Fetching additional rooms on confirmation page * feat(SW-1652): Fetching additional rooms on confirmation page Approved-by: Tobias Johansson
227 lines
6.3 KiB
TypeScript
227 lines
6.3 KiB
TypeScript
import { z } from "zod"
|
|
|
|
import { ChildBedTypeEnum } from "@/constants/booking"
|
|
|
|
import { phoneValidator } from "@/utils/zod/phoneValidator"
|
|
import { nullableStringValidator } from "@/utils/zod/stringValidator"
|
|
|
|
// MUTATION
|
|
export const createBookingSchema = z
|
|
.object({
|
|
data: z.object({
|
|
attributes: z.object({
|
|
reservationStatus: z.string(),
|
|
paymentUrl: z.string().nullable().optional(),
|
|
rooms: z
|
|
.array(
|
|
z.object({
|
|
confirmationNumber: z.string(),
|
|
cancellationNumber: z.string().nullable(),
|
|
priceChangedMetadata: z
|
|
.object({
|
|
roomPrice: z.number(),
|
|
totalPrice: z.number(),
|
|
})
|
|
.nullable()
|
|
.optional(),
|
|
})
|
|
)
|
|
.default([]),
|
|
errors: z
|
|
.array(
|
|
z.object({
|
|
confirmationNumber: z.string().nullable().optional(),
|
|
errorCode: z.string(),
|
|
description: z.string().nullable().optional(),
|
|
meta: z
|
|
.record(z.string(), z.union([z.string(), z.number()]))
|
|
.nullable()
|
|
.optional(),
|
|
})
|
|
)
|
|
.default([]),
|
|
}),
|
|
type: z.string(),
|
|
id: z.string(),
|
|
links: z.object({
|
|
self: z.object({
|
|
href: z.string().url(),
|
|
meta: z.object({
|
|
method: z.string(),
|
|
}),
|
|
}),
|
|
}),
|
|
}),
|
|
})
|
|
.transform((d) => ({
|
|
id: d.data.id,
|
|
links: d.data.links,
|
|
type: d.data.type,
|
|
reservationStatus: d.data.attributes.reservationStatus,
|
|
paymentUrl: d.data.attributes.paymentUrl,
|
|
rooms: d.data.attributes.rooms,
|
|
errors: d.data.attributes.errors,
|
|
}))
|
|
|
|
// QUERY
|
|
const childBedPreferencesSchema = z.object({
|
|
bedType: z.nativeEnum(ChildBedTypeEnum),
|
|
quantity: z.number().int(),
|
|
code: z.string().nullable().default(""),
|
|
})
|
|
|
|
const guestSchema = z.object({
|
|
email: z.string().email().nullable().default(""),
|
|
firstName: z.string().nullable().default(""),
|
|
lastName: z.string().nullable().default(""),
|
|
membershipNumber: z.string().nullable().default(""),
|
|
phoneNumber: phoneValidator().nullable().default(""),
|
|
})
|
|
|
|
const packageSchema = z
|
|
.object({
|
|
description: z.string().nullable().default(""),
|
|
type: z.string().nullable().default(""),
|
|
code: z.string().nullable().default(""),
|
|
price: z.object({
|
|
unit: z.number().int().nullable(),
|
|
unitPrice: z.number(),
|
|
totalPrice: z.number().nullable(),
|
|
totalUnit: z.number().int().nullable(),
|
|
currency: z.string().default(""),
|
|
points: z.number().int().nullable(),
|
|
}),
|
|
})
|
|
.transform((packageData) => ({
|
|
description: packageData.description,
|
|
code: packageData.code,
|
|
type: packageData.type,
|
|
currency: packageData.price.currency,
|
|
points: packageData.price.points,
|
|
totalPrice: packageData.price.totalPrice ?? 0,
|
|
totalUnit: packageData.price.totalUnit ?? 0,
|
|
unit: packageData.price.unit ?? 0,
|
|
unitPrice: packageData.price.unitPrice,
|
|
}))
|
|
|
|
const ancillarySchema = z
|
|
.object({
|
|
comment: z.string().default(""),
|
|
deliveryTime: z.string().default(""),
|
|
})
|
|
.nullable()
|
|
.default({
|
|
comment: "",
|
|
deliveryTime: "",
|
|
})
|
|
|
|
const rateDefinitionSchema = z.object({
|
|
breakfastIncluded: z.boolean().default(false),
|
|
cancellationRule: z.string().nullable().default(""),
|
|
cancellationText: z.string().nullable().default(""),
|
|
generalTerms: z.array(z.string()).default([]),
|
|
isMemberRate: z.boolean().default(false),
|
|
mustBeGuaranteed: z.boolean().default(false),
|
|
rateCode: z.string().nullable().default(""),
|
|
title: z.string().nullable().default(""),
|
|
})
|
|
|
|
export const linkedReservationSchema = z.object({
|
|
confirmationNumber: z.string().default(""),
|
|
hotelId: z.string().default(""),
|
|
checkinDate: z.string(),
|
|
checkoutDate: z.string(),
|
|
cancellationNumber: nullableStringValidator,
|
|
roomTypeCode: z.string().default(""),
|
|
adults: z.number().int(),
|
|
children: z.number().int(),
|
|
profileId: z.string().default(""),
|
|
})
|
|
|
|
const linksSchema = z.object({
|
|
addAncillary: z
|
|
.object({
|
|
href: z.string(),
|
|
meta: z.object({
|
|
method: z.string(),
|
|
}),
|
|
})
|
|
.nullable(),
|
|
cancel: z
|
|
.object({
|
|
href: z.string(),
|
|
meta: z.object({
|
|
method: z.string(),
|
|
}),
|
|
})
|
|
.nullable(),
|
|
guarantee: z
|
|
.object({
|
|
href: z.string(),
|
|
meta: z.object({
|
|
method: z.string(),
|
|
}),
|
|
})
|
|
.nullable(),
|
|
modify: z
|
|
.object({
|
|
href: z.string(),
|
|
meta: z.object({
|
|
method: z.string(),
|
|
}),
|
|
})
|
|
.nullable(),
|
|
self: z
|
|
.object({
|
|
href: z.string(),
|
|
meta: z.object({
|
|
method: z.string(),
|
|
}),
|
|
})
|
|
.nullable(),
|
|
})
|
|
|
|
export const bookingConfirmationSchema = z
|
|
.object({
|
|
data: z.object({
|
|
attributes: z.object({
|
|
adults: z.number().int(),
|
|
ancillary: ancillarySchema,
|
|
checkInDate: z.date({ coerce: true }),
|
|
checkOutDate: z.date({ coerce: true }),
|
|
childBedPreferences: z.array(childBedPreferencesSchema).default([]),
|
|
childrenAges: z.array(z.number().int()).default([]),
|
|
canChangeDate: z.boolean(),
|
|
computedReservationStatus: z.string().nullable().default(""),
|
|
confirmationNumber: z.string().nullable().default(""),
|
|
createDateTime: z.date({ coerce: true }),
|
|
currencyCode: z.string(),
|
|
guest: guestSchema,
|
|
isGuaranteedForLateArrival: z.boolean().optional(),
|
|
linkedReservations: z
|
|
.array(linkedReservationSchema)
|
|
.nullish()
|
|
.transform((v) => v ?? []),
|
|
hotelId: z.string(),
|
|
packages: z.array(packageSchema).default([]),
|
|
rateDefinition: rateDefinitionSchema,
|
|
reservationStatus: z.string().nullable().default(""),
|
|
roomPrice: z.number(),
|
|
roomTypeCode: z.string().nullable().default(""),
|
|
totalPrice: z.number(),
|
|
totalPriceExVat: z.number(),
|
|
vatAmount: z.number(),
|
|
vatPercentage: z.number(),
|
|
}),
|
|
id: z.string(),
|
|
type: z.literal("booking"),
|
|
links: linksSchema,
|
|
}),
|
|
})
|
|
.transform(({ data }) => ({
|
|
...data.attributes,
|
|
showAncillaries: !!data.links.addAncillary,
|
|
isCancelable: !!data.links.cancel,
|
|
isModifiable: !!data.links.modify,
|
|
}))
|