Merged in feat/SW-822-handle-breakfast-included (pull request #1138)

Feat/SW-822 handle breakfast included

* feat(SW-822): Added flag for breakfast included and hide breakfast step if included

* fix: check if window is defined to avoid error during SSR

* fix: remove return if rate definition is not found because its expected if input is undefined


Approved-by: Christel Westerberg
Approved-by: Arvid Norlin
This commit is contained in:
Tobias Johansson
2025-01-08 12:34:20 +00:00
parent 18dd08f10e
commit 6ca56f3138
7 changed files with 52 additions and 24 deletions

View File

@@ -126,7 +126,7 @@ export default async function StepPage({
return notFound() return notFound()
} }
const mustBeGuaranteed = roomAvailability?.mustBeGuaranteed ?? false const { mustBeGuaranteed, breakfastIncluded } = roomAvailability
const paymentGuarantee = intl.formatMessage({ const paymentGuarantee = intl.formatMessage({
id: "Payment Guarantee", id: "Payment Guarantee",
@@ -191,13 +191,18 @@ export default async function StepPage({
isMember: !!user, isMember: !!user,
rateDetails: roomAvailability.rateDetails, rateDetails: roomAvailability.rateDetails,
roomType: roomAvailability.selectedRoom.roomType, roomType: roomAvailability.selectedRoom.roomType,
breakfastIncluded,
} }
const showBreakfastStep = Boolean(
breakfastPackages?.length && !breakfastIncluded
)
return ( return (
<EnterDetailsProvider <EnterDetailsProvider
bedTypes={roomAvailability.bedTypes} bedTypes={roomAvailability.bedTypes}
booking={booking} booking={booking}
breakfastPackages={breakfastPackages} showBreakfastStep={showBreakfastStep}
packages={packages} packages={packages}
roomRate={{ roomRate={{
memberRate: roomAvailability.memberRate, memberRate: roomAvailability.memberRate,
@@ -231,13 +236,13 @@ export default async function StepPage({
</SectionAccordion> </SectionAccordion>
) : null} ) : null}
{breakfastPackages?.length ? ( {showBreakfastStep ? (
<SectionAccordion <SectionAccordion
header={intl.formatMessage({ id: "Food options" })} header={intl.formatMessage({ id: "Food options" })}
label={intl.formatMessage({ id: "Select breakfast options" })} label={intl.formatMessage({ id: "Select breakfast options" })}
step={StepEnum.breakfast} step={StepEnum.breakfast}
> >
<Breakfast packages={breakfastPackages} /> <Breakfast packages={breakfastPackages!} />
</SectionAccordion> </SectionAccordion>
) : null} ) : null}

View File

@@ -51,6 +51,7 @@ export default function SummaryUI({
isMember, isMember,
rateDetails, rateDetails,
roomType, roomType,
breakfastIncluded,
}: SummaryProps) { }: SummaryProps) {
const intl = useIntl() const intl = useIntl()
const lang = useLang() const lang = useLang()
@@ -242,7 +243,13 @@ export default function SummaryUI({
</Body> </Body>
</div> </div>
) : null} ) : null}
{breakfast === false ? ( {breakfastIncluded ? (
<div className={styles.entry}>
<Body color="uiTextHighContrast">
{intl.formatMessage({ id: "Breakfast included" })}
</Body>
</div>
) : breakfast === false ? (
<div className={styles.entry}> <div className={styles.entry}>
<Body color="uiTextHighContrast"> <Body color="uiTextHighContrast">
{intl.formatMessage({ id: "No breakfast" })} {intl.formatMessage({ id: "No breakfast" })}

View File

@@ -25,7 +25,7 @@ import type { DetailsState, InitialState } from "@/types/stores/enter-details"
export default function EnterDetailsProvider({ export default function EnterDetailsProvider({
bedTypes, bedTypes,
booking, booking,
breakfastPackages, showBreakfastStep,
children, children,
packages, packages,
roomRate, roomRate,
@@ -44,7 +44,7 @@ export default function EnterDetailsProvider({
roomTypeCode: bedTypes[0].value, roomTypeCode: bedTypes[0].value,
} }
} }
if (!breakfastPackages?.length) { if (!showBreakfastStep) {
initialData.breakfast = false initialData.breakfast = false
} }

View File

@@ -554,14 +554,20 @@ export const hotelQueryRouter = router({
(room) => room.roomType === selectedRoom?.roomType (room) => room.roomType === selectedRoom?.roomType
) )
if (!selectedRoom) { if (!selectedRoom) {
selectedRoomAvailabilityFailCounter.add(1, {
hotelId,
roomStayStartDate,
roomStayEndDate,
adults,
children,
bookingCode,
error_type: "not_found",
error: `Couldn't find selected room with input: ${roomTypeCode}`,
})
console.error("No matching room found") console.error("No matching room found")
return null return null
} }
const rateDetails = validateAvailabilityData.data.rateDefinitions.find(
(rateDef) => rateDef.rateCode === rateCode
)?.generalTerms
const rateTypes = selectedRoom.products.find( const rateTypes = selectedRoom.products.find(
(rate) => (rate) =>
rate.productType.public?.rateCode === rateCode || rate.productType.public?.rateCode === rateCode ||
@@ -569,20 +575,25 @@ export const hotelQueryRouter = router({
) )
if (!rateTypes) { if (!rateTypes) {
selectedRoomAvailabilityFailCounter.add(1, {
hotelId,
roomStayStartDate,
roomStayEndDate,
adults,
children,
bookingCode,
error_type: "not_found",
error: `Couldn't find rateTypes for selected room: ${JSON.stringify(selectedRoom)}`,
})
console.error("No matching rate found") console.error("No matching rate found")
return null return null
} }
const rates = rateTypes.productType const rates = rateTypes.productType
const mustBeGuaranteed = const rateDefinition =
validateAvailabilityData.data.rateDefinitions.filter(
(rate) => rate.rateCode === rateCode
)[0].mustBeGuaranteed
const cancellationText =
validateAvailabilityData.data.rateDefinitions.find( validateAvailabilityData.data.rateDefinitions.find(
(rate) => rate.rateCode === rateCode (rate) => rate.rateCode === rateCode
)?.cancellationText ?? "" )
const bedTypes = availableRoomsInCategory const bedTypes = availableRoomsInCategory
.map((availRoom) => { .map((availRoom) => {
@@ -623,9 +634,10 @@ export const hotelQueryRouter = router({
return { return {
selectedRoom, selectedRoom,
rateDetails, rateDetails: rateDefinition?.generalTerms,
mustBeGuaranteed, cancellationText: rateDefinition?.cancellationText ?? "",
cancellationText, mustBeGuaranteed: !!rateDefinition?.mustBeGuaranteed,
breakfastIncluded: !!rateDefinition?.breakfastIncluded,
memberRate: rates?.member, memberRate: rates?.member,
publicRate: rates.public, publicRate: rates.public,
bedTypes, bedTypes,

View File

@@ -15,4 +15,5 @@ export interface SummaryProps
extends Pick<RoomAvailability, "cancellationText" | "rateDetails">, extends Pick<RoomAvailability, "cancellationText" | "rateDetails">,
Pick<RoomAvailability["selectedRoom"], "roomType"> { Pick<RoomAvailability["selectedRoom"], "roomType"> {
isMember: boolean isMember: boolean
breakfastIncluded: boolean
} }

View File

@@ -9,7 +9,7 @@ import type { Packages } from "../requests/packages"
export interface DetailsProviderProps extends React.PropsWithChildren { export interface DetailsProviderProps extends React.PropsWithChildren {
booking: BookingData booking: BookingData
bedTypes: BedTypeSelection[] bedTypes: BedTypeSelection[]
breakfastPackages: BreakfastPackage[] | null showBreakfastStep: boolean
packages: Packages | null packages: Packages | null
roomRate: Pick<RoomAvailability, "memberRate" | "publicRate"> roomRate: Pick<RoomAvailability, "memberRate" | "publicRate">
searchParamsStr: string searchParamsStr: string

View File

@@ -1,4 +1,7 @@
import type { TrackingPosition, TrackingSDKData } from "@/types/components/tracking" import type {
TrackingPosition,
TrackingSDKData,
} from "@/types/components/tracking"
export function trackClick(name: string) { export function trackClick(name: string) {
pushToDataLayer({ pushToDataLayer({
@@ -60,7 +63,7 @@ export function createSDKPageObject(
return { return {
...trackingData, ...trackingData,
domain: window.location.host, domain: typeof window !== "undefined" ? window.location.host : "",
pageName: pageName, pageName: pageName,
siteSections: siteSections, siteSections: siteSections,
} }