feat: add multiroom tracking to booking flow

This commit is contained in:
Simon Emanuelsson
2025-03-05 11:53:05 +01:00
parent 540402b969
commit 1812591903
72 changed files with 2277 additions and 1308 deletions

View File

@@ -18,11 +18,14 @@ import DesktopSummary from "@/components/HotelReservation/EnterDetails/Summary/D
import MobileSummary from "@/components/HotelReservation/EnterDetails/Summary/Mobile"
import { generateChildrenString } from "@/components/HotelReservation/utils"
import Alert from "@/components/TempDesignSystem/Alert"
import TrackingSDK from "@/components/TrackingSDK"
import { getIntl } from "@/i18n"
import RoomProvider from "@/providers/Details/RoomProvider"
import EnterDetailsProvider from "@/providers/EnterDetailsProvider"
import { convertSearchParamsToObj } from "@/utils/url"
import { getTracking } from "./tracking"
import styles from "./page.module.css"
import { AvailabilityEnum } from "@/types/components/hotelReservation/selectHotel/selectHotel"
@@ -57,34 +60,30 @@ export default async function DetailsPage({
const childrenAsString =
room.childrenInRoom && generateChildrenString(room.childrenInRoom)
const selectedRoomAvailabilityInput = {
const packages = room.packages
? await getPackages({
adults: room.adults,
children: room.childrenInRoom?.length,
endDate: booking.toDate,
hotelId: booking.hotelId,
packageCodes: room.packages,
startDate: booking.fromDate,
lang,
})
: null
const roomAvailability = await getSelectedRoomAvailability({
adults: room.adults,
bookingCode: booking.bookingCode,
children: childrenAsString,
counterRateCode: room.counterRateCode,
hotelId: booking.hotelId,
packageCodes: room.packages,
rateCode: room.rateCode,
roomStayStartDate: booking.fromDate,
roomStayEndDate: booking.toDate,
roomStayStartDate: booking.fromDate,
roomTypeCode: room.roomTypeCode,
counterRateCode: room.counterRateCode,
bookingCode: booking.bookingCode,
}
const packages = room.packages
? await getPackages({
adults: room.adults,
children: room.childrenInRoom?.length,
endDate: booking.toDate,
hotelId: booking.hotelId,
packageCodes: room.packages,
startDate: booking.fromDate,
lang,
})
: null
const roomAvailability = await getSelectedRoomAvailability(
selectedRoomAvailabilityInput
)
})
if (!roomAvailability) {
// redirect back to select-rate if availability call fails
@@ -98,8 +97,11 @@ export default async function DetailsPage({
mustBeGuaranteed: roomAvailability.mustBeGuaranteed,
memberMustBeGuaranteed: roomAvailability.memberMustBeGuaranteed,
packages,
rateTitle: roomAvailability.rateTitle,
rate: roomAvailability.rate,
rateDefinitionTitle: roomAvailability.rateDefinitionTitle,
rateDetails: roomAvailability.rateDetails ?? [],
rateTitle: roomAvailability.rateTitle,
rateType: roomAvailability.rateType,
roomType: roomAvailability.selectedRoom.roomType,
roomTypeCode: roomAvailability.selectedRoom.roomTypeCode,
roomRate: {
@@ -122,41 +124,28 @@ export default async function DetailsPage({
language: lang,
})
const user = await getProfileSafely()
// const userTrackingData = await getUserTracking()
if (!hotelData || !rooms) {
return notFound()
}
// const arrivalDate = new Date(booking.fromDate)
// const departureDate = new Date(booking.toDate)
const { hotel } = hotelData
// TODO: add tracking
// const initialHotelsTrackingData: TrackingSDKHotelInfo = {
// searchTerm: searchParams.city,
// arrivalDate: format(arrivalDate, "yyyy-MM-dd"),
// departureDate: format(departureDate, "yyyy-MM-dd"),
// noOfAdults: adults,
// noOfChildren: childrenInRoom?.length,
// ageOfChildren: childrenInRoom?.map((c) => c.age).join(","),
// childBedPreference: childrenInRoom
// ?.map((c) => ChildBedMapEnum[c.bed])
// .join("|"),
// noOfRooms: 1, // // TODO: Handle multiple rooms
// duration: differenceInCalendarDays(departureDate, arrivalDate),
// leadTime: differenceInCalendarDays(arrivalDate, new Date()),
// searchType: "hotel",
// bookingTypeofDay: isWeekend(arrivalDate) ? "weekend" : "weekday",
// country: hotel?.address.country,
// hotelID: hotel?.operaId,
// region: hotel?.address.city,
// }
const { hotelsTrackingData, pageTrackingData } = getTracking(
booking,
hotel,
rooms,
!!breakfastPackages?.length,
searchParams.city,
!!user,
lang
)
const intl = await getIntl()
const firstRoom = rooms[0]
const multirooms = rooms.slice(1)
const isRoomNotAvailable = rooms.some((room) => !room.isAvailable)
return (
<EnterDetailsProvider
@@ -214,6 +203,7 @@ export default async function DetailsPage({
</aside>
</div>
</main>
<TrackingSDK hotelInfo={hotelsTrackingData} pageData={pageTrackingData} />
</EnterDetailsProvider>
)
}

View File

@@ -0,0 +1,101 @@
import { differenceInCalendarDays, format, isWeekend } from "date-fns"
import { getSpecialRoomType } from "@/utils/specialRoomType"
import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums"
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
import {
TrackingChannelEnum,
type TrackingSDKHotelInfo,
type TrackingSDKPageData,
} from "@/types/components/tracking"
import type { Hotel } from "@/types/hotel"
import type { Room } from "@/types/providers/details/room"
import type { Lang } from "@/constants/languages"
import type { SelectHotelParams } from "@/utils/url"
export function getTracking(
booking: SelectHotelParams<SelectRateSearchParams>,
hotel: Hotel,
rooms: Room[],
offersBreakfast: boolean,
city: string | undefined,
isMember: boolean,
lang: Lang
) {
const arrivalDate = new Date(booking.fromDate)
const departureDate = new Date(booking.toDate)
const pageTrackingData: TrackingSDKPageData = {
channel: TrackingChannelEnum.hotelreservation,
domainLanguage: lang,
pageId: "details",
pageName: "hotelreservation|details",
pageType: "bookingroomsandratespage",
siteSections: "hotelreservation|details",
siteVersion: "new-web",
}
const hotelsTrackingData: TrackingSDKHotelInfo = {
ageOfChildren: booking.rooms
.map(
(room) => room.childrenInRoom?.map((kid) => kid.age).join(",") ?? "-"
)
.join("|"),
analyticsRateCode: rooms.map((room) => room.rate).join("|"),
arrivalDate: format(arrivalDate, "yyyy-MM-dd"),
bookingTypeofDay: isWeekend(arrivalDate) ? "weekend" : "weekday",
breakfastOption: rooms
.map(() => (offersBreakfast ? "breakfast buffet" : "no breakfast"))
.join(","),
childBedPreference: booking.rooms
.map(
(room) =>
room.childrenInRoom
?.map((kid) => ChildBedMapEnum[kid.bed])
.join(",") ?? "-"
)
.join("|"),
country: hotel?.address.country,
departureDate: format(departureDate, "yyyy-MM-dd"),
duration: differenceInCalendarDays(departureDate, arrivalDate),
hotelID: hotel?.operaId,
leadTime: differenceInCalendarDays(arrivalDate, new Date()),
noOfAdults: booking.rooms.map((room) => room.adults).join(","),
noOfChildren: booking.rooms
.map((room) => room.childrenInRoom?.length ?? 0)
.join(","),
noOfRooms: booking.rooms.length,
rateCode: rooms
.map((room, idx) => {
if (idx === 0 && isMember && room.roomRate.memberRate) {
return room.roomRate.memberRate?.rateCode
}
return room.roomRate.publicRate?.rateCode
})
.join("|"),
rateCodeCancellationRule: rooms
.map((room) => room.cancellationText.toLowerCase())
.join(","),
rateCodeName: rooms.map((room) => room.rateDefinitionTitle).join(","),
rateCodeType: rooms.map((room) => room.rateType.toLowerCase()).join(","),
region: hotel?.address.city,
revenueCurrencyCode: rooms
.map(
(room) =>
room.roomRate.publicRate?.localPrice.currency ??
room.roomRate.memberRate?.localPrice.currency
)
.join(","),
searchTerm: city,
searchType: "hotel",
specialRoomType: rooms
.map((room) => getSpecialRoomType(room.packages))
.join(","),
}
return {
hotelsTrackingData,
pageTrackingData,
}
}