Merged in chore/refactor-hotel-trpc-routes (pull request #2891)

Chore/refactor hotel trpc routes

* chore(SW-3519): refactor trpc hotel routers

* chore(SW-3519): refactor trpc hotel routers

* refactor

* merge

* Merge branch 'master' of bitbucket.org:scandic-swap/web into chore/refactor-hotel-trpc-routes


Approved-by: Linus Flood
This commit is contained in:
Joakim Jäderberg
2025-10-01 12:55:45 +00:00
parent 332abdfba0
commit 8498026189
52 changed files with 2338 additions and 1794 deletions

View File

@@ -0,0 +1,8 @@
import { router } from "../../../.."
import { room } from "./room"
import { rooms } from "./rooms"
export const selectRate = router({
room,
rooms,
})

View File

@@ -0,0 +1,69 @@
import { z } from "zod"
import { Lang } from "@scandic-hotels/common/constants/language"
import { SEARCH_TYPE_REDEMPTION } from "../../../../constants/booking"
import { unauthorizedError } from "../../../../errors"
import { safeProtectedServiceProcedure } from "../../../../procedures"
import { getVerifiedUser } from "../../../user/utils/getVerifiedUser"
import { baseBookingSchema, baseRoomSchema } from "../../input"
import { getRoomsAvailability } from "../../services/getRoomsAvailability"
import { mergeRoomTypes } from "../../utils"
export const selectRateRoomAvailabilityInputSchema = z.object({
booking: baseBookingSchema.extend({
room: baseRoomSchema,
}),
lang: z.nativeEnum(Lang),
})
export const room = safeProtectedServiceProcedure
.input(selectRateRoomAvailabilityInputSchema)
.use(async ({ ctx, input, next }) => {
if (input.booking.searchType === SEARCH_TYPE_REDEMPTION) {
if (ctx.session?.token.access_token) {
const verifiedUser = await getVerifiedUser({
session: ctx.session,
})
if (!verifiedUser?.error) {
return next({
ctx: {
token: ctx.session.token.access_token,
userPoints: verifiedUser?.data.membership?.currentPoints ?? 0,
},
})
}
}
throw unauthorizedError()
}
return next({
ctx: {
token: ctx.serviceToken,
},
})
})
.query(async function ({ ctx, input }) {
const [availability] = await getRoomsAvailability(
{
booking: {
...input.booking,
rooms: [input.booking.room],
},
lang: input.lang,
},
ctx.token,
ctx.serviceToken,
ctx.userPoints
)
if (!availability || "error" in availability) {
return null
}
const roomConfigurations = mergeRoomTypes(availability.roomConfigurations)
return {
...availability,
roomConfigurations,
}
})

View File

@@ -0,0 +1,58 @@
import "server-only"
import { SEARCH_TYPE_REDEMPTION } from "../../../../../constants/booking"
import { unauthorizedError } from "../../../../../errors"
import { safeProtectedServiceProcedure } from "../../../../../procedures"
import { getVerifiedUser } from "../../../../user/utils/getVerifiedUser"
import { getRoomsAvailability } from "../../../services/getRoomsAvailability"
import { mergeRoomTypes } from "../../../utils"
import { selectRateRoomsAvailabilityInputSchema } from "./schema"
export const rooms = safeProtectedServiceProcedure
.input(selectRateRoomsAvailabilityInputSchema)
.use(async ({ ctx, input, next }) => {
if (input.booking.searchType === SEARCH_TYPE_REDEMPTION) {
if (ctx.session?.token.access_token) {
const verifiedUser = await getVerifiedUser({
session: ctx.session,
})
if (!verifiedUser?.error) {
return next({
ctx: {
token: ctx.session.token.access_token,
userPoints: verifiedUser?.data.membership?.currentPoints ?? 0,
},
})
}
}
throw unauthorizedError()
}
return next({
ctx: {
token: ctx.serviceToken,
},
})
})
.query(async function ({ ctx, input }) {
input.booking.rooms = input.booking.rooms.map((room) => ({
...room,
bookingCode: room.bookingCode || input.booking.bookingCode,
}))
const availability = await getRoomsAvailability(
input,
ctx.token,
ctx.serviceToken,
ctx.userPoints
)
for (const room of availability) {
if (!room || "error" in room) {
continue
}
room.roomConfigurations = mergeRoomTypes(room.roomConfigurations)
}
return availability
})

View File

@@ -0,0 +1,64 @@
import dayjs from "dayjs"
import { z } from "zod"
import { Lang } from "@scandic-hotels/common/constants/language"
import { baseBookingSchema, baseRoomSchema } from "../../../input"
export type RoomsAvailabilityInputRoom =
RoomsAvailabilityInputSchema["booking"]["rooms"][number]
export type RoomsAvailabilityOutputSchema = z.output<
typeof selectRateRoomsAvailabilityInputSchema
>
export type RoomsAvailabilityInputSchema = z.input<
typeof selectRateRoomsAvailabilityInputSchema
>
export const selectRateRoomsAvailabilityInputSchema = z
.object({
booking: baseBookingSchema.extend({
rooms: z.array(baseRoomSchema),
}),
lang: z.nativeEnum(Lang),
})
.refine(
(data) => {
const fromDate = dayjs(data.booking.fromDate)
return fromDate.isValid()
},
{
message: "FROMDATE_INVALID",
}
)
.refine(
(data) => {
const toDate = dayjs(data.booking.toDate)
return toDate.isValid()
},
{
message: "TODATE_INVALID",
}
)
.refine(
(data) => {
const fromDate = dayjs(data.booking.fromDate).startOf("day")
const toDate = dayjs(data.booking.toDate).startOf("day")
return fromDate.isBefore(toDate)
},
{
message: "TODATE_MUST_BE_AFTER_FROMDATE",
}
)
.refine(
(data) => {
const fromDate = dayjs(data.booking.fromDate)
const today = dayjs().startOf("day")
return fromDate.isSameOrAfter(today)
},
{
message: "FROMDATE_CANNOT_BE_IN_THE_PAST",
}
)