Merged in feat/sw-620-sort-hotels (pull request #868)
Feat/sw-620 sort hotels * SW-620 Add radio button to select box * feat(SW-620): Implement sorting on select hotel * Fix casing * Shallow copy hoteldata * Use translations * Remove unnecessary style * Import order * Type Approved-by: Pontus Dreij
This commit is contained in:
@@ -5,6 +5,7 @@ import { useMemo } from "react"
|
||||
import Title from "@/components/TempDesignSystem/Text/Title"
|
||||
|
||||
import HotelCard from "../HotelCard"
|
||||
import { DEFAULT_SORT } from "../SelectHotel/HotelSorter"
|
||||
|
||||
import styles from "./hotelCardListing.module.css"
|
||||
|
||||
@@ -12,6 +13,7 @@ import {
|
||||
type HotelCardListingProps,
|
||||
HotelCardListingTypeEnum,
|
||||
} from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
|
||||
import { SortOrder } from "@/types/components/hotelReservation/selectHotel/hotelSorter"
|
||||
|
||||
export default function HotelCardListing({
|
||||
hotelData,
|
||||
@@ -21,25 +23,58 @@ export default function HotelCardListing({
|
||||
}: HotelCardListingProps) {
|
||||
const searchParams = useSearchParams()
|
||||
|
||||
const sortBy = useMemo(
|
||||
() => searchParams.get("sort") ?? DEFAULT_SORT,
|
||||
[searchParams]
|
||||
)
|
||||
|
||||
const sortedHotels = useMemo(() => {
|
||||
switch (sortBy) {
|
||||
case SortOrder.Name:
|
||||
return [...hotelData].sort((a, b) =>
|
||||
a.hotelData.name.localeCompare(b.hotelData.name)
|
||||
)
|
||||
case SortOrder.TripAdvisorRating:
|
||||
return [...hotelData].sort(
|
||||
(a, b) =>
|
||||
(b.hotelData.ratings?.tripAdvisor.rating ?? 0) -
|
||||
(a.hotelData.ratings?.tripAdvisor.rating ?? 0)
|
||||
)
|
||||
case SortOrder.Price:
|
||||
return [...hotelData].sort(
|
||||
(a, b) =>
|
||||
parseInt(a.price?.memberAmount ?? "0", 10) -
|
||||
parseInt(b.price?.memberAmount ?? "0", 10)
|
||||
)
|
||||
case SortOrder.Distance:
|
||||
default:
|
||||
return [...hotelData].sort(
|
||||
(a, b) =>
|
||||
a.hotelData.location.distanceToCentre -
|
||||
b.hotelData.location.distanceToCentre
|
||||
)
|
||||
}
|
||||
}, [hotelData, sortBy])
|
||||
|
||||
const hotels = useMemo(() => {
|
||||
const appliedFilters = searchParams.get("filters")?.split(",")
|
||||
if (!appliedFilters || appliedFilters.length === 0) return hotelData
|
||||
if (!appliedFilters || appliedFilters.length === 0) return sortedHotels
|
||||
|
||||
return hotelData.filter((hotel) =>
|
||||
return sortedHotels.filter((hotel) =>
|
||||
appliedFilters.every((appliedFilterId) =>
|
||||
hotel.hotelData.detailedFacilities.some(
|
||||
(facility) => facility.id.toString() === appliedFilterId
|
||||
)
|
||||
)
|
||||
)
|
||||
}, [searchParams, hotelData])
|
||||
}, [searchParams, sortedHotels])
|
||||
|
||||
return (
|
||||
<section className={styles.hotelCards}>
|
||||
{hotels?.length ? (
|
||||
hotels.map((hotel) => (
|
||||
<HotelCard
|
||||
key={hotel.hotelData.name}
|
||||
key={hotel.hotelData.operaId}
|
||||
hotel={hotel}
|
||||
type={type}
|
||||
state={hotel.hotelData.name === activeCard ? "active" : "default"}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
"use client"
|
||||
|
||||
import { usePathname, useSearchParams } from "next/navigation"
|
||||
import { useCallback } from "react"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import Select from "@/components/TempDesignSystem/Select"
|
||||
|
||||
import {
|
||||
type SortItem,
|
||||
SortOrder,
|
||||
} from "@/types/components/hotelReservation/selectHotel/hotelSorter"
|
||||
|
||||
const sortItems: SortItem[] = [
|
||||
{ label: "Distance", value: SortOrder.Distance },
|
||||
{ label: "Name", value: SortOrder.Name },
|
||||
{ label: "Price", value: SortOrder.Price },
|
||||
{ label: "TripAdvisor rating", value: SortOrder.TripAdvisorRating },
|
||||
]
|
||||
|
||||
export const DEFAULT_SORT = SortOrder.Distance
|
||||
|
||||
export default function HotelSorter() {
|
||||
const searchParams = useSearchParams()
|
||||
const pathname = usePathname()
|
||||
const i18n = useIntl()
|
||||
|
||||
const onSelect = useCallback(
|
||||
(value: string | number) => {
|
||||
const newSort = value.toString()
|
||||
if (newSort === searchParams.get("sort")) {
|
||||
return
|
||||
}
|
||||
|
||||
const newSearchParams = new URLSearchParams(searchParams)
|
||||
newSearchParams.set("sort", newSort)
|
||||
|
||||
window.history.replaceState(
|
||||
null,
|
||||
"",
|
||||
`${pathname}?${newSearchParams.toString()}`
|
||||
)
|
||||
},
|
||||
[pathname, searchParams]
|
||||
)
|
||||
|
||||
return (
|
||||
<Select
|
||||
items={sortItems}
|
||||
label={i18n.formatMessage({ id: "Sort by" })}
|
||||
name="sort"
|
||||
showRadioButton
|
||||
onSelect={onSelect}
|
||||
/>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user