Merged in feat/booking-flow-performance (pull request #1282)
feat: booking flow performance * feat: booking flow performance * Cleanup Approved-by: Michael Zetterberg Approved-by: Pontus Dreij
This commit is contained in:
@@ -22,6 +22,7 @@ export default function FormContent({
|
||||
locations,
|
||||
formId,
|
||||
onSubmit,
|
||||
isSearching,
|
||||
}: BookingWidgetFormContentProps) {
|
||||
const intl = useIntl()
|
||||
const selectedDate = useWatch({ name: "date" })
|
||||
@@ -84,6 +85,7 @@ export default function FormContent({
|
||||
intent="primary"
|
||||
theme="base"
|
||||
type="submit"
|
||||
disabled={isSearching}
|
||||
>
|
||||
<Caption
|
||||
color="white"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use client"
|
||||
import { useRouter } from "next/navigation"
|
||||
import { useEffect, useState, useTransition } from "react"
|
||||
import { Form as FormRAC } from "react-aria-components"
|
||||
import { useFormContext } from "react-hook-form"
|
||||
|
||||
@@ -26,6 +27,7 @@ export default function Form({
|
||||
}: BookingWidgetFormProps) {
|
||||
const router = useRouter()
|
||||
const lang = useLang()
|
||||
const [isPending, startTransition] = useTransition()
|
||||
|
||||
const classNames = bookingWidgetVariants({
|
||||
type,
|
||||
@@ -36,7 +38,6 @@ export default function Form({
|
||||
|
||||
function onSubmit(data: BookingWidgetSchema) {
|
||||
const locationData: Location = JSON.parse(decodeURIComponent(data.location))
|
||||
|
||||
const bookingFlowPage =
|
||||
locationData.type == "cities" ? selectHotel(lang) : selectRate(lang)
|
||||
const bookingWidgetParams = convertObjToSearchParams({
|
||||
@@ -51,7 +52,9 @@ export default function Form({
|
||||
})
|
||||
|
||||
onClose()
|
||||
router.push(`${bookingFlowPage}?${bookingWidgetParams.toString()}`)
|
||||
startTransition(() => {
|
||||
router.push(`${bookingFlowPage}?${bookingWidgetParams.toString()}`)
|
||||
})
|
||||
if (!data.bookingCode?.value) {
|
||||
setValue("bookingCode.remember", false)
|
||||
localStorage.removeItem("bookingCode")
|
||||
@@ -72,6 +75,7 @@ export default function Form({
|
||||
locations={locations}
|
||||
formId={formId}
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
isSearching={isPending}
|
||||
/>
|
||||
</FormRAC>
|
||||
</section>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {
|
||||
getHeader,
|
||||
getLanguageSwitcher,
|
||||
getName,
|
||||
} from "@/lib/trpc/memoizedRequests"
|
||||
import { getHeader, getLanguageSwitcher } from "@/lib/trpc/memoizedRequests"
|
||||
|
||||
import { auth } from "@/auth"
|
||||
import { isValidSession } from "@/utils/session"
|
||||
|
||||
import MobileMenu from "../MobileMenu"
|
||||
|
||||
@@ -12,7 +11,7 @@ export default async function MobileMenuWrapper({
|
||||
// preloaded
|
||||
const languages = await getLanguageSwitcher()
|
||||
const header = await getHeader()
|
||||
const user = await getName()
|
||||
const session = await auth()
|
||||
|
||||
if (!languages || !header) {
|
||||
return null
|
||||
@@ -22,7 +21,7 @@ export default async function MobileMenuWrapper({
|
||||
<MobileMenu
|
||||
languageUrls={languages.urls}
|
||||
topLink={header.data.topLink}
|
||||
isLoggedIn={!!user}
|
||||
isLoggedIn={isValidSession(session)}
|
||||
>
|
||||
{children}
|
||||
</MobileMenu>
|
||||
|
||||
@@ -11,11 +11,10 @@ import TopMenu, { TopMenuSkeleton } from "./TopMenu"
|
||||
|
||||
import styles from "./header.module.css"
|
||||
|
||||
export default async function Header() {
|
||||
export default function Header() {
|
||||
void getHeader()
|
||||
void getLanguageSwitcher()
|
||||
void getName()
|
||||
|
||||
return (
|
||||
<header className={styles.header}>
|
||||
<Suspense fallback={<TopMenuSkeleton />}>
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
.hotelAlert {
|
||||
max-width: var(--max-width-navigation);
|
||||
margin: 0 auto;
|
||||
padding-top: var(--Spacing-x-one-and-half);
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
import { dt } from "@/lib/dt"
|
||||
import { getRoomsAvailability } from "@/lib/trpc/memoizedRequests"
|
||||
|
||||
import Alert from "@/components/TempDesignSystem/Alert"
|
||||
import { getIntl } from "@/i18n"
|
||||
import { safeTry } from "@/utils/safeTry"
|
||||
|
||||
import { generateChildrenString } from "../../utils"
|
||||
import { combineRoomAvailabilities } from "../utils"
|
||||
|
||||
import styles from "./NoRoomsAlert.module.css"
|
||||
|
||||
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import { AlertTypeEnum } from "@/types/enums/alert"
|
||||
import type { Lang } from "@/constants/languages"
|
||||
|
||||
type Props = {
|
||||
hotelId: number
|
||||
lang: Lang
|
||||
adultArray: number[]
|
||||
childArray?: Child[]
|
||||
fromDate: Date
|
||||
toDate: Date
|
||||
}
|
||||
|
||||
export async function NoRoomsAlert({
|
||||
hotelId,
|
||||
fromDate,
|
||||
toDate,
|
||||
childArray,
|
||||
adultArray,
|
||||
lang,
|
||||
}: Props) {
|
||||
const fromDateString = dt(fromDate).format("YYYY-MM-DD")
|
||||
const toDateString = dt(toDate).format("YYYY-MM-DD")
|
||||
|
||||
const uniqueAdultCounts = [...new Set(adultArray)]
|
||||
const roomsAvailabilityPromises = uniqueAdultCounts.map((adultCount) => {
|
||||
return safeTry(
|
||||
getRoomsAvailability({
|
||||
hotelId: hotelId,
|
||||
roomStayStartDate: fromDateString,
|
||||
roomStayEndDate: toDateString,
|
||||
adults: adultCount,
|
||||
children:
|
||||
childArray && childArray.length > 0
|
||||
? generateChildrenString(childArray)
|
||||
: undefined,
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
const roomsAvailabilityResults = await Promise.all(roomsAvailabilityPromises)
|
||||
|
||||
const roomsAvailability = combineRoomAvailabilities({
|
||||
availabilityResults: roomsAvailabilityResults,
|
||||
})
|
||||
|
||||
if (!roomsAvailability) {
|
||||
return null
|
||||
}
|
||||
|
||||
const noRoomsAvailable = roomsAvailability.roomConfigurations.reduce(
|
||||
(acc, room) => {
|
||||
return acc && room.status === "NotAvailable"
|
||||
},
|
||||
true
|
||||
)
|
||||
|
||||
if (!noRoomsAvailable) {
|
||||
return null
|
||||
}
|
||||
|
||||
const intl = await getIntl(lang)
|
||||
return (
|
||||
<div className={styles.hotelAlert}>
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
text={intl.formatMessage({
|
||||
id: "There are no rooms available that match your request",
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
import { Suspense } from "react"
|
||||
|
||||
import { getHotel } from "@/lib/trpc/memoizedRequests"
|
||||
|
||||
import { mapFacilityToIcon } from "@/components/ContentType/HotelPage/data"
|
||||
@@ -15,7 +13,6 @@ import { getSingleDecimal } from "@/utils/numberFormatting"
|
||||
|
||||
import ReadMore from "../../ReadMore"
|
||||
import TripAdvisorChip from "../../TripAdvisorChip"
|
||||
import { NoRoomsAlert } from "./NoRoomsAlert"
|
||||
|
||||
import styles from "./hotelInfoCard.module.css"
|
||||
|
||||
@@ -24,7 +21,6 @@ import type { HotelInfoCardProps } from "@/types/components/hotelReservation/sel
|
||||
export default async function HotelInfoCard({
|
||||
hotelId,
|
||||
lang,
|
||||
...props
|
||||
}: HotelInfoCardProps) {
|
||||
const hotelData = await getHotel({
|
||||
hotelId: hotelId.toString(),
|
||||
@@ -119,10 +115,6 @@ export default async function HotelInfoCard({
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
|
||||
<Suspense fallback={null} key={hotelId}>
|
||||
<NoRoomsAlert hotelId={hotelId} lang={lang} {...props} />
|
||||
</Suspense>
|
||||
</article>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import {
|
||||
} from "@/lib/trpc/memoizedRequests"
|
||||
|
||||
import { auth } from "@/auth"
|
||||
import Alert from "@/components/TempDesignSystem/Alert"
|
||||
import { getIntl } from "@/i18n"
|
||||
import { safeTry } from "@/utils/safeTry"
|
||||
import { isValidSession } from "@/utils/session"
|
||||
|
||||
@@ -13,8 +15,11 @@ import { generateChildrenString } from "../../utils"
|
||||
import { combineRoomAvailabilities } from "../utils"
|
||||
import Rooms from "."
|
||||
|
||||
import styles from "./rooms.module.css"
|
||||
|
||||
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
|
||||
import type { RoomsContainerProps } from "@/types/components/hotelReservation/selectRate/roomsContainer"
|
||||
import { AlertTypeEnum } from "@/types/enums/alert"
|
||||
|
||||
export async function RoomsContainer({
|
||||
adultArray,
|
||||
@@ -77,14 +82,24 @@ export async function RoomsContainer({
|
||||
availabilityResults: roomsAvailabilityResults,
|
||||
})
|
||||
|
||||
const intl = await getIntl(lang)
|
||||
|
||||
if (packagesError) {
|
||||
// TODO: Log packages error
|
||||
console.error("[RoomsContainer] unable to fetch packages")
|
||||
}
|
||||
|
||||
if (!roomsAvailability) {
|
||||
// HotelInfoCard has the logic for displaying when there are no rooms available
|
||||
return null
|
||||
return (
|
||||
<div className={styles.hotelAlert}>
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
text={intl.formatMessage({
|
||||
id: "There are no rooms available that match your request",
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -48,3 +48,9 @@
|
||||
opacity: 1;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.hotelAlert {
|
||||
max-width: var(--max-width-navigation);
|
||||
margin: 0 auto;
|
||||
padding: var(--Spacing-x-one-and-half);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ export interface BookingWidgetFormContentProps {
|
||||
locations: Locations
|
||||
formId: string
|
||||
onSubmit: () => void
|
||||
isSearching: boolean
|
||||
}
|
||||
|
||||
export enum ActionType {
|
||||
|
||||
Reference in New Issue
Block a user