fix: Switch to base64 photo upload for compatibility
Some checks failed
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled

The MinIO/Sharp approach doesn't work on the current server CPU architecture.
Switched to simple base64 encoding for photo uploads.

Changes:
- PhotoUpload component converts images to base64 data URLs
- 5MB file size limit
- Works on all platforms without external dependencies
- Stores photos directly in database (photoUrl field)

This is a temporary solution. For production scalability, we can:
- Upgrade server CPU to support Sharp
- Build Sharp from source
- Use Docker with prebuilt Sharp binaries
- Migrate to a proper CDN/object storage later

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-04 08:40:02 +00:00
parent 9c4bc1b90f
commit f6c1483a36
2 changed files with 23 additions and 25 deletions

View File

@@ -12,7 +12,6 @@ import {
CircularProgress,
} from '@mui/material';
import { PhotoCamera, Person } from '@mui/icons-material';
import { photosApi } from '@/lib/api/photos';
interface PhotoUploadProps {
value: string;
@@ -20,8 +19,6 @@ interface PhotoUploadProps {
label: string;
disabled?: boolean;
size?: number;
childId?: string;
type?: string;
}
export function PhotoUpload({
@@ -29,9 +26,7 @@ export function PhotoUpload({
onChange,
label,
disabled = false,
size = 100,
childId,
type = 'profile'
size = 100
}: PhotoUploadProps) {
const [imageError, setImageError] = useState(false);
const [uploadError, setUploadError] = useState<string>('');
@@ -56,10 +51,10 @@ export function PhotoUpload({
return;
}
// Validate file size (max 10MB - backend limit)
const maxSize = 10 * 1024 * 1024; // 10MB
// Validate file size (max 5MB for base64)
const maxSize = 5 * 1024 * 1024; // 5MB
if (file.size > maxSize) {
setUploadError('Image size must be less than 10MB');
setUploadError('Image size must be less than 5MB');
return;
}
@@ -67,21 +62,24 @@ export function PhotoUpload({
setUploading(true);
setUploadError('');
// Upload to backend - it handles Sharp optimization and MinIO storage
const result = await photosApi.uploadPhoto(file, {
childId,
type,
});
// Use the optimized URL from backend
onChange(result.photo.url);
setImageError(false);
// Convert to base64 (simple, works everywhere)
const reader = new FileReader();
reader.onload = (e) => {
const base64String = e.target?.result as string;
onChange(base64String);
setUploading(false);
setImageError(false);
};
reader.onerror = () => {
setUploadError('Failed to read image file');
setUploading(false);
};
reader.readAsDataURL(file);
} catch (error: any) {
console.error('Photo upload failed:', error);
setUploadError(error.response?.data?.message || 'Failed to upload photo');
} finally {
console.error('Photo processing failed:', error);
setUploadError('Failed to process photo');
setUploading(false);
} finally {
// Reset input
if (fileInputRef.current) {
fileInputRef.current.value = '';
@@ -177,8 +175,8 @@ export function PhotoUpload({
disabled={disabled || uploading}
helperText={
uploading
? 'Uploading and optimizing image...'
: 'Click camera to upload (auto-optimized) or paste URL'
? 'Processing image...'
: 'Click camera to upload or paste an image URL'
}
/>
</Paper>

File diff suppressed because one or more lines are too long