Enhance AnnuncioActions and ServizioMain components: refactor document handling and update layout for better responsiveness

This commit is contained in:
Marco Pedone 2025-08-19 19:14:27 +02:00
parent 0ae854ede5
commit 709ac307e1
3 changed files with 147 additions and 107 deletions

View file

@ -47,7 +47,7 @@ import {
} from "~/components/custom_ui/credenza";
import { LoadingPage } from "~/components/loading";
import Link from "next/link";
import { cn } from "~/lib/utils";
import { cn, formatCurrency } from "~/lib/utils";
import { useRef, useState } from "react";
import { z } from "zod/v4";
import { Separator } from "~/components/ui/separator";
@ -67,6 +67,8 @@ import {
type AnimatedButtonRef,
} from "~/components/custom_ui/animated-button";
import type { AnnunciId } from "~/schemas/public/Annunci";
import { useTranslation } from "~/providers/I18nProvider";
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
export const AnnuncioActions = () => {
const { servizioId, userId, isAdmin } = useServizio();
@ -537,21 +539,22 @@ const ContrattoSection = ({
<CardContent className="space-y-4">
{selectedDoc && (
<div className="flex flex-wrap items-center gap-3">
<DocInfo storageId={selectedDoc} />
<Button
aria-label="Reset Contratto"
variant="destructive"
className="flex items-center gap-3"
onClick={() => {
handleUpdate({
doc_contratto_ref: null,
doc_contratto_added: false,
});
setSelectedDoc(null);
}}
>
<Trash2 className="size-6" /> Reset
</Button>
<DocInfo storageId={selectedDoc}>
<Button
aria-label="Reset Contratto"
variant="destructive"
className="flex items-center gap-3"
onClick={() => {
handleUpdate({
doc_contratto_ref: null,
doc_contratto_added: false,
});
setSelectedDoc(null);
}}
>
<Trash2 className="size-6" />
</Button>
</DocInfo>
</div>
)}
<DocCombo
@ -628,21 +631,22 @@ const RicevutaSection = ({
<CardContent className="space-y-4">
{selectedDoc && (
<div className="flex flex-wrap items-center gap-3">
<DocInfo storageId={selectedDoc} />
<Button
aria-label="Reset Ricevuta"
variant="destructive"
className="flex items-center gap-3"
onClick={() => {
handleUpdate({
doc_registrazione_ref: null,
doc_registrazione_added: false,
});
setSelectedDoc(null);
}}
>
<Trash2 className="size-6" /> Reset
</Button>
<DocInfo storageId={selectedDoc}>
<Button
aria-label="Reset Ricevuta"
variant="destructive"
className="flex items-center gap-3"
onClick={() => {
handleUpdate({
doc_registrazione_ref: null,
doc_registrazione_added: false,
});
setSelectedDoc(null);
}}
>
<Trash2 className="size-6" />
</Button>
</DocInfo>
</div>
)}
<DocCombo
@ -754,9 +758,6 @@ const DocSection = ({
}) => {
const { userId } = useServizio();
const { data } = useServizioAnnuncio();
const [selectedDoc, setSelectedDoc] = useState<StorageindexId | null>(
data.doc_conferma_ref,
);
const utils = api.useUtils();
@ -771,19 +772,6 @@ const DocSection = ({
},
});
const handleSave = () => {
handleUpdate({
doc_conferma_ref: selectedDoc,
doc_conferma_added: selectedDoc != null,
});
if (selectedDoc) {
setUserStorage({
userId,
fileId: selectedDoc,
});
}
};
if (isLoading) return <LoadingPage />;
if (files == undefined) {
return <p>Errore nel caricamento dei documenti</p>;
@ -797,73 +785,85 @@ const DocSection = ({
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
{selectedDoc && (
<div className="flex flex-wrap items-center gap-3">
<DocInfo storageId={selectedDoc} />
<Button
aria-label="Reset Conferma"
variant="destructive"
className="flex items-center gap-3"
onClick={() => {
handleUpdate({
doc_conferma_ref: null,
doc_conferma_added: false,
});
}}
>
<Trash2 /> Reset
</Button>
{data.doc_conferma_ref && (
<div className="flex flex-wrap items-start gap-3">
<DocInfo storageId={data.doc_conferma_ref}>
<Button
aria-label="Reset Conferma"
variant="destructive"
className="flex items-center gap-3"
onClick={() => {
handleUpdate({
doc_conferma_ref: null,
doc_conferma_added: false,
});
}}
>
<Trash2 />
</Button>
</DocInfo>
</div>
)}
<DocCombo
files={files}
onSelect={(f) => {
setSelectedDoc(f.id);
}}
current={selectedDoc}
/>
<UploadModal isAdmin userId={userId} />
<div className="flex flex-wrap items-center gap-3">
<DocCombo
files={files}
onSelect={(f) => {
handleUpdate({
doc_conferma_ref: f.id,
doc_conferma_added: true,
});
setUserStorage({
userId,
fileId: f.id,
});
}}
current={data.doc_conferma_ref}
/>
<UploadModal isAdmin userId={userId} />
</div>
</CardContent>
<CardFooter>
<Button
aria-label="Save Conferma"
onClick={() => {
handleSave();
}}
variant="success"
>
Salva
</Button>
</CardFooter>
</Card>
);
};
const DocInfo = ({ storageId }: { storageId: StorageindexId }) => {
const DocInfo = ({
storageId,
children,
}: {
storageId: StorageindexId;
children: React.ReactNode;
}) => {
const { data: file_info } = api.storage.getStorageFromId.useQuery({
storageId,
});
if (!file_info) return null;
return (
<div className="flex flex-wrap items-center gap-2">
<div className="flex w-full flex-col gap-2">
<Label htmlFor="selected-file">File Selezionato: </Label>
<Link
aria-label="Open Selected File"
href={`/area-riservata/allegato-view/${storageId}`}
target="_blank"
className={cn(
buttonVariants({
variant: "outline",
}),
"flex w-fit items-center justify-center gap-2",
)}
id="selected-file"
>
{file_info.ext && <ExtIcon ext={file_info.ext} />}
{file_info.filename}
<ExternalLink className="size-4" />
</Link>
<div className="flex w-full items-center gap-2 sm:max-w-[30rem]">
<div className="flex w-full flex-1">
<Link
aria-label="Open Selected File"
href={`/area-riservata/allegato-view/${storageId}`}
target="_blank"
className={cn(
buttonVariants({
variant: "outline",
}),
"flex w-fit grow items-center gap-2",
)}
id="selected-file"
>
{file_info.ext && <ExtIcon ext={file_info.ext} />}
<span className="max-w-40 truncate sm:max-w-80">
{file_info.filename}
</span>
<ExternalLink className="size-4" />
</Link>
</div>
{children}
</div>
</div>
);
};
@ -981,7 +981,7 @@ const Caparra = ({
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center gap-3">
<div className="flex flex-wrap items-center gap-3">
<Button
aria-label="Import Caparra"
onClick={async () => {
@ -993,7 +993,7 @@ const Caparra = ({
variant="info"
>
<ClipboardPaste className="size-4" />
Clicca qui per importare la stringa dal gestionale
Dal gestionale
</Button>
<Button
aria-label="Reset Caparra"
@ -1009,7 +1009,6 @@ const Caparra = ({
variant="destructive"
>
<Trash2 className="size-4" />
Reset
</Button>
</div>
{caparra ? (
@ -1129,7 +1128,9 @@ const SendConferma = ({
}: {
handleUpdate: (upd: ServizioAnnunciUpdate) => void;
}) => {
const { servizio } = useServizio();
const { data } = useServizioAnnuncio();
const { t } = useTranslation();
const [check, setCheck] = useState(data.hasConfermaAdmin);
return (
@ -1137,10 +1138,47 @@ const SendConferma = ({
<CardHeader>
<CardTitle>Lavorazione Conferma</CardTitle>
<CardDescription>
Se accettare la conferma, controlla i parametri di ricerca prima!
controlla i parametri di ricerca prima!
</CardDescription>
</CardHeader>
<CardContent>
<CardContent className="space-y-4">
<div className="flex flex-col gap-2">
<p>Tipologia servizio: {servizio.tipologia}</p>
{(() => {
if (servizio.tipologia === TipologiaPosizioneEnum.Transitorio) {
return (
<>
<p>
Permanenza (da preferenze):{" "}
{servizio.permanenza
? t.preferenze.permanenza[servizio.permanenza]
: "non inserita"}
</p>
<p>
Permanenza (da descrizione): &quot;
{(() => {
const match = data.desc_it?.match(/Permanenza:.*$/m);
return match ? match[0] : "";
})()}
&quot;
</p>
</>
);
} else {
return (
<>
<p>
Budget (da preferenze): {formatCurrency(servizio.budget)}
</p>
<p>
Canone Mensile (da descrizione):{" "}
{formatCurrency(data.prezzo / 100)}
</p>
</>
);
}
})()}
</div>
<div className="flex items-center gap-3">
<Switch
aria-label="Conferma Lavorata"

View file

@ -164,7 +164,7 @@ const ServizioMain = () => {
}
content={
<div className="flex flex-col gap-4">
<div className="flex gap-3">
<div className="flex flex-wrap gap-3">
<Link
href={`/servizio/onboard/${servizio.servizio_id}`}
aria-label="Attiva Servizio"

View file

@ -621,6 +621,8 @@ export const getAllServizioAnnunci = async (userId: UsersId) => {
"servizio.created_at",
"servizio.decorrenza",
"servizio.tipologia",
"servizio.budget",
"servizio.permanenza",
"servizio.isInterrotto",
"servizio.isOkAcconto",
"servizio.isOkSaldo",