refactor: enhance AdminLavoraConferma component with GeneralSection and improve form handling in AnnuncioEditForm

This commit is contained in:
Marco Pedone 2025-12-16 16:43:42 +01:00
parent 4ce60fd827
commit c783dfed03
4 changed files with 194 additions and 35 deletions

View file

@ -12,6 +12,8 @@ import { useState } from "react";
import toast from "react-hot-toast";
import { useDebounce } from "react-use";
import z from "zod";
import { it } from "~/i18n/it";
import { handleConsegna } from "~/lib/annuncio_details";
import { formatCurrency } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import { useServizio, useServizioAnnuncio } from "~/providers/ServizioProvider";
@ -19,6 +21,7 @@ import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
import type { UsersStorageUserStorageId } from "~/schemas/public/UsersStorage";
import { api } from "~/utils/api";
import { Confirm } from "../confirm";
import { Counter } from "../counter";
import {
Credenza,
CredenzaBody,
@ -548,6 +551,12 @@ const TransitorioSection = () => {
});
};
const preferenzeDescrizione = data.desc_it?.match(/Permanenza:.*$/m);
const permanenzaAnnuncio = data.permanenza
? `${data.permanenza.join(" - ")} mesi`
: (preferenzeDescrizione?.[0] ??
"errore: testo non trovato in descrizione");
return (
<div className="flex flex-col gap-2">
<div className="max-w-sm">
@ -575,10 +584,8 @@ const TransitorioSection = () => {
/>
</div>
<p>
<span className="font-semibold">Permanenza in descrizione: </span>
{preferenzeDescrizione
? preferenzeDescrizione[0]
: "errore: testo non trovato in descrizione"}
<span className="font-semibold">Permanenza in annuncio: </span>
{permanenzaAnnuncio}
</p>
</div>
);
@ -639,6 +646,131 @@ const StabileSection = () => {
);
};
const GeneralSection = () => {
const { servizio } = useServizio();
const { data } = useServizioAnnuncio();
const { t } = useTranslation();
const { servizioId, userId } = useServizio();
const utils = api.useUtils();
const { mutate: update } = api.servizio.updateServizio.useMutation({
onError: (error) => {
toast.error(error.message);
},
onSuccess: async () => {
toast.success("Servizio modificato con successo");
await utils.servizio.getUserServizi.invalidate();
await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
},
});
const handleDisponibilitàChange = (value: ListOption) => {
update({
servizioId,
data: {
entromese: value.value !== "" ? parseInt(value.value) : null,
},
});
};
const handleAdultiChange = (value: number) => {
update({
servizioId,
data: {
n_adulti: value,
},
});
};
const handleMinoriChange = (value: number) => {
update({
servizioId,
data: {
n_minori: value,
},
});
};
const personeDescrizione = data.desc_it?.match(/Preferenza:.*$/m);
const personeAnnuncio = data.persone
? data.persone.join(", ").toUpperCase()
: (personeDescrizione?.[0] ?? "errore: testo non trovato in descrizione");
const dispAnnuncio = data.disponibile_da
? format(new Date(data.disponibile_da), "dd/MM/yyyy")
: handleConsegna({
consegna: data.consegna,
aggiornamento: it.card.in_aggiornamento,
consegna_da: it.card.consegna_da,
mesi: it.preferenze.mesi,
subito: it.card.consegna_subito,
});
return (
<>
<div className="flex flex-col gap-2">
<span className="font-semibold">Persone:</span>
<div className="flex w-full gap-4">
<div className="flex w-1/2 flex-col gap-2">
<Label htmlFor="n_adulti">{t.preferenze.nadulti_label}</Label>
<Counter
name="n_adulti"
onlyPositive
setValue={(v) => handleAdultiChange(Number(v))}
value={servizio.n_adulti || 0}
/>
</div>
<div className="flex w-1/2 flex-col gap-2">
<Label htmlFor="n_minori">{t.preferenze.nminori_label}</Label>
<Counter
name="n_minori"
onlyPositive
setValue={(v) => handleMinoriChange(Number(v))}
value={servizio.n_minori || 0}
/>
</div>
</div>
<p>
<span className="font-semibold">Persone in annuncio: </span>
{personeAnnuncio}
</p>
</div>
<div className="flex flex-col gap-2">
<span className="font-semibold">Entro mese:</span>
<div className="max-w-sm">
<Label htmlFor="select-mesi">{t.preferenze.dalmese_label}</Label>
<MultiSelect
defaultValue={
servizio.entromese !== null
? {
// biome-ignore lint/style/noNonNullAssertion: <known size>
label: t.preferenze.mesi[servizio.entromese]!,
value: String(servizio.entromese),
}
: undefined
}
elementId="select-mesi"
elementName="entro_mese"
isMulti={false}
onValueChange={handleDisponibilitàChange}
options={UnpackOptions({
options: t.preferenze.mesi,
})}
placeholder="Seleziona..."
/>
</div>
<p>
<span className="font-semibold">Disponibilità in annuncio: </span>
{dispAnnuncio}
</p>
</div>
</>
);
};
const SendConferma = () => {
const { servizio } = useServizio();
const { data } = useServizioAnnuncio();
@ -667,7 +799,7 @@ const SendConferma = () => {
</CardDescription>
</CardHeader>
<CardContent className="space-y-10">
<div className="flex flex-col gap-2">
<div className="flex flex-col gap-4">
<p>
<span className="font-semibold">Tipologia servizio: </span>
{servizio.tipologia}
@ -677,6 +809,7 @@ const SendConferma = () => {
) : (
<StabileSection />
)}
<GeneralSection />
</div>
<div className="flex items-center gap-3">
<Switch

View file

@ -1041,11 +1041,25 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
name="disponibile_da"
render={({ field }) => (
<FormItem>
<div className="flex flex-wrap items-center gap-x-2">
<div className="relative flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="disponibile_da">
Disponibile Da
</FormLabel>
<FormMessage />
{field.value !== null && (
<Button
className="-top-2 absolute right-0 flex items-center gap-1"
onClick={() => {
form.setValue("disponibile_da", null);
}}
size="sm"
type="button"
variant="link"
>
<RotateCw className="size-4" />
Reset
</Button>
)}
</div>
<Popover>
<PopoverTrigger asChild>
@ -1096,7 +1110,14 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
<FormField
control={form.control}
name="consegna"
render={({ field }) => (
render={({ field: { value, onChange } }) => {
const currVal =
value !== null
? consegnaOptions.filter(
(o) => value.toString() === o.value,
)[0]
: undefined;
return (
<FormItem>
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="select-consegna">
@ -1107,25 +1128,20 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
<FormControl>
<MultiSelect
defaultValue={
field.value
? consegnaOptions.filter((o) =>
field.value?.toString().includes(o.value),
)
: undefined
}
defaultValue={currVal}
elementId="select-consegna"
elementName="consegna"
isMulti={false}
onValueChange={async (value) => {
field.onChange(parseInt(value.value));
onChange(parseInt(value.value));
}}
options={consegnaOptions}
placeholder="Seleziona..."
/>
</FormControl>
</FormItem>
)}
);
}}
/>
}
children2={

View file

@ -14,6 +14,10 @@ export const handleConsegna = ({
aggiornamento: string;
}) => {
const currentMonth = new Date().getMonth() + 1;
console.log("handleConsegna", {
consegna: consegna,
currentMonth: currentMonth,
});
if (consegna !== null) {
if (consegna !== currentMonth) {
return `${mesi[consegna]}`;

View file

@ -635,6 +635,9 @@ export const getAllServizioAnnunci = async (userId: UsersId) => {
"servizio.skipPayment",
"servizio.skipControlloDoc",
"servizio.skipDocMotivazione",
"servizio.n_adulti",
"servizio.n_minori",
"servizio.entromese",
jsonObjectFrom(
eb
.selectFrom("users_storage")
@ -699,6 +702,9 @@ export const getAllServizioAnnunci = async (userId: UsersId) => {
"annunci.media_updated_at",
"annunci.homepage",
"annunci.web",
"annunci.disponibile_da",
"annunci.persone",
"annunci.permanenza",
withImages(),
withVideos(),
])