feat: add multiroom tracking to booking flow
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
"use client"
|
||||
|
||||
import { useBookingConfirmationStore } from "@/stores/booking-confirmation"
|
||||
|
||||
import TrackingSDK from "@/components/TrackingSDK"
|
||||
import useLang from "@/hooks/useLang"
|
||||
|
||||
import { getTracking } from "./tracking"
|
||||
|
||||
import type { Room } from "@/types/stores/booking-confirmation"
|
||||
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
|
||||
|
||||
export default function Tracking({
|
||||
bookingConfirmation,
|
||||
}: {
|
||||
bookingConfirmation: BookingConfirmation
|
||||
}) {
|
||||
const lang = useLang()
|
||||
const bookingRooms = useBookingConfirmationStore((state) => state.rooms)
|
||||
if (!bookingRooms.every(Boolean)) {
|
||||
return null
|
||||
}
|
||||
|
||||
const rooms = bookingRooms.filter((room): room is Room => !!room)
|
||||
|
||||
const { hotelsTrackingData, pageTrackingData, paymentInfo } = getTracking(
|
||||
lang,
|
||||
bookingConfirmation.booking,
|
||||
bookingConfirmation.hotel,
|
||||
rooms
|
||||
)
|
||||
|
||||
return (
|
||||
<TrackingSDK
|
||||
pageData={pageTrackingData}
|
||||
hotelInfo={hotelsTrackingData}
|
||||
paymentInfo={paymentInfo}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
import { differenceInCalendarDays, format, isWeekend } from "date-fns"
|
||||
|
||||
import { getSpecialRoomType } from "@/utils/specialRoomType"
|
||||
|
||||
import { invertedBedTypeMap } from "../../utils"
|
||||
|
||||
import {
|
||||
TrackingChannelEnum,
|
||||
type TrackingSDKHotelInfo,
|
||||
type TrackingSDKPageData,
|
||||
type TrackingSDKPaymentInfo,
|
||||
} from "@/types/components/tracking"
|
||||
import { BreakfastPackageEnum } from "@/types/enums/breakfast"
|
||||
import type { Room } from "@/types/stores/booking-confirmation"
|
||||
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
|
||||
import type { RateDefinition } from "@/types/trpc/routers/hotel/roomAvailability"
|
||||
import type { Lang } from "@/constants/languages"
|
||||
|
||||
function getRate(cancellationRule: RateDefinition["cancellationRule"] | null) {
|
||||
switch (cancellationRule) {
|
||||
case "CancellableBefore6PM":
|
||||
return "flex"
|
||||
case "Changeable":
|
||||
return "change"
|
||||
case "NotCancellable":
|
||||
return "save"
|
||||
default:
|
||||
return "-"
|
||||
}
|
||||
}
|
||||
|
||||
function findBreakfastPackage(
|
||||
packages: BookingConfirmation["booking"]["packages"]
|
||||
) {
|
||||
return packages.find(
|
||||
(pkg) => pkg.code === BreakfastPackageEnum.REGULAR_BREAKFAST
|
||||
)
|
||||
}
|
||||
|
||||
function mapBreakfastPackage(
|
||||
breakfastPackage: BookingConfirmation["booking"]["packages"][number],
|
||||
adults: number,
|
||||
operaId: string
|
||||
) {
|
||||
return {
|
||||
hotelid: operaId,
|
||||
productCategory: "", // TODO: Add category
|
||||
productId: breakfastPackage.code!, // Is not found unless code exists
|
||||
productName: "BreakfastAdult",
|
||||
productPoints: 0,
|
||||
productPrice: +breakfastPackage.unitPrice,
|
||||
productType: "food",
|
||||
productUnits: adults,
|
||||
}
|
||||
}
|
||||
|
||||
export function getTracking(
|
||||
lang: Lang,
|
||||
booking: BookingConfirmation["booking"],
|
||||
hotel: BookingConfirmation["hotel"],
|
||||
rooms: Room[]
|
||||
) {
|
||||
const arrivalDate = new Date(booking.checkInDate)
|
||||
const departureDate = new Date(booking.checkOutDate)
|
||||
|
||||
const pageTrackingData: TrackingSDKPageData = {
|
||||
channel: TrackingChannelEnum.hotelreservation,
|
||||
domainLanguage: lang,
|
||||
pageId: "booking-confirmation",
|
||||
pageName: `hotelreservation|confirmation`,
|
||||
pageType: "confirmation",
|
||||
siteSections: `hotelreservation|confirmation`,
|
||||
siteVersion: "new-web",
|
||||
}
|
||||
|
||||
const noOfAdults = rooms.map((r) => r.adults).join(",")
|
||||
const noOfChildren = rooms.map((r) => r.children ?? 0).join(",")
|
||||
const noOfRooms = rooms.length
|
||||
|
||||
const hotelsTrackingData: TrackingSDKHotelInfo = {
|
||||
ageOfChildren: rooms.map((r) => r.childrenAges?.join(",") ?? "-").join("|"),
|
||||
analyticsRateCode: rooms
|
||||
.map((r) => getRate(r.rateDefinition.cancellationRule))
|
||||
.join("|"),
|
||||
ancillaries: rooms
|
||||
.filter((r) => findBreakfastPackage(r.packages))
|
||||
.map((r) => {
|
||||
return mapBreakfastPackage(
|
||||
findBreakfastPackage(r.packages)!,
|
||||
r.adults,
|
||||
hotel.operaId
|
||||
)
|
||||
}),
|
||||
arrivalDate: format(arrivalDate, "yyyy-MM-dd"),
|
||||
bedType: rooms
|
||||
.map((r) => r.bedDescription)
|
||||
.join(",")
|
||||
.toLowerCase(),
|
||||
bnr: rooms.map((r) => r.confirmationNumber).join(","),
|
||||
bookingTypeofDay: isWeekend(arrivalDate) ? "weekend" : "weekday",
|
||||
breakfastOption: rooms
|
||||
.map((r) => {
|
||||
if (r.breakfastIncluded || r.breakfast) {
|
||||
return "breakfast buffet"
|
||||
}
|
||||
return "no breakfast"
|
||||
})
|
||||
.join(","),
|
||||
childBedPreference: rooms
|
||||
.map(
|
||||
(r) =>
|
||||
r.childBedPreferences
|
||||
.map((cbp) =>
|
||||
Array(cbp.quantity).fill(invertedBedTypeMap[cbp.bedType])
|
||||
)
|
||||
.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,
|
||||
noOfChildren,
|
||||
noOfRooms,
|
||||
rateCode: rooms.map((r) => r.rateDefinition.rateCode).join(","),
|
||||
rateCodeCancellationRule: rooms
|
||||
.map((r) => r.rateDefinition.cancellationText)
|
||||
.join(",")
|
||||
.toLowerCase(),
|
||||
rateCodeName: rooms
|
||||
.map((r) => r.rateDefinition.title)
|
||||
.join(",")
|
||||
.toLowerCase(),
|
||||
//rateCodeType: , //TODO: Add when available in API. "regular, promotion, corporate etx",
|
||||
region: hotel?.address.city,
|
||||
revenueCurrencyCode: rooms.map((r) => r.currencyCode).join(","),
|
||||
roomPrice: rooms.map((r) => r.roomPrice).join(","),
|
||||
roomTypeCode: rooms.map((r) => r.roomTypeCode ?? "-").join(","),
|
||||
searchType: "hotel",
|
||||
specialRoomType: rooms
|
||||
.map((room) => getSpecialRoomType(room.packages))
|
||||
.join(","),
|
||||
totalPrice: rooms.map((r) => r.totalPrice).join(","),
|
||||
}
|
||||
|
||||
const paymentInfo: TrackingSDKPaymentInfo = {
|
||||
paymentStatus: "confirmed",
|
||||
}
|
||||
|
||||
return {
|
||||
hotelsTrackingData,
|
||||
pageTrackingData,
|
||||
paymentInfo,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user