feat(01-04): DocumentsSection + NotesSection — link esterni e log decisioni read-only
- DocumentsSection: link clickabili con target="_blank" rel="noopener noreferrer" icone SVG inline per documento ed external link, hover state con colore accent - NotesSection: note read-only con timestamp in locale it-IT (D-12: cliente legge, admin scrive) empty state informativo per entrambi i componenti - SVG inline al posto di lucide-react per compatibilita' massima
This commit is contained in:
@@ -0,0 +1,71 @@
|
|||||||
|
import type { ClientView } from '@/lib/client-view';
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
interface DocumentsSectionProps {
|
||||||
|
documents: ClientView['documents'];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DocumentsSection({ documents }: DocumentsSectionProps) {
|
||||||
|
if (documents.length === 0) {
|
||||||
|
return (
|
||||||
|
<p className="text-sm text-[#999999] italic">
|
||||||
|
Nessun documento ancora condiviso.
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-2">
|
||||||
|
{documents.map((doc) => (
|
||||||
|
<Card
|
||||||
|
key={doc.id}
|
||||||
|
className="rounded-lg border border-[#e5e5e5] bg-white shadow-none p-0 overflow-hidden"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href={doc.url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="flex items-center justify-between gap-3 px-5 py-4 group hover:bg-[#f9f9f9] transition-colors"
|
||||||
|
>
|
||||||
|
{/* Icona documento */}
|
||||||
|
<div className="flex items-center gap-3 min-w-0">
|
||||||
|
<svg
|
||||||
|
className="w-4 h-4 text-[#0066cc] shrink-0"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth={2}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span className="text-sm font-medium text-[#1a1a1a] group-hover:text-[#0066cc] truncate transition-colors">
|
||||||
|
{doc.label}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Icona external link */}
|
||||||
|
<svg
|
||||||
|
className="w-4 h-4 text-[#999999] group-hover:text-[#0066cc] shrink-0 transition-colors"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth={2}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
d="M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import type { ClientView } from '@/lib/client-view';
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
interface NotesSectionProps {
|
||||||
|
notes: ClientView['notes'];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NotesSection({ notes }: NotesSectionProps) {
|
||||||
|
if (notes.length === 0) {
|
||||||
|
return (
|
||||||
|
<p className="text-sm text-[#999999] italic">
|
||||||
|
Nessuna nota ancora registrata. Le decisioni appariranno qui man mano che il progetto avanza.
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-3">
|
||||||
|
{notes.map((note) => {
|
||||||
|
const dateFormatted = new Date(note.created_at).toLocaleDateString('it-IT', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
day: 'numeric',
|
||||||
|
});
|
||||||
|
const timeFormatted = new Date(note.created_at).toLocaleTimeString('it-IT', {
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
key={note.id}
|
||||||
|
className="rounded-lg border border-[#e5e5e5] bg-white shadow-none p-5"
|
||||||
|
>
|
||||||
|
{/* Testo nota — sola lettura (D-12: admin scrive, cliente legge) */}
|
||||||
|
<p className="text-sm text-[#1a1a1a] leading-relaxed whitespace-pre-wrap">
|
||||||
|
{note.body}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Timestamp */}
|
||||||
|
<p className="text-xs text-[#999999] mt-3">
|
||||||
|
{dateFormatted} alle {timeFormatted}
|
||||||
|
</p>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user