fix(SW-978) Checks for null data on hotels
This commit is contained in:
@@ -14,6 +14,7 @@ import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import { fetchAvailableHotels, getFiltersFromHotels } from "../../utils"
|
||||
|
||||
import { HotelData } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
|
||||
import type { SelectHotelSearchParams } from "@/types/components/hotelReservation/selectHotel/selectHotelSearchParams"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
@@ -52,11 +53,15 @@ export default async function SelectHotelMapPage({
|
||||
children,
|
||||
})
|
||||
|
||||
const hotelPins = getHotelPins(hotels)
|
||||
const filterList = getFiltersFromHotels(hotels)
|
||||
const validHotels = hotels.filter(
|
||||
(hotel): hotel is HotelData => hotel !== null
|
||||
)
|
||||
|
||||
const hotelPins = getHotelPins(validHotels)
|
||||
const filterList = getFiltersFromHotels(validHotels)
|
||||
const cityCoordinates = await getCityCoordinates({
|
||||
city: city.name,
|
||||
hotel: { address: hotels[0].hotelData.address.streetAddress },
|
||||
hotel: { address: hotels?.[0]?.hotelData?.address.streetAddress },
|
||||
})
|
||||
|
||||
return (
|
||||
@@ -65,7 +70,7 @@ export default async function SelectHotelMapPage({
|
||||
apiKey={googleMapsApiKey}
|
||||
hotelPins={hotelPins}
|
||||
mapId={googleMapId}
|
||||
hotels={hotels}
|
||||
hotels={validHotels}
|
||||
filterList={filterList}
|
||||
cityCoordinates={cityCoordinates}
|
||||
/>
|
||||
|
||||
@@ -33,6 +33,7 @@ import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import styles from "./page.module.css"
|
||||
|
||||
import { 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"
|
||||
@@ -82,7 +83,11 @@ export default async function SelectHotelPage({
|
||||
children,
|
||||
})
|
||||
|
||||
const filterList = getFiltersFromHotels(hotels)
|
||||
const validHotels = hotels.filter(
|
||||
(hotel): hotel is HotelData => hotel !== null
|
||||
)
|
||||
|
||||
const filterList = getFiltersFromHotels(validHotels)
|
||||
const breadcrumbs = [
|
||||
{
|
||||
title: intl.formatMessage({ id: "Home" }),
|
||||
@@ -177,7 +182,7 @@ export default async function SelectHotelPage({
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
<HotelCardListing hotelData={hotels} />
|
||||
<HotelCardListing hotelData={validHotels} />
|
||||
</div>
|
||||
</main>
|
||||
</>
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import { getHotelData } from "@/lib/trpc/memoizedRequests"
|
||||
import { serverClient } from "@/lib/trpc/server"
|
||||
import { badRequestError } from "@/server/errors/trpc"
|
||||
|
||||
import { getLang } from "@/i18n/serverContext"
|
||||
|
||||
import type { AvailabilityInput } from "@/types/components/hotelReservation/selectHotel/availabilityInput"
|
||||
import type { HotelData } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
|
||||
import type {
|
||||
HotelData,
|
||||
NullableHotelData,
|
||||
} from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
|
||||
import type {
|
||||
CategorizedFilters,
|
||||
Filter,
|
||||
@@ -30,10 +34,10 @@ const hotelFacilitiesFilterNames = [
|
||||
|
||||
export async function fetchAvailableHotels(
|
||||
input: AvailabilityInput
|
||||
): Promise<HotelData[]> {
|
||||
): Promise<NullableHotelData[]> {
|
||||
const availableHotels = await serverClient().hotel.availability.hotels(input)
|
||||
|
||||
if (!availableHotels) throw new Error()
|
||||
if (!availableHotels) return []
|
||||
|
||||
const language = getLang()
|
||||
|
||||
@@ -43,7 +47,7 @@ export async function fetchAvailableHotels(
|
||||
language,
|
||||
})
|
||||
|
||||
if (!hotelData) throw new Error()
|
||||
if (!hotelData) return { hotelData: null, price: hotel.productType }
|
||||
|
||||
return {
|
||||
hotelData: hotelData.data.attributes,
|
||||
@@ -55,7 +59,13 @@ export async function fetchAvailableHotels(
|
||||
}
|
||||
|
||||
export function getFiltersFromHotels(hotels: HotelData[]): CategorizedFilters {
|
||||
const filters = hotels.flatMap((hotel) => hotel.hotelData.detailedFacilities)
|
||||
if (hotels.length === 0)
|
||||
return { facilityFilters: [], surroundingsFilters: [] }
|
||||
|
||||
const filters = hotels.flatMap((hotel) => {
|
||||
if (!hotel.hotelData) return []
|
||||
return hotel.hotelData.detailedFacilities
|
||||
})
|
||||
|
||||
const uniqueFilterIds = [...new Set(filters.map((filter) => filter.id))]
|
||||
const filterList: Filter[] = uniqueFilterIds
|
||||
|
||||
@@ -41,18 +41,11 @@ function HotelCard({
|
||||
const { hotelData } = hotel
|
||||
const { price } = hotel
|
||||
|
||||
const amenities = hotelData.detailedFacilities.slice(0, 5)
|
||||
|
||||
const classNames = hotelCardVariants({
|
||||
type,
|
||||
state,
|
||||
})
|
||||
|
||||
const handleMouseEnter = useCallback(() => {
|
||||
if (onHotelCardHover) {
|
||||
if (onHotelCardHover && hotelData) {
|
||||
onHotelCardHover(hotelData.name)
|
||||
}
|
||||
}, [onHotelCardHover, hotelData.name])
|
||||
}, [onHotelCardHover, hotelData])
|
||||
|
||||
const handleMouseLeave = useCallback(() => {
|
||||
if (onHotelCardHover) {
|
||||
@@ -60,6 +53,15 @@ function HotelCard({
|
||||
}
|
||||
}, [onHotelCardHover])
|
||||
|
||||
if (!hotel || !hotelData) return null
|
||||
|
||||
const amenities = hotelData.detailedFacilities.slice(0, 5)
|
||||
|
||||
const classNames = hotelCardVariants({
|
||||
type,
|
||||
state,
|
||||
})
|
||||
|
||||
return (
|
||||
<article
|
||||
className={classNames}
|
||||
@@ -82,8 +84,8 @@ function HotelCard({
|
||||
<section className={styles.hotelInformation}>
|
||||
<div className={styles.titleContainer}>
|
||||
<HotelLogo
|
||||
hotelId={hotel.hotelData.operaId}
|
||||
hotelType={hotel.hotelData.hotelType}
|
||||
hotelId={hotelData.operaId}
|
||||
hotelType={hotelData.hotelType}
|
||||
/>
|
||||
<Subtitle textTransform="capitalize" color="uiTextHighContrast">
|
||||
{hotelData.name}
|
||||
|
||||
@@ -17,7 +17,7 @@ export default function HotelCardDialogListing({
|
||||
activeCard,
|
||||
onActiveCardChange,
|
||||
}: HotelCardDialogListingProps) {
|
||||
const hotelsPinData = getHotelPins(hotels)
|
||||
const hotelsPinData = hotels ? getHotelPins(hotels) : []
|
||||
const activeCardRef = useRef<HTMLDivElement | null>(null)
|
||||
const observerRef = useRef<IntersectionObserver | null>(null)
|
||||
const dialogRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
@@ -2,6 +2,8 @@ import type { HotelData } from "@/types/components/hotelReservation/selectHotel/
|
||||
import type { HotelPin } from "@/types/components/hotelReservation/selectHotel/map"
|
||||
|
||||
export function getHotelPins(hotels: HotelData[]): HotelPin[] {
|
||||
if (hotels.length === 0) return []
|
||||
|
||||
return hotels.map((hotel) => ({
|
||||
coordinates: {
|
||||
lat: hotel.hotelData.location.latitude,
|
||||
|
||||
@@ -144,7 +144,7 @@ export const getBookingConfirmation = cache(
|
||||
export const getCityCoordinates = cache(
|
||||
async function getMemoizedCityCoordinates(input: {
|
||||
city: string
|
||||
hotel: { address: string }
|
||||
hotel: { address: string | undefined }
|
||||
}) {
|
||||
return serverClient().hotel.map.city(input)
|
||||
}
|
||||
|
||||
@@ -77,6 +77,6 @@ export const getRoomPackagesInputSchema = z.object({
|
||||
export const getCityCoordinatesInputSchema = z.object({
|
||||
city: z.string(),
|
||||
hotel: z.object({
|
||||
address: z.string(),
|
||||
address: z.string().optional(),
|
||||
}),
|
||||
})
|
||||
|
||||
@@ -18,3 +18,7 @@ export type HotelData = {
|
||||
hotelData: Hotel
|
||||
price: ProductType
|
||||
}
|
||||
|
||||
export interface NullableHotelData extends Omit<HotelData, "hotelData"> {
|
||||
hotelData: HotelData["hotelData"] | null
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ export interface HotelCardDialogProps {
|
||||
}
|
||||
|
||||
export interface HotelCardDialogListingProps {
|
||||
hotels: HotelData[]
|
||||
hotels: HotelData[] | null
|
||||
activeCard: string | null | undefined
|
||||
onActiveCardChange: (hotelName: string | null) => void
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user