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
+1 -1
View File
@@ -896,7 +896,7 @@ describe("AuthProvider methods", () => {
});
const file = new File(["avatar"], "avatar.png", { type: "image/png" });
await expect(result.current.uploadAvatar(file)).rejects.toThrow("Upload failed");
await expect(result.current.uploadAvatar(file)).rejects.toThrow("UNKNOWN");
});
it("deleteAvatar succeeds and refreshes user", async () => {
@@ -170,9 +170,11 @@ describe("useMedications", () => {
const { result } = renderHook(() => useMedications());
const file = new File(["test"], "test.jpg", { type: "image/jpeg" });
await act(async () => {
await result.current.uploadMedImage(1, file);
});
await expect(
act(async () => {
await result.current.uploadMedImage(1, file);
})
).rejects.toThrow("Upload failed");
expect(result.current.uploadingImage).toBe(false);
});