feat: implement project contacts fetching and display in ProjectViewPage

This commit is contained in:
2025-12-10 14:54:59 +01:00
parent 628ace4ad5
commit b1a1735a12

View File

@@ -30,6 +30,7 @@ export default function ProjectViewPage() {
const [uploadedFiles, setUploadedFiles] = useState([]);
const [editingNoteId, setEditingNoteId] = useState(null);
const [editText, setEditText] = useState('');
const [projectContacts, setProjectContacts] = useState([]);
// Helper function to parse note text with links
const parseNoteText = (text) => {
@@ -163,9 +164,14 @@ export default function ProjectViewPage() {
const filesRes = await fetch(`/api/files?entityType=project&entityId=${params.id}`);
const filesData = filesRes.ok ? await filesRes.json() : [];
// Fetch project contacts
const contactsRes = await fetch(`/api/projects/${params.id}/contacts`);
const contactsData = contactsRes.ok ? await contactsRes.json() : [];
setProject(projectData);
setNotes(notesData);
setUploadedFiles(filesData);
setProjectContacts(contactsData);
} catch (error) {
console.error('Error fetching data:', error);
setProject(null);
@@ -221,6 +227,17 @@ export default function ProjectViewPage() {
return "success";
};
const getContactTypeBadge = (type) => {
const types = {
project: { label: "Projekt", variant: "primary" },
contractor: { label: "Wykonawca", variant: "warning" },
office: { label: "Urząd", variant: "info" },
supplier: { label: "Dostawca", variant: "success" },
other: { label: "Inny", variant: "secondary" },
};
return types[type] || types.other;
};
return (
<PageContainer>
{/* Mobile: Full-width title, Desktop: Standard PageHeader */}
@@ -479,12 +496,53 @@ export default function ProjectViewPage() {
{project.contact && (
<div className="border-t pt-4">
<span className="text-sm font-medium text-gray-500 block mb-1">
Kontakt
Kontakt (stary format)
</span>
<p className="text-gray-900 font-medium">{project.contact}</p>
</div>
)}
{/* New Contacts System */}
{projectContacts.length > 0 && (
<div className="border-t pt-4">
<span className="text-sm font-medium text-gray-500 block mb-2">
Kontakty
</span>
<div className="space-y-2">
{projectContacts.map((contact) => {
const typeBadge = getContactTypeBadge(contact.contact_type);
return (
<div
key={contact.contact_id}
className="p-3 bg-gray-50 rounded-md border border-gray-200"
>
<div className="flex items-center gap-2 mb-1">
<span className="font-medium text-gray-900">
{contact.name}
</span>
{contact.is_primary === 1 && (
<Badge variant="success" size="xs">
Główny
</Badge>
)}
<Badge variant={typeBadge.variant} size="xs">
{typeBadge.label}
</Badge>
</div>
<div className="text-sm text-gray-600 space-y-0.5">
{contact.phone && <div>📞 {contact.phone}</div>}
{contact.email && <div>📧 {contact.email}</div>}
{contact.company && (
<div className="text-xs text-gray-500">🏢 {contact.company}</div>
)}
</div>
</div>
);
})}
</div>
</div>
)}
{project.coordinates && (
<div className="border-t pt-4">
<span className="text-sm font-medium text-gray-500 block mb-1">