diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/page.tsx
index 662d051d7..76f30ed5b 100644
--- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/page.tsx
+++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/page.tsx
@@ -1,42 +1,18 @@
import { notFound } from "next/navigation"
import { Suspense } from "react"
-import {
- selectHotel,
- selectHotelMap,
-} from "@/constants/routes/hotelReservation"
import { getLocations } from "@/lib/trpc/memoizedRequests"
-import {
- fetchAvailableHotels,
- getFiltersFromHotels,
-} from "@/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/utils"
-import HotelCardListing from "@/components/HotelReservation/HotelCardListing"
-import HotelCount from "@/components/HotelReservation/SelectHotel/HotelCount"
-import HotelFilter from "@/components/HotelReservation/SelectHotel/HotelFilter"
-import HotelSorter from "@/components/HotelReservation/SelectHotel/HotelSorter"
-import MobileMapButtonContainer from "@/components/HotelReservation/SelectHotel/MobileMapButtonContainer"
+import SelectHotel from "@/components/HotelReservation/SelectHotel"
+import { SelectHotelSkeleton } from "@/components/HotelReservation/SelectHotel/SelectHotelSkeleton"
import {
generateChildrenString,
getHotelReservationQueryParams,
} from "@/components/HotelReservation/SelectRate/RoomSelection/utils"
-import { ChevronRightIcon } from "@/components/Icons"
-import StaticMap from "@/components/Maps/StaticMap"
-import Alert from "@/components/TempDesignSystem/Alert"
-import Breadcrumbs from "@/components/TempDesignSystem/Breadcrumbs"
-import BreadcrumbsSkeleton from "@/components/TempDesignSystem/Breadcrumbs/BreadcrumbsSkeleton"
-import Button from "@/components/TempDesignSystem/Button"
-import Link from "@/components/TempDesignSystem/Link"
-import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
-import { getIntl } from "@/i18n"
import { setLang } from "@/i18n/serverContext"
-import styles from "./page.module.css"
-
-import type { HotelData } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
import type { SelectHotelSearchParams } from "@/types/components/hotelReservation/selectHotel/selectHotelSearchParams"
-import { AlertTypeEnum } from "@/types/enums/alert"
-import { LangParams, PageArgs } from "@/types/params"
+import type { LangParams, PageArgs } from "@/types/params"
export default async function SelectHotelPage({
params,
@@ -55,10 +31,6 @@ export default async function SelectHotelPage({
if (!city) return notFound()
- const isCityWithCountry = (city: any): city is { country: string } =>
- "country" in city
-
- const intl = await getIntl()
const selectHotelParams = new URLSearchParams(searchParams)
const selectHotelParamsObject =
getHotelReservationQueryParams(selectHotelParams)
@@ -70,121 +42,25 @@ export default async function SelectHotelPage({
return notFound()
}
- const adults = selectHotelParamsObject.room[0].adults // TODO: Handle multiple rooms
- const children = selectHotelParamsObject.room[0].child
+ const adultsParams = selectHotelParamsObject.room[0].adults // TODO: Handle multiple rooms
+ const childrenParams = selectHotelParamsObject.room[0].child
? generateChildrenString(selectHotelParamsObject.room[0].child)
: undefined // TODO: Handle multiple rooms
- const hotels = await fetchAvailableHotels({
- cityId: city.id,
- roomStayStartDate: searchParams.fromDate,
- roomStayEndDate: searchParams.toDate,
- adults,
- children,
- })
-
- const validHotels = hotels.filter(
- (hotel): hotel is HotelData => hotel !== null
- )
-
- const filterList = getFiltersFromHotels(validHotels)
- const breadcrumbs = [
- {
- title: intl.formatMessage({ id: "Home" }),
- href: `/${params.lang}`,
- uid: "home-page",
- },
- {
- title: intl.formatMessage({ id: "Hotel reservation" }),
- href: `/${params.lang}/hotelreservation`,
- uid: "hotel-reservation",
- },
- {
- title: intl.formatMessage({ id: "Select hotel" }),
- href: `${selectHotel(params.lang)}/?${selectHotelParams}`,
- uid: "select-hotel",
- },
- {
- title: city.name,
- uid: city.id,
- },
- ]
-
- const isAllUnavailable = hotels.every((hotel) => hotel.price === undefined)
+ const reservationParams = {
+ selectHotelParams,
+ searchParams,
+ adultsParams,
+ childrenParams,
+ }
return (
- <>
-
- }>
-
-
-
-
- {city.name}
-
-
-
-
-
-
-
-
-
-
- {hotels.length > 0 ? ( // TODO: Temp fix until API returns hotels that are not available
-
-
-
-
-
-
- ) : (
-
-
-
- )}
-
-
-
- {isAllUnavailable && (
-
- )}
-
-
-
- >
+ }>
+
+
)
}
diff --git a/components/HotelReservation/HotelCard/HotelCardSkeleton.module.css b/components/HotelReservation/HotelCard/HotelCardSkeleton.module.css
new file mode 100644
index 000000000..2305130c7
--- /dev/null
+++ b/components/HotelReservation/HotelCard/HotelCardSkeleton.module.css
@@ -0,0 +1,58 @@
+.card {
+ font-size: 14px;
+ display: flex;
+ flex-direction: column;
+ background-color: #fff;
+ border-radius: var(--Corner-radius-Large);
+ border: 1px solid var(--Base-Border-Subtle);
+ position: relative;
+ height: 100%;
+ justify-content: space-between;
+ min-height: 200px;
+ flex: 1;
+ overflow: hidden;
+}
+
+.imageContainer {
+ aspect-ratio: 16/9;
+ width: 100%;
+ height: 200px;
+}
+
+.priceVariants {
+ display: flex;
+ flex-direction: column;
+ gap: var(--Spacing-x1);
+ padding: var(--Spacing-x2);
+ flex: 1;
+}
+
+.content {
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+ gap: var(--Spacing-x1);
+ padding: var(--Spacing-x2);
+}
+
+.text {
+ display: none;
+}
+
+@media (min-width: 1367px) {
+ .content {
+ padding: var(--Spacing-x2) 0 var(--Spacing-x2) var(--Spacing-x2);
+ }
+
+ .text {
+ display: block;
+ }
+
+ .card {
+ flex-direction: row;
+ }
+ .imageContainer {
+ width: 315px;
+ height: 100%;
+ }
+}
diff --git a/components/HotelReservation/HotelCard/HotelCardSkeleton.tsx b/components/HotelReservation/HotelCard/HotelCardSkeleton.tsx
new file mode 100644
index 000000000..9c62f413a
--- /dev/null
+++ b/components/HotelReservation/HotelCard/HotelCardSkeleton.tsx
@@ -0,0 +1,33 @@
+import SkeletonShimmer from "@/components/SkeletonShimmer"
+
+import styles from "./HotelCardSkeleton.module.css"
+
+export function HotelCardSkeleton() {
+ return (
+
+ {/* image container */}
+
+
+
+
+
+
+
+ {/* price variants */}
+ {Array.from({ length: 2 }).map((_, index) => (
+
+ ))}
+
+
+ )
+}
diff --git a/components/HotelReservation/SelectHotel/SelectHotelSkeleton.tsx b/components/HotelReservation/SelectHotel/SelectHotelSkeleton.tsx
new file mode 100644
index 000000000..7b8fe5d72
--- /dev/null
+++ b/components/HotelReservation/SelectHotel/SelectHotelSkeleton.tsx
@@ -0,0 +1,42 @@
+import SkeletonShimmer from "@/components/SkeletonShimmer"
+
+import { HotelCardSkeleton } from "../HotelCard/HotelCardSkeleton"
+
+import styles from "./selectHotel.module.css"
+
+type Props = {
+ count?: number
+}
+
+export async function SelectHotelSkeleton({ count = 4 }: Props) {
+ return (
+
+
+
+
+
+ {Array.from({ length: count }).map((_, index) => (
+
+ ))}
+
+
+
+ )
+}
diff --git a/components/HotelReservation/SelectHotel/index.tsx b/components/HotelReservation/SelectHotel/index.tsx
new file mode 100644
index 000000000..9acb038d7
--- /dev/null
+++ b/components/HotelReservation/SelectHotel/index.tsx
@@ -0,0 +1,154 @@
+import {
+ selectHotel,
+ selectHotelMap,
+} from "@/constants/routes/hotelReservation"
+
+import {
+ fetchAvailableHotels,
+ getFiltersFromHotels,
+} from "@/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/utils"
+import { ChevronRightIcon } from "@/components/Icons"
+import StaticMap from "@/components/Maps/StaticMap"
+import Alert from "@/components/TempDesignSystem/Alert"
+import Breadcrumbs from "@/components/TempDesignSystem/Breadcrumbs"
+import Button from "@/components/TempDesignSystem/Button"
+import Link from "@/components/TempDesignSystem/Link"
+import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
+import { getIntl } from "@/i18n"
+
+import HotelCardListing from "../HotelCardListing"
+import HotelCount from "./HotelCount"
+import HotelFilter from "./HotelFilter"
+import HotelSorter from "./HotelSorter"
+import MobileMapButtonContainer from "./MobileMapButtonContainer"
+
+import styles from "./selectHotel.module.css"
+
+import type { HotelData } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
+import type { SelectHotelProps } from "@/types/components/hotelReservation/selectHotel/selectHotel"
+import { AlertTypeEnum } from "@/types/enums/alert"
+
+export default async function SelectHotel({
+ city,
+ params,
+ reservationParams,
+}: SelectHotelProps) {
+ const { selectHotelParams, searchParams, adultsParams, childrenParams } =
+ reservationParams
+
+ const intl = await getIntl()
+
+ const hotels = await fetchAvailableHotels({
+ cityId: city.id,
+ roomStayStartDate: searchParams.fromDate,
+ roomStayEndDate: searchParams.toDate,
+ adults: adultsParams,
+ children: childrenParams?.toString(),
+ })
+
+ const isCityWithCountry = (city: any): city is { country: string } =>
+ "country" in city
+
+ const validHotels = hotels.filter(
+ (hotel): hotel is HotelData => hotel !== null
+ )
+
+ const filterList = getFiltersFromHotels(validHotels)
+ const breadcrumbs = [
+ {
+ title: intl.formatMessage({ id: "Home" }),
+ href: `/${params.lang}`,
+ uid: "home-page",
+ },
+ {
+ title: intl.formatMessage({ id: "Hotel reservation" }),
+ href: `/${params.lang}/hotelreservation`,
+ uid: "hotel-reservation",
+ },
+ {
+ title: intl.formatMessage({ id: "Select hotel" }),
+ href: `${selectHotel(params.lang)}/?${selectHotelParams}`,
+ uid: "select-hotel",
+ },
+ {
+ title: city.name,
+ uid: city.id,
+ },
+ ]
+
+ const isAllUnavailable = hotels.every((hotel) => hotel.price === undefined)
+
+ return (
+ <>
+
+
+
+
+ {city.name}
+
+
+
+
+
+
+
+
+
+
+ {hotels.length > 0 ? ( // TODO: Temp fix until API returns hotels that are not available
+
+
+
+
+
+
+ ) : (
+
+
+
+ )}
+
+
+
+ {isAllUnavailable && (
+
+ )}
+
+
+
+ >
+ )
+}
diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/page.module.css b/components/HotelReservation/SelectHotel/selectHotel.module.css
similarity index 88%
rename from app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/page.module.css
rename to components/HotelReservation/SelectHotel/selectHotel.module.css
index 052d9ee6b..264b8b10b 100644
--- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/page.module.css
+++ b/components/HotelReservation/SelectHotel/selectHotel.module.css
@@ -7,6 +7,7 @@
max-width: var(--max-width);
margin: 0 auto;
}
+
.header {
display: flex;
flex-direction: column;
@@ -34,6 +35,10 @@
flex-direction: column;
}
+.sideBarItem {
+ display: none;
+}
+
.link {
display: none;
}
@@ -59,6 +64,10 @@
display: none;
}
+.skeletonContainer .title {
+ margin-bottom: var(--Spacing-x3);
+}
+
@media (min-width: 768px) {
.main {
padding: var(--Spacing-x5);
@@ -92,6 +101,9 @@
.sideBar {
max-width: 340px;
}
+ .sideBarItem {
+ display: block;
+ }
.filter {
display: block;
}
@@ -114,4 +126,10 @@
.buttonContainer {
display: none;
}
+ .skeletonContainer .title {
+ margin-bottom: 0;
+ }
+ .skeletonContainer .sideBar {
+ gap: var(--Spacing-x3);
+ }
}
diff --git a/types/components/hotelReservation/selectHotel/selectHotel.ts b/types/components/hotelReservation/selectHotel/selectHotel.ts
index d5f8807bd..016645813 100644
--- a/types/components/hotelReservation/selectHotel/selectHotel.ts
+++ b/types/components/hotelReservation/selectHotel/selectHotel.ts
@@ -1,4 +1,8 @@
-import { CheckInData, Hotel, ParkingData } from "@/types/hotel"
+import { Lang } from "@/constants/languages"
+
+import type { CheckInData, Hotel, ParkingData } from "@/types/hotel"
+import type { Location } from "@/types/trpc/routers/hotel/locations"
+import type { SelectHotelSearchParams } from "./selectHotelSearchParams"
export enum AvailabilityEnum {
Available = "Available",
@@ -35,3 +39,16 @@ export interface CheckInCheckOutProps {
export interface MeetingsAndConferencesProps {
meetingDescription: string
}
+
+export interface SelectHotelProps {
+ city: Location
+ params: {
+ lang: Lang
+ }
+ reservationParams: {
+ selectHotelParams: URLSearchParams
+ searchParams: SelectHotelSearchParams
+ adultsParams: number
+ childrenParams: string | undefined
+ }
+}