186 lines
4.4 KiB
TypeScript
186 lines
4.4 KiB
TypeScript
"use client";
|
|
import {
|
|
createContext,
|
|
useContext,
|
|
useMemo,
|
|
useTransition,
|
|
type FC,
|
|
type ReactNode,
|
|
} 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: (
|
|
value: number | ((old: number | null) => number | null) | null,
|
|
) => Promise<URLSearchParams>;
|
|
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] = useQueryState(
|
|
"p",
|
|
parseAsInteger.withDefault(0).withOptions({ clearOnDefault: true }),
|
|
);
|
|
|
|
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("");
|
|
await 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,
|
|
|
|
ResetParams,
|
|
nFiltri,
|
|
isLoading,
|
|
}}
|
|
>
|
|
{children}
|
|
</RicercaContext.Provider>
|
|
);
|
|
};
|