Merged in feat/SW-1076-no-room-availability (pull request #1467)

Feat/SW-1076 no room availability

* fix: update booking error codes

* feat(SW-1076): handle no room availabilty on enter-details

* fix: parse to json in api mutation instead of expecting json

* fix: remove 'isComplete' state from sectionAccordion because it was not needed


Approved-by: Simon.Emanuelsson
This commit is contained in:
Tobias Johansson
2025-03-10 12:13:15 +00:00
parent 131cbfcda3
commit 7c233ab846
23 changed files with 139 additions and 63 deletions

View File

@@ -2,8 +2,8 @@ import { redirect } from "next/navigation"
import {
BOOKING_CONFIRMATION_NUMBER,
BookingErrorCodeEnum,
MEMBERSHIP_FAILED_ERROR,
PaymentErrorCodeEnum,
} from "@/constants/booking"
import {
bookingConfirmation,
@@ -70,17 +70,17 @@ export default async function PaymentCallbackPage({
"errorCode",
error
? error.errorCode.toString()
: PaymentErrorCodeEnum.Failed.toString()
: BookingErrorCodeEnum.TransactionFailed
)
} catch {
console.error(
`[payment-callback] failed to get booking status for ${confirmationNumber}, status: ${status}`
)
if (status === "cancel") {
searchObject.set("errorCode", PaymentErrorCodeEnum.Cancelled.toString())
searchObject.set("errorCode", BookingErrorCodeEnum.TransactionCancelled)
}
if (status === "error") {
searchObject.set("errorCode", PaymentErrorCodeEnum.Failed.toString())
searchObject.set("errorCode", BookingErrorCodeEnum.TransactionFailed)
errorMessage = `Failed to get booking status for ${confirmationNumber}, status: ${status}`
}
}

View File

@@ -1,6 +1,7 @@
import { notFound } from "next/navigation"
import { notFound, redirect } from "next/navigation"
import { Suspense } from "react"
import { selectRate } from "@/constants/routes/hotelReservation"
import {
getBreakfastPackages,
getHotel,
@@ -16,13 +17,17 @@ import RoomOne from "@/components/HotelReservation/EnterDetails/Room/One"
import DesktopSummary from "@/components/HotelReservation/EnterDetails/Summary/Desktop"
import MobileSummary from "@/components/HotelReservation/EnterDetails/Summary/Mobile"
import { generateChildrenString } from "@/components/HotelReservation/utils"
import Alert from "@/components/TempDesignSystem/Alert"
import { getIntl } from "@/i18n"
import RoomProvider from "@/providers/Details/RoomProvider"
import EnterDetailsProvider from "@/providers/EnterDetailsProvider"
import { convertSearchParamsToObj } from "@/utils/url"
import styles from "./page.module.css"
import { AvailabilityEnum } from "@/types/components/hotelReservation/selectHotel/selectHotel"
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
import { AlertTypeEnum } from "@/types/enums/alert"
import type { LangParams, PageArgs } from "@/types/params"
import type { Room } from "@/types/providers/details/room"
@@ -81,7 +86,8 @@ export default async function DetailsPage({
)
if (!roomAvailability) {
continue // TODO: handle no room availability
// redirect back to select-rate if availability call fails
redirect(`${selectRate(lang)}?${selectRoomParams.toString()}`)
}
rooms.push({
@@ -98,6 +104,8 @@ export default async function DetailsPage({
memberRate: roomAvailability?.memberRate,
publicRate: roomAvailability.publicRate,
},
isAvailable:
roomAvailability.selectedRoom.status === AvailabilityEnum.Available,
})
}
@@ -139,8 +147,11 @@ export default async function DetailsPage({
// region: hotel?.address.city,
// }
const intl = await getIntl()
const firstRoom = rooms[0]
const multirooms = rooms.slice(1)
const isRoomNotAvailable = rooms.some((room) => !room.isAvailable)
return (
<EnterDetailsProvider
booking={booking}
@@ -153,6 +164,21 @@ export default async function DetailsPage({
<main>
<HotelHeader hotelData={hotelData} />
<div className={styles.container}>
{isRoomNotAvailable && (
<Alert
type={AlertTypeEnum.Alarm}
variant="inline"
heading={intl.formatMessage({ id: "Room sold out" })}
text={intl.formatMessage({
id: "Unfortunately, one of the rooms you selected is sold out. Please choose another room to proceed.",
})}
link={{
title: intl.formatMessage({ id: "Change room" }),
url: `${selectRate(lang)}?${selectRoomParams.toString()}`,
keepSearchParams: true,
}}
/>
)}
<div className={styles.content}>
<RoomProvider idx={0} room={firstRoom}>
<RoomOne user={user} />