Merged in feat/SW-338-filter-sort-ui (pull request #896)

Feat/SW-338 design filters and sorting on select hotel

* feat(SW-338): design hotel sort dropdown

* Translations

* feat(SW-338): style filters

* Bold

* Import type

* Translations

* Rename and add translation

* Rename translation


Approved-by: Bianca Widstam
This commit is contained in:
Niclas Edenvin
2024-11-15 07:18:30 +00:00
parent a6a0b0cf15
commit 18d40120b9
20 changed files with 159 additions and 71 deletions

View File

@@ -104,7 +104,7 @@ export default function HotelCard({
</div>
<Caption color="uiTextPlaceholder">
{intl.formatMessage(
{ id: "Distance to city centre" },
{ id: "Distance in km to city centre" },
{ number: hotelData.location.distanceToCentre }
)}
</Caption>

View File

@@ -31,7 +31,7 @@ export default function HotelSelectionHeader({
</div>
<Caption color="textMediumContrast">
{intl.formatMessage(
{ id: "Distance to city centre" },
{ id: "Distance in km to city centre" },
{ number: hotel.location.distanceToCentre }
)}
</Caption>

View File

@@ -3,16 +3,30 @@
display: none;
}
.container form {
display: flex;
flex-direction: column;
gap: var(--Spacing-x3);
}
.facilities {
font-family: var(--typography-Body-Bold-fontFamily);
margin-bottom: var(--Spacing-x3);
padding-bottom: var(--Spacing-x3);
}
.facilities:first-of-type {
border-bottom: 1px solid var(--Base-Border-Subtle);
}
.facilities ul {
margin-top: var(--Spacing-x2);
}
.filter {
display: grid;
grid-template-columns: repeat(2, minmax(min-content, max-content));
gap: var(--Spacing-x-one-and-half);
margin-bottom: var(--Spacing-x-one-and-half);
margin-bottom: var(--Spacing-x1);
align-items: center;
}

View File

@@ -2,26 +2,29 @@
import { usePathname, useSearchParams } from "next/navigation"
import { useCallback, useEffect } from "react"
import { useForm } from "react-hook-form"
import { FormProvider, useForm } from "react-hook-form"
import { useIntl } from "react-intl"
import Checkbox from "@/components/TempDesignSystem/Form/Checkbox"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import Title from "@/components/TempDesignSystem/Text/Title"
import styles from "./hotelFilter.module.css"
import { HotelFiltersProps } from "@/types/components/hotelReservation/selectHotel/hotelFilters"
import type { HotelFiltersProps } from "@/types/components/hotelReservation/selectHotel/hotelFilters"
export default function HotelFilter({ filters }: HotelFiltersProps) {
const intl = useIntl()
const searchParams = useSearchParams()
const pathname = usePathname()
const { watch, handleSubmit, getValues, register } = useForm<
Record<string, boolean | undefined>
>({
const methods = useForm<Record<string, boolean | undefined>>({
defaultValues: searchParams
?.get("filters")
?.split(",")
.reduce((acc, curr) => ({ ...acc, [curr]: true }), {}),
})
const { watch, handleSubmit, getValues, register } = methods
const submitFilter = useCallback(() => {
const newSearchParams = new URLSearchParams(searchParams)
@@ -52,41 +55,36 @@ export default function HotelFilter({ filters }: HotelFiltersProps) {
return (
<aside className={styles.container}>
<div className={styles.facilities}>
<FormProvider {...methods}>
<form onSubmit={handleSubmit(submitFilter)}>
{intl.formatMessage({ id: "Hotel facilities" })}
<ul>
{filters.facilityFilters.map((filter) => (
<li key={`li-${filter.id}`} className={styles.filter}>
<input
type="checkbox"
id={`checkbox-${filter.id.toString()}`}
{...register(filter.id.toString())}
/>
<label htmlFor={`checkbox-${filter.id.toString()}`}>
{filter.name}
</label>
</li>
))}
</ul>
<Title as="h4">{intl.formatMessage({ id: "Filter by" })}</Title>
<div className={styles.facilities}>
<Subtitle>
{intl.formatMessage({ id: "Hotel facilities" })}
</Subtitle>
<ul>
{filters.facilityFilters.map((filter) => (
<li key={`li-${filter.id}`} className={styles.filter}>
<Checkbox name={filter.id.toString()}>{filter.name}</Checkbox>
</li>
))}
</ul>
</div>
{intl.formatMessage({ id: "Hotel surroundings" })}
<ul>
{filters.surroundingsFilters.map((filter) => (
<li key={`li-${filter.id}`} className={styles.filter}>
<input
type="checkbox"
id={`checkbox-${filter.id.toString()}`}
{...register(filter.id.toString())}
/>
<label htmlFor={`checkbox-${filter.id.toString()}`}>
{filter.name}
</label>
</li>
))}
</ul>
<div className={styles.facilities}>
<Subtitle>
{intl.formatMessage({ id: "Hotel surroundings" })}
</Subtitle>
<ul>
{filters.surroundingsFilters.map((filter) => (
<li key={`li-${filter.id}`} className={styles.filter}>
<Checkbox name={filter.id.toString()}>{filter.name}</Checkbox>
</li>
))}
</ul>
</div>
</form>
</div>
</FormProvider>
</aside>
)
}

View File

@@ -0,0 +1,3 @@
.container {
width: 339px;
}

View File

@@ -6,24 +6,19 @@ import { useIntl } from "react-intl"
import Select from "@/components/TempDesignSystem/Select"
import styles from "./hotelSorter.module.css"
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 intl = useIntl()
const onSelect = useCallback(
(value: string | number) => {
@@ -43,14 +38,30 @@ export default function HotelSorter() {
},
[pathname, searchParams]
)
const sortItems: SortItem[] = [
{
label: intl.formatMessage({ id: "Distance to city center" }),
value: SortOrder.Distance,
},
{ label: intl.formatMessage({ id: "Name" }), value: SortOrder.Name },
{ label: intl.formatMessage({ id: "Price" }), value: SortOrder.Price },
{
label: intl.formatMessage({ id: "TripAdvisor rating" }),
value: SortOrder.TripAdvisorRating,
},
]
return (
<Select
items={sortItems}
label={i18n.formatMessage({ id: "Sort by" })}
name="sort"
showRadioButton
onSelect={onSelect}
/>
<div className={styles.container}>
<Select
items={sortItems}
defaultSelectedKey={searchParams.get("sort") ?? DEFAULT_SORT}
label={intl.formatMessage({ id: "Sort by" })}
name="sort"
showRadioButton
discreet
onSelect={onSelect}
/>
</div>
)
}