diff --git a/backend/services/memberService.js b/backend/services/memberService.js index c3938a2b..c18a700e 100644 --- a/backend/services/memberService.js +++ b/backend/services/memberService.js @@ -363,10 +363,10 @@ class MemberService { } if (!imageRecord) { - // Get latest image (highest sortOrder, then highest id) + // Ohne explizite imageId immer das Primärbild liefern (kleinste sortOrder). imageRecord = await MemberImage.findOne({ where: { memberId }, - order: [['sortOrder', 'DESC'], ['id', 'DESC']] + order: [['sortOrder', 'ASC'], ['id', 'ASC']] }); } @@ -1666,12 +1666,12 @@ class MemberService { continue; } - const latestImage = this._selectLatestImage(images); - if (!latestImage) { + const primaryImage = this._selectPrimaryImage(images); + if (!primaryImage) { continue; } - const fileName = latestImage.fileName || `${latestImage.id}.jpg`; + const fileName = primaryImage.fileName || `${primaryImage.id}.jpg`; const filePath = path.join('images', 'members', String(member.id), fileName); if (!fs.existsSync(filePath)) { continue; @@ -1847,24 +1847,19 @@ class MemberService { }; } - _selectLatestImage(images) { + _selectPrimaryImage(images) { if (!Array.isArray(images) || images.length === 0) { return null; } return images .slice() .sort((a, b) => { - const updatedA = a.updatedAt ? new Date(a.updatedAt).getTime() : 0; - const updatedB = b.updatedAt ? new Date(b.updatedAt).getTime() : 0; - if (updatedA !== updatedB) { - return updatedB - updatedA; - } const sortA = Number.isFinite(a.sortOrder) ? a.sortOrder : parseInt(a.sortOrder || '0', 10); const sortB = Number.isFinite(b.sortOrder) ? b.sortOrder : parseInt(b.sortOrder || '0', 10); if (sortA !== sortB) { - return sortB - sortA; + return sortA - sortB; } - return (b.id || 0) - (a.id || 0); + return (a.id || 0) - (b.id || 0); })[0]; } diff --git a/frontend/src/components/MemberGalleryDialog.vue b/frontend/src/components/MemberGalleryDialog.vue index 620c7681..ed4099f8 100644 --- a/frontend/src/components/MemberGalleryDialog.vue +++ b/frontend/src/components/MemberGalleryDialog.vue @@ -305,8 +305,29 @@ export default { } .gallery-member-item.is-participant { - background-color: transparent; - border: none; + box-shadow: + inset 0 0 0 4px #22c55e, + inset 0 0 0 999px rgba(34, 197, 94, 0.22); +} + +.gallery-member-item.is-participant::after { + content: '✓'; + position: absolute; + top: 8px; + right: 8px; + width: 26px; + height: 26px; + border-radius: 999px; + background: #16a34a; + color: #ffffff; + font-size: 16px; + font-weight: 800; + display: flex; + align-items: center; + justify-content: center; + z-index: 12; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35); + pointer-events: none; } .gallery-member-image { @@ -344,7 +365,9 @@ export default { } .gallery-member-item.is-participant .gallery-member-name { - color: #d9f7df; + color: #ffffff; + background-color: rgba(22, 163, 74, 0.82) !important; + font-weight: 700; } .gallery-member-placeholder {