useProductFilters
unknown
typescript
a year ago
1.8 kB
22
Indexable
import { usePathname, useRouter } from "next/navigation"
import { useCallback, useEffect, useMemo, useState } from "react"
interface ProductFilters {
search: string | null
category: string | null
rating: [number, number] | null
maxPrice: number | null
}
type FilterKey = keyof ProductFilters
type FilterValue = string | number | [number, number] | null
const initFilters: ProductFilters = {
search: null,
category: null,
rating: null,
maxPrice: null,
}
const parseFilterValue = (value: FilterValue): string | null => {
if (value === null) {
return null
}
if (typeof value === "string") {
return value
}
if (typeof value === "number") {
return value.toString()
}
if (
Array.isArray(value) &&
value.length === 2 &&
typeof value[0] === "number" &&
typeof value[1] === "number"
) {
return `${value[0]} - ${value[1]}`
}
return null
}
export default function useProductFilters() {
const router = useRouter()
const pathname = usePathname()
const [filters, setFilters] = useState<ProductFilters>(initFilters)
const params = useMemo(() => {
const params = new URLSearchParams()
for (const key of Object.keys(filters)) {
const value = parseFilterValue(filters[key as FilterKey])
if (!!value) {
params.set(key, value)
} else {
params.delete(key)
}
}
return params
}, [filters])
const setFilter = <K extends FilterKey>(
key: K,
value: ProductFilters[K]
): void => {
setFilters((filters) => ({ ...filters, [key]: value }))
}
const getFilter = useCallback(
<K extends FilterKey>(key: K): ProductFilters[K] => {
return filters[key]
},
[filters]
)
return { setFilter, getFilter }
}
Editor is loading...
Leave a Comment