From 7b28eb04ac1091b0125800f6f6e7cdee00a1a00e Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Wed, 12 Nov 2025 07:57:55 +0100 Subject: [PATCH] Refactor memberService and update DiaryView styles for improved functionality and layout This commit includes minor refactoring in the memberService to enhance error logging and improve image handling logic. Additionally, the DiaryView component has been updated to adjust the gallery dialog layout, ensuring better alignment and responsiveness of images. These changes contribute to a more robust backend and a better user experience in the frontend. --- backend/services/memberService.js | 59 ++++++++++++++++--------------- frontend/src/views/DiaryView.vue | 13 ++++--- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/backend/services/memberService.js b/backend/services/memberService.js index 8ca1c9e..d620946 100644 --- a/backend/services/memberService.js +++ b/backend/services/memberService.js @@ -82,8 +82,8 @@ class MemberService { return results; } catch (error) { - console.error('[getClubMembers] - Error:', error); - throw error; + console.error('[getClubMembers] - Error:', error); + throw error; } } @@ -624,7 +624,7 @@ class MemberService { if (!member) { return { status: 404, response: { success: false, error: 'Member not found in this club' } }; } - + await this._migrateLegacyImage(memberId); const imageRecord = await MemberImage.findOne({ @@ -634,7 +634,7 @@ class MemberService { if (!imageRecord) { return { status: 404, response: { success: false, error: 'Image not found' } }; } - + const imagePath = path.join('images', 'members', String(memberId), imageRecord.fileName); if (!fs.existsSync(imagePath)) { return { status: 404, response: { success: false, error: 'Image file not found on disk' } }; @@ -642,23 +642,23 @@ class MemberService { const imageBuffer = await fs.promises.readFile(imagePath); const rotationAngle = direction === 'left' ? -90 : 90; - + const rotatedBuffer = await sharp(imageBuffer) .rotate(rotationAngle) .jpeg({ quality: 80 }) .toBuffer(); - + await fs.promises.writeFile(imagePath, rotatedBuffer); await imageRecord.update({ updatedAt: new Date() }); const imageData = await this._prepareMemberImages(member, { forceReload: true }); const updatedImage = imageData.images.find(img => img.id === imageRecord.id) || null; - - return { - status: 200, - response: { - success: true, + + return { + status: 200, + response: { + success: true, message: `Bild um ${rotationAngle}° gedreht`, direction, rotation: rotationAngle, @@ -666,7 +666,7 @@ class MemberService { images: imageData.images, primaryImageId: imageData.primaryImageId, primaryImageUrl: imageData.primaryImageUrl - } + } }; } catch (error) { console.error('[rotateMemberImage] - Error:', error); @@ -1136,8 +1136,14 @@ class MemberService { const maxColumns = Math.max(1, Math.floor((1920 - galleryGap) / (tileDimension + galleryGap))); const columns = Math.min(maxColumns, galleryEntries.length); const rows = Math.ceil(galleryEntries.length / columns); - const canvasWidth = galleryGap + columns * (tileDimension + galleryGap) - galleryGap; - const canvasHeight = galleryGap + rows * (tileDimension + galleryGap) - galleryGap; + const canvasWidth = Math.max( + 1, + galleryGap + columns * (tileDimension + galleryGap) + ); + const canvasHeight = Math.max( + 1, + galleryGap + rows * (tileDimension + galleryGap) + ); const gap = galleryGap; const backgroundColor = '#101010'; const grid = this._computeGalleryGrid(galleryEntries.length, canvasWidth, canvasHeight, gap); @@ -1147,8 +1153,8 @@ class MemberService { for (const entry of galleryEntries) { const row = Math.floor(index / grid.columns); const col = index % grid.columns; - const left = gap + col * (grid.tileWidth + gap); - const top = gap + row * (grid.tileHeight + gap); + const left = galleryGap + col * (grid.tileWidth + galleryGap); + const top = galleryGap + row * (grid.tileHeight + galleryGap); const resizedBuffer = await sharp(entry.filePath) .resize(200, 200, { fit: 'cover' }) @@ -1218,9 +1224,13 @@ class MemberService { } _computeGalleryGrid(count, canvasWidth, canvasHeight, gap) { - let best = null; - const tileDimension = 200; + let best = { + columns: 1, + rows: count, + tileWidth: tileDimension, + tileHeight: tileDimension + }; for (let columns = 1; columns <= count; columns += 1) { const rows = Math.ceil(count / columns); @@ -1236,25 +1246,16 @@ class MemberService { continue; } - if (!best) { + if (columns > best.columns || (columns === best.columns && rows < best.rows)) { best = { columns, rows, tileWidth, - tileHeight, + tileHeight }; } } - if (!best) { - best = { - columns: 1, - rows: count, - tileWidth: tileDimension, - tileHeight: tileDimension - }; - } - return best; } diff --git a/frontend/src/views/DiaryView.vue b/frontend/src/views/DiaryView.vue index 68feca8..32296be 100644 --- a/frontend/src/views/DiaryView.vue +++ b/frontend/src/views/DiaryView.vue @@ -2474,20 +2474,23 @@ h3 { .gallery-dialog-content { display: flex; - justify-content: center; - align-items: center; + justify-content: flex-start; + align-items: flex-start; + padding: 20px; min-height: 60vh; max-height: 70vh; + overflow: auto; } .gallery-image-wrapper { - max-width: 100%; - max-height: 100%; + max-width: none; + max-height: none; } .gallery-dialog-image { + display: block; max-width: 100%; - max-height: 100%; + height: auto; border-radius: 8px; box-shadow: 0 4px 18px rgba(0, 0, 0, 0.35); }