"use client"; import { parseAsArrayOf, parseAsBoolean, parseAsInteger, parseAsString, parseAsStringLiteral, useQueryState, } from "nuqs"; import { createContext, type FC, type ReactNode, useContext, useMemo, useTransition, } from "react"; 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; minBudget: number | null; setMinBudget: ( value: number | ((old: number | null) => number | null) | null, ) => Promise; maxBudget: number | null; setMaxBudget: ( 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; 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; prezzo: 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( "m", parseAsBoolean.withDefault(false).withOptions({ startTransition }), ); const [tipo, setTipo] = useQueryState( "t", parseAsString.withDefault("").withOptions({ startTransition }), ); const [comune, setComune] = useQueryState( "c", parseAsString.withDefault("").withOptions({ startTransition }), ); const [consegna, setConsegna] = useQueryState( "f", parseAsArrayOf(parseAsInteger).withOptions({ startTransition }), ); const [minBudget, setMinBudget] = useQueryState( "bmin", parseAsInteger.withOptions({ startTransition }), ); const [maxBudget, setMaxBudget] = useQueryState( "bmax", parseAsInteger.withOptions({ startTransition }), ); const [sort, setSort] = useQueryState( "s", parseAsStringLiteral(sortOptions) .withDefault("Recenti") .withOptions({ startTransition }), ); const tipologieOptions = useMemo(() => { const set = new Set(); options.forEach((item) => { if (!comune || item.comune === comune) { if (!consegna || consegna.includes(item.consegna)) { if (!minBudget || item.prezzo >= minBudget) { if (!maxBudget || item.prezzo <= maxBudget) { set.add(item.tipo); } } } } }); return Array.from(set); }, [options, comune, consegna, minBudget, maxBudget]); const comuniOptions = useMemo(() => { const set = new Set(); options.forEach((item) => { if (!tipo || item.tipo === tipo) { if (!consegna || consegna.includes(item.consegna)) { if (!minBudget || item.prezzo >= minBudget) { if (!maxBudget || item.prezzo <= maxBudget) { set.add(item.comune); } } } } }); return Array.from(set).sort((a, b) => a.localeCompare(b)); }, [options, tipo, consegna, minBudget, maxBudget]); const consegnaOptions = useMemo(() => { const set = new Set(); options.forEach((item) => { if (!tipo || item.tipo === tipo) { if (!comune || item.comune === comune) { if (!minBudget || item.prezzo >= minBudget) { if (!maxBudget || item.prezzo <= maxBudget) { set.add(item.consegna); } } } } }); const currentMonth = new Date().getMonth() + 1; // 1-12 return Array.from(set).sort((a, b) => { // Calculate distance from current month (wrapping around) const distA = (a - currentMonth + 12) % 12; const distB = (b - currentMonth + 12) % 12; return distA - distB; }); }, [options, tipo, comune, minBudget, maxBudget]); const ResetParams = async () => { await setTipo(""); await setComune(""); await setConsegna(null); await setMinBudget(null); await setMaxBudget(null); await setSort("Recenti"); }; const nFiltri = [tipo, comune].reduce( (count, item) => (item !== "" ? count + 1 : count), 0, ) + (consegna !== null ? 1 : 0) + (sort !== "Recenti" ? 1 : 0) + (minBudget !== null ? 1 : 0) + (maxBudget !== null ? 1 : 0); return ( {children} ); };