feat: Implement S3 avatar resolution for network connections, refine messaging initial conversation selection, and adjust profile display logic and header navigation.
This commit is contained in:
@@ -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<string | null>(null);
|
||||
const [processingIds, setProcessingIds] = useState<Set<string>>(new Set());
|
||||
const [avatarUrls, setAvatarUrls] = useState<Record<string, string>>({});
|
||||
|
||||
// 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<string, string> = {};
|
||||
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 (
|
||||
<InvitationCard
|
||||
key={request.id}
|
||||
id={request.id}
|
||||
name={userName}
|
||||
avatar={profile?.avatar || request.user?.avatar || '/assets/icons/user-placeholder-icon.svg'}
|
||||
avatar={resolvedAvatar || '/assets/icons/user-placeholder-icon.svg'}
|
||||
description={request.message || 'No message provided'}
|
||||
createdAt={request.createdAt}
|
||||
isProcessing={processingIds.has(request.id)}
|
||||
@@ -252,12 +283,14 @@ export default function NetworkPage() {
|
||||
{connections.map((connection) => {
|
||||
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 (
|
||||
<ConnectionCard
|
||||
key={connection.id}
|
||||
id={connection.userId}
|
||||
name={userName}
|
||||
avatar={profile?.avatar || connection.user?.avatar || '/assets/icons/user-placeholder-icon.svg'}
|
||||
avatar={resolvedAvatar || '/assets/icons/user-placeholder-icon.svg'}
|
||||
email={connection.user?.email || ''}
|
||||
connectedAt={connection.respondedAt || connection.updatedAt}
|
||||
onMessage={handleMessage}
|
||||
|
||||
Reference in New Issue
Block a user