From b3d5326adbfdff6bae754fae800ecb43fde486b7 Mon Sep 17 00:00:00 2001 From: Hrishikesh Vaipurkar Date: Wed, 21 May 2025 12:27:11 +0000 Subject: [PATCH] Merged in feat/SW-1232-filter-improvements-select-hot (pull request #2168) feat: SW-1232 Implemented disabling of filters and show hotel count * feat: SW-1232 Implemented disabling of filters and show hotel count * feat: SW-1232 Optimised code Approved-by: Niclas Edenvin --- .../(standard)/select-hotel/utils.ts | 60 +-------------- .../FilterCheckbox/filterCheckbox.module.css | 9 +++ .../HotelFilter/FilterCheckbox/index.tsx | 2 + .../SelectHotel/HotelFilter/index.tsx | 76 ++++++++++++------- .../HotelReservation/SelectHotel/helpers.ts | 34 +++++++-- .../selectHotel/filterCheckbox.ts | 1 + .../selectHotel/hotelFilters.ts | 9 ++- 7 files changed, 95 insertions(+), 96 deletions(-) diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/utils.ts b/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/utils.ts index d54df6248..37e79043f 100644 --- a/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/utils.ts +++ b/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/utils.ts @@ -7,32 +7,9 @@ import type { AlternativeHotelsAvailabilityInput, AvailabilityInput, } from "@/types/components/hotelReservation/selectHotel/availabilityInput" -import type { - HotelData, - NullableHotelData, -} from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps" -import type { CategorizedFilters } from "@/types/components/hotelReservation/selectHotel/hotelFilters" -import type { DetailedFacility } from "@/types/hotel" +import type { NullableHotelData } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps" import type { HotelsAvailabilityItem } from "@/types/trpc/routers/hotel/availability" -const hotelSurroundingsFilterNames = [ - "Hotel surroundings", - "Hotel omgivelser", - "Hotelumgebung", - "Hotellia lähellä", - "Hotellomgivelser", - "Omgivningar", -] - -const hotelFacilitiesFilterNames = [ - "Hotel facilities", - "Hotellfaciliteter", - "Hotelfaciliteter", - "Hotel faciliteter", - "Hotel-Infos", - "Hotellin palvelut", -] - export async function fetchAvailableHotels( input: AvailabilityInput ): Promise { @@ -98,38 +75,3 @@ async function enhanceHotels(hotels: { return await Promise.all(hotelFetchers) } - -export function getFiltersFromHotels(hotels: HotelData[]): CategorizedFilters { - 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: DetailedFacility[] = uniqueFilterIds - .map((filterId) => filters.find((filter) => filter.id === filterId)) - .filter((filter): filter is DetailedFacility => filter !== undefined) - .sort((a, b) => b.sortOrder - a.sortOrder) - - return filterList.reduce( - (acc, filter) => { - if (filter.filter && hotelSurroundingsFilterNames.includes(filter.filter)) - return { - facilityFilters: acc.facilityFilters, - surroundingsFilters: [...acc.surroundingsFilters, filter], - } - - if (filter.filter && hotelFacilitiesFilterNames.includes(filter.filter)) - return { - facilityFilters: [...acc.facilityFilters, filter], - surroundingsFilters: acc.surroundingsFilters, - } - - return acc - }, - { facilityFilters: [], surroundingsFilters: [] } - ) -} diff --git a/apps/scandic-web/components/HotelReservation/SelectHotel/HotelFilter/FilterCheckbox/filterCheckbox.module.css b/apps/scandic-web/components/HotelReservation/SelectHotel/HotelFilter/FilterCheckbox/filterCheckbox.module.css index 3d1fb7ec7..b301a57b8 100644 --- a/apps/scandic-web/components/HotelReservation/SelectHotel/HotelFilter/FilterCheckbox/filterCheckbox.module.css +++ b/apps/scandic-web/components/HotelReservation/SelectHotel/HotelFilter/FilterCheckbox/filterCheckbox.module.css @@ -33,3 +33,12 @@ forced-color-adjust: none; background: var(--UI-Input-Controls-Surface-Normal); } + +.container[data-disabled] { + color: var(--Text-Interactive-Disabled); + cursor: not-allowed; +} +.container[data-disabled] .checkbox { + border-color: var(--Text-Interactive-Disabled); + background: var(--Surface-Primary-Disabled); +} diff --git a/apps/scandic-web/components/HotelReservation/SelectHotel/HotelFilter/FilterCheckbox/index.tsx b/apps/scandic-web/components/HotelReservation/SelectHotel/HotelFilter/FilterCheckbox/index.tsx index b8cfb0572..5938348b1 100644 --- a/apps/scandic-web/components/HotelReservation/SelectHotel/HotelFilter/FilterCheckbox/index.tsx +++ b/apps/scandic-web/components/HotelReservation/SelectHotel/HotelFilter/FilterCheckbox/index.tsx @@ -13,6 +13,7 @@ export default function FilterCheckbox({ isSelected, name, id, + isDisabled, onChange, }: FilterCheckboxProps) { return ( @@ -20,6 +21,7 @@ export default function FilterCheckbox({ className={styles.container} isSelected={isSelected} onChange={() => onChange(id)} + isDisabled={isDisabled} > {({ isSelected }) => ( <> diff --git a/apps/scandic-web/components/HotelReservation/SelectHotel/HotelFilter/index.tsx b/apps/scandic-web/components/HotelReservation/SelectHotel/HotelFilter/index.tsx index 3e6eab8e7..66a971041 100644 --- a/apps/scandic-web/components/HotelReservation/SelectHotel/HotelFilter/index.tsx +++ b/apps/scandic-web/components/HotelReservation/SelectHotel/HotelFilter/index.tsx @@ -14,7 +14,10 @@ import FilterCheckbox from "./FilterCheckbox" import styles from "./hotelFilter.module.css" -import type { HotelFiltersProps } from "@/types/components/hotelReservation/selectHotel/hotelFilters" +import type { + HotelFilter, + HotelFiltersProps, +} from "@/types/components/hotelReservation/selectHotel/hotelFilters" export default function HotelFilter({ className, filters }: HotelFiltersProps) { const intl = useIntl() @@ -49,6 +52,47 @@ export default function HotelFilter({ className, filters }: HotelFiltersProps) { return null } + let filteredHotelIds: string[] | undefined + if (activeFilters.length) { + const allFilters = [ + ...filters.facilityFilters, + ...filters.surroundingsFilters, + ] + filteredHotelIds = allFilters + .filter((f) => activeFilters.includes(f.id.toString())) + .map((f) => f.hotelIds) + .reduce((accumlatedHotelIds, currentHotelIds) => + accumlatedHotelIds?.filter((hotelId) => + currentHotelIds?.includes(hotelId) + ) + ) + } + + function filterOutput(filters: HotelFilter[]) { + return filters.map((filter) => { + const isDisabled = filteredHotelIds?.length + ? !filter.hotelIds?.some((hotelId) => + filteredHotelIds.includes(hotelId) + ) + : false + return ( +
  • + toggleFilter(filter.id.toString())} + isSelected={activeFilters.some((f) => f === filter.id.toString())} + isDisabled={isDisabled} + /> + {!isDisabled ? ( + // eslint-disable-next-line formatjs/no-literal-string-in-jsx + {`(${filteredHotelIds?.filter((id) => filter.hotelIds.includes(id))?.length ?? filter.hotelIds.length})`} + ) : null} +
  • + ) + }) + } + return ( diff --git a/apps/scandic-web/components/HotelReservation/SelectHotel/helpers.ts b/apps/scandic-web/components/HotelReservation/SelectHotel/helpers.ts index c990fc21e..5716a28dc 100644 --- a/apps/scandic-web/components/HotelReservation/SelectHotel/helpers.ts +++ b/apps/scandic-web/components/HotelReservation/SelectHotel/helpers.ts @@ -9,13 +9,16 @@ import type { AlternativeHotelsAvailabilityInput, AvailabilityInput, } from "@/types/components/hotelReservation/selectHotel/availabilityInput" -import type { CategorizedFilters } from "@/types/components/hotelReservation/selectHotel/hotelFilters" +import type { + CategorizedFilters, + HotelFilter, +} from "@/types/components/hotelReservation/selectHotel/hotelFilters" import { AvailabilityEnum } from "@/types/components/hotelReservation/selectHotel/selectHotel" import type { AlternativeHotelsSearchParams, SelectHotelSearchParams, } from "@/types/components/hotelReservation/selectHotel/selectHotelSearchParams" -import type { AdditionalData, DetailedFacility, Hotel } from "@/types/hotel" +import type { AdditionalData, Hotel } from "@/types/hotel" import type { HotelsAvailabilityItem } from "@/types/trpc/routers/hotel/availability" import type { HotelLocation, @@ -253,12 +256,31 @@ export function getFiltersFromHotels( return defaultFilters } - const filters = hotels.flatMap(({ hotel }) => hotel.detailedFacilities) + const filters = hotels.flatMap(({ hotel }) => + hotel.detailedFacilities.map( + (facility) => + { + ...facility, + hotelId: hotel.operaId, + hotelIds: [hotel.operaId], + } + ) + ) const uniqueFilterIds = [...new Set(filters.map((filter) => filter.id))] - const filterList: DetailedFacility[] = uniqueFilterIds - .map((filterId) => filters.find((filter) => filter.id === filterId)) - .filter((filter): filter is DetailedFacility => filter !== undefined) + const filterList: HotelFilter[] = uniqueFilterIds + .map((filterId) => { + const filter = filters.find((f) => f.id === filterId) + + // List and include all hotel Ids having same filter / amenity + if (filter) { + filter.hotelIds = filters + .filter((f) => f.id === filterId) + .map((f) => f.hotelId) + } + return filter + }) + .filter((filter): filter is HotelFilter => filter !== undefined) .sort((a, b) => b.sortOrder - a.sortOrder) return filterList.reduce((filters, filter) => { diff --git a/apps/scandic-web/types/components/hotelReservation/selectHotel/filterCheckbox.ts b/apps/scandic-web/types/components/hotelReservation/selectHotel/filterCheckbox.ts index 38045a1c1..23670912b 100644 --- a/apps/scandic-web/types/components/hotelReservation/selectHotel/filterCheckbox.ts +++ b/apps/scandic-web/types/components/hotelReservation/selectHotel/filterCheckbox.ts @@ -1,6 +1,7 @@ export type FilterCheckboxProps = { name: string id: string + isDisabled?: boolean isSelected: boolean onChange: (filterId: string) => void } diff --git a/apps/scandic-web/types/components/hotelReservation/selectHotel/hotelFilters.ts b/apps/scandic-web/types/components/hotelReservation/selectHotel/hotelFilters.ts index adab15ced..a485d585b 100644 --- a/apps/scandic-web/types/components/hotelReservation/selectHotel/hotelFilters.ts +++ b/apps/scandic-web/types/components/hotelReservation/selectHotel/hotelFilters.ts @@ -1,8 +1,13 @@ import type { Hotel } from "@/types/hotel" +export type HotelFilter = Hotel["detailedFacilities"][number] & { + hotelId: string + hotelIds: string[] +} + export type CategorizedFilters = { - facilityFilters: Hotel["detailedFacilities"] - surroundingsFilters: Hotel["detailedFacilities"] + facilityFilters: HotelFilter[] + surroundingsFilters: HotelFilter[] } export type HotelFiltersProps = { filters: CategorizedFilters