Merged in fix/SW-925-select-rate-page-public-rates (pull request #937)
fix(SW-925): Don't throw error if api for packages throws error Approved-by: Niclas Edenvin
This commit is contained in:
@@ -108,7 +108,7 @@ export default async function SelectRatePage({
|
||||
roomsAvailability={roomsAvailability}
|
||||
roomCategories={roomCategories ?? []}
|
||||
user={user}
|
||||
packages={packages ?? []}
|
||||
availablePackages={packages ?? []}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -99,11 +99,13 @@ export default function RoomFilter({
|
||||
<form onSubmit={handleSubmit(submitFilter)}>
|
||||
<div className={styles.roomsFilter}>
|
||||
{filterOptions.map((option) => {
|
||||
const { code, description } = option
|
||||
const { code, description, itemCode } = option
|
||||
const isPetRoom = code === RoomPackageCodeEnum.PET_ROOM
|
||||
const isAllergyRoom = code === RoomPackageCodeEnum.ALLERGY_ROOM
|
||||
const isDisabled =
|
||||
(isAllergyRoom && petFriendly) || (isPetRoom && allergyFriendly)
|
||||
(isAllergyRoom && petFriendly) ||
|
||||
(isPetRoom && allergyFriendly) ||
|
||||
!itemCode
|
||||
|
||||
const checkboxChip = (
|
||||
<CheckboxChip
|
||||
|
||||
@@ -14,7 +14,7 @@ export default function RoomSelection({
|
||||
roomsAvailability,
|
||||
roomCategories,
|
||||
user,
|
||||
packages,
|
||||
availablePackages,
|
||||
selectedPackages,
|
||||
setRateSummary,
|
||||
rateSummary,
|
||||
@@ -72,7 +72,7 @@ export default function RoomSelection({
|
||||
roomCategories={roomCategories}
|
||||
handleSelectRate={setRateSummary}
|
||||
selectedPackages={selectedPackages}
|
||||
packages={packages}
|
||||
packages={availablePackages}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
@@ -81,7 +81,7 @@ export default function RoomSelection({
|
||||
<RateSummary
|
||||
rateSummary={rateSummary}
|
||||
isUserLoggedIn={isUserLoggedIn}
|
||||
packages={packages}
|
||||
packages={availablePackages}
|
||||
roomsAvailability={roomsAvailability}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { filterDuplicateRoomTypesByLowestPrice } from "./utils"
|
||||
import styles from "./rooms.module.css"
|
||||
|
||||
import {
|
||||
DefaultFilterOptions,
|
||||
RoomPackageCodeEnum,
|
||||
type RoomPackageCodes,
|
||||
} from "@/types/components/hotelReservation/selectRate/roomFilter"
|
||||
@@ -25,7 +26,7 @@ export default function Rooms({
|
||||
roomsAvailability,
|
||||
roomCategories = [],
|
||||
user,
|
||||
packages,
|
||||
availablePackages,
|
||||
}: SelectRateProps) {
|
||||
const visibleRooms: RoomConfiguration[] =
|
||||
filterDuplicateRoomTypesByLowestPrice(roomsAvailability.roomConfigurations)
|
||||
@@ -47,6 +48,30 @@ export default function Rooms({
|
||||
(state) => state.setRoomsAvailable
|
||||
)
|
||||
|
||||
const defaultPackages: DefaultFilterOptions[] = [
|
||||
{
|
||||
code: RoomPackageCodeEnum.ACCESSIBILITY_ROOM,
|
||||
description: "Accessible Room",
|
||||
itemCode: availablePackages.find(
|
||||
(pkg) => pkg.code === RoomPackageCodeEnum.ACCESSIBILITY_ROOM
|
||||
)?.itemCode,
|
||||
},
|
||||
{
|
||||
code: RoomPackageCodeEnum.ALLERGY_ROOM,
|
||||
description: "Allergy Room",
|
||||
itemCode: availablePackages.find(
|
||||
(pkg) => pkg.code === RoomPackageCodeEnum.ALLERGY_ROOM
|
||||
)?.itemCode,
|
||||
},
|
||||
{
|
||||
code: RoomPackageCodeEnum.PET_ROOM,
|
||||
description: "Pet Room",
|
||||
itemCode: availablePackages.find(
|
||||
(pkg) => pkg.code === RoomPackageCodeEnum.PET_ROOM
|
||||
)?.itemCode,
|
||||
},
|
||||
]
|
||||
|
||||
const handleFilter = useCallback(
|
||||
(filter: Record<RoomPackageCodeEnum, boolean | undefined>) => {
|
||||
const filteredPackages = Object.keys(filter).filter(
|
||||
@@ -80,20 +105,10 @@ export default function Rooms({
|
||||
room.features.some((feature) => feature.code === filteredPackage)
|
||||
)
|
||||
)
|
||||
let notAvailableRooms = visibleRooms.filter((room) =>
|
||||
filteredPackages.every(
|
||||
(filteredPackage) =>
|
||||
!room.features.some((feature) => feature.code === filteredPackage)
|
||||
)
|
||||
)
|
||||
// Clone nested object to keep original object intact and not messup the room data
|
||||
notAvailableRooms = JSON.parse(JSON.stringify(notAvailableRooms))
|
||||
notAvailableRooms.forEach((room) => {
|
||||
room.status = "NotAvailable"
|
||||
})
|
||||
|
||||
setRooms({
|
||||
...roomsAvailability,
|
||||
roomConfigurations: [...filteredRooms, ...notAvailableRooms],
|
||||
roomConfigurations: [...filteredRooms],
|
||||
})
|
||||
|
||||
if (filteredRooms.length == 0) {
|
||||
@@ -104,7 +119,9 @@ export default function Rooms({
|
||||
|
||||
const petRoomPackage =
|
||||
(filteredPackages.includes(RoomPackageCodeEnum.PET_ROOM) &&
|
||||
packages.find((pkg) => pkg.code === RoomPackageCodeEnum.PET_ROOM)) ||
|
||||
availablePackages.find(
|
||||
(pkg) => pkg.code === RoomPackageCodeEnum.PET_ROOM
|
||||
)) ||
|
||||
undefined
|
||||
|
||||
const features = filteredRooms.find((room) =>
|
||||
@@ -124,7 +141,7 @@ export default function Rooms({
|
||||
roomsAvailability,
|
||||
visibleRooms,
|
||||
rateSummary,
|
||||
packages,
|
||||
availablePackages,
|
||||
noRoomsAvailable,
|
||||
setNoRoomsAvailable,
|
||||
setRoomsAvailable,
|
||||
@@ -136,13 +153,13 @@ export default function Rooms({
|
||||
<RoomFilter
|
||||
numberOfRooms={rooms.roomConfigurations.length}
|
||||
onFilter={handleFilter}
|
||||
filterOptions={packages}
|
||||
filterOptions={defaultPackages}
|
||||
/>
|
||||
<RoomSelection
|
||||
roomsAvailability={rooms}
|
||||
roomCategories={roomCategories}
|
||||
user={user}
|
||||
packages={packages}
|
||||
availablePackages={availablePackages}
|
||||
selectedPackages={selectedPackages}
|
||||
setRateSummary={setRateSummary}
|
||||
rateSummary={rateSummary}
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--Spacing-x-half);
|
||||
padding: var(--Spacing-x1) var(--Spacing-x-one-and-half);
|
||||
padding: calc(var(--Spacing-x1) - 2px) var(--Spacing-x-one-and-half);
|
||||
border: 1px solid var(--Base-Border-Subtle);
|
||||
border-radius: var(--Corner-radius-Small);
|
||||
background-color: var(--Base-Surface-Secondary-light-Normal);
|
||||
cursor: pointer;
|
||||
height: 32px;
|
||||
background-color: var(--Base-Surface-Secondary-light-Normal);
|
||||
}
|
||||
|
||||
.label[data-selected="true"],
|
||||
@@ -21,8 +23,9 @@
|
||||
}
|
||||
|
||||
.label[data-disabled="true"] {
|
||||
background-color: var(--Base-Button-Primary-Fill-Disabled);
|
||||
border-color: var(--Base-Button-Primary-Fill-Disabled);
|
||||
background-color: var(--UI-Input-Controls-Surface-Disabled);
|
||||
border-color: var(--UI-Input-Controls-Border-Disabled);
|
||||
color: var(--Base-Text-Disabled);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
|
||||
@@ -864,22 +864,24 @@ export const packagesSchema = z.object({
|
||||
|
||||
export const getRoomPackagesSchema = z
|
||||
.object({
|
||||
data: z.object({
|
||||
attributes: z.object({
|
||||
hotelId: z.number(),
|
||||
packages: z.array(packagesSchema).optional().default([]),
|
||||
}),
|
||||
relationships: z
|
||||
.object({
|
||||
links: z.array(
|
||||
z.object({
|
||||
url: z.string(),
|
||||
type: z.string(),
|
||||
})
|
||||
),
|
||||
})
|
||||
.optional(),
|
||||
type: z.string(),
|
||||
}),
|
||||
data: z
|
||||
.object({
|
||||
attributes: z.object({
|
||||
hotelId: z.number(),
|
||||
packages: z.array(packagesSchema).optional().default([]),
|
||||
}),
|
||||
relationships: z
|
||||
.object({
|
||||
links: z.array(
|
||||
z.object({
|
||||
url: z.string(),
|
||||
type: z.string(),
|
||||
})
|
||||
),
|
||||
})
|
||||
.optional(),
|
||||
type: z.string(),
|
||||
})
|
||||
.optional(),
|
||||
})
|
||||
.transform((data) => data.data.attributes.packages)
|
||||
.transform((data) => data.data?.attributes?.packages ?? [])
|
||||
|
||||
@@ -939,12 +939,10 @@ export const hotelQueryRouter = router({
|
||||
"api.hotels.packages error",
|
||||
JSON.stringify({ query: { hotelId, params } })
|
||||
)
|
||||
throw serverErrorByStatus(apiResponse.status, apiResponse)
|
||||
}
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
const validatedPackagesData = getRoomPackagesSchema.safeParse(apiJson)
|
||||
|
||||
if (!validatedPackagesData.success) {
|
||||
getHotelFailCounter.add(1, {
|
||||
hotelId,
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import {
|
||||
getRoomPackagesSchema,
|
||||
packagesSchema,
|
||||
} from "@/server/routers/hotels/output"
|
||||
import { packagesSchema } from "@/server/routers/hotels/output"
|
||||
|
||||
export enum RoomPackageCodeEnum {
|
||||
PET_ROOM = "PETR",
|
||||
ALLERGY_ROOM = "ALLG",
|
||||
ACCESSIBILITY_ROOM = "ACCE",
|
||||
}
|
||||
|
||||
export interface DefaultFilterOptions {
|
||||
code: RoomPackageCodeEnum
|
||||
description: string
|
||||
itemCode: string | undefined
|
||||
}
|
||||
export interface RoomFilterProps {
|
||||
numberOfRooms: number
|
||||
onFilter: (filter: Record<string, boolean | undefined>) => void
|
||||
filterOptions: RoomPackageData
|
||||
filterOptions: DefaultFilterOptions[]
|
||||
}
|
||||
|
||||
export type RoomPackage = z.output<typeof packagesSchema>
|
||||
|
||||
@@ -8,7 +8,7 @@ export interface RoomSelectionProps {
|
||||
roomsAvailability: RoomsAvailability
|
||||
roomCategories: RoomData[]
|
||||
user: SafeUser
|
||||
packages: RoomPackageData | undefined
|
||||
availablePackages: RoomPackageData | undefined
|
||||
selectedPackages: RoomPackageCodes[]
|
||||
setRateSummary: (rateSummary: Rate) => void
|
||||
rateSummary: Rate | null
|
||||
@@ -18,5 +18,5 @@ export interface SelectRateProps {
|
||||
roomsAvailability: RoomsAvailability
|
||||
roomCategories: RoomData[]
|
||||
user: SafeUser
|
||||
packages: RoomPackageData
|
||||
availablePackages: RoomPackageData
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user