feat: enable user profile avatar upload and display across header and settings.

This commit is contained in:
pradeepkumar
2026-02-01 00:35:22 +05:30
parent 465551fea5
commit 1ec1696db7
3 changed files with 389 additions and 61 deletions

View File

@@ -4,6 +4,8 @@ import { useState, useEffect, useRef } from 'react';
import Link from 'next/link';
import Image from 'next/image';
import { useSession, signOut } from 'next-auth/react';
import { agentsService } from '@/services/agents.service';
import { uploadService } from '@/services/upload.service';
const navLinks = [
{ label: 'Education', href: '/education' },
@@ -15,6 +17,7 @@ export function CommonHeader() {
const { data: session } = useSession();
const [showProfileMenu, setShowProfileMenu] = useState(false);
const profileMenuRef = useRef<HTMLDivElement>(null);
const [profileImage, setProfileImage] = useState<string | null>(null);
// Close dropdown when clicking outside
useEffect(() => {
@@ -33,9 +36,34 @@ export function CommonHeader() {
};
}, [showProfileMenu]);
// Fetch profile image from backend
useEffect(() => {
const fetchProfileImage = async () => {
try {
const profile = await agentsService.getMyProfile();
if (profile.avatar) {
try {
const avatarUrl = await uploadService.getPresignedDownloadUrl(profile.avatar);
setProfileImage(avatarUrl);
} catch {
setProfileImage(profile.avatar);
}
}
} catch (err) {
console.error('Failed to fetch profile image:', err);
}
};
if (session) {
fetchProfileImage();
}
}, [session]);
const userName = session?.user?.name;
const userEmail = session?.user?.email;
const userRole = (session?.user as any)?.role;
// Use fetched profile image, fallback to session image
const userImage = profileImage || session?.user?.image;
// Determine dashboard link based on user role
const dashboardLink = userRole === 'AGENT' ? '/agent/dashboard' : '/user/dashboard';
@@ -90,14 +118,22 @@ export function CommonHeader() {
className="flex items-center gap-3 hover:opacity-80 transition-opacity cursor-pointer"
>
{/* Avatar */}
<div className="w-[35px] h-[35px] rounded-full overflow-hidden border-2 border-[#e58625]">
<Image
src="/assets/icons/user-placeholder-icon.svg"
alt="Profile"
width={35}
height={35}
className="w-full h-full object-cover"
/>
<div className="w-[35px] h-[35px] rounded-full overflow-hidden border-2 border-[#e58625] bg-gray-100">
{userImage ? (
<img
src={userImage}
alt="Profile"
className="w-full h-full object-cover"
/>
) : (
<Image
src="/assets/icons/user-placeholder-icon.svg"
alt="Profile"
width={35}
height={35}
className="w-full h-full object-cover"
/>
)}
</div>
{/* Greeting Text */}
<div className="flex flex-col text-left">
@@ -118,14 +154,22 @@ export function CommonHeader() {
{/* User Profile Section */}
<div className="flex items-center gap-3 px-4 py-4 border-b border-black/10">
<div className="w-[42px] h-[42px] rounded-full overflow-hidden flex-shrink-0">
<Image
src="/assets/icons/user-placeholder-icon.svg"
alt="Profile"
width={42}
height={42}
className="w-full h-full object-cover"
/>
<div className="w-[42px] h-[42px] rounded-full overflow-hidden flex-shrink-0 bg-gray-100">
{userImage ? (
<img
src={userImage}
alt="Profile"
className="w-full h-full object-cover"
/>
) : (
<Image
src="/assets/icons/user-placeholder-icon.svg"
alt="Profile"
width={42}
height={42}
className="w-full h-full object-cover"
/>
)}
</div>
<div className="flex flex-col">
<p className="font-fractul font-medium text-[16px] leading-[20px] text-black">