feat: break apart loading of room availability and hotel card
feat: add skeletons
This commit is contained in:
@@ -4,9 +4,9 @@ import { Suspense } from "react"
|
|||||||
import { dt } from "@/lib/dt"
|
import { dt } from "@/lib/dt"
|
||||||
import { getHotelData, getLocations } from "@/lib/trpc/memoizedRequests"
|
import { getHotelData, getLocations } from "@/lib/trpc/memoizedRequests"
|
||||||
|
|
||||||
import LoadingSpinner from "@/components/Current/LoadingSpinner"
|
|
||||||
import HotelInfoCard from "@/components/HotelReservation/SelectRate/HotelInfoCard"
|
import HotelInfoCard from "@/components/HotelReservation/SelectRate/HotelInfoCard"
|
||||||
import { RoomsContainer } from "@/components/HotelReservation/SelectRate/Rooms/RoomsContainer"
|
import { RoomsContainer } from "@/components/HotelReservation/SelectRate/Rooms/RoomsContainer"
|
||||||
|
import { RoomsContainerSkeleton } from "@/components/HotelReservation/SelectRate/Rooms/RoomsContainerSkeleton"
|
||||||
import { getHotelReservationQueryParams } from "@/components/HotelReservation/SelectRate/RoomSelection/utils"
|
import { getHotelReservationQueryParams } from "@/components/HotelReservation/SelectRate/RoomSelection/utils"
|
||||||
import { setLang } from "@/i18n/serverContext"
|
import { setLang } from "@/i18n/serverContext"
|
||||||
import { safeTry } from "@/utils/safeTry"
|
import { safeTry } from "@/utils/safeTry"
|
||||||
@@ -71,7 +71,8 @@ export default async function SelectRatePage({
|
|||||||
adultCount={adults}
|
adultCount={adults}
|
||||||
childArray={children ?? []}
|
childArray={children ?? []}
|
||||||
/>
|
/>
|
||||||
<Suspense key={hotelId} fallback={<LoadingSpinner />}>
|
|
||||||
|
<Suspense key={hotelId} fallback={<RoomsContainerSkeleton />}>
|
||||||
<RoomsContainer
|
<RoomsContainer
|
||||||
hotelId={hotelId}
|
hotelId={hotelId}
|
||||||
lang={params.lang}
|
lang={params.lang}
|
||||||
|
|||||||
@@ -42,23 +42,10 @@ export default async function HotelInfoCard({
|
|||||||
const hotelAttributes = hotelData?.data.attributes
|
const hotelAttributes = hotelData?.data.attributes
|
||||||
const intl = await getIntl()
|
const intl = await getIntl()
|
||||||
|
|
||||||
// const noRoomsAvailable = useRoomAvailableStore(
|
|
||||||
// (state) => state.noRoomsAvailable
|
|
||||||
// )
|
|
||||||
// const setNoRoomsAvailable = useRoomAvailableStore(
|
|
||||||
// (state) => state.setNoRoomsAvailable
|
|
||||||
// )
|
|
||||||
|
|
||||||
const sortedFacilities = hotelAttributes?.detailedFacilities
|
const sortedFacilities = hotelAttributes?.detailedFacilities
|
||||||
.sort((a, b) => b.sortOrder - a.sortOrder)
|
.sort((a, b) => b.sortOrder - a.sortOrder)
|
||||||
.slice(0, 5)
|
.slice(0, 5)
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// if (noAvailability) {
|
|
||||||
// setNoRoomsAvailable()
|
|
||||||
// }
|
|
||||||
// }, [noAvailability, setNoRoomsAvailable])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<article className={styles.container}>
|
<article className={styles.container}>
|
||||||
{hotelAttributes && (
|
{hotelAttributes && (
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
.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%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.priceVariants {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--Spacing-x1);
|
||||||
|
padding: var(--Spacing-x2);
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import SkeletonShimmer from "@/components/SkeletonShimmer"
|
||||||
|
|
||||||
|
import styles from "./RoomCardSkeleton.module.css"
|
||||||
|
|
||||||
|
export function RoomCardSkeleton() {
|
||||||
|
return (
|
||||||
|
<article className={styles.card}>
|
||||||
|
{/* image container */}
|
||||||
|
<div className={styles.imageContainer}>
|
||||||
|
<SkeletonShimmer width={"100%"} height="100%" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.priceVariants}>
|
||||||
|
{/* price variants */}
|
||||||
|
{Array.from({ length: 3 }).map((_, index) => (
|
||||||
|
<SkeletonShimmer key={index} height={"100px"} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
.container {
|
||||||
|
padding: var(--Spacing-x2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterContainer {
|
||||||
|
height: 38px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeletonContainer {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||||||
|
/* used to hide overflowing rows */
|
||||||
|
grid-template-rows: auto;
|
||||||
|
grid-auto-rows: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 20px;
|
||||||
|
gap: var(--Spacing-x2);
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||||
|
import { getIntl } from "@/i18n"
|
||||||
|
|
||||||
|
import { RoomCardSkeleton } from "../RoomSelection/RoomCard/RoomCardSkeleton"
|
||||||
|
|
||||||
|
import styles from "./RoomsContainerSkeleton.module.css"
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
count?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function RoomsContainerSkeleton({ count = 4 }: Props) {
|
||||||
|
const intl = await getIntl()
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.filterContainer}></div>
|
||||||
|
<div className={styles.skeletonContainer}>
|
||||||
|
{Array.from({ length: count }).map((_, index) => (
|
||||||
|
<RoomCardSkeleton key={index} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -82,6 +82,8 @@ export function getSiteConfigConnections(refs: GetSiteConfigRefData) {
|
|||||||
const siteConfigData = refs.all_site_config.items[0]
|
const siteConfigData = refs.all_site_config.items[0]
|
||||||
const connections: System["system"][] = []
|
const connections: System["system"][] = []
|
||||||
|
|
||||||
|
if (!siteConfigData) return connections
|
||||||
|
|
||||||
const alertConnection = siteConfigData.sitewide_alert.alertConnection
|
const alertConnection = siteConfigData.sitewide_alert.alertConnection
|
||||||
|
|
||||||
alertConnection.edges.forEach(({ node }) => {
|
alertConnection.edges.forEach(({ node }) => {
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import { create } from "zustand"
|
|
||||||
|
|
||||||
interface RoomAvailabilityState {
|
|
||||||
noRoomsAvailable: boolean
|
|
||||||
setNoRoomsAvailable: () => void
|
|
||||||
setRoomsAvailable: () => void
|
|
||||||
}
|
|
||||||
|
|
||||||
const useRoomAvailableStore = create<RoomAvailabilityState>((set) => ({
|
|
||||||
noRoomsAvailable: false,
|
|
||||||
setNoRoomsAvailable: () => set(() => ({ noRoomsAvailable: true })),
|
|
||||||
setRoomsAvailable: () => set(() => ({ noRoomsAvailable: false })),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export default useRoomAvailableStore
|
|
||||||
Reference in New Issue
Block a user