diff --git a/app/[lang]/(live)/@bookingwidget/loading.tsx b/app/[lang]/(live)/@bookingwidget/loading.tsx index f62e3acb5..c45dee2ad 100644 --- a/app/[lang]/(live)/@bookingwidget/loading.tsx +++ b/app/[lang]/(live)/@bookingwidget/loading.tsx @@ -1,6 +1,6 @@ import { env } from "@/env/server" -import BookingWidgetSkeleton from "@/components/BookingWidget/BookingWidgetSkeleton" +import { BookingWidgetSkeleton } from "@/components/BookingWidget/Client" export default function LoadingBookingWidget() { if (env.HIDE_FOR_NEXT_RELEASE) { diff --git a/components/BookingWidget/BookingWidgetSkeleton.tsx b/components/BookingWidget/BookingWidgetSkeleton.tsx deleted file mode 100644 index a784f0636..000000000 --- a/components/BookingWidget/BookingWidgetSkeleton.tsx +++ /dev/null @@ -1,90 +0,0 @@ -"use client" -import { useIntl } from "react-intl" - -import { SearchIcon } from "@/components/Icons" - -import { SearchSkeleton } from "../Forms/BookingWidget/FormContent/Search" -import { VoucherSkeleton } from "../Forms/BookingWidget/FormContent/Voucher" -import { bookingWidgetVariants } from "../Forms/BookingWidget/variants" -import SkeletonShimmer from "../SkeletonShimmer" -import Button from "../TempDesignSystem/Button" -import Caption from "../TempDesignSystem/Text/Caption" - -import formStyles from "../Forms/BookingWidget/form.module.css" -import formContentStyles from "../Forms/BookingWidget/FormContent/formContent.module.css" -import widgetStyles from "./bookingWidget.module.css" - -export default function BookingWidgetSkeleton() { - const intl = useIntl() - - const classNames = bookingWidgetVariants({ - type: "full", - }) - - return ( -
-
-
-
-
-
- -
-
- - {intl.formatMessage( - { id: "booking.nights" }, - { totalNights: 0 } - )} - - -
-
- - {intl.formatMessage({ id: "Guests & Rooms" })} - - -
-
-
- -
-
- -
-
-
-
- {/*
- -
-
-
- */} -
- ) -} diff --git a/components/BookingWidget/Client.tsx b/components/BookingWidget/Client.tsx index 70daa6a20..f3944e7ab 100644 --- a/components/BookingWidget/Client.tsx +++ b/components/BookingWidget/Client.tsx @@ -6,14 +6,18 @@ import { FormProvider, useForm } from "react-hook-form" import { dt } from "@/lib/dt" import { StickyElementNameEnum } from "@/stores/sticky-position" -import Form from "@/components/Forms/BookingWidget" +import Form, { + BookingWidgetFormSkeleton, +} from "@/components/Forms/BookingWidget" import { bookingWidgetSchema } from "@/components/Forms/BookingWidget/schema" import { CloseLargeIcon } from "@/components/Icons" import useStickyPosition from "@/hooks/useStickyPosition" import { debounce } from "@/utils/debounce" import { getFormattedUrlQueryParams } from "@/utils/url" -import MobileToggleButton from "./MobileToggleButton" +import MobileToggleButton, { + MobileToggleButtonSkeleton, +} from "./MobileToggleButton" import styles from "./bookingWidget.module.css" @@ -36,7 +40,6 @@ export default function BookingWidgetClient({ name: StickyElementNameEnum.BOOKING_WIDGET, }) - const bookingWidgetSearchData: BookingWidgetSearchParams | undefined = searchParams ? (getFormattedUrlQueryParams(new URLSearchParams(searchParams), { @@ -79,9 +82,7 @@ export default function BookingWidgetClient({ const methods = useForm({ defaultValues: { search: selectedLocation?.name ?? "", - location: selectedLocation - ? JSON.stringify(selectedLocation) - : undefined, + location: selectedLocation ? JSON.stringify(selectedLocation) : undefined, date: { // UTC is required to handle requests from far away timezones https://scandichotels.atlassian.net/browse/SWAP-6375 & PET-507 // This is specifically to handle timezones falling in different dates. @@ -147,9 +148,11 @@ export default function BookingWidgetClient({ ? JSON.parse(sessionStorageSearchData) : undefined - !(selectedLocation?.name) && initialSelectedLocation?.name && + !selectedLocation?.name && + initialSelectedLocation?.name && methods.setValue("search", initialSelectedLocation.name) - !selectedLocation && sessionStorageSearchData && + !selectedLocation && + sessionStorageSearchData && methods.setValue("location", encodeURIComponent(sessionStorageSearchData)) }, [methods, selectedLocation]) @@ -173,3 +176,14 @@ export default function BookingWidgetClient({ ) } + +export function BookingWidgetSkeleton() { + return ( + <> +
+ +
+ + + ) +} diff --git a/components/BookingWidget/MobileToggleButton/index.tsx b/components/BookingWidget/MobileToggleButton/index.tsx index 80026ff93..c8ef26189 100644 --- a/components/BookingWidget/MobileToggleButton/index.tsx +++ b/components/BookingWidget/MobileToggleButton/index.tsx @@ -7,6 +7,7 @@ import { dt } from "@/lib/dt" import { StickyElementNameEnum } from "@/stores/sticky-position" import { EditIcon, SearchIcon } from "@/components/Icons" +import SkeletonShimmer from "@/components/SkeletonShimmer" import Divider from "@/components/TempDesignSystem/Divider" import Body from "@/components/TempDesignSystem/Text/Body" import Caption from "@/components/TempDesignSystem/Text/Caption" @@ -24,7 +25,6 @@ import type { Location } from "@/types/trpc/routers/hotel/locations" export default function MobileToggleButton({ openMobileSearch, }: BookingWidgetToggleButtonProps) { - const [hasMounted, setHasMounted] = useState(false) const intl = useIntl() const lang = useLang() const d = useWatch({ name: "date" }) @@ -46,14 +46,6 @@ export default function MobileToggleButton({ const selectedFromDate = dt(d.fromDate).locale(lang).format("D MMM") const selectedToDate = dt(d.toDate).locale(lang).format("D MMM") - useEffect(() => { - setHasMounted(true) - }, []) - - if (!hasMounted) { - return null - } - const locationAndDateIsSet = parsedLocation && d const totalRooms = rooms.length @@ -133,3 +125,33 @@ export default function MobileToggleButton({ ) } + +export function MobileToggleButtonSkeleton() { + const intl = useIntl() + const bookingWidgetMobileRef = useRef(null) + useStickyPosition({ + ref: bookingWidgetMobileRef, + name: StickyElementNameEnum.BOOKING_WIDGET_MOBILE, + }) + + return ( +
+
+ + {intl.formatMessage({ id: "Where to" })} + + +
+ +
+ + {intl.formatMessage({ id: "booking.nights" }, { totalNights: 0 })} + + +
+
+ +
+
+ ) +} diff --git a/components/Forms/BookingWidget/FormContent/index.tsx b/components/Forms/BookingWidget/FormContent/index.tsx index d5dba4d47..dc7306fca 100644 --- a/components/Forms/BookingWidget/FormContent/index.tsx +++ b/components/Forms/BookingWidget/FormContent/index.tsx @@ -1,5 +1,4 @@ "use client" -import { useState } from "react" import { useWatch } from "react-hook-form" import { useIntl } from "react-intl" @@ -9,11 +8,12 @@ import DatePicker from "@/components/DatePicker" import GuestsRoomsPickerForm from "@/components/GuestsRoomsPicker" import GuestsRoomsProvider from "@/components/GuestsRoomsPicker/Provider/GuestsRoomsProvider" import { SearchIcon } from "@/components/Icons" +import SkeletonShimmer from "@/components/SkeletonShimmer" import Button from "@/components/TempDesignSystem/Button" import Caption from "@/components/TempDesignSystem/Text/Caption" -import Search from "./Search" -import Voucher from "./Voucher" +import Search, { SearchSkeleton } from "./Search" +import Voucher, { VoucherSkeleton } from "./Voucher" import styles from "./formContent.module.css" @@ -90,3 +90,53 @@ export default function FormContent({ ) } + +export function BookingWidgetFormContentSkeleton() { + const intl = useIntl() + + return ( +
+
+
+ +
+
+ + {intl.formatMessage({ id: "booking.nights" }, { totalNights: 0 })} + + +
+
+ + {intl.formatMessage({ id: "Guests & Rooms" })} + + +
+
+
+ +
+
+ +
+
+ ) +} diff --git a/components/Forms/BookingWidget/index.tsx b/components/Forms/BookingWidget/index.tsx index 6c78ea341..b1018368b 100644 --- a/components/Forms/BookingWidget/index.tsx +++ b/components/Forms/BookingWidget/index.tsx @@ -6,7 +6,7 @@ import { selectHotel, selectRate } from "@/constants/routes/hotelReservation" import useLang from "@/hooks/useLang" -import FormContent from "./FormContent" +import FormContent, { BookingWidgetFormContentSkeleton } from "./FormContent" import { bookingWidgetVariants } from "./variants" import styles from "./form.module.css" @@ -69,3 +69,17 @@ export default function Form({ locations, type }: BookingWidgetFormProps) { ) } + +export function BookingWidgetFormSkeleton() { + const classNames = bookingWidgetVariants({ + type: "full", + }) + + return ( +
+ + + +
+ ) +}