feat: Introduce user profile service and enable role-based profile management for users and agents, including avatar uploads and a dismissible error message in the hero section.

This commit is contained in:
pradeepkumar
2026-02-01 00:50:09 +05:30
parent 1ec1696db7
commit c4afc421cf
6 changed files with 270 additions and 79 deletions

View File

@@ -148,7 +148,8 @@ class UploadService {
}
/**
* Upload avatar image (uses agent profile ID as filename for auto-replacement)
* Upload avatar image for AGENTS (uses agent profile ID as filename for auto-replacement)
* S3 path: {env}/agents/{agentId}/avatar.{ext}
* Returns the S3 key (not full URL) for storage in database
*/
async uploadAvatar(
@@ -179,6 +180,39 @@ class UploadService {
};
}
/**
* Upload avatar image for regular USERS (uses user ID as folder)
* S3 path: {env}/users/{userId}/avatar.{ext}
* Returns the S3 key (not full URL) for storage in database
*/
async uploadUserAvatar(
file: File,
onProgress?: (progress: UploadProgress) => void
): Promise<UploadedFile> {
// Step 1: Get presigned URL from backend (uses user ID as folder)
const response = await api.post<{ data: PresignedUrlResponse }>(
`${this.basePath}/user-avatar-presigned-url`,
{
filename: file.name,
contentType: file.type,
}
);
const { uploadUrl, key } = response.data.data;
// Step 2: Upload directly to S3
await this.uploadToS3(uploadUrl, file, onProgress);
// Step 3: Return uploaded file info with KEY (not full URL) for database storage
return {
id: key,
name: file.name,
size: file.size,
type: file.type,
url: key, // Store the S3 key, not the full URL
uploadedAt: new Date().toISOString(),
};
}
/**
* Get a presigned download URL for an S3 key
*/

View File

@@ -0,0 +1,50 @@
import api from './api';
export interface UserProfile {
id: string;
userId: string;
email: string;
firstName: string | null;
lastName: string | null;
phone: string | null;
avatar: string | null;
city: string | null;
state: string | null;
country: string | null;
createdAt: string;
updatedAt: string;
}
export interface UpdateUserProfileData {
firstName?: string;
lastName?: string;
phone?: string;
avatar?: string | null;
city?: string;
state?: string;
country?: string;
}
interface ApiResponse<T> {
success: boolean;
data: T;
message?: string;
}
export const usersService = {
/**
* Get current user's profile
*/
async getMyProfile(): Promise<UserProfile> {
const response = await api.get<ApiResponse<UserProfile>>('/users/profile/me');
return response.data.data;
},
/**
* Update current user's profile
*/
async updateProfile(data: UpdateUserProfileData): Promise<UserProfile> {
const response = await api.patch<ApiResponse<UserProfile>>('/users/profile/me', data);
return response.data.data;
},
};