feat: enhance document upload functionality and add save state indicators in Admin sections

This commit is contained in:
Marco Pedone 2026-02-19 10:48:31 +01:00
parent 8f3802ede3
commit 890f0572f3
2 changed files with 119 additions and 14 deletions

View file

@ -1,5 +1,6 @@
import { format } from "date-fns";
import {
CircleAlert,
CircleCheck,
ClipboardPaste,
FlaskConical,
@ -230,7 +231,18 @@ const DocSection = () => {
});
}}
/>
<UploadModal isAdmin userId={userId} />
<UploadModal
cb_onUpload={async ({ storageIds }) => {
if (storageIds.length === 1 && storageIds[0]) {
await updateServizioAnnunci({
doc_conferma_added: true,
doc_conferma_ref: storageIds[0],
});
}
}}
isAdmin
userId={userId}
/>
</div>
</CardContent>
</Card>
@ -266,13 +278,16 @@ const parseCaparra = (ingest: string) => {
const Caparra = () => {
const { data, updateServizioAnnunci } = useServizioAnnuncio();
const [caparra, setCaparra] = useState<CaparraObj | undefined>({
const initialCaparra = {
caparra_causale: data.caparra_causale,
caparra_iban: data.caparra_iban,
caparra_importo: data.caparra_importo,
caparra_intestazione: data.caparra_intestazione,
});
};
const [caparra, setCaparra] = useState<CaparraObj | undefined>(
initialCaparra,
);
const handleSave = async () => {
await updateServizioAnnunci({
caparra_causale: caparra?.caparra_causale || null,
@ -415,9 +430,10 @@ const Caparra = () => {
<p>Inserisci la stringa dal gestionale e elabora</p>
)}
</CardContent>
<CardFooter>
<CardFooter className="gap-4">
<Button
aria-label="Save Caparra"
disabled={JSON.stringify(caparra) === JSON.stringify(initialCaparra)}
onClick={async () => {
await handleSave();
}}
@ -425,6 +441,19 @@ const Caparra = () => {
>
Salva
</Button>
{JSON.stringify(caparra) !== JSON.stringify(initialCaparra) ? (
<div className="flex items-center gap-2">
<CircleAlert className="size-5 text-orange-500" />
<span className="text-orange-500">Salva modifiche</span>
</div>
) : (
Object.values(initialCaparra).every((v) => v !== null) && (
<div className="flex items-center gap-2">
<CircleCheck className="size-5 text-green-500" />
<span className="text-green-500">Dati salvati</span>
</div>
)
)}
</CardFooter>
</Card>
);

View file

@ -1,4 +1,11 @@
import { CircleCheck, ClipboardPaste, Pen, Trash2, Wrench } from "lucide-react";
import {
CircleAlert,
CircleCheck,
ClipboardPaste,
Pen,
Trash2,
Wrench,
} from "lucide-react";
import { useState } from "react";
import toast from "react-hot-toast";
import z from "zod";
@ -77,6 +84,7 @@ export const AdminContratto = () => {
const ContrattoSection = () => {
const { userId } = useServizio();
const { data, updateServizioAnnunci } = useServizioAnnuncio();
const initialDoc = data.doc_contratto_ref;
const [selectedDoc, setSelectedDoc] = useState<string | null>(
data.doc_contratto_ref,
);
@ -112,6 +120,7 @@ const ContrattoSection = () => {
if (files === undefined) {
return <p>Errore nel caricamento dei documenti</p>;
}
return (
<Card>
<CardHeader>
@ -146,11 +155,20 @@ const ContrattoSection = () => {
setSelectedDoc(f.id);
}}
/>
<UploadModal isAdmin userId={userId} />
<UploadModal
cb_onUpload={({ storageIds }) => {
if (storageIds.length === 1 && storageIds[0]) {
setSelectedDoc(storageIds[0]);
}
}}
isAdmin
userId={userId}
/>
</CardContent>
<CardFooter>
<CardFooter className="gap-4">
<Button
aria-label="Save Contratto"
disabled={selectedDoc === initialDoc}
onClick={async () => {
await handleSave();
}}
@ -158,6 +176,20 @@ const ContrattoSection = () => {
>
Salva
</Button>
{selectedDoc !== initialDoc ? (
<div className="flex items-center gap-2">
<CircleAlert className="size-5 text-orange-500" />
<span className="text-orange-500">Salva modifiche</span>
</div>
) : (
initialDoc &&
selectedDoc === initialDoc && (
<div className="flex items-center gap-2">
<CircleCheck className="size-5 text-green-500" />
<span className="text-green-500">Dati salvati</span>
</div>
)
)}
</CardFooter>
</Card>
);
@ -217,8 +249,7 @@ const parseContrattoImport = (ingest: string) => {
const ContrattoImport = () => {
const { data, updateServizioAnnunci } = useServizioAnnuncio();
const [contratto, setContratto] = useState<ContrattoImportObj | undefined>({
const initialContratto = {
contratto_decorrenza: data.contratto_decorrenza
? new Date(data.contratto_decorrenza)
: null,
@ -227,7 +258,11 @@ const ContrattoImport = () => {
: null,
contratto_tipo: data.contratto_tipo as ContrattoImportObj["contratto_tipo"],
gestionale_id: data.gestionale_id,
});
};
const [contratto, setContratto] = useState<ContrattoImportObj | undefined>(
initialContratto,
);
const handleSave = async () => {
await updateServizioAnnunci({
contratto_decorrenza: contratto?.contratto_decorrenza || null,
@ -404,9 +439,12 @@ const ContrattoImport = () => {
<p>Inserisci la stringa dal gestionale e elabora</p>
)}
</CardContent>
<CardFooter>
<CardFooter className="gap-4">
<Button
aria-label="Save Contratto"
disabled={
JSON.stringify(contratto) === JSON.stringify(initialContratto)
}
onClick={async () => {
await handleSave();
}}
@ -414,6 +452,19 @@ const ContrattoImport = () => {
>
Salva
</Button>
{JSON.stringify(contratto) !== JSON.stringify(initialContratto) ? (
<div className="flex items-center gap-2">
<CircleAlert className="size-5 text-orange-500" />
<span className="text-orange-500">Salva modifiche</span>
</div>
) : (
Object.values(initialContratto).every((v) => v !== null) && (
<div className="flex items-center gap-2">
<CircleCheck className="size-5 text-green-500" />
<span className="text-green-500">Dati salvati</span>
</div>
)
)}
</CardFooter>
</Card>
);
@ -422,6 +473,7 @@ const ContrattoImport = () => {
const RicevutaSection = () => {
const { userId } = useServizio();
const { data, updateServizioAnnunci } = useServizioAnnuncio();
const initialDoc = data.doc_registrazione_ref;
const [selectedDoc, setSelectedDoc] = useState<string | null>(
data.doc_registrazione_ref,
);
@ -457,6 +509,7 @@ const RicevutaSection = () => {
if (files === undefined) {
return <p>Errore nel caricamento dei documenti</p>;
}
return (
<Card>
<CardHeader>
@ -491,11 +544,20 @@ const RicevutaSection = () => {
setSelectedDoc(f.id);
}}
/>
<UploadModal isAdmin userId={userId} />
<UploadModal
cb_onUpload={({ storageIds }) => {
if (storageIds.length === 1 && storageIds[0]) {
setSelectedDoc(storageIds[0]);
}
}}
isAdmin
userId={userId}
/>
</CardContent>
<CardFooter>
<CardFooter className="gap-4">
<Button
aria-label="Save Ricevuta"
disabled={selectedDoc === initialDoc}
onClick={async () => {
await handleSave();
}}
@ -503,6 +565,20 @@ const RicevutaSection = () => {
>
Salva
</Button>
{selectedDoc !== initialDoc ? (
<div className="flex items-center gap-2">
<CircleAlert className="size-5 text-orange-500" />
<span className="text-orange-500">Salva modifiche</span>
</div>
) : (
initialDoc &&
selectedDoc === initialDoc && (
<div className="flex items-center gap-2">
<CircleCheck className="size-5 text-green-500" />
<span className="text-green-500">Dati salvati</span>
</div>
)
)}
</CardFooter>
</Card>
);