Merged in feat/SW-1451-country-page-sorting (pull request #1426)

Feat/SW-1451 country page filtering and sorting

* feat(SW-1451): implemented sorting and filtering on country pages

* feat(SW-1451): Renamed hotel-data to destination-data because of its multi-purpose use

* feat(SW-1451): Now filtering after change of url instead of inside the store after submit


Approved-by: Fredrik Thorsson
This commit is contained in:
Erik Tiekstra
2025-02-28 06:30:16 +00:00
parent 747201b0f7
commit bee6c6d83a
69 changed files with 1124 additions and 531 deletions

View File

@@ -0,0 +1,39 @@
import { useParams } from "next/navigation"
import { useEffect } from "react"
import { useDestinationDataStore } from "@/stores/destination-data"
export default function DestinationDataProviderContent({
children,
}: React.PropsWithChildren) {
const params = useParams()
const { basePath, updateActiveFiltersAndSort } = useDestinationDataStore(
(state) => ({
basePath: state.basePathnameWithoutFilters,
updateActiveFiltersAndSort: state.actions.updateActiveFiltersAndSort,
})
)
useEffect(() => {
const currentUrl = new URL(window.location.href)
const searchParams = currentUrl.searchParams
const currentPathname = currentUrl.pathname
const currentHash = currentUrl.hash
const sort = searchParams.get("sort")
const filters = []
const pathParts = currentPathname.split("/")
const lastPathPart = pathParts[pathParts.length - 1]
if (basePath !== currentPathname) {
filters.push(lastPathPart)
}
if (currentHash) {
const hashValue = currentHash.substring(1)
filters.push(...hashValue.split("&"))
}
updateActiveFiltersAndSort(filters, sort)
}, [params, updateActiveFiltersAndSort, basePath])
return <>{children}</>
}

View File

@@ -0,0 +1,39 @@
"use client"
import { usePathname } from "next/navigation"
import { useRef } from "react"
import { createDestinationDataStore } from "@/stores/destination-data"
import { DestinationDataContext } from "@/contexts/DestinationData"
import DestinationDataProviderContent from "./Content"
import type { DestinationDataStore } from "@/types/contexts/destination-data"
import type { DestinationDataProviderProps } from "@/types/providers/destination-data"
export default function DestinationDataProvider({
allCities = [],
allHotels,
sortItems,
children,
}: DestinationDataProviderProps) {
const storeRef = useRef<DestinationDataStore>()
const pathname = usePathname()
if (!storeRef.current) {
storeRef.current = createDestinationDataStore({
allCities,
allHotels,
pathname,
sortItems,
})
}
return (
<DestinationDataContext.Provider value={storeRef.current}>
<DestinationDataProviderContent>
{children}
</DestinationDataProviderContent>
</DestinationDataContext.Provider>
)
}

View File

@@ -1,65 +0,0 @@
"use client"
import { usePathname, useRouter, useSearchParams } from "next/navigation"
import { useRef } from "react"
import { createHotelDataStore } from "@/stores/hotel-data"
import { DEFAULT_SORT } from "@/stores/hotel-data/helper"
import { HotelDataContext } from "@/contexts/HotelData"
import type { HotelDataStore } from "@/types/contexts/hotel-data"
import type { HotelDataProviderProps } from "@/types/providers/hotel-data"
import type { SubmitCallbackData } from "@/types/stores/hotel-data"
export default function HotelDataProvider({
allHotels,
filterFromUrl,
sortItems,
children,
}: HotelDataProviderProps) {
const storeRef = useRef<HotelDataStore>()
const searchParams = useSearchParams()
const pathname = usePathname()
const router = useRouter()
function submitCallbackFn({ sort, filters, basePath }: SubmitCallbackData) {
const parsedUrl = new URL(window.location.href)
const searchParams = parsedUrl.searchParams
if (sort === DEFAULT_SORT && searchParams.has("sort")) {
searchParams.delete("sort")
} else if (sort !== DEFAULT_SORT) {
searchParams.set("sort", sort)
}
const [firstFilter, ...remainingFilters] = filters
parsedUrl.pathname = basePath
if (firstFilter) {
parsedUrl.pathname += `/${firstFilter}`
}
if (remainingFilters.length > 0) {
parsedUrl.hash = `#${remainingFilters.join("&")}`
} else {
parsedUrl.hash = ""
}
router.push(parsedUrl.toString(), { scroll: false })
}
if (!storeRef.current) {
storeRef.current = createHotelDataStore({
allHotels,
pathname,
searchParams,
filterFromUrl,
sortItems,
submitCallbackFn,
})
}
return (
<HotelDataContext.Provider value={storeRef.current}>
{children}
</HotelDataContext.Provider>
)
}