beetask/frontend/src/services/userService.ts
Gabriel Santana de Menezes 59a5c61585 feat: add MinIO image server and profile photo upload
Infrastructure: MinIO service added to docker-compose (prod + dev) with
minio-init container that creates the avatars bucket with public read
policy. Traefik routes minio.task.beetech.dev → port 9000.

Backend: native MinIO SDK integration via MinioStorageService;
UploadUserPhotoUseCase validates 5 MB limit and image content-type;
new POST /auth/profile/photo endpoint (multipart). All hardcoded
ui-avatars.com fallback URLs removed from 6 use cases — backend now
returns null when user has no photo.

Frontend: ProfilePage gains clickable avatar with camera overlay,
file picker, preview, and photo upload on save. UserAvatar gains
onError handler for broken URLs and xs size. OrganizationAdminPage
replaces hardcoded ui-avatars.com with UserAvatar component.

CI/CD: deploy-main.yml passes 5 new MinIO secrets to the server and
writes them to .env.production.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 18:01:59 -04:00

34 lines
743 B
TypeScript

import { apiFetch } from '../lib/api'
export interface UpdateProfilePayload {
name: string
email: string
}
export interface UpdateProfileResult {
name: string
email: string
photo: string
}
export interface UploadPhotoResult {
photoUrl: string
}
export const userService = {
updateProfile: async (payload: UpdateProfilePayload): Promise<UpdateProfileResult> => {
return apiFetch<UpdateProfileResult>('/auth/profile', {
method: 'PUT',
body: payload,
})
},
uploadPhoto: async (file: File): Promise<UploadPhotoResult> => {
const form = new FormData()
form.append('photo', file)
return apiFetch<UploadPhotoResult>('/auth/profile/photo', {
method: 'POST',
body: form,
})
},
}