Merged in fix/SW-2438-remove-breakfast-tracking (pull request #1872)

fix(SW-2438): remove breakfast tracking on enter details

* fix(SW-2438): remove breakfast tracking on enter details

* fix(SW-2438): show breakfastOption if already chosen on page load

* fix(SW-2438): if breakfast option does not exists (scandic go) remove breakfastOption from tracking

* fix(SW-2438): fix merge conflicts

* fix(SW-2438): fix comment

* fix(SW-2438): fix comment

* fix(SW-2438): fix merge


Approved-by: Tobias Johansson
Approved-by: Matilda Landström
This commit is contained in:
Bianca Widstam
2025-04-29 10:46:52 +00:00
parent 6520bc5bc5
commit 03902da897
3 changed files with 84 additions and 35 deletions

View File

@@ -15,15 +15,13 @@ import Multiroom from "@/components/HotelReservation/EnterDetails/Room/Multiroom
import RoomOne from "@/components/HotelReservation/EnterDetails/Room/One" import RoomOne from "@/components/HotelReservation/EnterDetails/Room/One"
import DesktopSummary from "@/components/HotelReservation/EnterDetails/Summary/Desktop" import DesktopSummary from "@/components/HotelReservation/EnterDetails/Summary/Desktop"
import MobileSummary from "@/components/HotelReservation/EnterDetails/Summary/Mobile" import MobileSummary from "@/components/HotelReservation/EnterDetails/Summary/Mobile"
import EnterDetailsTrackingWrapper from "@/components/HotelReservation/EnterDetails/Tracking"
import Alert from "@/components/TempDesignSystem/Alert" import Alert from "@/components/TempDesignSystem/Alert"
import TrackingSDK from "@/components/TrackingSDK"
import { getIntl } from "@/i18n" import { getIntl } from "@/i18n"
import RoomProvider from "@/providers/Details/RoomProvider" import RoomProvider from "@/providers/Details/RoomProvider"
import EnterDetailsProvider from "@/providers/EnterDetailsProvider" import EnterDetailsProvider from "@/providers/EnterDetailsProvider"
import { convertSearchParamsToObj } from "@/utils/url" import { convertSearchParamsToObj } from "@/utils/url"
import { getTracking } from "./tracking"
import styles from "./page.module.css" import styles from "./page.module.css"
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate" import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
@@ -96,16 +94,6 @@ export default async function DetailsPage({
hotel.merchantInformationData.alternatePaymentOptions = [] hotel.merchantInformationData.alternatePaymentOptions = []
} }
const { hotelsTrackingData, pageTrackingData, ancillaries } = getTracking(
booking,
hotel,
rooms,
!!breakfastPackages.length,
searchParams.city,
!!user,
lang
)
const intl = await getIntl() const intl = await getIntl()
const firstRoom = rooms[0] const firstRoom = rooms[0]
@@ -170,10 +158,13 @@ export default async function DetailsPage({
</aside> </aside>
</div> </div>
</main> </main>
<TrackingSDK <EnterDetailsTrackingWrapper
hotelInfo={hotelsTrackingData} booking={booking}
pageData={pageTrackingData} hotel={hotel}
ancillaries={ancillaries} city={searchParams.city}
isMember={!!user}
lang={lang}
rooms={rooms}
/> />
</EnterDetailsProvider> </EnterDetailsProvider>
) )

View File

@@ -0,0 +1,54 @@
"use client"
import { useEnterDetailsStore } from "@/stores/enter-details"
import TrackingSDK from "@/components/TrackingSDK"
import { getTracking } from "./tracking"
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
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"
interface TrackingWrapperProps {
booking: SelectHotelParams<SelectRateSearchParams>
hotel: Hotel
rooms: Room[]
city: string | undefined
isMember: boolean
lang: Lang
}
export default function EnterDetailsTrackingWrapper({
booking,
hotel,
rooms,
city,
isMember,
lang,
}: TrackingWrapperProps) {
const { storedRooms, breakfastPackages } = useEnterDetailsStore((state) => ({
storedRooms: state.rooms,
breakfastPackages: state.breakfastPackages,
}))
const { hotelsTrackingData, pageTrackingData, ancillaries } = getTracking(
booking,
hotel,
rooms,
city,
isMember,
lang,
storedRooms,
breakfastPackages
)
return (
<TrackingSDK
hotelInfo={hotelsTrackingData}
pageData={pageTrackingData}
ancillaries={ancillaries}
/>
)
}

View File

@@ -6,6 +6,7 @@ import { sumPackages } from "@/components/HotelReservation/utils"
import { getSpecialRoomType } from "@/utils/specialRoomType" import { getSpecialRoomType } from "@/utils/specialRoomType"
import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums" import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums"
import type { BreakfastPackages } from "@/types/components/hotelReservation/breakfast"
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter" import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate" import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
import { import {
@@ -17,6 +18,7 @@ import {
import { CurrencyEnum } from "@/types/enums/currency" import { CurrencyEnum } from "@/types/enums/currency"
import type { Hotel } from "@/types/hotel" import type { Hotel } from "@/types/hotel"
import type { Room } from "@/types/providers/details/room" import type { Room } from "@/types/providers/details/room"
import type { RoomState } from "@/types/stores/enter-details"
import type { import type {
PriceProduct, PriceProduct,
Product, Product,
@@ -28,13 +30,27 @@ export function getTracking(
booking: SelectHotelParams<SelectRateSearchParams>, booking: SelectHotelParams<SelectRateSearchParams>,
hotel: Hotel, hotel: Hotel,
rooms: Room[], rooms: Room[],
offersBreakfast: boolean,
city: string | undefined, city: string | undefined,
isMember: boolean, isMember: boolean,
lang: Lang lang: Lang,
storedRooms: RoomState[],
breakfastPackages: BreakfastPackages
) { ) {
const arrivalDate = new Date(booking.fromDate) const arrivalDate = new Date(booking.fromDate)
const departureDate = new Date(booking.toDate) const departureDate = new Date(booking.toDate)
const shouldSkipBreakfastOption =
storedRooms.every((r) => r.room.breakfast === undefined) ||
!breakfastPackages.length
const breakfastOption = shouldSkipBreakfastOption
? undefined
: storedRooms
.map((r) => {
if (r.room.breakfast === undefined) return "-"
if (!r.room.breakfast) return "no breakfast"
return r.room.breakfast.description
})
.join("|")
const pageTrackingData: TrackingSDKPageData = { const pageTrackingData: TrackingSDKPageData = {
channel: TrackingChannelEnum.hotelreservation, channel: TrackingChannelEnum.hotelreservation,
@@ -45,7 +61,6 @@ export function getTracking(
siteSections: "hotelreservation|details", siteSections: "hotelreservation|details",
siteVersion: "new-web", siteVersion: "new-web",
} }
const hotelsTrackingData: TrackingSDKHotelInfo = { const hotelsTrackingData: TrackingSDKHotelInfo = {
ageOfChildren: booking.rooms ageOfChildren: booking.rooms
.map( .map(
@@ -54,9 +69,8 @@ export function getTracking(
.join("|"), .join("|"),
analyticsRateCode: rooms.map((room) => room.rate).join("|"), analyticsRateCode: rooms.map((room) => room.rate).join("|"),
arrivalDate: format(arrivalDate, "yyyy-MM-dd"), arrivalDate: format(arrivalDate, "yyyy-MM-dd"),
// only include bedtype here if it is "preselected" meanining there is only 1 bedType: storedRooms
bedType: rooms .map((r) => (r.room.bedType ? r.room.bedType.description : "-"))
.map((r) => (r?.bedTypes?.length === 1 ? r.bedTypes[0].description : "-"))
.join("|"), .join("|"),
// Comma separated booking code values in "code,code,n/a" format for multiroom and "code" or "n/a" for singleroom // Comma separated booking code values in "code,code,n/a" format for multiroom and "code" or "n/a" for singleroom
// n/a is used whenever code is Not applicable as defined by Tracking team // n/a is used whenever code is Not applicable as defined by Tracking team
@@ -70,9 +84,7 @@ export function getTracking(
.join(", ") .join(", ")
: undefined, : undefined,
bookingTypeofDay: isWeekend(arrivalDate) ? "weekend" : "weekday", bookingTypeofDay: isWeekend(arrivalDate) ? "weekend" : "weekday",
breakfastOption: rooms breakfastOption,
.map(() => (offersBreakfast ? "breakfast buffet" : "no breakfast"))
.join(","),
childBedPreference: booking.rooms childBedPreference: booking.rooms
.map( .map(
(room) => (room) =>
@@ -140,6 +152,7 @@ export function getTracking(
return "-" return "-"
}) })
.join("|"), .join("|"),
rateCodeCancellationRule: rooms rateCodeCancellationRule: rooms
.map((room) => room.cancellationText.toLowerCase()) .map((room) => room.cancellationText.toLowerCase())
.join(","), .join(","),
@@ -179,7 +192,6 @@ export function getTracking(
.map((room) => getSpecialRoomType(room.packages)) .map((room) => getSpecialRoomType(room.packages))
.join(","), .join(","),
} }
const roomsWithPetRoom = rooms.filter(hasPetRoom) const roomsWithPetRoom = rooms.filter(hasPetRoom)
const ancillaries: TrackingSDKAncillaries = roomsWithPetRoom const ancillaries: TrackingSDKAncillaries = roomsWithPetRoom
.slice(0, 1) // should only be one item .slice(0, 1) // should only be one item
@@ -205,7 +217,6 @@ export function getTracking(
ancillaries, ancillaries,
} }
} }
function hasPublicPrice( function hasPublicPrice(
roomRate: Product roomRate: Product
): roomRate is PriceProduct & { public: NonNullable<PriceProduct["public"]> } { ): roomRate is PriceProduct & { public: NonNullable<PriceProduct["public"]> } {
@@ -214,7 +225,6 @@ function hasPublicPrice(
} }
return false return false
} }
function hasMemberPrice( function hasMemberPrice(
roomRate: Product roomRate: Product
): roomRate is PriceProduct & { member: NonNullable<PriceProduct["member"]> } { ): roomRate is PriceProduct & { member: NonNullable<PriceProduct["member"]> } {
@@ -223,7 +233,6 @@ function hasMemberPrice(
} }
return false return false
} }
function hasPetRoom( function hasPetRoom(
room: Room room: Room
): room is Room & { packages: NonNullable<Room["packages"]> } { ): room is Room & { packages: NonNullable<Room["packages"]> } {
@@ -232,17 +241,14 @@ function hasPetRoom(
} }
return room.packages.some((p) => p.code === RoomPackageCodeEnum.PET_ROOM) return room.packages.some((p) => p.code === RoomPackageCodeEnum.PET_ROOM)
} }
function calcTotalPrice(rooms: Room[], isMember: boolean) { function calcTotalPrice(rooms: Room[], isMember: boolean) {
const totalRoomPrice = calcTotalRoomPrice(rooms, isMember) const totalRoomPrice = calcTotalRoomPrice(rooms, isMember)
const totalPackageSum = rooms.reduce((total, room) => { const totalPackageSum = rooms.reduce((total, room) => {
const packageSum = sumPackages(room.packages) const packageSum = sumPackages(room.packages)
return (total += packageSum.price ?? 0) return (total += packageSum.price ?? 0)
}, 0) }, 0)
return totalRoomPrice + totalPackageSum return totalRoomPrice + totalPackageSum
} }
function calcTotalRoomPrice(rooms: Room[], isMember: boolean) { function calcTotalRoomPrice(rooms: Room[], isMember: boolean) {
return rooms.reduce((total, room, idx) => { return rooms.reduce((total, room, idx) => {
// When it comes special rates, only redemption has additional price and that should be added // When it comes special rates, only redemption has additional price and that should be added
@@ -257,14 +263,12 @@ function calcTotalRoomPrice(rooms: Room[], isMember: boolean) {
) { ) {
return 0 return 0
} }
const isMainRoom = idx === 0 const isMainRoom = idx === 0
if (hasMemberPrice(room.roomRate) && isMember && isMainRoom) { if (hasMemberPrice(room.roomRate) && isMember && isMainRoom) {
total += room.roomRate.member.localPrice.pricePerStay total += room.roomRate.member.localPrice.pricePerStay
} else if (hasPublicPrice(room.roomRate)) { } else if (hasPublicPrice(room.roomRate)) {
total += room.roomRate.public.localPrice.pricePerStay total += room.roomRate.public.localPrice.pricePerStay
} }
return total return total
}, 0) }, 0)
} }