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:
Pontus Dreij
2024-11-20 13:46:43 +00:00
9 changed files with 78 additions and 53 deletions

View File

@@ -108,7 +108,7 @@ export default async function SelectRatePage({
roomsAvailability={roomsAvailability} roomsAvailability={roomsAvailability}
roomCategories={roomCategories ?? []} roomCategories={roomCategories ?? []}
user={user} user={user}
packages={packages ?? []} availablePackages={packages ?? []}
/> />
</> </>
) )

View File

@@ -99,11 +99,13 @@ export default function RoomFilter({
<form onSubmit={handleSubmit(submitFilter)}> <form onSubmit={handleSubmit(submitFilter)}>
<div className={styles.roomsFilter}> <div className={styles.roomsFilter}>
{filterOptions.map((option) => { {filterOptions.map((option) => {
const { code, description } = option const { code, description, itemCode } = option
const isPetRoom = code === RoomPackageCodeEnum.PET_ROOM const isPetRoom = code === RoomPackageCodeEnum.PET_ROOM
const isAllergyRoom = code === RoomPackageCodeEnum.ALLERGY_ROOM const isAllergyRoom = code === RoomPackageCodeEnum.ALLERGY_ROOM
const isDisabled = const isDisabled =
(isAllergyRoom && petFriendly) || (isPetRoom && allergyFriendly) (isAllergyRoom && petFriendly) ||
(isPetRoom && allergyFriendly) ||
!itemCode
const checkboxChip = ( const checkboxChip = (
<CheckboxChip <CheckboxChip

View File

@@ -14,7 +14,7 @@ export default function RoomSelection({
roomsAvailability, roomsAvailability,
roomCategories, roomCategories,
user, user,
packages, availablePackages,
selectedPackages, selectedPackages,
setRateSummary, setRateSummary,
rateSummary, rateSummary,
@@ -72,7 +72,7 @@ export default function RoomSelection({
roomCategories={roomCategories} roomCategories={roomCategories}
handleSelectRate={setRateSummary} handleSelectRate={setRateSummary}
selectedPackages={selectedPackages} selectedPackages={selectedPackages}
packages={packages} packages={availablePackages}
/> />
</li> </li>
))} ))}
@@ -81,7 +81,7 @@ export default function RoomSelection({
<RateSummary <RateSummary
rateSummary={rateSummary} rateSummary={rateSummary}
isUserLoggedIn={isUserLoggedIn} isUserLoggedIn={isUserLoggedIn}
packages={packages} packages={availablePackages}
roomsAvailability={roomsAvailability} roomsAvailability={roomsAvailability}
/> />
)} )}

View File

@@ -11,6 +11,7 @@ import { filterDuplicateRoomTypesByLowestPrice } from "./utils"
import styles from "./rooms.module.css" import styles from "./rooms.module.css"
import { import {
DefaultFilterOptions,
RoomPackageCodeEnum, RoomPackageCodeEnum,
type RoomPackageCodes, type RoomPackageCodes,
} from "@/types/components/hotelReservation/selectRate/roomFilter" } from "@/types/components/hotelReservation/selectRate/roomFilter"
@@ -25,7 +26,7 @@ export default function Rooms({
roomsAvailability, roomsAvailability,
roomCategories = [], roomCategories = [],
user, user,
packages, availablePackages,
}: SelectRateProps) { }: SelectRateProps) {
const visibleRooms: RoomConfiguration[] = const visibleRooms: RoomConfiguration[] =
filterDuplicateRoomTypesByLowestPrice(roomsAvailability.roomConfigurations) filterDuplicateRoomTypesByLowestPrice(roomsAvailability.roomConfigurations)
@@ -47,6 +48,30 @@ export default function Rooms({
(state) => state.setRoomsAvailable (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( const handleFilter = useCallback(
(filter: Record<RoomPackageCodeEnum, boolean | undefined>) => { (filter: Record<RoomPackageCodeEnum, boolean | undefined>) => {
const filteredPackages = Object.keys(filter).filter( const filteredPackages = Object.keys(filter).filter(
@@ -80,20 +105,10 @@ export default function Rooms({
room.features.some((feature) => feature.code === filteredPackage) 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({ setRooms({
...roomsAvailability, ...roomsAvailability,
roomConfigurations: [...filteredRooms, ...notAvailableRooms], roomConfigurations: [...filteredRooms],
}) })
if (filteredRooms.length == 0) { if (filteredRooms.length == 0) {
@@ -104,7 +119,9 @@ export default function Rooms({
const petRoomPackage = const petRoomPackage =
(filteredPackages.includes(RoomPackageCodeEnum.PET_ROOM) && (filteredPackages.includes(RoomPackageCodeEnum.PET_ROOM) &&
packages.find((pkg) => pkg.code === RoomPackageCodeEnum.PET_ROOM)) || availablePackages.find(
(pkg) => pkg.code === RoomPackageCodeEnum.PET_ROOM
)) ||
undefined undefined
const features = filteredRooms.find((room) => const features = filteredRooms.find((room) =>
@@ -124,7 +141,7 @@ export default function Rooms({
roomsAvailability, roomsAvailability,
visibleRooms, visibleRooms,
rateSummary, rateSummary,
packages, availablePackages,
noRoomsAvailable, noRoomsAvailable,
setNoRoomsAvailable, setNoRoomsAvailable,
setRoomsAvailable, setRoomsAvailable,
@@ -136,13 +153,13 @@ export default function Rooms({
<RoomFilter <RoomFilter
numberOfRooms={rooms.roomConfigurations.length} numberOfRooms={rooms.roomConfigurations.length}
onFilter={handleFilter} onFilter={handleFilter}
filterOptions={packages} filterOptions={defaultPackages}
/> />
<RoomSelection <RoomSelection
roomsAvailability={rooms} roomsAvailability={rooms}
roomCategories={roomCategories} roomCategories={roomCategories}
user={user} user={user}
packages={packages} availablePackages={availablePackages}
selectedPackages={selectedPackages} selectedPackages={selectedPackages}
setRateSummary={setRateSummary} setRateSummary={setRateSummary}
rateSummary={rateSummary} rateSummary={rateSummary}

View File

@@ -2,11 +2,13 @@
display: flex; display: flex;
align-items: center; align-items: center;
gap: var(--Spacing-x-half); 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: 1px solid var(--Base-Border-Subtle);
border-radius: var(--Corner-radius-Small); border-radius: var(--Corner-radius-Small);
background-color: var(--Base-Surface-Secondary-light-Normal); background-color: var(--Base-Surface-Secondary-light-Normal);
cursor: pointer; cursor: pointer;
height: 32px;
background-color: var(--Base-Surface-Secondary-light-Normal);
} }
.label[data-selected="true"], .label[data-selected="true"],
@@ -21,8 +23,9 @@
} }
.label[data-disabled="true"] { .label[data-disabled="true"] {
background-color: var(--Base-Button-Primary-Fill-Disabled); background-color: var(--UI-Input-Controls-Surface-Disabled);
border-color: var(--Base-Button-Primary-Fill-Disabled); border-color: var(--UI-Input-Controls-Border-Disabled);
color: var(--Base-Text-Disabled);
cursor: not-allowed; cursor: not-allowed;
} }

View File

@@ -864,22 +864,24 @@ export const packagesSchema = z.object({
export const getRoomPackagesSchema = z export const getRoomPackagesSchema = z
.object({ .object({
data: z.object({ data: z
attributes: z.object({ .object({
hotelId: z.number(), attributes: z.object({
packages: z.array(packagesSchema).optional().default([]), hotelId: z.number(),
}), packages: z.array(packagesSchema).optional().default([]),
relationships: z }),
.object({ relationships: z
links: z.array( .object({
z.object({ links: z.array(
url: z.string(), z.object({
type: z.string(), url: z.string(),
}) type: z.string(),
), })
}) ),
.optional(), })
type: z.string(), .optional(),
}), type: z.string(),
})
.optional(),
}) })
.transform((data) => data.data.attributes.packages) .transform((data) => data.data?.attributes?.packages ?? [])

View File

@@ -939,12 +939,10 @@ export const hotelQueryRouter = router({
"api.hotels.packages error", "api.hotels.packages error",
JSON.stringify({ query: { hotelId, params } }) JSON.stringify({ query: { hotelId, params } })
) )
throw serverErrorByStatus(apiResponse.status, apiResponse)
} }
const apiJson = await apiResponse.json() const apiJson = await apiResponse.json()
const validatedPackagesData = getRoomPackagesSchema.safeParse(apiJson) const validatedPackagesData = getRoomPackagesSchema.safeParse(apiJson)
if (!validatedPackagesData.success) { if (!validatedPackagesData.success) {
getHotelFailCounter.add(1, { getHotelFailCounter.add(1, {
hotelId, hotelId,

View File

@@ -1,19 +1,22 @@
import { z } from "zod" import { z } from "zod"
import { import { packagesSchema } from "@/server/routers/hotels/output"
getRoomPackagesSchema,
packagesSchema,
} from "@/server/routers/hotels/output"
export enum RoomPackageCodeEnum { export enum RoomPackageCodeEnum {
PET_ROOM = "PETR", PET_ROOM = "PETR",
ALLERGY_ROOM = "ALLG", ALLERGY_ROOM = "ALLG",
ACCESSIBILITY_ROOM = "ACCE", ACCESSIBILITY_ROOM = "ACCE",
} }
export interface DefaultFilterOptions {
code: RoomPackageCodeEnum
description: string
itemCode: string | undefined
}
export interface RoomFilterProps { export interface RoomFilterProps {
numberOfRooms: number numberOfRooms: number
onFilter: (filter: Record<string, boolean | undefined>) => void onFilter: (filter: Record<string, boolean | undefined>) => void
filterOptions: RoomPackageData filterOptions: DefaultFilterOptions[]
} }
export type RoomPackage = z.output<typeof packagesSchema> export type RoomPackage = z.output<typeof packagesSchema>

View File

@@ -8,7 +8,7 @@ export interface RoomSelectionProps {
roomsAvailability: RoomsAvailability roomsAvailability: RoomsAvailability
roomCategories: RoomData[] roomCategories: RoomData[]
user: SafeUser user: SafeUser
packages: RoomPackageData | undefined availablePackages: RoomPackageData | undefined
selectedPackages: RoomPackageCodes[] selectedPackages: RoomPackageCodes[]
setRateSummary: (rateSummary: Rate) => void setRateSummary: (rateSummary: Rate) => void
rateSummary: Rate | null rateSummary: Rate | null
@@ -18,5 +18,5 @@ export interface SelectRateProps {
roomsAvailability: RoomsAvailability roomsAvailability: RoomsAvailability
roomCategories: RoomData[] roomCategories: RoomData[]
user: SafeUser user: SafeUser
packages: RoomPackageData availablePackages: RoomPackageData
} }