Merged in chore/improve-my-stay-load-times (pull request #3514)
chore: Improve My Stay load times * Restructure My Stay page to avoid data fetching waterfalls Approved-by: Linus Flood Approved-by: Matilda Landström
This commit is contained in:
@@ -27,6 +27,7 @@ import AdditionalInfoForm from "@/components/HotelReservation/FindMyBooking/Addi
|
|||||||
import accessBooking, {
|
import accessBooking, {
|
||||||
ACCESS_GRANTED,
|
ACCESS_GRANTED,
|
||||||
ERROR_BAD_REQUEST,
|
ERROR_BAD_REQUEST,
|
||||||
|
ERROR_NOT_FOUND,
|
||||||
ERROR_UNAUTHORIZED,
|
ERROR_UNAUTHORIZED,
|
||||||
} from "@/components/HotelReservation/MyStay/accessBooking"
|
} from "@/components/HotelReservation/MyStay/accessBooking"
|
||||||
import { Ancillaries } from "@/components/HotelReservation/MyStay/Ancillaries"
|
import { Ancillaries } from "@/components/HotelReservation/MyStay/Ancillaries"
|
||||||
@@ -74,39 +75,23 @@ async function MyStay(props: {
|
|||||||
notFound()
|
notFound()
|
||||||
}
|
}
|
||||||
|
|
||||||
const { confirmationNumber, lastName } = parseRefId(refId)
|
|
||||||
|
|
||||||
const isLoggedIn = await isLoggedInUser()
|
|
||||||
|
|
||||||
const cookieStore = await cookies()
|
const cookieStore = await cookies()
|
||||||
const bv = cookieStore.get("bv")?.value
|
const bv = cookieStore.get("bv")?.value
|
||||||
let bookingConfirmation
|
|
||||||
if (isLoggedIn) {
|
|
||||||
bookingConfirmation = await getBookingConfirmation(refId)
|
|
||||||
} else if (bv) {
|
|
||||||
logger.debug(`MyStay: bv`, bv)
|
|
||||||
const {
|
|
||||||
firstName,
|
|
||||||
email,
|
|
||||||
confirmationNumber: bvConfirmationNo,
|
|
||||||
} = JSON.parse(bv) as AdditionalInfoCookieValue
|
|
||||||
|
|
||||||
if (firstName && email && bvConfirmationNo === confirmationNumber) {
|
const { confirmationNumber, lastName } = parseRefId(refId)
|
||||||
bookingConfirmation = await findBooking(
|
const isLoggedIn = await isLoggedInUser()
|
||||||
confirmationNumber,
|
const [{ error, bookingConfirmation }, user] = await Promise.all([
|
||||||
lastName,
|
getOrFindBookingConfirmation({
|
||||||
firstName,
|
refId,
|
||||||
email
|
isLoggedIn,
|
||||||
)
|
confirmationNumber,
|
||||||
} else {
|
lastName,
|
||||||
return (
|
bv,
|
||||||
<RenderAdditionalInfoForm
|
}),
|
||||||
confirmationNumber={confirmationNumber}
|
getProfileSafely(),
|
||||||
lastName={lastName}
|
])
|
||||||
/>
|
|
||||||
)
|
if (error === "MISSING_INFO") {
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return (
|
return (
|
||||||
<RenderAdditionalInfoForm
|
<RenderAdditionalInfoForm
|
||||||
confirmationNumber={confirmationNumber}
|
confirmationNumber={confirmationNumber}
|
||||||
@@ -121,208 +106,226 @@ async function MyStay(props: {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const { additionalData, booking, hotel, roomCategories } = bookingConfirmation
|
const { booking } = bookingConfirmation
|
||||||
|
|
||||||
const user = await getProfileSafely()
|
const { code } = accessBooking(booking.guest, lastName, user, bv)
|
||||||
|
|
||||||
const intl = await getIntl()
|
switch (code) {
|
||||||
|
case ACCESS_GRANTED.code:
|
||||||
|
return (
|
||||||
|
<MyStayPage
|
||||||
|
bookingConfirmation={bookingConfirmation}
|
||||||
|
user={user}
|
||||||
|
lang={lang}
|
||||||
|
isWebview={!!isWebview}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
case ERROR_NOT_FOUND.code:
|
||||||
|
return notFound()
|
||||||
|
case ERROR_BAD_REQUEST.code:
|
||||||
|
return (
|
||||||
|
<RenderAdditionalInfoForm
|
||||||
|
confirmationNumber={confirmationNumber}
|
||||||
|
lastName={lastName}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
case ERROR_UNAUTHORIZED.code: {
|
||||||
|
if (!bv) return notFound()
|
||||||
|
|
||||||
const access = accessBooking(booking.guest, lastName, user, bv)
|
return (
|
||||||
|
<RenderFindMyBookingForm
|
||||||
if (access === ACCESS_GRANTED) {
|
bv={bv}
|
||||||
const fromDate = dt(booking.checkInDate).format("YYYY-MM-DD")
|
lastName={lastName}
|
||||||
const toDate = dt(booking.checkOutDate).format("YYYY-MM-DD")
|
confirmationNumber={confirmationNumber}
|
||||||
|
/>
|
||||||
const linkedReservationsPromise = getLinkedReservations(booking.refId)
|
|
||||||
|
|
||||||
const packagesInput = {
|
|
||||||
adults: booking.adults,
|
|
||||||
children: booking.childrenAges.length,
|
|
||||||
endDate: toDate,
|
|
||||||
hotelId: hotel.operaId,
|
|
||||||
lang,
|
|
||||||
startDate: fromDate,
|
|
||||||
packageCodes: [
|
|
||||||
BreakfastPackageEnum.ANCILLARY_REGULAR_BREAKFAST,
|
|
||||||
BreakfastPackageEnum.ANCILLARY_CHILD_PAYING_BREAKFAST,
|
|
||||||
BreakfastPackageEnum.FREE_CHILD_BREAKFAST,
|
|
||||||
],
|
|
||||||
}
|
|
||||||
const supportedCards = hotel.merchantInformationData.cards
|
|
||||||
const savedPaymentCardsInput = { supportedCards }
|
|
||||||
|
|
||||||
const hasBreakfastPackage = booking.packages.find(
|
|
||||||
(pkg) => pkg.code === BreakfastPackageEnum.REGULAR_BREAKFAST
|
|
||||||
)
|
|
||||||
const breakfastIncluded = booking.rateDefinition.breakfastIncluded
|
|
||||||
const shouldFetchBreakfastPackages =
|
|
||||||
!hasBreakfastPackage && !breakfastIncluded
|
|
||||||
if (shouldFetchBreakfastPackages) {
|
|
||||||
void getPackages(packagesInput)
|
|
||||||
}
|
|
||||||
const isOwnBooking = user?.email === booking.guest.email
|
|
||||||
if (user && isOwnBooking) {
|
|
||||||
void getSavedPaymentCardsSafely(savedPaymentCardsInput)
|
|
||||||
}
|
|
||||||
|
|
||||||
let breakfastPackages = null
|
|
||||||
if (shouldFetchBreakfastPackages) {
|
|
||||||
breakfastPackages = await getPackages(packagesInput)
|
|
||||||
}
|
|
||||||
let savedCreditCards = null
|
|
||||||
if (user && isOwnBooking) {
|
|
||||||
savedCreditCards = await getSavedPaymentCardsSafely(
|
|
||||||
savedPaymentCardsInput
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
let ancillaryPackagesPromise = null
|
default:
|
||||||
if (booking.showAncillaries) {
|
const _exhaustiveCheck: never = code
|
||||||
ancillaryPackagesPromise = getAncillaryPackages({
|
throw new Error(`Unknown access code: ${code}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function MyStayPage({
|
||||||
|
bookingConfirmation,
|
||||||
|
user,
|
||||||
|
lang,
|
||||||
|
isWebview,
|
||||||
|
}: {
|
||||||
|
bookingConfirmation: BookingConfirmation
|
||||||
|
user: SafeUser | null
|
||||||
|
lang: Lang
|
||||||
|
isWebview: boolean
|
||||||
|
}) {
|
||||||
|
const intl = await getIntl()
|
||||||
|
|
||||||
|
const { additionalData, booking, hotel, roomCategories } = bookingConfirmation
|
||||||
|
|
||||||
|
const fromDate = dt(booking.checkInDate).format("YYYY-MM-DD")
|
||||||
|
const toDate = dt(booking.checkOutDate).format("YYYY-MM-DD")
|
||||||
|
|
||||||
|
const packagesInput = {
|
||||||
|
adults: booking.adults,
|
||||||
|
children: booking.childrenAges.length,
|
||||||
|
endDate: toDate,
|
||||||
|
hotelId: hotel.operaId,
|
||||||
|
lang,
|
||||||
|
startDate: fromDate,
|
||||||
|
packageCodes: [
|
||||||
|
BreakfastPackageEnum.ANCILLARY_REGULAR_BREAKFAST,
|
||||||
|
BreakfastPackageEnum.ANCILLARY_CHILD_PAYING_BREAKFAST,
|
||||||
|
BreakfastPackageEnum.FREE_CHILD_BREAKFAST,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
const supportedCards = hotel.merchantInformationData.cards
|
||||||
|
const savedPaymentCardsInput = { supportedCards }
|
||||||
|
|
||||||
|
const hasBreakfastPackage = booking.packages.find(
|
||||||
|
(pkg) => pkg.code === BreakfastPackageEnum.REGULAR_BREAKFAST
|
||||||
|
)
|
||||||
|
const breakfastIncluded = booking.rateDefinition.breakfastIncluded
|
||||||
|
const shouldFetchBreakfastPackages =
|
||||||
|
!hasBreakfastPackage && !breakfastIncluded
|
||||||
|
|
||||||
|
const isOwnBooking = user?.email === booking.guest.email
|
||||||
|
const shouldGetCards = user && isOwnBooking
|
||||||
|
|
||||||
|
const [breakfastPackages, savedCreditCards] = await Promise.all([
|
||||||
|
shouldFetchBreakfastPackages ? getPackages(packagesInput) : noop(),
|
||||||
|
shouldGetCards
|
||||||
|
? getSavedPaymentCardsSafely(savedPaymentCardsInput)
|
||||||
|
: noop(),
|
||||||
|
])
|
||||||
|
|
||||||
|
const imageSrc =
|
||||||
|
hotel.hotelContent.images.src ||
|
||||||
|
additionalData.gallery?.heroImages[0]?.src ||
|
||||||
|
hotel.galleryImages[0]?.src
|
||||||
|
|
||||||
|
const baseUrl = env.PUBLIC_URL || "https://www.scandichotels.com"
|
||||||
|
const promoUrl = new URL(`${baseUrl}/${lang}/`)
|
||||||
|
const hotelUrl = new URL(`${baseUrl}${bookingConfirmation.url}/`)
|
||||||
|
promoUrl.searchParams.set("hotel", hotel.operaId)
|
||||||
|
|
||||||
|
const maskedBookingConfirmation = maskBookingConfirmation(bookingConfirmation)
|
||||||
|
const maskedUser = isOwnBooking ? maskUser(user) : null
|
||||||
|
|
||||||
|
const hotelWithFilteredAlerts = {
|
||||||
|
...hotel,
|
||||||
|
specialAlerts: filterOverlappingDates(
|
||||||
|
hotel.specialAlerts,
|
||||||
|
dt.utc(fromDate),
|
||||||
|
dt.utc(toDate)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
const linkedReservationsPromise = getLinkedReservations(booking.refId)
|
||||||
|
const ancillaryPackagesPromise = booking.showAncillaries
|
||||||
|
? getAncillaryPackages({
|
||||||
fromDate,
|
fromDate,
|
||||||
hotelId: hotel.operaId,
|
hotelId: hotel.operaId,
|
||||||
toDate,
|
toDate,
|
||||||
})
|
})
|
||||||
}
|
: null
|
||||||
|
|
||||||
const imageSrc =
|
return (
|
||||||
hotel.hotelContent.images.src ||
|
<MyStayProvider
|
||||||
additionalData.gallery?.heroImages[0]?.src ||
|
bookingConfirmation={maskedBookingConfirmation}
|
||||||
hotel.galleryImages[0]?.src
|
breakfastPackages={breakfastPackages}
|
||||||
|
lang={lang}
|
||||||
const baseUrl = env.PUBLIC_URL || "https://www.scandichotels.com"
|
linkedReservationsPromise={linkedReservationsPromise}
|
||||||
const promoUrl = new URL(`${baseUrl}/${lang}/`)
|
refId={booking.refId}
|
||||||
const hotelUrl = new URL(`${baseUrl}${bookingConfirmation.url}/`)
|
roomCategories={roomCategories}
|
||||||
|
savedCreditCards={savedCreditCards}
|
||||||
promoUrl.searchParams.set("hotel", hotel.operaId)
|
isLoggedIn={!!user}
|
||||||
|
>
|
||||||
const maskedBookingConfirmation = {
|
<main className={styles.main}>
|
||||||
...bookingConfirmation,
|
<div className={styles.imageContainer}>
|
||||||
booking: {
|
<div className={styles.blurOverlay} />
|
||||||
...bookingConfirmation.booking,
|
{imageSrc && (
|
||||||
guest: {
|
<Image
|
||||||
...bookingConfirmation.booking.guest,
|
className={styles.image}
|
||||||
email: maskValue.email(bookingConfirmation.booking.guest.email),
|
src={imageSrc}
|
||||||
phoneNumber: maskValue.phone(
|
alt={hotelWithFilteredAlerts.name}
|
||||||
bookingConfirmation.booking.guest.phoneNumber ?? ""
|
fill
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} satisfies BookingConfirmation
|
|
||||||
|
|
||||||
const maskedUser =
|
|
||||||
user && isOwnBooking
|
|
||||||
? ({
|
|
||||||
...user,
|
|
||||||
email: maskValue.email(user.email),
|
|
||||||
phoneNumber: maskValue.phone(user.phoneNumber ?? ""),
|
|
||||||
} satisfies SafeUser)
|
|
||||||
: null
|
|
||||||
|
|
||||||
hotel.specialAlerts = filterOverlappingDates(
|
|
||||||
hotel.specialAlerts,
|
|
||||||
dt.utc(fromDate),
|
|
||||||
dt.utc(toDate)
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<MyStayProvider
|
|
||||||
bookingConfirmation={maskedBookingConfirmation}
|
|
||||||
breakfastPackages={breakfastPackages}
|
|
||||||
lang={lang}
|
|
||||||
linkedReservationsPromise={linkedReservationsPromise}
|
|
||||||
refId={booking.refId}
|
|
||||||
roomCategories={roomCategories}
|
|
||||||
savedCreditCards={savedCreditCards}
|
|
||||||
isLoggedIn={isLoggedIn}
|
|
||||||
>
|
|
||||||
<main className={styles.main}>
|
|
||||||
<div className={styles.imageContainer}>
|
|
||||||
<div className={styles.blurOverlay} />
|
|
||||||
{imageSrc && (
|
|
||||||
<Image
|
|
||||||
className={styles.image}
|
|
||||||
src={imageSrc}
|
|
||||||
alt={hotel.name}
|
|
||||||
fill
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className={styles.content}>
|
|
||||||
<div className={styles.headerContainer}>
|
|
||||||
<Header cityName={hotel.cityName} name={hotel.name} />
|
|
||||||
<ReferenceCard />
|
|
||||||
</div>
|
|
||||||
{booking.showAncillaries && ancillaryPackagesPromise && (
|
|
||||||
<Ancillaries
|
|
||||||
ancillariesPromise={ancillaryPackagesPromise}
|
|
||||||
packages={breakfastPackages}
|
|
||||||
user={maskedUser}
|
|
||||||
savedCreditCards={savedCreditCards}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<SingleRoom user={maskedUser} />
|
|
||||||
<MultiRoom user={maskedUser} />
|
|
||||||
|
|
||||||
<BookingSummary hotelUrl={hotelUrl.toString()} hotel={hotel} />
|
|
||||||
{!isWebview && (
|
|
||||||
<Promo
|
|
||||||
title={intl.formatMessage({
|
|
||||||
id: "booking.bookNextStay.title",
|
|
||||||
defaultMessage: "Book your next stay",
|
|
||||||
})}
|
|
||||||
text={intl.formatMessage({
|
|
||||||
id: "booking.bookAnotherStayDescription",
|
|
||||||
defaultMessage:
|
|
||||||
"Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.",
|
|
||||||
})}
|
|
||||||
buttonText={intl.formatMessage({
|
|
||||||
id: "myStay.promo.bookNextStay.buttonText",
|
|
||||||
defaultMessage: "Explore Scandic hotels",
|
|
||||||
})}
|
|
||||||
href={promoUrl.toString()}
|
|
||||||
image={hotel.hotelContent.images}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</MyStayProvider>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (access === ERROR_BAD_REQUEST) {
|
|
||||||
return (
|
|
||||||
<RenderAdditionalInfoForm
|
|
||||||
confirmationNumber={confirmationNumber}
|
|
||||||
lastName={lastName}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (access === ERROR_UNAUTHORIZED) {
|
|
||||||
if (bv) {
|
|
||||||
const { firstName, email } = JSON.parse(bv) as AdditionalInfoCookieValue
|
|
||||||
|
|
||||||
return (
|
|
||||||
<main className={styles.main}>
|
|
||||||
<div className={styles.form}>
|
|
||||||
<FindMyBooking
|
|
||||||
error={FindMyBookingErrorEnum.BOOKING_ACCESS_DENIED}
|
|
||||||
defaultValues={{
|
|
||||||
firstName,
|
|
||||||
lastName,
|
|
||||||
confirmationNumber,
|
|
||||||
email,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className={styles.content}>
|
||||||
|
<div className={styles.headerContainer}>
|
||||||
|
<Header
|
||||||
|
cityName={hotelWithFilteredAlerts.cityName}
|
||||||
|
name={hotelWithFilteredAlerts.name}
|
||||||
|
/>
|
||||||
|
<ReferenceCard />
|
||||||
</div>
|
</div>
|
||||||
</main>
|
{booking.showAncillaries && ancillaryPackagesPromise && (
|
||||||
)
|
<Ancillaries
|
||||||
} else {
|
ancillariesPromise={ancillaryPackagesPromise}
|
||||||
}
|
packages={breakfastPackages}
|
||||||
}
|
user={maskedUser}
|
||||||
|
savedCreditCards={savedCreditCards}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
return notFound()
|
<SingleRoom user={maskedUser} />
|
||||||
|
<MultiRoom user={maskedUser} />
|
||||||
|
|
||||||
|
<BookingSummary
|
||||||
|
hotelUrl={hotelUrl.toString()}
|
||||||
|
hotel={hotelWithFilteredAlerts}
|
||||||
|
/>
|
||||||
|
{!isWebview && (
|
||||||
|
<Promo
|
||||||
|
title={intl.formatMessage({
|
||||||
|
id: "booking.bookNextStay.title",
|
||||||
|
defaultMessage: "Book your next stay",
|
||||||
|
})}
|
||||||
|
text={intl.formatMessage({
|
||||||
|
id: "booking.bookAnotherStayDescription",
|
||||||
|
defaultMessage:
|
||||||
|
"Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.",
|
||||||
|
})}
|
||||||
|
buttonText={intl.formatMessage({
|
||||||
|
id: "myStay.promo.bookNextStay.buttonText",
|
||||||
|
defaultMessage: "Explore Scandic hotels",
|
||||||
|
})}
|
||||||
|
href={promoUrl.toString()}
|
||||||
|
image={hotelWithFilteredAlerts.hotelContent.images}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</MyStayProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function RenderFindMyBookingForm({
|
||||||
|
bv,
|
||||||
|
lastName,
|
||||||
|
confirmationNumber,
|
||||||
|
}: {
|
||||||
|
bv: string
|
||||||
|
lastName: string
|
||||||
|
confirmationNumber: string
|
||||||
|
}) {
|
||||||
|
const { firstName, email } = JSON.parse(bv) as AdditionalInfoCookieValue
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className={styles.main}>
|
||||||
|
<div className={styles.form}>
|
||||||
|
<FindMyBooking
|
||||||
|
error={FindMyBookingErrorEnum.BOOKING_ACCESS_DENIED}
|
||||||
|
defaultValues={{
|
||||||
|
firstName,
|
||||||
|
lastName,
|
||||||
|
confirmationNumber,
|
||||||
|
email,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function RenderAdditionalInfoForm({
|
function RenderAdditionalInfoForm({
|
||||||
@@ -343,3 +346,75 @@ function RenderAdditionalInfoForm({
|
|||||||
</main>
|
</main>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function maskUser(user: SafeUser | null): SafeUser | null {
|
||||||
|
if (!user) return null
|
||||||
|
|
||||||
|
return {
|
||||||
|
...user,
|
||||||
|
email: maskValue.email(user.email),
|
||||||
|
phoneNumber: maskValue.phone(user.phoneNumber ?? ""),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function maskBookingConfirmation(
|
||||||
|
bookingConfirmation: BookingConfirmation
|
||||||
|
): BookingConfirmation {
|
||||||
|
return {
|
||||||
|
...bookingConfirmation,
|
||||||
|
booking: {
|
||||||
|
...bookingConfirmation.booking,
|
||||||
|
guest: {
|
||||||
|
...bookingConfirmation.booking.guest,
|
||||||
|
email: maskValue.email(bookingConfirmation.booking.guest.email),
|
||||||
|
phoneNumber: maskValue.phone(
|
||||||
|
bookingConfirmation.booking.guest.phoneNumber ?? ""
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getOrFindBookingConfirmation({
|
||||||
|
refId,
|
||||||
|
confirmationNumber,
|
||||||
|
lastName,
|
||||||
|
isLoggedIn,
|
||||||
|
bv,
|
||||||
|
}: {
|
||||||
|
refId: string
|
||||||
|
confirmationNumber: string
|
||||||
|
lastName: string
|
||||||
|
isLoggedIn: boolean
|
||||||
|
bv?: string
|
||||||
|
}) {
|
||||||
|
if (isLoggedIn)
|
||||||
|
return { bookingConfirmation: await getBookingConfirmation(refId) } as const
|
||||||
|
|
||||||
|
if (!bv) return { error: "MISSING_INFO", bookingConfirmation: null } as const
|
||||||
|
|
||||||
|
logger.debug(`MyStay: bv`, bv)
|
||||||
|
const {
|
||||||
|
firstName,
|
||||||
|
email,
|
||||||
|
confirmationNumber: bvConfirmationNo,
|
||||||
|
} = JSON.parse(bv) as AdditionalInfoCookieValue
|
||||||
|
|
||||||
|
if (!firstName || !email || bvConfirmationNo !== confirmationNumber) {
|
||||||
|
return { error: "MISSING_INFO", bookingConfirmation: null } as const
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
bookingConfirmation: await findBooking(
|
||||||
|
confirmationNumber,
|
||||||
|
lastName,
|
||||||
|
firstName,
|
||||||
|
email
|
||||||
|
),
|
||||||
|
} as const
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to handle conditional Promise.all calls
|
||||||
|
async function noop() {
|
||||||
|
return Promise.resolve(null)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user