From 9274377a3d1d3e8b3d70b929bd4e9707829220f0 Mon Sep 17 00:00:00 2001 From: Linas Date: Mon, 24 Aug 2026 17:20:28 +0300 Subject: [PATCH] Add attestato generation UI "Genera Attestato" button on the association detail page downloads the certificate PDF from the new backend endpoint; the edit dialog gained a ratification-code field (used on the certificate). Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_017hQcuUQFue2bFvrYw2UQhK --- app/dashboard/[id]/page.tsx | 26 +++++++++++++++++-- .../associations/edit-association-dialog.tsx | 13 ++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/app/dashboard/[id]/page.tsx b/app/dashboard/[id]/page.tsx index 65c83fa..2e58e46 100644 --- a/app/dashboard/[id]/page.tsx +++ b/app/dashboard/[id]/page.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from "react"; import { useParams, useRouter } from "next/navigation"; -import { ArrowLeft, Loader2, Plus, Trash2 } from "lucide-react"; +import { ArrowLeft, FileDown, Loader2, Plus, Trash2 } from "lucide-react"; import { AppHeader } from "@/components/layout/app-header"; import { PageHeader } from "@/components/layout/page-header"; import { AssociateFormDialog } from "@/components/associations/associate-form-dialog"; @@ -14,7 +14,7 @@ import { UserFormDialog } from "@/components/associations/user-form-dialog"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { ConfirmDialog } from "@/components/ui/confirm-dialog"; -import { deleteAssociation, getAssociation, updateAssociation } from "@/lib/api"; +import { deleteAssociation, downloadAttestato, getAssociation, updateAssociation } from "@/lib/api"; import type { Associate, Association, User } from "@/lib/models"; export default function AssociationDetailPage() { @@ -31,6 +31,8 @@ export default function AssociationDetailPage() { const [userDialogOpen, setUserDialogOpen] = useState(false); const [editingUserIndex, setEditingUserIndex] = useState(undefined); + const [generatingAttestato, setGeneratingAttestato] = useState(false); + useEffect(() => { getAssociation(id) .then(setAssociation) @@ -106,6 +108,18 @@ export default function AssociationDetailPage() { router.push("/dashboard"); }; + const handleDownloadAttestato = async () => { + if (!association) return; + setGeneratingAttestato(true); + try { + await downloadAttestato(id, association.name); + } catch (error) { + console.error("Failed to generate attestato:", error); + } finally { + setGeneratingAttestato(false); + } + }; + if (loading) { return (
@@ -137,6 +151,14 @@ export default function AssociationDetailPage() { description={`${association.associates?.length ?? 0} soci registrati`} actions={ <> + { @@ -38,6 +39,7 @@ export function EditAssociationDialog({ setAddress(association.address); setVatNumber(association.vatNumber ?? ""); setRuntsId(association.runtsId ?? ""); + setRatificationCode(association.ratificationCode ?? ""); setIsShown(association.isShown ?? true); } }, [open, association]); @@ -52,6 +54,7 @@ export function EditAssociationDialog({ address, vatNumber, runtsId, + ratificationCode, isShown, }); onSaved(updated); @@ -98,6 +101,16 @@ export function EditAssociationDialog({ setRuntsId(e.target.value)} />
+
+ + setRatificationCode(e.target.value)} + placeholder="Usato nell'attestato di adesione" + /> +
+