Merged in feat/refactor-select-rate (pull request #1402)
Select-rate: refactor - converted RoomsContainer into a client component * feat/select-rate - refactor and fixed duplicate key warning * Rooms as client component * Fixed lang in input * It works * Cleanup * Cleanup * PR fixes Approved-by: Joakim Jäderberg
This commit is contained in:
@@ -86,6 +86,7 @@ export default async function DetailsPage({
|
|||||||
hotelId: booking.hotelId,
|
hotelId: booking.hotelId,
|
||||||
packageCodes: room.packages,
|
packageCodes: room.packages,
|
||||||
startDate: booking.fromDate,
|
startDate: booking.fromDate,
|
||||||
|
lang,
|
||||||
})
|
})
|
||||||
: null
|
: null
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ type Props = {
|
|||||||
count?: number
|
count?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function RoomsContainerSkeleton({ count = 4 }: Props) {
|
export function RoomsContainerSkeleton({ count = 4 }: Props) {
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<div className={styles.filterContainer}></div>
|
<div className={styles.filterContainer}></div>
|
||||||
|
|||||||
@@ -1,109 +1,59 @@
|
|||||||
|
"use client"
|
||||||
|
import { useSession } from "next-auth/react"
|
||||||
|
|
||||||
import { dt } from "@/lib/dt"
|
import { dt } from "@/lib/dt"
|
||||||
import {
|
|
||||||
getHotel,
|
|
||||||
getPackages,
|
|
||||||
getRoomsAvailability,
|
|
||||||
} from "@/lib/trpc/memoizedRequests"
|
|
||||||
|
|
||||||
import { auth } from "@/auth"
|
import useLang from "@/hooks/useLang"
|
||||||
import { generateChildrenString } from "@/components/HotelReservation/utils"
|
|
||||||
import RatesProvider from "@/providers/RatesProvider"
|
import RatesProvider from "@/providers/RatesProvider"
|
||||||
import { isValidSession } from "@/utils/session"
|
import { isValidClientSession } from "@/utils/clientSession"
|
||||||
|
|
||||||
import { combineRoomAvailabilities } from "../utils"
|
import { useHotelPackages, useRoomsAvailability } from "../utils"
|
||||||
import RateSummary from "./RateSummary"
|
import RateSummary from "./RateSummary"
|
||||||
import Rooms from "./Rooms"
|
import Rooms from "./Rooms"
|
||||||
|
import { RoomsContainerSkeleton } from "./RoomsContainerSkeleton"
|
||||||
|
|
||||||
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
|
|
||||||
import type { RoomsContainerProps } from "@/types/components/hotelReservation/selectRate/roomsContainer"
|
import type { RoomsContainerProps } from "@/types/components/hotelReservation/selectRate/roomsContainer"
|
||||||
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
|
|
||||||
import type { Lang } from "@/constants/languages"
|
|
||||||
|
|
||||||
export function preload(
|
export function RoomsContainer({
|
||||||
hotelId: string,
|
|
||||||
lang: Lang,
|
|
||||||
fromDate: string,
|
|
||||||
toDate: string,
|
|
||||||
adults: number[],
|
|
||||||
children?: Child[]
|
|
||||||
) {
|
|
||||||
void getHotel({ hotelId, isCardOnlyPayment: false, language: lang })
|
|
||||||
void getPackages({
|
|
||||||
adults: adults[0],
|
|
||||||
children: children ? children?.length : undefined,
|
|
||||||
endDate: toDate,
|
|
||||||
hotelId,
|
|
||||||
packageCodes: [
|
|
||||||
RoomPackageCodeEnum.ACCESSIBILITY_ROOM,
|
|
||||||
RoomPackageCodeEnum.PET_ROOM,
|
|
||||||
RoomPackageCodeEnum.ALLERGY_ROOM,
|
|
||||||
],
|
|
||||||
startDate: fromDate,
|
|
||||||
})
|
|
||||||
|
|
||||||
const uniqueAdultsCount = Array.from(new Set(adults))
|
|
||||||
uniqueAdultsCount.forEach((adultsInRoom) => {
|
|
||||||
void getRoomsAvailability({
|
|
||||||
adults: adultsInRoom,
|
|
||||||
children: children ? generateChildrenString(children) : undefined,
|
|
||||||
hotelId: +hotelId,
|
|
||||||
roomStayEndDate: toDate,
|
|
||||||
roomStayStartDate: fromDate,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function RoomsContainer({
|
|
||||||
adultArray,
|
adultArray,
|
||||||
booking,
|
booking,
|
||||||
childArray,
|
childArray,
|
||||||
fromDate,
|
fromDate,
|
||||||
hotelId,
|
hotelId,
|
||||||
lang,
|
hotelData,
|
||||||
toDate,
|
toDate,
|
||||||
}: RoomsContainerProps) {
|
}: RoomsContainerProps) {
|
||||||
const session = await auth()
|
const { data: session } = useSession()
|
||||||
const isUserLoggedIn = isValidSession(session)
|
const isUserLoggedIn = isValidClientSession(session)
|
||||||
|
const lang = useLang()
|
||||||
|
|
||||||
const fromDateString = dt(fromDate).format("YYYY-MM-DD")
|
const fromDateString = dt(fromDate).format("YYYY-MM-DD")
|
||||||
const toDateString = dt(toDate).format("YYYY-MM-DD")
|
const toDateString = dt(toDate).format("YYYY-MM-DD")
|
||||||
|
|
||||||
const hotelData = await getHotel({
|
|
||||||
hotelId: hotelId.toString(),
|
|
||||||
isCardOnlyPayment: false,
|
|
||||||
language: lang,
|
|
||||||
})
|
|
||||||
|
|
||||||
const uniqueAdultsCount = Array.from(new Set(adultArray))
|
const uniqueAdultsCount = Array.from(new Set(adultArray))
|
||||||
const roomsAvailabilityResults = await Promise.allSettled(
|
|
||||||
uniqueAdultsCount.map((adultCount) =>
|
const { isPending: isLoadingAvailability, data: roomsAvailability } =
|
||||||
getRoomsAvailability({
|
useRoomsAvailability(
|
||||||
adults: adultCount,
|
uniqueAdultsCount,
|
||||||
hotelId: hotelId,
|
hotelId,
|
||||||
roomStayEndDate: toDateString,
|
fromDateString,
|
||||||
roomStayStartDate: fromDateString,
|
toDateString,
|
||||||
children:
|
lang,
|
||||||
childArray && childArray.length > 0
|
childArray
|
||||||
? generateChildrenString(childArray)
|
|
||||||
: undefined,
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const { data: packages, isPending: isLoadingPackages } = useHotelPackages(
|
||||||
|
adultArray,
|
||||||
|
childArray,
|
||||||
|
fromDateString,
|
||||||
|
toDateString,
|
||||||
|
hotelId,
|
||||||
|
lang
|
||||||
)
|
)
|
||||||
|
|
||||||
const roomsAvailability = combineRoomAvailabilities(roomsAvailabilityResults)
|
if (isLoadingAvailability || isLoadingPackages) {
|
||||||
|
return <RoomsContainerSkeleton />
|
||||||
const packages = await getPackages({
|
}
|
||||||
adults: adultArray[0],
|
|
||||||
children: childArray ? childArray.length : undefined,
|
|
||||||
endDate: toDateString,
|
|
||||||
hotelId: hotelId.toString(),
|
|
||||||
packageCodes: [
|
|
||||||
RoomPackageCodeEnum.ACCESSIBILITY_ROOM,
|
|
||||||
RoomPackageCodeEnum.PET_ROOM,
|
|
||||||
RoomPackageCodeEnum.ALLERGY_ROOM,
|
|
||||||
],
|
|
||||||
startDate: fromDateString,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!hotelData?.hotel) {
|
if (!hotelData?.hotel) {
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -10,11 +10,7 @@ import { getHotelSearchDetails } from "@/app/[lang]/(live)/(public)/hotelreserva
|
|||||||
import HotelInfoCard, {
|
import HotelInfoCard, {
|
||||||
HotelInfoCardSkeleton,
|
HotelInfoCardSkeleton,
|
||||||
} from "@/components/HotelReservation/SelectRate/HotelInfoCard"
|
} from "@/components/HotelReservation/SelectRate/HotelInfoCard"
|
||||||
import {
|
import { RoomsContainer } from "@/components/HotelReservation/SelectRate/RoomsContainer"
|
||||||
preload,
|
|
||||||
RoomsContainer,
|
|
||||||
} from "@/components/HotelReservation/SelectRate/RoomsContainer"
|
|
||||||
import { RoomsContainerSkeleton } from "@/components/HotelReservation/SelectRate/RoomsContainer/RoomsContainerSkeleton"
|
|
||||||
import TrackingSDK from "@/components/TrackingSDK"
|
import TrackingSDK from "@/components/TrackingSDK"
|
||||||
import { setLang } from "@/i18n/serverContext"
|
import { setLang } from "@/i18n/serverContext"
|
||||||
import { convertSearchParamsToObj } from "@/utils/url"
|
import { convertSearchParamsToObj } from "@/utils/url"
|
||||||
@@ -45,15 +41,6 @@ export default async function SelectRatePage({
|
|||||||
selectHotelParams.toDate
|
selectHotelParams.toDate
|
||||||
)
|
)
|
||||||
|
|
||||||
preload(
|
|
||||||
hotel.id,
|
|
||||||
params.lang,
|
|
||||||
fromDate.format("YYYY-MM-DD"),
|
|
||||||
toDate.format("YYYY-MM-DD"),
|
|
||||||
adultsInRoom,
|
|
||||||
childrenInRoom
|
|
||||||
)
|
|
||||||
|
|
||||||
const hotelData = await getHotel({
|
const hotelData = await getHotel({
|
||||||
hotelId: hotel.id,
|
hotelId: hotel.id,
|
||||||
isCardOnlyPayment: false,
|
isCardOnlyPayment: false,
|
||||||
@@ -104,18 +91,17 @@ export default async function SelectRatePage({
|
|||||||
<HotelInfoCard hotelData={hotelData} />
|
<HotelInfoCard hotelData={hotelData} />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
|
||||||
<Suspense key={suspenseKey} fallback={<RoomsContainerSkeleton />}>
|
<RoomsContainer
|
||||||
<RoomsContainer
|
hotelData={hotelData}
|
||||||
adultArray={adultsInRoom}
|
adultArray={adultsInRoom}
|
||||||
booking={booking}
|
booking={booking}
|
||||||
childArray={childrenInRoom}
|
childArray={childrenInRoom}
|
||||||
fromDate={arrivalDate}
|
fromDate={arrivalDate}
|
||||||
hotelId={hotelId}
|
hotelId={hotelId}
|
||||||
lang={params.lang}
|
toDate={departureDate}
|
||||||
toDate={departureDate}
|
/>
|
||||||
/>
|
|
||||||
</Suspense>
|
<Suspense key={`${suspenseKey}-tracking`} fallback={null}>
|
||||||
<Suspense key={suspenseKey} fallback={null}>
|
|
||||||
<TrackingSDK
|
<TrackingSDK
|
||||||
pageData={pageTrackingData}
|
pageData={pageTrackingData}
|
||||||
hotelInfo={hotelsTrackingData}
|
hotelInfo={hotelsTrackingData}
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
|
import { trpc } from "@/lib/trpc/client"
|
||||||
|
|
||||||
|
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
|
||||||
|
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||||
import type { RoomsAvailability } from "@/types/trpc/routers/hotel/roomAvailability"
|
import type { RoomsAvailability } from "@/types/trpc/routers/hotel/roomAvailability"
|
||||||
|
import type { Lang } from "@/constants/languages"
|
||||||
|
|
||||||
export function combineRoomAvailabilities(
|
export function combineRoomAvailabilities(
|
||||||
availabilityResults: PromiseSettledResult<RoomsAvailability | null>[]
|
availabilityResults: PromiseSettledResult<RoomsAvailability | null>[]
|
||||||
@@ -37,3 +42,56 @@ export function getRates(
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useRoomsAvailability(
|
||||||
|
uniqueAdultsCount: number[],
|
||||||
|
hotelId: number,
|
||||||
|
fromDateString: string,
|
||||||
|
toDateString: string,
|
||||||
|
lang: Lang,
|
||||||
|
childArray?: Child[]
|
||||||
|
) {
|
||||||
|
const returnValue =
|
||||||
|
trpc.hotel.availability.roomsCombinedAvailability.useQuery({
|
||||||
|
hotelId,
|
||||||
|
roomStayStartDate: fromDateString,
|
||||||
|
roomStayEndDate: toDateString,
|
||||||
|
uniqueAdultsCount,
|
||||||
|
childArray,
|
||||||
|
lang,
|
||||||
|
})
|
||||||
|
|
||||||
|
const combinedAvailability = returnValue.data?.length
|
||||||
|
? combineRoomAvailabilities(
|
||||||
|
returnValue.data as PromiseSettledResult<RoomsAvailability | null>[]
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
|
||||||
|
return {
|
||||||
|
...returnValue,
|
||||||
|
data: combinedAvailability,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useHotelPackages(
|
||||||
|
adultArray: number[],
|
||||||
|
childArray: Child[] | undefined,
|
||||||
|
fromDateString: string,
|
||||||
|
toDateString: string,
|
||||||
|
hotelId: number,
|
||||||
|
lang: Lang
|
||||||
|
) {
|
||||||
|
return trpc.hotel.packages.get.useQuery({
|
||||||
|
adults: adultArray[0], // Using the first adult count
|
||||||
|
children: childArray ? childArray.length : undefined,
|
||||||
|
endDate: toDateString,
|
||||||
|
hotelId: hotelId.toString(),
|
||||||
|
packageCodes: [
|
||||||
|
RoomPackageCodeEnum.ACCESSIBILITY_ROOM,
|
||||||
|
RoomPackageCodeEnum.PET_ROOM,
|
||||||
|
RoomPackageCodeEnum.ALLERGY_ROOM,
|
||||||
|
],
|
||||||
|
startDate: fromDateString,
|
||||||
|
lang: lang,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import type {
|
|||||||
import type { Lang } from "@/constants/languages"
|
import type { Lang } from "@/constants/languages"
|
||||||
import type {
|
import type {
|
||||||
GetHotelsByCSFilterInput,
|
GetHotelsByCSFilterInput,
|
||||||
GetRoomsAvailabilityInput,
|
|
||||||
GetSelectedRoomAvailabilityInput,
|
GetSelectedRoomAvailabilityInput,
|
||||||
} from "@/server/routers/hotels/input"
|
} from "@/server/routers/hotels/input"
|
||||||
import type { GetSavedPaymentCardsInput } from "@/server/routers/user/input"
|
import type { GetSavedPaymentCardsInput } from "@/server/routers/user/input"
|
||||||
@@ -87,12 +86,6 @@ export const getHotelPage = cache(async function getMemoizedHotelPage() {
|
|||||||
return serverClient().contentstack.hotelPage.get()
|
return serverClient().contentstack.hotelPage.get()
|
||||||
})
|
})
|
||||||
|
|
||||||
export const getRoomsAvailability = cache(
|
|
||||||
async function getMemoizedRoomAvailability(input: GetRoomsAvailabilityInput) {
|
|
||||||
return serverClient().hotel.availability.rooms(input)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
export const getSelectedRoomAvailability = cache(
|
export const getSelectedRoomAvailability = cache(
|
||||||
function getMemoizedSelectedRoomAvailability(
|
function getMemoizedSelectedRoomAvailability(
|
||||||
input: GetSelectedRoomAvailabilityInput
|
input: GetSelectedRoomAvailabilityInput
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { Lang } from "@/constants/languages"
|
import { Lang } from "@/constants/languages"
|
||||||
|
|
||||||
|
import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums"
|
||||||
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
|
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
|
||||||
import { Country } from "@/types/enums/country"
|
import { Country } from "@/types/enums/country"
|
||||||
|
|
||||||
@@ -23,14 +24,22 @@ export const getHotelsByHotelIdsAvailabilityInputSchema = z.object({
|
|||||||
bookingCode: z.string().optional().default(""),
|
bookingCode: z.string().optional().default(""),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const roomsAvailabilityInputSchema = z.object({
|
export const roomsCombinedAvailabilityInputSchema = z.object({
|
||||||
hotelId: z.number(),
|
hotelId: z.number(),
|
||||||
roomStayStartDate: z.string(),
|
roomStayStartDate: z.string(),
|
||||||
roomStayEndDate: z.string(),
|
roomStayEndDate: z.string(),
|
||||||
adults: z.number(),
|
uniqueAdultsCount: z.array(z.number()),
|
||||||
children: z.string().optional(),
|
childArray: z
|
||||||
|
.array(
|
||||||
|
z.object({
|
||||||
|
bed: z.nativeEnum(ChildBedMapEnum),
|
||||||
|
age: z.number(),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.optional(),
|
||||||
bookingCode: z.string().optional(),
|
bookingCode: z.string().optional(),
|
||||||
rateCode: z.string().optional(),
|
rateCode: z.string().optional(),
|
||||||
|
lang: z.nativeEnum(Lang),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const selectedRoomAvailabilityInputSchema = z.object({
|
export const selectedRoomAvailabilityInputSchema = z.object({
|
||||||
@@ -49,10 +58,6 @@ export type GetSelectedRoomAvailabilityInput = z.input<
|
|||||||
typeof selectedRoomAvailabilityInputSchema
|
typeof selectedRoomAvailabilityInputSchema
|
||||||
>
|
>
|
||||||
|
|
||||||
export type GetRoomsAvailabilityInput = z.input<
|
|
||||||
typeof roomsAvailabilityInputSchema
|
|
||||||
>
|
|
||||||
|
|
||||||
export const ratesInputSchema = z.object({
|
export const ratesInputSchema = z.object({
|
||||||
hotelId: z.string(),
|
hotelId: z.string(),
|
||||||
})
|
})
|
||||||
@@ -109,6 +114,7 @@ export const roomPackagesInputSchema = z.object({
|
|||||||
adults: z.number(),
|
adults: z.number(),
|
||||||
children: z.number().optional().default(0),
|
children: z.number().optional().default(0),
|
||||||
packageCodes: z.array(z.string()).optional().default([]),
|
packageCodes: z.array(z.string()).optional().default([]),
|
||||||
|
lang: z.nativeEnum(Lang),
|
||||||
})
|
})
|
||||||
export const cityCoordinatesInputSchema = z.object({
|
export const cityCoordinatesInputSchema = z.object({
|
||||||
city: z.string(),
|
city: z.string(),
|
||||||
|
|||||||
@@ -70,10 +70,14 @@ export const metrics = {
|
|||||||
fail: meter.createCounter("trpc.hotel.packages.get-fail"),
|
fail: meter.createCounter("trpc.hotel.packages.get-fail"),
|
||||||
success: meter.createCounter("trpc.hotel.packages.get-success"),
|
success: meter.createCounter("trpc.hotel.packages.get-success"),
|
||||||
},
|
},
|
||||||
roomAvailability: {
|
roomsCombinedAvailability: {
|
||||||
counter: meter.createCounter("trpc.hotel.availability.rooms"),
|
counter: meter.createCounter("trpc.hotel.roomsCombinedAvailability.rooms"),
|
||||||
fail: meter.createCounter("trpc.hotel.availability.rooms-fail"),
|
fail: meter.createCounter(
|
||||||
success: meter.createCounter("trpc.hotel.availability.rooms-success"),
|
"trpc.hotel.roomsCombinedAvailability.rooms-fail"
|
||||||
|
),
|
||||||
|
success: meter.createCounter(
|
||||||
|
"trpc.hotel.roomsCombinedAvailability.rooms-success"
|
||||||
|
),
|
||||||
},
|
},
|
||||||
selectedRoomAvailability: {
|
selectedRoomAvailability: {
|
||||||
counter: meter.createCounter("trpc.hotel.availability.room"),
|
counter: meter.createCounter("trpc.hotel.availability.room"),
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import {
|
|||||||
nearbyHotelIdsInput,
|
nearbyHotelIdsInput,
|
||||||
ratesInputSchema,
|
ratesInputSchema,
|
||||||
roomPackagesInputSchema,
|
roomPackagesInputSchema,
|
||||||
roomsAvailabilityInputSchema,
|
roomsCombinedAvailabilityInputSchema,
|
||||||
selectedRoomAvailabilityInputSchema,
|
selectedRoomAvailabilityInputSchema,
|
||||||
} from "./input"
|
} from "./input"
|
||||||
import { metrics } from "./metrics"
|
import { metrics } from "./metrics"
|
||||||
@@ -470,128 +470,98 @@ export const hotelQueryRouter = router({
|
|||||||
const apiLang = toApiLang(lang)
|
const apiLang = toApiLang(lang)
|
||||||
return getHotelsAvailabilityByHotelIds(input, apiLang, ctx.serviceToken)
|
return getHotelsAvailabilityByHotelIds(input, apiLang, ctx.serviceToken)
|
||||||
}),
|
}),
|
||||||
rooms: serviceProcedure
|
|
||||||
.input(roomsAvailabilityInputSchema)
|
roomsCombinedAvailability: serviceProcedure
|
||||||
|
.input(roomsCombinedAvailabilityInputSchema)
|
||||||
.query(async ({ input, ctx }) => {
|
.query(async ({ input, ctx }) => {
|
||||||
const { lang } = ctx
|
const { lang } = input
|
||||||
const apiLang = toApiLang(lang)
|
const apiLang = toApiLang(lang)
|
||||||
const {
|
const {
|
||||||
hotelId,
|
hotelId,
|
||||||
roomStayStartDate,
|
roomStayStartDate,
|
||||||
roomStayEndDate,
|
roomStayEndDate,
|
||||||
adults,
|
uniqueAdultsCount,
|
||||||
children,
|
childArray,
|
||||||
bookingCode,
|
bookingCode,
|
||||||
rateCode,
|
rateCode,
|
||||||
} = input
|
} = input
|
||||||
|
|
||||||
const params: Record<string, string | number | undefined> = {
|
const metricsData = {
|
||||||
roomStayStartDate,
|
|
||||||
roomStayEndDate,
|
|
||||||
adults,
|
|
||||||
...(children && { children }),
|
|
||||||
...(bookingCode && { bookingCode }),
|
|
||||||
language: apiLang,
|
|
||||||
}
|
|
||||||
|
|
||||||
metrics.roomAvailability.counter.add(1, {
|
|
||||||
hotelId,
|
hotelId,
|
||||||
roomStayStartDate,
|
roomStayStartDate,
|
||||||
roomStayEndDate,
|
roomStayEndDate,
|
||||||
adults,
|
uniqueAdultsCount,
|
||||||
children,
|
childArray: childArray ? JSON.stringify(childArray) : undefined,
|
||||||
bookingCode,
|
bookingCode,
|
||||||
})
|
}
|
||||||
|
|
||||||
|
metrics.roomsCombinedAvailability.counter.add(1, metricsData)
|
||||||
|
|
||||||
console.info(
|
console.info(
|
||||||
"api.hotels.roomsAvailability start",
|
"api.hotels.roomsCombinedAvailability start",
|
||||||
JSON.stringify({ query: { hotelId, params } })
|
JSON.stringify({ query: { hotelId, params: metricsData } })
|
||||||
)
|
|
||||||
const apiResponse = await api.get(
|
|
||||||
api.endpoints.v1.Availability.hotel(hotelId.toString()),
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${ctx.serviceToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
params
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!apiResponse.ok) {
|
const availabilityResponses = await Promise.allSettled(
|
||||||
const text = await apiResponse.text()
|
uniqueAdultsCount.map(async (adultCount: number) => {
|
||||||
metrics.roomAvailability.fail.add(1, {
|
const params: Record<string, string | number | undefined> = {
|
||||||
hotelId,
|
roomStayStartDate,
|
||||||
roomStayStartDate,
|
roomStayEndDate,
|
||||||
roomStayEndDate,
|
adults: adultCount,
|
||||||
adults,
|
...(childArray &&
|
||||||
children,
|
childArray.length > 0 && {
|
||||||
bookingCode,
|
children: childArray.join(","),
|
||||||
error_type: "http_error",
|
}),
|
||||||
error: JSON.stringify({
|
...(bookingCode && { bookingCode }),
|
||||||
status: apiResponse.status,
|
language: apiLang,
|
||||||
statusText: apiResponse.statusText,
|
}
|
||||||
text,
|
|
||||||
}),
|
const apiResponse = await api.get(
|
||||||
})
|
api.endpoints.v1.Availability.hotel(hotelId.toString()),
|
||||||
console.error(
|
{
|
||||||
"api.hotels.roomsAvailability error",
|
headers: {
|
||||||
JSON.stringify({
|
Authorization: `Bearer ${ctx.serviceToken}`,
|
||||||
query: { hotelId, params },
|
},
|
||||||
error: {
|
|
||||||
status: apiResponse.status,
|
|
||||||
statusText: apiResponse.statusText,
|
|
||||||
text,
|
|
||||||
},
|
},
|
||||||
})
|
params
|
||||||
)
|
)
|
||||||
return null
|
|
||||||
}
|
|
||||||
const apiJson = await apiResponse.json()
|
|
||||||
|
|
||||||
const validateAvailabilityData =
|
if (!apiResponse.ok) {
|
||||||
roomsAvailabilitySchema.safeParse(apiJson)
|
const text = await apiResponse.text()
|
||||||
if (!validateAvailabilityData.success) {
|
metrics.roomsCombinedAvailability.fail.add(1, metricsData)
|
||||||
metrics.roomAvailability.fail.add(1, {
|
console.error("Failed API call", { params, text })
|
||||||
hotelId,
|
return { error: "http_error", details: text }
|
||||||
roomStayStartDate,
|
}
|
||||||
roomStayEndDate,
|
|
||||||
adults,
|
const apiJson = await apiResponse.json()
|
||||||
children,
|
|
||||||
bookingCode,
|
const validateAvailabilityData =
|
||||||
error_type: "validation_error",
|
roomsAvailabilitySchema.safeParse(apiJson)
|
||||||
error: JSON.stringify(validateAvailabilityData.error),
|
|
||||||
})
|
if (!validateAvailabilityData.success) {
|
||||||
console.error(
|
console.error("Validation error", {
|
||||||
"api.hotels.roomsAvailability validation error",
|
params,
|
||||||
JSON.stringify({
|
error: validateAvailabilityData.error,
|
||||||
query: { hotelId, params },
|
})
|
||||||
error: validateAvailabilityData.error,
|
metrics.roomsCombinedAvailability.fail.add(1, metricsData)
|
||||||
})
|
return {
|
||||||
)
|
error: "validation_error",
|
||||||
return null
|
details: validateAvailabilityData.error,
|
||||||
}
|
}
|
||||||
metrics.roomAvailability.success.add(1, {
|
}
|
||||||
hotelId,
|
|
||||||
roomStayStartDate,
|
if (rateCode) {
|
||||||
roomStayEndDate,
|
validateAvailabilityData.data.mustBeGuaranteed =
|
||||||
adults,
|
validateAvailabilityData.data.rateDefinitions.find(
|
||||||
children,
|
(rate) => rate.rateCode === rateCode
|
||||||
bookingCode,
|
)?.mustBeGuaranteed
|
||||||
})
|
}
|
||||||
console.info(
|
|
||||||
"api.hotels.roomsAvailability success",
|
return validateAvailabilityData.data
|
||||||
JSON.stringify({
|
|
||||||
query: { hotelId, params: params },
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
metrics.roomsCombinedAvailability.success.add(1, metricsData)
|
||||||
if (rateCode) {
|
return availabilityResponses
|
||||||
validateAvailabilityData.data.mustBeGuaranteed =
|
|
||||||
validateAvailabilityData.data.rateDefinitions.filter(
|
|
||||||
(rate) => rate.rateCode === rateCode
|
|
||||||
)[0].mustBeGuaranteed
|
|
||||||
}
|
|
||||||
|
|
||||||
return validateAvailabilityData.data
|
|
||||||
}),
|
}),
|
||||||
room: serviceProcedure
|
room: serviceProcedure
|
||||||
.input(selectedRoomAvailabilityInputSchema)
|
.input(selectedRoomAvailabilityInputSchema)
|
||||||
@@ -885,40 +855,35 @@ export const hotelQueryRouter = router({
|
|||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
rates: router({
|
rates: router({
|
||||||
get: publicProcedure
|
get: publicProcedure.input(ratesInputSchema).query(async ({}) => {
|
||||||
.input(ratesInputSchema)
|
// TODO: Do a real API call when the endpoint is ready
|
||||||
.query(async ({ input, ctx }) => {
|
// const { hotelId } = input
|
||||||
// TODO: Do a real API call when the endpoint is ready
|
|
||||||
// const { hotelId } = input
|
|
||||||
|
|
||||||
// const params = new URLSearchParams()
|
// const params = new URLSearchParams()
|
||||||
// const apiLang = toApiLang(language)
|
// const apiLang = toApiLang(language)
|
||||||
// params.set("hotelId", hotelId.toString())
|
// params.set("hotelId", hotelId.toString())
|
||||||
// params.set("language", apiLang)
|
// params.set("language", apiLang)
|
||||||
|
|
||||||
console.info("api.hotels.rates start", JSON.stringify({}))
|
console.info("api.hotels.rates start", JSON.stringify({}))
|
||||||
const validatedHotelData = ratesSchema.safeParse(tempRatesData)
|
const validatedHotelData = ratesSchema.safeParse(tempRatesData)
|
||||||
|
|
||||||
if (!tempRatesData) {
|
if (!tempRatesData) {
|
||||||
console.error(
|
console.error("api.hotels.rates error", JSON.stringify({ error: null }))
|
||||||
"api.hotels.rates error",
|
//Can't return null here since consuming component does not handle null yet
|
||||||
JSON.stringify({ error: null })
|
// return null
|
||||||
)
|
}
|
||||||
//Can't return null here since consuming component does not handle null yet
|
if (!validatedHotelData.success) {
|
||||||
// return null
|
console.error(
|
||||||
}
|
"api.hotels.rates validation error",
|
||||||
if (!validatedHotelData.success) {
|
JSON.stringify({
|
||||||
console.error(
|
error: validatedHotelData.error,
|
||||||
"api.hotels.rates validation error",
|
})
|
||||||
JSON.stringify({
|
)
|
||||||
error: validatedHotelData.error,
|
throw badRequestError()
|
||||||
})
|
}
|
||||||
)
|
console.info("api.hotels.rates success", JSON.stringify({}))
|
||||||
throw badRequestError()
|
return validatedHotelData.data
|
||||||
}
|
}),
|
||||||
console.info("api.hotels.rates success", JSON.stringify({}))
|
|
||||||
return validatedHotelData.data
|
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
get: serviceProcedure
|
get: serviceProcedure
|
||||||
.input(hotelInputSchema)
|
.input(hotelInputSchema)
|
||||||
@@ -1544,7 +1509,7 @@ export const hotelQueryRouter = router({
|
|||||||
const { hotelId, startDate, endDate, adults, children, packageCodes } =
|
const { hotelId, startDate, endDate, adults, children, packageCodes } =
|
||||||
input
|
input
|
||||||
|
|
||||||
const { lang } = ctx
|
const { lang } = input
|
||||||
|
|
||||||
const apiLang = toApiLang(lang)
|
const apiLang = toApiLang(lang)
|
||||||
|
|
||||||
|
|||||||
@@ -35,16 +35,6 @@ export const hotelsByHotelIdAvailabilityFailCounter = meter.createCounter(
|
|||||||
"trpc.hotel.availability.hotels-by-hotel-id-fail"
|
"trpc.hotel.availability.hotels-by-hotel-id-fail"
|
||||||
)
|
)
|
||||||
|
|
||||||
export const roomsAvailabilityCounter = meter.createCounter(
|
|
||||||
"trpc.hotel.availability.rooms"
|
|
||||||
)
|
|
||||||
export const roomsAvailabilitySuccessCounter = meter.createCounter(
|
|
||||||
"trpc.hotel.availability.rooms-success"
|
|
||||||
)
|
|
||||||
export const roomsAvailabilityFailCounter = meter.createCounter(
|
|
||||||
"trpc.hotel.availability.rooms-fail"
|
|
||||||
)
|
|
||||||
|
|
||||||
export const selectedRoomAvailabilityCounter = meter.createCounter(
|
export const selectedRoomAvailabilityCounter = meter.createCounter(
|
||||||
"trpc.hotel.availability.room"
|
"trpc.hotel.availability.room"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Lang } from "@/constants/languages"
|
import type { HotelData } from "@/types/hotel"
|
||||||
import type { Child, SelectRateSearchParams } from "./selectRate"
|
import type { Child, SelectRateSearchParams } from "./selectRate"
|
||||||
|
|
||||||
export interface RoomsContainerProps {
|
export interface RoomsContainerProps {
|
||||||
@@ -7,6 +7,6 @@ export interface RoomsContainerProps {
|
|||||||
childArray?: Child[]
|
childArray?: Child[]
|
||||||
fromDate: Date
|
fromDate: Date
|
||||||
hotelId: number
|
hotelId: number
|
||||||
lang: Lang
|
|
||||||
toDate: Date
|
toDate: Date
|
||||||
|
hotelData: HotelData | null
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user