refactor: update consegna handling to support multiple values and adjust related components

This commit is contained in:
Marco Pedone 2025-12-29 18:33:00 +01:00
parent 2082ea2c62
commit c6b325368a
6 changed files with 112 additions and 38 deletions

View file

@ -50,7 +50,7 @@ const MapDisplay = memo(
}: { }: {
selectTipo: string; selectTipo: string;
selectComune: string; selectComune: string;
selectConsegna: number | null; selectConsegna: number[] | null;
setSelected: Dispatch<SetStateAction<AnnuncioRicercaWPosition | null>>; setSelected: Dispatch<SetStateAction<AnnuncioRicercaWPosition | null>>;
}) => { }) => {
const { data, isLoading } = api.annunci.getMapping.useQuery({ const { data, isLoading } = api.annunci.getMapping.useQuery({

View file

@ -289,7 +289,7 @@ export const it: LangDict = {
Faqs.come_confermare, Faqs.come_confermare,
], ],
comune: "Comune", comune: "Comune",
consegna: "Consegna", consegna: "Disponibile da",
filtri_attivi: "Filtri attivi", filtri_attivi: "Filtri attivi",
filtri_reset: "Reset filtri", filtri_reset: "Reset filtri",
filtro_attivo: "Filtro attivo", filtro_attivo: "Filtro attivo",

View file

@ -123,21 +123,14 @@ const Filters = () => {
setTipo, setTipo,
comune, comune,
setComune, setComune,
consegna,
setConsegna,
sort, sort,
setSort, setSort,
comuniOptions, comuniOptions,
tipologieOptions, tipologieOptions,
consegnaOptions,
ResetParams, ResetParams,
nFiltri, nFiltri,
} = useRicerca(); } = useRicerca();
const mappedConsegnaOptions = useMemo(
// biome-ignore lint/style/noNonNullAssertion: <known lenght>
() => consegnaOptions.map((m) => t.parametri.mesi[m]!).filter(Boolean),
[consegnaOptions, t.parametri.mesi],
);
return ( return (
<> <>
<SelectFilter <SelectFilter
@ -166,7 +159,8 @@ const Filters = () => {
placeholder={t.seleziona_placeholder} placeholder={t.seleziona_placeholder}
value={comune} value={comune}
/> />
<SelectFilter <ConsegnaFilter />
{/* <SelectFilter
defaultValue={""} defaultValue={""}
handleReset={async () => { handleReset={async () => {
await setConsegna(null); await setConsegna(null);
@ -187,7 +181,7 @@ const Filters = () => {
options={mappedConsegnaOptions} options={mappedConsegnaOptions}
placeholder={t.seleziona_placeholder} placeholder={t.seleziona_placeholder}
value={consegna ? t.parametri.mesi[consegna] || "" : ""} value={consegna ? t.parametri.mesi[consegna] || "" : ""}
/> /> */}
<SelectFilter <SelectFilter
defaultValue={sort} defaultValue={sort}
handleReset={async () => { handleReset={async () => {
@ -274,7 +268,7 @@ const RicercaHeader = () => {
<div className="flex w-full items-center gap-2 sm:w-auto"> <div className="flex w-full items-center gap-2 sm:w-auto">
<DrowdownFilters /> <DrowdownFilters />
<Button <Button
className="flex w-fit flex-row items-center gap-2" className="flex w-fit flex-row items-center gap-2 md:w-24"
onClick={async () => { onClick={async () => {
await setMap((v) => !v); await setMap((v) => !v);
}} }}
@ -416,3 +410,78 @@ export const SelectFilter = <T extends string>({
</div> </div>
); );
}; };
const ConsegnaFilter = () => {
const { t } = useTranslation();
const {
consegna: consegna2,
setConsegna: setConsegna2,
consegnaOptions,
} = useRicerca();
const mappedConsegnaOptions = useMemo(() => {
if (consegnaOptions.length === 0) return [];
return consegnaOptions
.map((c) =>
t.parametri.mesi[c] ? { value: c, label: t.parametri.mesi[c] } : null,
)
.filter((v) => v !== null);
}, [consegnaOptions, t.parametri.mesi]);
const onValueChange = async (value: number) => {
if (consegna2?.includes(value)) {
// Remove value
const newConsegna2 = consegna2.filter((c) => c !== value);
await setConsegna2(newConsegna2.length > 0 ? newConsegna2 : null);
return;
}
// Add value
const newConsegna2 = consegna2 ? [...consegna2, value] : [value];
await setConsegna2(newConsegna2);
return;
};
return (
<div className="flex flex-col gap-2">
<div className="flex h-4 flex-row gap-4 px-1">
<Label
className={cn(
"font-semibold text-muted-foreground",
consegna2 !== null && consegna2.length > 0 && "text-primary",
)}
>
{t.annunci.consegna}
</Label>
{consegna2 !== null && consegna2.length > 0 && (
<button
className="cursor-pointer"
onClick={async () => {
await setConsegna2(null);
}}
type="button"
>
<RotateCcwIcon className="size-4" />
</button>
)}
</div>
<div className="flex flex-wrap gap-1 rounded-md bg-background p-1">
{mappedConsegnaOptions.map(({ value, label }) => (
<Button
className={cn(
consegna2?.includes(value) && "border border-primary",
)}
key={value}
onClick={async () => {
await onValueChange(value);
}}
size="sm"
variant={consegna2?.includes(value) ? "default" : "outline"}
>
<span className="text-sm">{label.substring(0, 3)}</span>
</Button>
))}
</div>
</div>
);
};

View file

@ -1,5 +1,6 @@
"use client"; "use client";
import { import {
parseAsArrayOf,
parseAsBoolean, parseAsBoolean,
parseAsInteger, parseAsInteger,
parseAsString, parseAsString,
@ -28,9 +29,10 @@ type RicercaContextType = {
setComune: ( setComune: (
value: string | ((old: string) => string | null) | null, value: string | ((old: string) => string | null) | null,
) => Promise<URLSearchParams>; ) => Promise<URLSearchParams>;
consegna: number | null;
consegna: number[] | null;
setConsegna: ( setConsegna: (
value: number | ((old: number | null) => number | null) | null, value: number[] | ((old: number[] | null) => number[] | null) | null,
) => Promise<URLSearchParams>; ) => Promise<URLSearchParams>;
sort: SortTypes; sort: SortTypes;
setSort: ( setSort: (
@ -88,7 +90,7 @@ export const RicercaProvider: FC<{
); );
const [consegna, setConsegna] = useQueryState( const [consegna, setConsegna] = useQueryState(
"consegna", "consegna",
parseAsInteger.withOptions({ startTransition }), parseAsArrayOf(parseAsInteger).withOptions({ startTransition }),
); );
const [sort, setSort] = useQueryState( const [sort, setSort] = useQueryState(
"sort", "sort",
@ -101,7 +103,7 @@ export const RicercaProvider: FC<{
const set = new Set<string>(); const set = new Set<string>();
options.forEach((item) => { options.forEach((item) => {
if (!comune || item.comune === comune) { if (!comune || item.comune === comune) {
if (!consegna || item.consegna === consegna) { if (!consegna || consegna.includes(item.consegna)) {
set.add(item.tipo); set.add(item.tipo);
} }
} }
@ -113,7 +115,7 @@ export const RicercaProvider: FC<{
const set = new Set<string>(); const set = new Set<string>();
options.forEach((item) => { options.forEach((item) => {
if (!tipo || item.tipo === tipo) { if (!tipo || item.tipo === tipo) {
if (!consegna || item.consegna === consegna) { if (!consegna || consegna.includes(item.consegna)) {
set.add(item.comune); set.add(item.comune);
} }
} }
@ -159,24 +161,27 @@ export const RicercaProvider: FC<{
<RicercaContext.Provider <RicercaContext.Provider
value={{ value={{
comune, comune,
comuniOptions,
consegna,
consegnaOptions,
isLoading,
map,
nFiltri,
ResetParams,
setComune, setComune,
comuniOptions,
consegna,
setConsegna, setConsegna,
consegnaOptions,
tipo,
setTipo,
tipologieOptions,
sort,
setSort,
sortOptions: sortOptions,
map,
setMap, setMap,
setSort, nFiltri,
setTipo, isLoading,
sort, ResetParams,
sortOptions: sortOptions,
tipo,
tipologieOptions,
}} }}
> >
{children} {children}

View file

@ -71,7 +71,7 @@ export const annunciRouter = createTRPCRouter({
.input( .input(
z.object({ z.object({
comune: z.string().optional(), comune: z.string().optional(),
consegna: z.number().optional(), consegna: z.number().array().optional(),
tipologia: z.string().optional(), tipologia: z.string().optional(),
}), }),
) )
@ -94,7 +94,7 @@ export const annunciRouter = createTRPCRouter({
.input( .input(
z.object({ z.object({
comune: z.string().optional(), comune: z.string().optional(),
consegna: z.number().optional(), consegna: z.number().array().optional(),
sort: z.enum(["Recenti", "Prezzo", "Consegna", "Mq"]).optional(), sort: z.enum(["Recenti", "Prezzo", "Consegna", "Mq"]).optional(),
tipologia: z.string().optional(), tipologia: z.string().optional(),
}), }),

View file

@ -180,7 +180,7 @@ export const get_AnnunciPositionsHandler = async ({
}: { }: {
tipologia?: string; tipologia?: string;
comune?: string; comune?: string;
consegna?: number; consegna?: number[];
}): Promise<AnnuncioRicercaWPosition[]> => { }): Promise<AnnuncioRicercaWPosition[]> => {
try { try {
let query = db let query = db
@ -222,7 +222,7 @@ export const get_AnnunciPositionsHandler = async ({
query = query.where("comune", "like", comune); query = query.where("comune", "like", comune);
} }
if (consegna) { if (consegna) {
query = query.where("consegna", "=", consegna); query = query.where("consegna", "in", consegna);
} }
const annunci = await query.execute(); const annunci = await query.execute();
@ -273,7 +273,7 @@ export const getAnnunciRicerca = async ({
}: { }: {
tipologia?: string; tipologia?: string;
comune?: string; comune?: string;
consegna?: number; consegna?: number[];
sort?: "Recenti" | "Prezzo" | "Consegna" | "Mq"; sort?: "Recenti" | "Prezzo" | "Consegna" | "Mq";
}): Promise<AnnuncioRicerca[]> => { }): Promise<AnnuncioRicerca[]> => {
try { try {
@ -313,7 +313,7 @@ export const getAnnunciRicerca = async ({
query = query.where("comune", "like", comune); query = query.where("comune", "like", comune);
} }
if (consegna) { if (consegna) {
query = query.where("consegna", "=", consegna); query = query.where("consegna", "in", consegna);
} }
switch (sort) { switch (sort) {