diff --git a/src/app/dashboard/professional-network/page.tsx b/src/app/dashboard/professional-network/page.tsx new file mode 100644 index 0000000..13461e0 --- /dev/null +++ b/src/app/dashboard/professional-network/page.tsx @@ -0,0 +1,155 @@ +'use client'; + +import { useMemo, useState } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import Link from 'next/link'; +import { apiFetch } from '../../../lib/api'; +import { useSession } from '../../../components/session-provider'; + +interface Contact { id: string; firstName: string; lastName: string | null; role: string | null; organization: string | null; tags: string[]; email: string | null; linkedinUrl: string | null; country: string | null; createdAt: string; } + +const PRO_TAGS = ['mentor', 'investor', 'investitor', 'partner', 'partener', 'advisor', 'board', 'client', 'collaborator', 'coleg', 'colleague', 'recruiter', 'founder', 'ceo', 'cto']; +const INDUSTRIES = ['Tech', 'Finance', 'Legal', 'Healthcare', 'Education', 'Consulting', 'AI/ML', 'SaaS', 'Altele']; + +export default function ProfessionalNetworkPage() { + const { activeTenant } = useSession(); + const tenantId = activeTenant?.tenantId ?? ''; + const [search, setSearch] = useState(''); + const [tagFilter, setTagFilter] = useState(''); + + const { data: contacts = [], isLoading } = useQuery({ + queryKey: ['pro-network', tenantId], + queryFn: () => apiFetch('/v1/contacts?limit=500', { tenantId }), + enabled: Boolean(tenantId), staleTime: 60_000, + }); + + const network = useMemo(() => + contacts.filter((c) => c.tags.some((t) => PRO_TAGS.includes(t.toLowerCase()))), + [contacts]); + + const tagCounts = useMemo(() => { + const counts: Record = {}; + for (const c of network) { + for (const t of c.tags) { + if (PRO_TAGS.includes(t.toLowerCase())) { + counts[t.toLowerCase()] = (counts[t.toLowerCase()] ?? 0) + 1; + } + } + } + return Object.entries(counts).sort((a, b) => b[1] - a[1]).slice(0, 8); + }, [network]); + + const filtered = useMemo(() => { + let list = network; + if (tagFilter) list = list.filter((c) => c.tags.some((t) => t.toLowerCase() === tagFilter)); + if (search.trim()) { + const q = search.toLowerCase(); + list = list.filter((c) => + `${c.firstName} ${c.lastName ?? ''} ${c.organization ?? ''} ${c.role ?? ''}`.toLowerCase().includes(q) + ); + } + return list.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()); + }, [network, tagFilter, search]); + + const stats = useMemo(() => { + const countries = new Set(network.map((c) => c.country).filter(Boolean)).size; + const orgs = new Set(network.map((c) => c.organization).filter(Boolean)).size; + const withLinkedIn = network.filter((c) => c.linkedinUrl).length; + return { countries, orgs, withLinkedIn }; + }, [network]); + + return ( +
+
+

Rețea Profesională

+

+ {isLoading ? 'Se încarcă…' : `${network.length} contacte profesionale cheie din ${contacts.length} total`} +

+
+ + {/* Stats */} +
+
+

{network.length}

+

rețea profesională

+
+
+

{stats.orgs}

+

organizații

+
+
+

{stats.countries}

+

țări

+
+
+

{stats.withLinkedIn}

+

LinkedIn

+
+
+ + {/* Tag breakdown */} +
+ + {tagCounts.map(([tag, count]) => ( + + ))} +
+ + {/* Search */} + setSearch(e.target.value)} + placeholder="Caută după nume, companie, rol…" + className="w-full rounded-lg border bg-background px-4 py-2.5 text-sm text-ink focus:outline-none focus:ring-2 focus:ring-ring" /> + + {isLoading ? ( +
Se încarcă…
+ ) : filtered.length === 0 ? ( +
+

💼

+

+ {network.length === 0 + ? 'Niciun contact profesional. Adaugă contacte cu tag mentor/investor/partner din Contacte.' + : 'Niciun rezultat pentru filtrul curent.'} +

+ {network.length === 0 && ( + Gestionează contacte → + )} +
+ ) : ( +
+ {filtered.map((c) => { + const proTags = c.tags.filter((t) => PRO_TAGS.includes(t.toLowerCase())); + return ( +
+
+
+

{c.firstName} {c.lastName ?? ''}

+ {c.role &&

{c.role}

} + {c.organization &&

{c.organization}

} +
+
+ {proTags.slice(0, 2).map((t) => ( + {t} + ))} +
+
+
+ {c.email && {c.email}} + {c.linkedinUrl && LinkedIn →} + {c.country && !c.email && !c.linkedinUrl && {c.country}} +
+
+ ); + })} +
+ )} + + ← Toate relațiile +
+ ); +}