feat: image upload optimization with sharp, thumbnails, and structured error codes (#304)

- Add sharp for server-side image processing (WebP conversion + thumbnails)
- New shared backend utility for image upload, optimization, and cleanup
- Return structured error codes from upload endpoints (IMAGE_TOO_LARGE, INVALID_TYPE, etc.)
- Frontend error code mapping with i18n support (EN + DE)
- MedicationAvatar tries thumbnail first, falls back to full image
- Error display in MedicationsPage, MobileEditModal, and Auth avatar upload

Closes #302
This commit is contained in:
Daniel Volz
2026-02-24 23:52:59 +01:00
committed by GitHub
parent 7a32b2045e
commit 96b2a0c96f
15 changed files with 916 additions and 93 deletions
+8 -1
View File
@@ -59,6 +59,7 @@ export interface MobileEditModalProps {
meds: Medication[];
onUploadMedImage: (medId: number, file: File) => Promise<void>;
onDeleteMedImage: (medId: number) => Promise<void>;
imageUploadError: string | null;
// Actions
onClose: () => void;
onResetForm: () => void;
@@ -105,6 +106,7 @@ export function MobileEditModal({
meds,
onUploadMedImage,
onDeleteMedImage,
imageUploadError,
onClose,
_onResetForm,
onSaveMedication,
@@ -454,9 +456,14 @@ export function MobileEditModal({
<input
type="file"
accept="image/*"
onChange={(e) => e.target.files?.[0] && onUploadMedImage(editingId, e.target.files[0])}
onChange={(e) => {
const file = e.target.files?.[0];
e.target.value = "";
if (file) void onUploadMedImage(editingId, file);
}}
/>
)}
{imageUploadError && <span className="field-error">{imageUploadError}</span>}
</div>
)}
</div>