팀배정 성별, 에버표시
This commit is contained in:
@@ -1369,7 +1369,7 @@ exports.getEventParticipants = async (req, res) => {
|
|||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
model: Member,
|
model: Member,
|
||||||
attributes: ['id', 'name', 'email', 'phone', 'memberType']
|
attributes: ['id', 'name', 'email', 'phone', 'memberType', 'gender']
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
order: [
|
order: [
|
||||||
|
|||||||
@@ -94,6 +94,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { getEventTypeLabel, getEventStatusLabel } from '@/utils/enumMappings';
|
import { getEventTypeLabel, getEventStatusLabel } from '@/utils/enumMappings';
|
||||||
import { ref, computed, watch } from 'vue';
|
import { ref, computed, watch } from 'vue';
|
||||||
|
import eventService from '../../services/eventService';
|
||||||
import TeamGeneration from './TeamGeneration.vue';
|
import TeamGeneration from './TeamGeneration.vue';
|
||||||
import Dialog from 'primevue/dialog';
|
import Dialog from 'primevue/dialog';
|
||||||
import ParticipantManagement from './ParticipantManagement.vue';
|
import ParticipantManagement from './ParticipantManagement.vue';
|
||||||
@@ -157,9 +158,33 @@ watch(() => eventModel.value.id, async (eventId) => {
|
|||||||
|
|
||||||
// 참가확정 참가자 목록을 계산하는 computed 속성
|
// 참가확정 참가자 목록을 계산하는 computed 속성
|
||||||
const confirmedParticipants = ref([]);
|
const confirmedParticipants = ref([]);
|
||||||
function updateConfirmedParticipants() {
|
async function updateConfirmedParticipants() {
|
||||||
|
try {
|
||||||
|
// 이벤트 참가자 필터링
|
||||||
const arr = eventModel.value.EventParticipants?.filter(p => p.status === 'confirmed' || p.status === 'pending') || [];
|
const arr = eventModel.value.EventParticipants?.filter(p => p.status === 'confirmed' || p.status === 'pending') || [];
|
||||||
|
|
||||||
|
// 참가자 데이터에 에버리지 정보 추가
|
||||||
|
if (arr.length > 0 && eventModel.value.id) {
|
||||||
|
// 최신 참가자 데이터 가져오기
|
||||||
|
const latestParticipants = await eventService.getEventParticipants(eventModel.value.id);
|
||||||
|
|
||||||
|
// 참가자 데이터 매핑 (에버리지 정보 포함)
|
||||||
|
confirmedParticipants.value = arr.map(p => {
|
||||||
|
// 최신 참가자 데이터에서 해당 참가자 찾기
|
||||||
|
const latestData = latestParticipants.find(lp => lp.id === p.id);
|
||||||
|
if (latestData) {
|
||||||
|
// 최신 데이터로 업데이트 (에버리지 정보 포함)
|
||||||
|
return latestData;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
confirmedParticipants.value = arr;
|
confirmedParticipants.value = arr;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('참가자 데이터 업데이트 중 오류:', error);
|
||||||
|
confirmedParticipants.value = eventModel.value.EventParticipants?.filter(p => p.status === 'confirmed' || p.status === 'pending') || [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 최초 및 eventModel 변경 시 동기화
|
// 최초 및 eventModel 변경 시 동기화
|
||||||
watch(() => eventModel.value.EventParticipants, updateConfirmedParticipants, { immediate: true, deep: true });
|
watch(() => eventModel.value.EventParticipants, updateConfirmedParticipants, { immediate: true, deep: true });
|
||||||
|
|||||||
@@ -44,6 +44,8 @@
|
|||||||
<span class="badge bg-primary text-white mr-1">{{ mIdx + 1 }}</span>
|
<span class="badge bg-primary text-white mr-1">{{ mIdx + 1 }}</span>
|
||||||
<span>{{ member.name }}</span>
|
<span>{{ member.name }}</span>
|
||||||
<span v-if="getMemberAverage(member) !== null" class="text-xs text-gray-700 ml-1">({{ getMemberAverage(member) }})</span>
|
<span v-if="getMemberAverage(member) !== null" class="text-xs text-gray-700 ml-1">({{ getMemberAverage(member) }})</span>
|
||||||
|
<span v-if="getMemberGender(member) === 'male'" class="gender-icon male ml-1" title="남성">♂</span>
|
||||||
|
<span v-else-if="getMemberGender(member) === 'female'" class="gender-icon female ml-1" title="여성">♀</span>
|
||||||
<Button icon="pi pi-times" class="p-button-text p-button-danger p-0" @click="removeMemberFromTeam(idx, mIdx)" v-if="team.members.length > 0" />
|
<Button icon="pi pi-times" class="p-button-text p-button-danger p-0" @click="removeMemberFromTeam(idx, mIdx)" v-if="team.members.length > 0" />
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
@@ -62,6 +64,8 @@
|
|||||||
<span v-if="getMemberAverage(slotProps.option) !== null" class="text-xs text-gray-700 ml-1">
|
<span v-if="getMemberAverage(slotProps.option) !== null" class="text-xs text-gray-700 ml-1">
|
||||||
({{ getMemberAverage(slotProps.option) }})
|
({{ getMemberAverage(slotProps.option) }})
|
||||||
</span>
|
</span>
|
||||||
|
<span v-if="getMemberGender(slotProps.option) === 'male'" class="gender-icon male ml-1" title="남성">♂</span>
|
||||||
|
<span v-else-if="getMemberGender(slotProps.option) === 'female'" class="gender-icon female ml-1" title="여성">♀</span>
|
||||||
</template>
|
</template>
|
||||||
<template #value="slotProps">
|
<template #value="slotProps">
|
||||||
<span v-if="slotProps.value">
|
<span v-if="slotProps.value">
|
||||||
@@ -69,6 +73,8 @@
|
|||||||
<span v-if="getMemberAverage(slotProps.value) !== null" class="text-xs text-gray-700 ml-1">
|
<span v-if="getMemberAverage(slotProps.value) !== null" class="text-xs text-gray-700 ml-1">
|
||||||
({{ getMemberAverage(slotProps.value) }})
|
({{ getMemberAverage(slotProps.value) }})
|
||||||
</span>
|
</span>
|
||||||
|
<span v-if="getMemberGender(slotProps.value) === 'male'" class="gender-icon male ml-1" title="남성">♂</span>
|
||||||
|
<span v-else-if="getMemberGender(slotProps.value) === 'female'" class="gender-icon female ml-1" title="여성">♀</span>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</Select>
|
</Select>
|
||||||
@@ -102,19 +108,62 @@ import { ref, computed, watch, unref } from 'vue';
|
|||||||
|
|
||||||
// 참가자 에버리지 구하기
|
// 참가자 에버리지 구하기
|
||||||
function getMemberAverage(member) {
|
function getMemberAverage(member) {
|
||||||
if (!member.id) return null;
|
if (!member || !member.id) return null;
|
||||||
|
|
||||||
|
// 객체 자체에서 에버리지 값 추출 시도
|
||||||
|
if (member.average !== undefined && member.average !== null) {
|
||||||
|
return Number(member.average);
|
||||||
|
}
|
||||||
|
|
||||||
// 원본 참가자 객체에서 id로 찾아서 평균값 추출
|
// 원본 참가자 객체에서 id로 찾아서 평균값 추출
|
||||||
const arr = unref(props.participants);
|
const arr = unref(props.participants);
|
||||||
const p = arr.find(x => x.id === member.id);
|
const p = arr.find(x => x.id === member.id || x.participantId === member.id || x.memberId === member.id);
|
||||||
|
|
||||||
if (!p) return null;
|
if (!p) return null;
|
||||||
if (p.Member && typeof p.Member.average === 'number') return p.Member.average;
|
|
||||||
if (typeof p.average === 'number') return p.average;
|
// 다양한 구조에서 값 추출 시도
|
||||||
if (typeof p.averageScore === 'number') return p.averageScore;
|
if (p.Member && p.Member.average !== undefined && p.Member.average !== null) {
|
||||||
|
return Number(p.Member.average);
|
||||||
|
}
|
||||||
|
if (p.average !== undefined && p.average !== null) {
|
||||||
|
return Number(p.average);
|
||||||
|
}
|
||||||
|
if (p.averageScore !== undefined && p.averageScore !== null) {
|
||||||
|
return Number(p.averageScore);
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// 팀 에버리지(평균)
|
|
||||||
|
// 참가자 성별 정보 가져오기
|
||||||
|
function getMemberGender(member) {
|
||||||
|
if (!member) return null;
|
||||||
|
|
||||||
|
// 객체 자체에서 성별 정보 추출 시도
|
||||||
|
if (member.gender) {
|
||||||
|
return member.gender;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 원본 참가자 객체에서 찾기
|
||||||
|
const arr = unref(props.participants);
|
||||||
|
const p = arr.find(x => x.id === member.id || x.participantId === member.id || x.memberId === member.id);
|
||||||
|
|
||||||
|
if (!p) return null;
|
||||||
|
|
||||||
|
// Member 객체에서 성별 정보 확인
|
||||||
|
if (p.Member && p.Member.gender) {
|
||||||
|
return p.Member.gender;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// 팀 에버리지(평균) - 에버리지가 0인 사람은 제외
|
||||||
function getTeamAverage(team) {
|
function getTeamAverage(team) {
|
||||||
const avgs = team.members.map(getMemberAverage).filter(v => typeof v === 'number');
|
// 에버리지가 0보다 큰 값만 필터링
|
||||||
|
const avgs = team.members
|
||||||
|
.map(getMemberAverage)
|
||||||
|
.filter(v => typeof v === 'number' && v > 0);
|
||||||
|
|
||||||
if (!avgs.length) return 0;
|
if (!avgs.length) return 0;
|
||||||
return avgs.reduce((a, b) => a + b, 0) / avgs.length;
|
return avgs.reduce((a, b) => a + b, 0) / avgs.length;
|
||||||
}
|
}
|
||||||
@@ -345,5 +394,14 @@ watch(() => props.participants, () => {
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
margin-right: 0.25em;
|
margin-right: 0.25em;
|
||||||
}
|
}
|
||||||
|
.gender-icon {
|
||||||
|
font-size: 0.9em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.gender-icon.male {
|
||||||
|
color: #2196F3;
|
||||||
|
}
|
||||||
|
.gender-icon.female {
|
||||||
|
color: #E91E63;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user