infoalloggi-monorepo/apps/infoalloggi/src/providers/RicercaProvider.tsx

190 lines
4.5 KiB
TypeScript
Raw Normal View History

2025-08-04 17:45:44 +02:00
"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<URLSearchParams>;
tipo: string;
setTipo: (
value: string | ((old: string) => string | null) | null,
) => Promise<URLSearchParams>;
comune: string;
setComune: (
value: string | ((old: string) => string | null) | null,
) => Promise<URLSearchParams>;
consegna: number | null;
setConsegna: (
value: number | ((old: number | null) => number | null) | null,
) => Promise<URLSearchParams>;
sort: SortTypes;
setSort: (
value: SortTypes | ((old: SortTypes) => SortTypes | null) | null,
) => Promise<URLSearchParams>;
comuniOptions: string[];
tipologieOptions: string[];
consegnaOptions: number[];
sortOptions: typeof sortOptions;
page: number;
setPage: Dispatch<SetStateAction<number>>;
lastPageCount: number;
setlastPageCount: Dispatch<SetStateAction<number>>;
ResetParams: () => Promise<void>;
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<RicercaContextType | undefined>(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<string>();
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<string>();
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<number>();
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 (
<RicercaContext.Provider
value={{
map,
setMap,
tipo,
setTipo,
comune,
setComune,
consegna,
setConsegna,
sort,
setSort,
comuniOptions,
tipologieOptions,
consegnaOptions,
sortOptions: sortOptions,
page,
setPage,
lastPageCount,
setlastPageCount,
ResetParams,
nFiltri,
isLoading,
}}
>
{children}
</RicercaContext.Provider>
);
};