"use client"; import { createContext, useContext, useMemo, useState, useTransition, type Dispatch, type FC, type ReactNode, type SetStateAction, } from "react"; import { parseAsBoolean, parseAsInteger, parseAsString, parseAsStringLiteral, useQueryState, } from "nuqs"; type RicercaContextType = { map: boolean; setMap: ( value: boolean | ((old: boolean) => boolean | null) | null, ) => Promise; tipo: string; setTipo: ( value: string | ((old: string) => string | null) | null, ) => Promise; comune: string; setComune: ( value: string | ((old: string) => string | null) | null, ) => Promise; consegna: number | null; setConsegna: ( value: number | ((old: number | null) => number | null) | null, ) => Promise; sort: SortTypes; setSort: ( value: SortTypes | ((old: SortTypes) => SortTypes | null) | null, ) => Promise; comuniOptions: string[]; tipologieOptions: string[]; consegnaOptions: number[]; sortOptions: typeof sortOptions; page: number; setPage: Dispatch>; lastPageCount: number; setlastPageCount: Dispatch>; ResetParams: () => Promise; nFiltri: number; isLoading: boolean; }; const sortOptions = ["Recenti", "Prezzo", "Consegna", "Mq", ""] as const; //sort as string union export type SortTypes = (typeof sortOptions)[number]; export type AnnunciOptions = { comune: string; tipo: string; consegna: number; }[]; const RicercaContext = createContext(undefined); export const useRicerca = () => { const context = useContext(RicercaContext); if (!context) { throw new Error("useRicerca must be used within a RicercaProvider"); } return context; }; export const RicercaProvider: FC<{ children: ReactNode; options: AnnunciOptions; }> = ({ children, options }) => { const [isLoading, startTransition] = useTransition(); const [map, setMap] = useQueryState( "map", parseAsBoolean.withDefault(false).withOptions({ startTransition }), ); const [tipo, setTipo] = useQueryState( "tipo", parseAsString.withDefault("").withOptions({ startTransition }), ); const [comune, setComune] = useQueryState( "comune", parseAsString.withDefault("").withOptions({ startTransition }), ); const [consegna, setConsegna] = useQueryState( "consegna", parseAsInteger.withOptions({ startTransition }), ); const [sort, setSort] = useQueryState( "sort", parseAsStringLiteral(sortOptions) .withDefault("") .withOptions({ startTransition }), ); const [page, setPage] = useState(0); const [lastPageCount, setlastPageCount] = useState(100); const tipologieOptions = useMemo(() => { const set = new Set(); options.forEach((item) => { if (!comune || item.comune === comune) { if (!consegna || item.consegna === consegna) { set.add(item.tipo); } } }); return Array.from(set); }, [options, comune, consegna]); const comuniOptions = useMemo(() => { const set = new Set(); options.forEach((item) => { if (!tipo || item.tipo === tipo) { if (!consegna || item.consegna === consegna) { set.add(item.comune); } } }); return Array.from(set); }, [options, tipo, consegna]); const consegnaOptions = useMemo(() => { const set = new Set(); options.forEach((item) => { if (!tipo || item.tipo === tipo) { if (!comune || item.comune === comune) { set.add(item.consegna); } } }); return Array.from(set); }, [options, tipo, comune]); const ResetParams = async () => { await setTipo(""); await setComune(""); await setConsegna(null); await setSort(""); setPage(0); }; const nFiltri = [tipo, comune, sort].reduce( (count, item) => (item !== "" ? count + 1 : count), 0, ) + (consegna !== null ? 1 : 0); return ( {children} ); };