feat: Integrate photo upload with MinIO storage and Sharp optimization
Now uses the existing infrastructure instead of base64: - Created photos API client for multipart/form-data upload - Upload to /api/v1/photos/upload endpoint - Backend handles Sharp image optimization (resize, compress, format conversion) - MinIO/S3-compatible storage for scalable file management - 10MB file size limit (up from 5MB base64) - Shows upload progress with spinner - Returns optimized CDN-ready URLs - Proper error handling with backend validation Benefits over previous base64 approach: ✅ Images optimized with Sharp (smaller sizes, better quality) ✅ Stored in MinIO (scalable object storage) ✅ CDN-ready URLs for fast delivery ✅ No database bloat from base64 strings ✅ Supports larger files (10MB vs 5MB) ✅ Automatic thumbnail generation ✅ Better performance and scalability 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
48
maternal-web/lib/api/photos.ts
Normal file
48
maternal-web/lib/api/photos.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import apiClient from './client';
|
||||
|
||||
export interface PhotoUploadResult {
|
||||
photo: {
|
||||
id: string;
|
||||
url: string;
|
||||
thumbnailUrl?: string;
|
||||
originalUrl?: string;
|
||||
storageKey: string;
|
||||
};
|
||||
}
|
||||
|
||||
export const photosApi = {
|
||||
/**
|
||||
* Upload a photo for profile/child
|
||||
* Uses multipart/form-data to send file to backend
|
||||
* Backend handles image optimization via Sharp and storage via MinIO
|
||||
*/
|
||||
uploadPhoto: async (
|
||||
file: File,
|
||||
options?: {
|
||||
childId?: string;
|
||||
type?: string;
|
||||
caption?: string;
|
||||
}
|
||||
): Promise<PhotoUploadResult> => {
|
||||
const formData = new FormData();
|
||||
formData.append('photo', file);
|
||||
|
||||
if (options?.childId) {
|
||||
formData.append('childId', options.childId);
|
||||
}
|
||||
if (options?.type) {
|
||||
formData.append('type', options.type);
|
||||
}
|
||||
if (options?.caption) {
|
||||
formData.append('caption', options.caption);
|
||||
}
|
||||
|
||||
const response = await apiClient.post('/api/v1/photos/upload', formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
});
|
||||
|
||||
return response.data.data;
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user