diff --git a/src/app/admin/clients/[id]/actions.ts b/src/app/admin/clients/[id]/actions.ts index 2bf835a..15ad379 100644 --- a/src/app/admin/clients/[id]/actions.ts +++ b/src/app/admin/clients/[id]/actions.ts @@ -117,6 +117,23 @@ export async function addDocument(clientId: string, formData: FormData) { revalidatePath(`/admin/clients/${clientId}`); } +export async function updateDocument( + documentId: string, + clientId: string, + formData: FormData +) { + const parsed = docSchema.safeParse({ + label: formData.get("label"), + url: formData.get("url"), + }); + if (!parsed.success) throw new Error(parsed.error.issues[0].message); + await db + .update(documents) + .set(parsed.data) + .where(eq(documents.id, documentId)); + revalidatePath(`/admin/clients/${clientId}`); +} + export async function deleteDocument(documentId: string, clientId: string) { await db.delete(documents).where(eq(documents.id, documentId)); revalidatePath(`/admin/clients/${clientId}`); diff --git a/src/components/admin/DocumentRow.tsx b/src/components/admin/DocumentRow.tsx new file mode 100644 index 0000000..b306026 --- /dev/null +++ b/src/components/admin/DocumentRow.tsx @@ -0,0 +1,114 @@ +"use client"; + +import { useState, useTransition } from "react"; +import { useRouter } from "next/navigation"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { updateDocument, deleteDocument } from "@/app/admin/clients/[id]/actions"; +import type { Document } from "@/db/schema"; + +export function DocumentRow({ + doc, + clientId, +}: { + doc: Document; + clientId: string; +}) { + const [editing, setEditing] = useState(false); + const [error, setError] = useState(null); + const [, startTransition] = useTransition(); + const router = useRouter(); + + function handleSave(fd: FormData) { + setError(null); + startTransition(async () => { + try { + await updateDocument(doc.id, clientId, fd); + setEditing(false); + router.refresh(); + } catch (e) { + setError(e instanceof Error ? e.message : "Errore nel salvataggio"); + } + }); + } + + function handleDelete() { + startTransition(async () => { + await deleteDocument(doc.id, clientId); + router.refresh(); + }); + } + + if (editing) { + return ( +
+ + + {error &&

{error}

} +
+ + +
+
+ ); + } + + return ( +
+ + {doc.label} + +
+ + +
+
+ ); +} \ No newline at end of file diff --git a/src/components/admin/tabs/DocumentsTab.tsx b/src/components/admin/tabs/DocumentsTab.tsx index 036bdec..89757a5 100644 --- a/src/components/admin/tabs/DocumentsTab.tsx +++ b/src/components/admin/tabs/DocumentsTab.tsx @@ -1,4 +1,5 @@ -import { addDocument, deleteDocument } from "@/app/admin/clients/[id]/actions"; +import { addDocument } from "@/app/admin/clients/[id]/actions"; +import { DocumentRow } from "@/components/admin/DocumentRow"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; @@ -14,9 +15,9 @@ export async function DocumentsTab({ documents, clientId }: Props) { "use server"; await addDocument(clientId, fd); }} - className="bg-white border border-gray-200 rounded-lg p-4 space-y-3" + className="bg-white border border-[#e5e7eb] rounded-lg p-4 space-y-3" > -

Aggiungi documento

+

Aggiungi documento

{documents.length === 0 && ( -

Nessun documento ancora.

+

Nessun documento ancora.

)}
{documents.map((doc) => ( -
- - {doc.label} - -
{ - "use server"; - await deleteDocument(doc.id, clientId); - }} - > - -
-
+ ))}
diff --git a/src/components/client-dashboard.tsx b/src/components/client-dashboard.tsx index 3581fec..3aa75d3 100644 --- a/src/components/client-dashboard.tsx +++ b/src/components/client-dashboard.tsx @@ -16,21 +16,16 @@ interface ClientDashboardProps { export function ClientDashboard({ view, token, comments }: ClientDashboardProps) { return (
- {/* Header: logo iamcavalli (piccolo) + brand_name cliente (prominente) */} + {/* Header */}
-
+
- {/* iamcavalli — piccolo, angolo sinistro */} iamcavalli - - {/* Brand name cliente — prominente, centrato */}

{view.client.brand_name}

- - {/* Spacer bilanciatore */}
@@ -38,7 +33,7 @@ export function ClientDashboard({ view, token, comments }: ClientDashboardProps) {/* Barra progresso globale */}
-
+

Avanzamento Progetto

{view.global_progress_pct}%

@@ -47,58 +42,73 @@ export function ClientDashboard({ view, token, comments }: ClientDashboardProps)
- {/* Contenuto principale */} -
- {/* Brief progetto */} - {view.client.brief && ( -
-

- {view.client.brief} -

-
- )} + {/* Layout principale: sidebar sinistra + contenuto destro */} +
+
- {/* Fasi — toggle timeline/kanban */} -
- } - phases={view.phases} - token={token} - comments={comments} - /> -
+ {/* ── Sidebar sinistra ── */} +
+ {/* Note — solo se presenti */} + {view.notes.length > 0 && ( +
+

+ Note & Decisioni +

+ +
+ )} +
+ + + {/* ── Contenuto principale ── */} +
+ {/* Brief progetto */} + {view.client.brief && ( +

+ {view.client.brief} +

+ )} + + {/* Fasi — toggle timeline/kanban */} + + } + phases={view.phases} + token={token} + comments={comments} + /> +
+ +
+
{/* Footer */}