import { format } from "date-fns";
import {
CircleCheck,
ClipboardPaste,
FlaskConical,
Pen,
Trash2,
Wrench,
} from "lucide-react";
import Link from "next/link";
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";
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,
CredenzaClose,
CredenzaContent,
CredenzaDescription,
CredenzaFooter,
CredenzaHeader,
CredenzaTitle,
CredenzaTrigger,
} from "../custom_ui/credenza";
import { NumberInput } from "../custom_ui/InputNumber";
import {
type ListOption,
MultiSelect,
UnpackOptions,
} from "../custom_ui/multiselect";
import { LoadingPage } from "../loading";
import { Button } from "../ui/button";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "../ui/card";
import { Label } from "../ui/label";
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
import { Switch } from "../ui/switch";
import { UploadModal } from "../upload_modal";
import { ServizioPacksInfos } from "./servizio_actions";
import { DocCombo, DocInfo } from "./shared";
export const AdminLavoraConferma = () => {
const { servizio } = useServizio();
const { data } = useServizioAnnuncio();
return (
Lavorazione conferma
Consegna status modal
{servizio.tipologia === TipologiaPosizioneEnum.Transitorio && (
)}
);
};
const DebugActions = () => {
const { servizioId, userId } = useServizio();
const { annuncioId } = useServizioAnnuncio();
const utils = api.useUtils();
const { mutate } = api.servizio.updateServizioAnnunci.useMutation({
onError: (error) => {
toast.error(error.message);
},
onSuccess: async () => {
await utils.servizio.getAllServizioAnnunci.invalidate({
userId: userId,
});
await utils.servizio.getServizio.invalidate({
servizioId,
});
toast.success("Dati salvati con successo");
},
});
return (
{
mutate({
annuncioId,
servizioId,
data: {
user_confirmed_at: null,
},
});
}}
title="Elimina annuncio"
>
);
};
const DocSection = () => {
const { userId } = useServizio();
const { data, updateServizioAnnunci } = useServizioAnnuncio();
const utils = api.useUtils();
// const { mutate: updateServizio } = api.servizio.UpdateConfermaDoc.useMutation(
// {
// onError: (error) => {
// toast.error(error.message);
// },
// onSuccess: async () => {
// await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
// await utils.servizio.getServizio.invalidate({
// servizioId,
// });
// toast.success("Dati salvati con successo");
// },
// },
// );
const { data: files, isLoading } = api.storage.getAll.useQuery();
const { mutate: setUserStorage } =
api.storage.addUserStorageEntry.useMutation({
onSuccess: async () => {
await utils.storage.retrieveUserFileData.invalidate({
userId,
});
await utils.storage.getAll.invalidate();
},
});
if (isLoading) return ;
if (files === undefined) {
return
Errore nel caricamento dei documenti
;
}
return (
Documento di Conferma
documento che l'utente vedra alla conferma
{data.doc_conferma_ref && (
)}
{
await updateServizioAnnunci({
doc_conferma_added: true,
doc_conferma_ref: f.id,
});
setUserStorage({
storageId: f.id,
userId,
});
}}
/>
);
};
const CaparraSchema = z.object({
caparra_causale: z.string().nullable(),
caparra_iban: z.string().nullable(),
caparra_importo: z.string().nullable(),
caparra_intestazione: z.string().nullable(),
});
type CaparraObj = z.infer;
const parseCaparra = (ingest: string) => {
let parsedJson: unknown;
try {
parsedJson = JSON.parse(ingest);
} catch {
toast.error(
'Stringa non valida, clicca "copia stringa" nel gestionale e poi questo pulsante',
);
return undefined;
}
const parsed = CaparraSchema.safeParse(parsedJson);
if (parsed.success) {
return parsed.data;
}
console.error("Invalid caparra format:", parsed.error);
return undefined;
};
const Caparra = () => {
const { data, updateServizioAnnunci } = useServizioAnnuncio();
const [caparra, setCaparra] = useState({
caparra_causale: data.caparra_causale,
caparra_iban: data.caparra_iban,
caparra_importo: data.caparra_importo,
caparra_intestazione: data.caparra_intestazione,
});
const handleSave = async () => {
await updateServizioAnnunci({
caparra_causale: caparra?.caparra_causale || null,
caparra_iban: caparra?.caparra_iban || null,
caparra_importo: caparra?.caparra_importo || null,
caparra_intestazione: caparra?.caparra_intestazione || null,
});
};
return (
Dati Pagamento Caparra
dati per il pagamento della caparra, da mostrare all'utente
{caparra ? (
Intestazione:
{caparra.caparra_intestazione}{" "}
IBAN:
{caparra.caparra_iban}{" "}
Importo:
{caparra.caparra_importo}{" "}
Causale:
{caparra.caparra_causale}{" "}
) : (
Inserisci la stringa dal gestionale e elabora
)}
);
};
const MotivazioneSection = () => {
const { servizioId } = useServizio();
const { t } = useTranslation();
const { data: servizio } = api.servizio.getServizio.useQuery({ servizioId });
if (!servizio) return null;
return (
Motivazione di transitorietà
Informazioni relative alla motivazione di transitorietà inserite
dall'utente
Motivazione specificata:
{servizio.motivazione_transitorio ? (
{
t.parametri.motivazioni_mappings.find(
(m) => m.id === servizio.motivazione_transitorio,
)?.title
}
) : (
Non inserita
)}
Data scadenza motivazione inserita:{" "}
{servizio.scadenza_motivazione_transitoria ? (
format(servizio.scadenza_motivazione_transitoria, "dd/MM/yyyy")
) : (
Non inserita
)}
{!servizio.skipDocMotivazione && (
Documento caricato:
{servizio.doc_motivazione_ref ? (
) : (
Non caricato
)}
)}
);
};
const FileLink = ({
userStorageId,
}: {
userStorageId: UsersStorageUserStorageId;
}) => {
const { data: storageId } =
api.storage.getStorageIdFromUserStorageId.useQuery({
userStorageId,
});
if (!storageId) return null;
return (
Vedi documento
);
};
const TransitorioSection = () => {
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 });
await utils.servizio.getPacksSolution.invalidate({ servizioId });
},
});
const handlePermanenzaChange = (value: ListOption) => {
update({
servizioId,
data: {
permanenza: value.value !== "" ? parseInt(value.value) : null,
},
});
};
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 (
Permanenza in annuncio:
{permanenzaAnnuncio}
);
};
const StabileSection = () => {
const { servizio, servizioId, userId } = useServizio();
const { data } = useServizioAnnuncio();
const [value, setValue] = useState(servizio.budget);
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 });
await utils.servizio.getPacksSolution.invalidate({ servizioId });
},
});
useDebounce(
() => {
if (value === servizio.budget) return;
update({
servizioId,
data: {
budget: value,
},
});
},
1000,
[value],
);
return (
Budget (da preferenze servizio):
{
if (val !== undefined) {
setValue(val);
}
}}
stepper={50}
suffix=" €"
/>
Prezzo in descrizione:
{formatCurrency(data.prezzo / 100)}
);
};
const GeneralSection = () => {
const { data } = useServizioAnnuncio();
const { t } = useTranslation();
const { servizio, 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 });
await utils.servizio.getPacksSolution.invalidate({ servizioId });
},
});
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.parametri.mesi,
subito: it.card.consegna_subito,
});
return (
<>
Persone:
handleAdultiChange(Number(v))}
value={servizio.n_adulti || 0}
/>
handleMinoriChange(Number(v))}
value={servizio.n_minori || 0}
/>
Persone in annuncio:
{personeAnnuncio}
label: t.parametri.mesi[servizio.entromese]!,
value: String(servizio.entromese),
}
: undefined
}
elementId="select-mesi"
elementName="entro_mese"
isMulti={false}
onValueChange={handleDisponibilitàChange}
options={UnpackOptions({
options: t.parametri.mesi,
})}
placeholder="Seleziona..."
/>
Disponibilità in annuncio:
{dispAnnuncio}
>
);
};
const SendConferma = () => {
const { servizio } = useServizio();
const { data } = useServizioAnnuncio();
const utils = api.useUtils();
const { mutate: handleUpdate } =
api.servizio.adminUpdateConfermaStatus.useMutation({
onSuccess: async () => {
await utils.servizio.getAllServizioAnnunci.invalidate();
await utils.servizio.getServizio.invalidate({
servizioId: servizio.servizio_id,
});
toast.success("Status aggiornato con successo");
},
onError: (error) => {
toast.error(`Errore durante l'aggiornamento: ${error.message}`);
},
});
const docOk = data.doc_conferma_added && data.doc_conferma_ref;
const caparraOk =
data.caparra_iban &&
data.caparra_importo &&
data.caparra_intestazione &&
data.caparra_causale;
return (
Lavorazione Conferma
controlla i parametri di ricerca prima!
Tipologia servizio:
{servizio.tipologia}
{servizio.tipologia === TipologiaPosizioneEnum.Transitorio ? (
) : (
)}
{!docOk && (
Attenzione: il documento di conferma non è stato ancora caricato
)}
{!caparraOk && (
Attenzione: i dati per il pagamento della caparra non sono
completi
)}
{
handleUpdate({
servizioId: servizio.servizio_id,
annuncioId: data.id,
status: c,
});
}}
/>
);
};