오류 수정, 통계 보강
This commit is contained in:
@@ -19,8 +19,8 @@
|
||||
<TabPanel value="기본정보">
|
||||
<div class="event-details p-3">
|
||||
<div class="flex align-items-center gap-2 mb-3">
|
||||
<Badge :value="getEventTypeName(eventModel.eventType)" :severity="getStatusSeverity(eventModel.status)" />
|
||||
<Badge :value="getStatusName(eventModel.status)" :severity="getStatusSeverity(eventModel.status)" />
|
||||
<Badge :value="getEventTypeLabel(eventModel.eventType)" :severity="getEventTypeSeverity(eventModel.eventType)" />
|
||||
<Badge :value="getEventStatusLabel(eventModel.status)" :severity="getStatusSeverity(eventModel.status)" />
|
||||
</div>
|
||||
<div class="card surface-100 p-3 mb-3">
|
||||
<div class="grid">
|
||||
@@ -92,6 +92,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { getEventTypeLabel, getEventStatusLabel } from '@/utils/enumMappings';
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import TeamGeneration from './TeamGeneration.vue';
|
||||
import Dialog from 'primevue/dialog';
|
||||
@@ -101,8 +102,8 @@ import ScoreManagement from './ScoreManagement.vue';
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean, required: true },
|
||||
event: { type: Object, default: () => ({}) },
|
||||
getEventTypeName: { type: Function, required: true },
|
||||
getStatusName: { type: Function, required: true },
|
||||
// getEventTypeName, getStatusName prop 제거 (enumMappings.js 함수로 일원화)
|
||||
getEventTypeSeverity: { type: Function, required: true },
|
||||
getStatusSeverity: { type: Function, required: true },
|
||||
formatDate: { type: Function, required: true },
|
||||
// 팀 기능 사용 권한 여부
|
||||
@@ -157,7 +158,7 @@ watch(() => eventModel.value.id, async (eventId) => {
|
||||
// 참가확정 참가자 목록을 계산하는 computed 속성
|
||||
const confirmedParticipants = ref([]);
|
||||
function updateConfirmedParticipants() {
|
||||
const arr = eventModel.value.EventParticipants?.filter(p => p.status === '참가확정' || p.status === '참가예정') || [];
|
||||
const arr = eventModel.value.EventParticipants?.filter(p => p.status === 'confirmed' || p.status === 'pending') || [];
|
||||
confirmedParticipants.value = arr;
|
||||
}
|
||||
// 최초 및 eventModel 변경 시 동기화
|
||||
|
||||
@@ -21,13 +21,13 @@
|
||||
|
||||
<div class="col-12 md:col-6">
|
||||
<label for="eventType">이벤트 유형 *</label>
|
||||
<Select id="eventType" v-model="eventModel.eventType" variant="filled" :options="eventTypeOptions" optionLabel="name" optionValue="value" placeholder="유형 선택" :class="{'p-invalid': submitted && !eventModel.eventType, 'w-full': true}"/>
|
||||
<Select id="eventType" v-model="eventModel.eventType" variant="filled" :options="EVENT_TYPE_OPTIONS" optionLabel="name" optionValue="value" placeholder="유형 선택" :class="{'p-invalid': submitted && !eventModel.eventType, 'w-full': true}"/>
|
||||
<small class="p-error" v-if="submitted && !eventModel.eventType">이벤트 유형은 필수입니다.</small>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-6">
|
||||
<label for="status">상태 *</label>
|
||||
<Select id="status" v-model="eventModel.status" :options="statusOptions" optionLabel="name" optionValue="value" placeholder="상태 선택" :class="{'p-invalid': submitted && !eventModel.status, 'w-full': true}" />
|
||||
<Select id="status" v-model="eventModel.status" :options="EVENT_STATUS_OPTIONS" optionLabel="name" optionValue="value" placeholder="상태 선택" :class="{'p-invalid': submitted && !eventModel.status, 'w-full': true}" />
|
||||
<small class="p-error" v-if="submitted && !eventModel.status">상태는 필수입니다.</small>
|
||||
</div>
|
||||
|
||||
@@ -96,17 +96,17 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch, toRefs, computed } from 'vue';
|
||||
import { ref, watch } from 'vue';
|
||||
import InputGroup from 'primevue/inputgroup';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const statusOptions = [
|
||||
{ name: '준비', value: '준비' },
|
||||
{ name: '활성', value: '활성' },
|
||||
{ name: '완료', value: '완료' },
|
||||
{ name: '취소', value: '취소' },
|
||||
{ name: '삭제', value: '삭제' }
|
||||
];
|
||||
import {
|
||||
EVENT_TYPE_OPTIONS,
|
||||
EVENT_STATUS_OPTIONS,
|
||||
getEventTypeLabel,
|
||||
getEventStatusLabel,
|
||||
getEventTypeSeverity,
|
||||
getStatusSeverity
|
||||
} from '@/utils/enumMappings';
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
@@ -129,18 +129,12 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits(['update:visible', 'save', 'hide']);
|
||||
|
||||
// 이벤트 타입 옵션
|
||||
const eventTypeOptions = [
|
||||
{ name: '정기전', value: '정기전' },
|
||||
{ name: '번개', value: '번개' },
|
||||
{ name: '연습', value: '연습' },
|
||||
{ name: '교류전', value: '교류전' },
|
||||
{ name: '이벤트', value: '이벤트' },
|
||||
{ name: '기타', value: '기타' }
|
||||
];
|
||||
|
||||
// 이벤트 모델
|
||||
const eventModel = ref({ ...props.event });
|
||||
const eventModel = ref({
|
||||
...props.event,
|
||||
status: props.event.status ?? 'ready',
|
||||
eventType: props.event.eventType ?? 'regular'
|
||||
});
|
||||
import { useToast } from 'primevue/usetoast';
|
||||
const toast = useToast();
|
||||
const loadingHash = ref(false);
|
||||
@@ -158,7 +152,9 @@ watch(() => props.event, (newValue) => {
|
||||
...newValue,
|
||||
startDate: formatDate(newValue.startDate),
|
||||
endDate: formatDate(newValue.endDate),
|
||||
registrationDeadline: formatDate(newValue.registrationDeadline)
|
||||
registrationDeadline: formatDate(newValue.registrationDeadline),
|
||||
status: newValue.status ?? 'ready',
|
||||
eventType: newValue.eventType ?? 'regular'
|
||||
};
|
||||
eventModel.value = formattedEvent;
|
||||
}, { deep: true });
|
||||
|
||||
@@ -251,7 +251,7 @@
|
||||
<Select
|
||||
id="eventType"
|
||||
v-model="eventData.eventType"
|
||||
:options="eventTypeOptions"
|
||||
:options="EVENT_TYPE_OPTIONS"
|
||||
optionLabel="name"
|
||||
optionValue="value"
|
||||
placeholder="이벤트 유형 선택"
|
||||
@@ -359,7 +359,7 @@
|
||||
</div>
|
||||
<div class="summary-item">
|
||||
<span class="summary-label">유형:</span>
|
||||
<span class="summary-value">{{ getEventTypeName(eventData.eventType) }}</span>
|
||||
<span class="summary-value">{{ getEventTypeLabel(eventData.eventType) }}</span>
|
||||
</div>
|
||||
<div class="summary-item">
|
||||
<span class="summary-label">시작일:</span>
|
||||
@@ -493,12 +493,12 @@
|
||||
|
||||
<div class="field col-6 mb-3">
|
||||
<label for="newMemberGender" class="mb-1">성별</label>
|
||||
<Select id="newMemberGender" v-model="newMember.gender" :options="genderOptions" optionLabel="name" optionValue="code" placeholder="성별 선택" class="w-full" />
|
||||
<Select id="newMemberGender" v-model="newMember.gender" :options="GENDER_OPTIONS" optionLabel="name" optionValue="value" placeholder="성별 선택" class="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-6 mb-3">
|
||||
<label for="newMemberType" class="mb-1">회원 유형</label>
|
||||
<Select id="newMemberType" v-model="newMember.memberType" :options="memberTypeOptions" optionLabel="name" optionValue="code" placeholder="회원 유형 선택" class="w-full" :disabled="newMemberMode === 'guest'" />
|
||||
<Select id="newMemberType" v-model="newMember.memberType" :options="MEMBER_TYPE_OPTIONS" optionLabel="name" optionValue="code" placeholder="회원 유형 선택" class="w-full" :disabled="newMemberMode === 'guest'" />
|
||||
</div>
|
||||
|
||||
<div class="field col-6 mb-3">
|
||||
@@ -518,7 +518,7 @@
|
||||
|
||||
<div class="field col-6 mb-3">
|
||||
<label for="newMemberStatus" class="mb-1">상태</label>
|
||||
<Select id="newMemberStatus" v-model="newMember.status" :options="statusOptions" optionLabel="label" optionValue="value" placeholder="상태 선택" class="w-full" />
|
||||
<Select id="newMemberStatus" v-model="newMember.status" :options="STATUS_OPTIONS" optionLabel="label" optionValue="value" placeholder="상태 선택" class="w-full" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -530,8 +530,21 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, watch } from 'vue';
|
||||
import {
|
||||
getEventTypeLabel,
|
||||
getStatusLabel,
|
||||
getPaymentStatusLabel,
|
||||
getMemberTypeLabel,
|
||||
getGenderLabel,
|
||||
EVENT_TYPE_OPTIONS,
|
||||
STATUS_OPTIONS,
|
||||
PAYMENT_STATUS_OPTIONS,
|
||||
MEMBER_TYPE_OPTIONS,
|
||||
GENDER_OPTIONS
|
||||
} from '@/utils/enumMappings';
|
||||
import { ref, reactive, computed, watch, nextTick, onMounted } from 'vue';
|
||||
import { useToast } from 'primevue/usetoast';
|
||||
import dayjs from 'dayjs';
|
||||
import { useClubStore } from '@/stores/clubStore';
|
||||
import eventService from '@/services/eventService';
|
||||
import clubService from '@/services/clubService';
|
||||
@@ -661,37 +674,7 @@ const newMember = ref({
|
||||
status: 'active'
|
||||
});
|
||||
|
||||
// 성별 옵션
|
||||
const genderOptions = [
|
||||
{ name: '남성', code: '남성' },
|
||||
{ name: '여성', code: '여성' }
|
||||
];
|
||||
|
||||
// 회원 유형 옵션
|
||||
const memberTypeOptions = [
|
||||
{ name: '정회원', code: '정회원' },
|
||||
{ name: '준회원', code: '준회원' },
|
||||
{ name: '명예회원', code: '명예회원' },
|
||||
{ name: '운영진', code: '운영진' },
|
||||
{ name: '게스트', code: '게스트' }
|
||||
];
|
||||
|
||||
// 상태 옵션
|
||||
const statusOptions = [
|
||||
{ label: '활성', value: 'active' },
|
||||
{ label: '비활성', value: 'inactive' },
|
||||
{ label: '정지', value: 'suspended' }
|
||||
];
|
||||
|
||||
// 이벤트 유형 옵션
|
||||
const eventTypeOptions = [
|
||||
{ name: '정기전', value: '정기전' },
|
||||
{ name: '번개', value: '번개' },
|
||||
{ name: '연습', value: '연습' },
|
||||
{ name: '교류전', value: '교류전' },
|
||||
{ name: '이벤트', value: '이벤트' },
|
||||
{ name: '기타', value: '기타' }
|
||||
];
|
||||
|
||||
// 점수에 핸디캡 포함 여부
|
||||
const scoresIncludeHandicap = ref(false);
|
||||
@@ -714,7 +697,7 @@ const loadClubMembers = async () => {
|
||||
clubMembers.value = response.data.map(member => ({
|
||||
id: member.id,
|
||||
name: member.name,
|
||||
gender: member.gender,
|
||||
gender: getGenderLabel(member.gender),
|
||||
average: member.average || 0,
|
||||
handicap: member.handicap || 0
|
||||
}));
|
||||
@@ -1098,11 +1081,7 @@ const getUniqueTeamCount = () => {
|
||||
return teams.size;
|
||||
};
|
||||
|
||||
// 이벤트 유형 이름 조회
|
||||
const getEventTypeName = (type) => {
|
||||
const option = eventTypeOptions.find(opt => opt.value === type);
|
||||
return option ? option.name : type;
|
||||
};
|
||||
|
||||
|
||||
// 날짜 포맷
|
||||
const formatDate = (date) => {
|
||||
|
||||
@@ -23,17 +23,17 @@
|
||||
</Column>
|
||||
<Column field="Member.memberType" header="회원 유형" sortable>
|
||||
<template #body="slotProps">
|
||||
<Badge :value="getMemberTypeName(slotProps.data.Member.memberType)" :severity="getMemberTypeSeverity(slotProps.data.Member.memberType)" />
|
||||
<Badge :value="getMemberTypeLabel(slotProps.data.Member.memberType)" :severity="getMemberTypeSeverity(slotProps.data.Member.memberType)" />
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="status" header="참가 상태" sortable>
|
||||
<template #body="slotProps">
|
||||
<Badge :value="getStatusName(slotProps.data.status)" :severity="getStatusSeverity(slotProps.data.status)" />
|
||||
<Badge :value="getParticipantStatusLabel(slotProps.data.status)" :severity="getParticipantStatusSeverity(slotProps.data.status)" />
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="paymentStatus" header="결제 상태" sortable>
|
||||
<template #body="slotProps">
|
||||
<Badge :value="getPaymentStatusName(slotProps.data.paymentStatus)" :severity="getPaymentStatusSeverity(slotProps.data.paymentStatus)" />
|
||||
<Badge :value="getPaymentStatusLabel(slotProps.data.paymentStatus)" :severity="getPaymentStatusSeverity(slotProps.data.paymentStatus)" />
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="createdAt" header="등록일" sortable>
|
||||
@@ -72,7 +72,7 @@
|
||||
<Select
|
||||
id="status"
|
||||
v-model="editingParticipant.status"
|
||||
:options="participantStatusOptions"
|
||||
:options="PARTICIPANT_STATUS_OPTIONS"
|
||||
optionLabel="name"
|
||||
optionValue="value"
|
||||
placeholder="상태를 선택하세요"
|
||||
@@ -85,7 +85,7 @@
|
||||
<Select
|
||||
id="paymentStatus"
|
||||
v-model="editingParticipant.paymentStatus"
|
||||
:options="paymentStatusOptions"
|
||||
:options="PAYMENT_STATUS_OPTIONS"
|
||||
optionLabel="name"
|
||||
optionValue="value"
|
||||
placeholder="결제 상태를 선택하세요"
|
||||
@@ -114,6 +114,16 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
PARTICIPANT_STATUS_OPTIONS,
|
||||
PAYMENT_STATUS_OPTIONS,
|
||||
getMemberTypeLabel,
|
||||
getMemberTypeSeverity,
|
||||
getParticipantStatusLabel,
|
||||
getParticipantStatusSeverity,
|
||||
getPaymentStatusLabel,
|
||||
getPaymentStatusSeverity
|
||||
} from '@/utils/enumMappings';
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { useToast } from 'primevue/usetoast';
|
||||
import eventService from '@/services/eventService';
|
||||
@@ -142,22 +152,11 @@ const clubId = ref(localStorage.getItem('clubId') || null);
|
||||
const editingParticipant = ref({
|
||||
clubId: clubId.value,
|
||||
memberId: null,
|
||||
status: '참가예정',
|
||||
paymentStatus: '미납'
|
||||
status: 'pending',
|
||||
paymentStatus: 'unpaid'
|
||||
});
|
||||
const participantToDelete = ref(null);
|
||||
|
||||
const participantStatusOptions = [
|
||||
{ name: '참가 예정', value: '참가예정' },
|
||||
{ name: '참가 확정', value: '참가확정' },
|
||||
{ name: '취소', value: '취소' }
|
||||
];
|
||||
|
||||
const paymentStatusOptions = [
|
||||
{ name: '미납', value: '미납' },
|
||||
{ name: '납부 완료', value: '납부완료' }
|
||||
];
|
||||
|
||||
const fetchParticipants = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
@@ -179,8 +178,8 @@ const openNewDialog = () => {
|
||||
editingParticipant.value = {
|
||||
clubId: localStorage.getItem('clubId') || null,
|
||||
memberId: null,
|
||||
status: '참가예정',
|
||||
paymentStatus: '미납'
|
||||
status: 'pending',
|
||||
paymentStatus: 'unpaid'
|
||||
};
|
||||
submitted.value = false;
|
||||
participantDialog.value = true;
|
||||
@@ -284,58 +283,6 @@ const formatDate = (date) => {
|
||||
return dayjs(date).format('YYYY-MM-DD HH:mm');
|
||||
};
|
||||
|
||||
const getMemberTypeName = (type) => {
|
||||
const types = {
|
||||
regular: '정회원',
|
||||
associate: '준회원',
|
||||
guest: '게스트'
|
||||
};
|
||||
return types[type] || type;
|
||||
};
|
||||
|
||||
const getMemberTypeSeverity = (type) => {
|
||||
const severities = {
|
||||
regular: 'success',
|
||||
associate: 'info',
|
||||
guest: 'warning'
|
||||
};
|
||||
return severities[type] || 'info';
|
||||
};
|
||||
|
||||
const getStatusName = (status) => {
|
||||
const statuses = {
|
||||
참가예정: '참가 예정',
|
||||
참가완료: '참가 완료',
|
||||
취소: '취소'
|
||||
};
|
||||
return statuses[status] || status;
|
||||
};
|
||||
|
||||
const getStatusSeverity = (status) => {
|
||||
const severities = {
|
||||
참가예정: 'warning',
|
||||
참가완료: 'success',
|
||||
취소: 'danger'
|
||||
};
|
||||
return severities[status] || 'info';
|
||||
};
|
||||
|
||||
const getPaymentStatusName = (status) => {
|
||||
const statuses = {
|
||||
미납: '미납',
|
||||
납부완료: '납부 완료'
|
||||
};
|
||||
return statuses[status] || status;
|
||||
};
|
||||
|
||||
const getPaymentStatusSeverity = (status) => {
|
||||
const severities = {
|
||||
미납: 'danger',
|
||||
납부완료: 'success'
|
||||
};
|
||||
return severities[status] || 'info';
|
||||
};
|
||||
|
||||
const dialogTitle = computed(() => {
|
||||
return editingParticipant.value.id ? '참가자 정보 수정' : '참가자 추가';
|
||||
});
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<Select
|
||||
v-model="team._selectedMember"
|
||||
:options="availableMembersForTeam(idx)"
|
||||
optionLabel="name"
|
||||
:optionLabel="memberOptionLabel"
|
||||
placeholder="팀원 선택"
|
||||
style="width: 180px;"
|
||||
>
|
||||
@@ -88,6 +88,15 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
// 이름(에버리지)로 Select optionLabel 표시
|
||||
function memberOptionLabel(option) {
|
||||
if (!option) return '';
|
||||
const avg = getMemberAverage(option);
|
||||
return avg !== null && avg !== undefined && avg !== ''
|
||||
? `${option.name} (${avg})`
|
||||
: option.name;
|
||||
}
|
||||
|
||||
import draggable from 'vuedraggable'; // npm install vuedraggable@next 필요 (vue3)
|
||||
import { ref, computed, watch, unref } from 'vue';
|
||||
|
||||
@@ -161,7 +170,8 @@ function addMemberToTeam(teamIdx) {
|
||||
if (!team.members.some(m => m.id === member.id)) {
|
||||
team.members.push({ id: member.id, name: member.name });
|
||||
}
|
||||
team._selectedMember = null;
|
||||
// 모든 팀의 셀렉트 선택값을 초기화 (동일인 중복 선택 방지)
|
||||
teams.value.forEach(t => { t._selectedMember = null; });
|
||||
}
|
||||
|
||||
function removeMemberFromTeam(teamIdx, memberIdx) {
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<Tag :value="slotProps.value.group" :severity="slotProps.value.group === '참가자' ? 'success' : 'info'" class="mr-2" />
|
||||
<span style="font-weight:bold;">{{ slotProps.value.name }}</span>
|
||||
<span style="color:#888; font-size:0.93em; margin-left: 0.5em;">
|
||||
{{ slotProps.value.memberType }} / {{ slotProps.value.gender }} / 에버리지: {{ slotProps.value.average ?? '-' }}
|
||||
{{ getMemberTypeLabel(slotProps.value.memberType) }} / {{ getGenderLabel(slotProps.value.gender) }} / 에버리지: {{ slotProps.value.average ?? '-' }}
|
||||
</span>
|
||||
</div>
|
||||
<span v-else>
|
||||
@@ -46,7 +46,7 @@
|
||||
<Tag :value="slotProps.option.group" :severity="slotProps.option.group === '참가자' ? 'success' : 'info'" class="mr-2" />
|
||||
<span style="font-weight:bold;">{{ slotProps.option.name }}</span>
|
||||
<span style="color:#888; font-size:0.93em; margin-left: 0.5em;">
|
||||
{{ slotProps.option.memberType }} / {{ slotProps.option.gender }} / 에버리지: {{ slotProps.option.average ?? '-' }}
|
||||
{{ getMemberTypeLabel(slotProps.option.memberType) }} / {{ getGenderLabel(slotProps.option.gender) }} / 에버리지: {{ slotProps.option.average ?? '-' }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
@@ -65,7 +65,7 @@
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label>성별</label>
|
||||
<Select v-model="newGuest.gender" :options="genderOptions" optionLabel="label" optionValue="value" placeholder="성별 선택" class="w-full" />
|
||||
<Select v-model="newGuest.gender" :options="GENDER_OPTIONS" optionLabel="label" optionValue="value" placeholder="성별 선택" class="w-full" />
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label>에버리지</label>
|
||||
@@ -80,7 +80,7 @@
|
||||
<label>참가 상태</label>
|
||||
<Select
|
||||
v-model="status"
|
||||
:options="statusOptions"
|
||||
:options="STATUS_OPTIONS"
|
||||
optionLabel="label"
|
||||
optionValue="value"
|
||||
placeholder="상태를 선택하세요"
|
||||
@@ -118,6 +118,15 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
STATUS_OPTIONS,
|
||||
GENDER_OPTIONS,
|
||||
PAYMENT_STATUS_OPTIONS,
|
||||
getGenderLabel,
|
||||
getMemberTypeLabel,
|
||||
getStatusLabel,
|
||||
getPaymentStatusLabel
|
||||
} from '@/utils/enumMappings';
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import Tag from 'primevue/tag';
|
||||
import InputText from 'primevue/inputtext';
|
||||
@@ -198,24 +207,18 @@ const error = ref('');
|
||||
const submitted = ref(false);
|
||||
|
||||
const statusOptions = [
|
||||
{ label: '참가예정', value: '참가예정' },
|
||||
{ label: '참가확정', value: '참가확정' },
|
||||
{ label: '취소', value: '취소' }
|
||||
{ label: getStatusLabel('참가예정'), value: '참가예정' },
|
||||
{ label: getStatusLabel('참가확정'), value: '참가확정' },
|
||||
{ label: getStatusLabel('취소'), value: '취소' }
|
||||
];
|
||||
const paymentStatusOptions = [
|
||||
{ label: '미납', value: '미납' },
|
||||
{ label: '납부완료', value: '납부완료' }
|
||||
{ label: getPaymentStatusLabel('미납'), value: '미납' },
|
||||
{ label: getPaymentStatusLabel('납부완료'), value: '납부완료' }
|
||||
];
|
||||
|
||||
const newGuest = ref({ name: '', phone: '', gender: '' });
|
||||
|
||||
import PublicEventService from '@/services/PublicEventService';
|
||||
|
||||
const newGuest = ref({ name: '', phone: '', gender: '' });
|
||||
const genderOptions = [
|
||||
{ label: '남성', value: '남성' },
|
||||
{ label: '여성', value: '여성' }
|
||||
];
|
||||
|
||||
async function addNewGuest() {
|
||||
error.value = '';
|
||||
if (!newGuest.value.name || !newGuest.value.phone || !newGuest.value.gender) {
|
||||
|
||||
@@ -16,18 +16,9 @@
|
||||
<Tag v-if="member.isGuest" value="G" severity="warning" class="ml-2" />
|
||||
</div>
|
||||
<div class="info-under-name">
|
||||
{{ member.gender || '-' }}
|
||||
<span v-if="member.status" :class="{
|
||||
'status-cancel': member.status === '취소',
|
||||
'status-pending': member.status === '참가예정'
|
||||
}">
|
||||
· {{ member.status }}
|
||||
</span>
|
||||
<span v-if="member.paymentStatus" :class="{
|
||||
'payment-unpaid': member.paymentStatus === '미납'
|
||||
}">
|
||||
· {{ member.paymentStatus }}
|
||||
</span>
|
||||
{{ getGenderLabel(member.gender) || '-' }}
|
||||
<span v-if="member.status" :class="{ 'status-cancel': member.status === 'canceled', 'status-pending': member.status === 'pending' }">· {{ getParticipantStatusLabel(member.status) }}</span>
|
||||
<span v-if="member.paymentStatus" :class="{ 'payment-unpaid': member.paymentStatus === 'unpaid' }">· {{ getPaymentStatusLabel(member.paymentStatus) }}</span>
|
||||
</div>
|
||||
<div class="member-meta">핸디캡: {{ member.handicap ?? '-' }} / 에버리지: {{ member.average ?? '-' }}</div>
|
||||
<div class="member-meta">{{ member.comment }}</div>
|
||||
@@ -55,8 +46,16 @@
|
||||
@blur="onScoreBlur(member, n, teamNumber)"
|
||||
@keydown.enter="onScoreEnter(member, n, teamNumber)"
|
||||
/>
|
||||
<span v-else>{{ member.scores?.[n - 1] ?? '-' }}</span>
|
||||
|
||||
<span
|
||||
v-else-if="
|
||||
!canInputScore &&
|
||||
member.scores?.[n-1] &&
|
||||
Number(member.scores[n-1]?.score) !==
|
||||
Number(member.scores[n-1]?.score) + Number(member.scores[n-1]?.handicap ?? member.handicap ?? 0)
|
||||
"
|
||||
>
|
||||
{{ member.scores[n-1]?.score }}
|
||||
</span>
|
||||
<!-- 핸디캡 포함 점수 표시 -->
|
||||
<span :class="scoreColorClass(scoreStates[member.participantId + '-' + n], scoresProxy[member.participantId + '-' + n], member.handicap)"
|
||||
class="score-hc-value score-status-text"
|
||||
@@ -92,6 +91,8 @@
|
||||
<script setup>
|
||||
import { computed, onMounted, watch, ref } from 'vue';
|
||||
import { calculateIndividualRankings, getRankColorClass } from '@/utils/rankingUtils';
|
||||
import { getGenderLabel, getParticipantStatusLabel, getPaymentStatusLabel } from '@/utils/enumMappings';
|
||||
|
||||
const props = defineProps({
|
||||
title: String,
|
||||
members: Array,
|
||||
|
||||
Reference in New Issue
Block a user