diff --git a/src/app/(agent)/agent/network/page.tsx b/src/app/(agent)/agent/network/page.tsx index 9616433..397dbfd 100644 --- a/src/app/(agent)/agent/network/page.tsx +++ b/src/app/(agent)/agent/network/page.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useState, useEffect } from 'react'; +import { useState, useEffect, useCallback } from 'react'; import Image from 'next/image'; import { useRouter } from 'next/navigation'; import { NetworkSidebar } from './component/NetworkSidebar'; @@ -8,6 +8,7 @@ import { InvitationCard } from './component/InvitationCard'; import { ConnectionCard } from './component/ConnectionCard'; import { connectionRequestsService, ConnectionRequest, ConnectionRequestCounts } from '@/services/connection-requests.service'; import { messagesService } from '@/services/messages.service'; +import { uploadService } from '@/services/upload.service'; export default function NetworkPage() { const router = useRouter(); @@ -17,6 +18,31 @@ export default function NetworkPage() { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [processingIds, setProcessingIds] = useState>(new Set()); + const [avatarUrls, setAvatarUrls] = useState>({}); + + // Helper to check if a string is an S3 key (not a URL or local path) + const isS3Key = (value: string | null | undefined): boolean => { + if (!value) return false; + return !value.startsWith('http') && !value.startsWith('/') && !value.startsWith('data:'); + }; + + // Resolve S3 avatar keys to presigned URLs + const resolveAvatars = useCallback(async (requests: ConnectionRequest[]) => { + const newUrls: Record = {}; + for (const req of requests) { + const avatar = req.user?.userProfile?.avatar || req.user?.avatar; + if (avatar && isS3Key(avatar) && !avatarUrls[req.id]) { + try { + newUrls[req.id] = await uploadService.getPresignedDownloadUrl(avatar); + } catch { + // Keep empty, will show placeholder + } + } + } + if (Object.keys(newUrls).length > 0) { + setAvatarUrls(prev => ({ ...prev, ...newUrls })); + } + }, [avatarUrls]); // Fetch connection requests on mount useEffect(() => { @@ -38,6 +64,9 @@ export default function NetworkPage() { setPendingRequests(pending); setConnections(accepted); setCounts(requestCounts); + + // Resolve avatars for all requests + resolveAvatars([...pending, ...accepted]); } catch (err) { console.error('Failed to fetch connection requests:', err); setError('Failed to load connection requests'); @@ -198,12 +227,14 @@ export default function NetworkPage() { {pendingRequests.map((request) => { const profile = request.user?.userProfile; const userName = [profile?.firstName, profile?.lastName].filter(Boolean).join(' ') || request.user?.email || 'Unknown User'; + const rawAvatar = profile?.avatar || request.user?.avatar; + const resolvedAvatar = avatarUrls[request.id] || (rawAvatar && !isS3Key(rawAvatar) ? rawAvatar : null); return ( { const profile = connection.user?.userProfile; const userName = [profile?.firstName, profile?.lastName].filter(Boolean).join(' ') || connection.user?.email || 'Unknown User'; + const rawAvatar = profile?.avatar || connection.user?.avatar; + const resolvedAvatar = avatarUrls[connection.id] || (rawAvatar && !isS3Key(rawAvatar) ? rawAvatar : null); return ( 200 - ? description.slice(0, 200) + '...' + const maxDescLength = 150; + const truncatedDescription = description && description.length > maxDescLength + ? description.slice(0, maxDescLength) + '...' : description || ''; + const INITIAL_TAG_COUNT = 6; return ( -
+
{/* Profile Image & View Profile Button */}

{showFullBio ? description : truncatedDescription} - {description.length > 200 && ( + {description.length > maxDescLength && ( <> {' '} )}

diff --git a/src/components/layout/CommonHeader.tsx b/src/components/layout/CommonHeader.tsx index 068ed8c..00ff71d 100644 --- a/src/components/layout/CommonHeader.tsx +++ b/src/components/layout/CommonHeader.tsx @@ -57,7 +57,7 @@ export function CommonHeader() { return (
-
+
{/* Logo */} - {/* Navigation - Desktop only */} -