fix: Switch to base64 photo upload for compatibility
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:
@@ -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
Reference in New Issue
Block a user