188 lines
4.7 KiB
Vue
188 lines
4.7 KiB
Vue
<template>
|
|
<div v-if="isOpen" class="modal-dialog" @click.self="closeModal">
|
|
<div class="modal-content modal-scroll">
|
|
<h5 class="modal-title">📅 내 연차 사용 내역</h5>
|
|
<button class="close-btn" @click="closeModal">✖</button>
|
|
|
|
<!-- 연차 사용 및 받은 연차 리스트 -->
|
|
<div class="modal-body" v-if="mergedVacations.length > 0">
|
|
<ol class="vacation-list">
|
|
<li
|
|
v-for="(vacation, index) in mergedVacations"
|
|
:key="index"
|
|
class="vacation-item"
|
|
>
|
|
<span v-if="vacation.type === 'used'" class="vacation-index">
|
|
{{ totalUsedVacationCount - usedVacations.findIndex(v => v.date === vacation.date) }})
|
|
</span>
|
|
<span :class="vacation.type === 'used' ? 'minus-symbol' : 'plus-symbol'">
|
|
{{ vacation.type === 'used' ? '-' : '+' }}
|
|
</span>
|
|
<span
|
|
:style="{ color: userColors[vacation.senderId || vacation.receiverId] || '#000' }"
|
|
class="vacation-date"
|
|
>
|
|
{{ formatDate(vacation.date) }}
|
|
<span class="vacation-type">
|
|
({{ vacation.halfDay ? '반차' : '풀 연차' }})
|
|
<span v-if="vacation.senderId"> (보낸 연차)</span>
|
|
</span>
|
|
</span>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
|
|
<!-- 연차 데이터 없음 -->
|
|
<p v-if="mergedVacations.length === 0" class="no-data">
|
|
🚫 사용한 연차가 없습니다.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { defineProps, defineEmits, computed } from "vue";
|
|
|
|
const props = defineProps({
|
|
isOpen: Boolean,
|
|
myVacations: {
|
|
type: Array,
|
|
default: () => [],
|
|
},
|
|
receivedVacations: {
|
|
type: Array,
|
|
default: () => [],
|
|
},
|
|
userColors: {
|
|
type: Object,
|
|
default: () => ({}),
|
|
},
|
|
});
|
|
|
|
const emit = defineEmits(["close"]);
|
|
|
|
// ✅ 사용한 연차 개수
|
|
const totalUsedVacationCount = computed(() => props.myVacations.length);
|
|
|
|
// ✅ 사용한 연차 + 받은 연차 통합 후 내림차순 정렬
|
|
const usedVacations = computed(() =>
|
|
props.myVacations.map(v => ({ ...v, type: "used" }))
|
|
);
|
|
|
|
const receivedVacations = computed(() =>
|
|
props.receivedVacations.map(v => ({ ...v, type: "received" }))
|
|
);
|
|
|
|
// ✅ 정확한 정렬 및 리스트 병합
|
|
const mergedVacations = computed(() => {
|
|
return [...usedVacations.value, ...receivedVacations.value].sort(
|
|
(a, b) => new Date(b.date) - new Date(a.date)
|
|
);
|
|
});
|
|
|
|
// ✅ 날짜 형식 변환 (YYYY-MM-DD)
|
|
const formatDate = (dateString) => {
|
|
const date = new Date(dateString);
|
|
return date.toISOString().split("T")[0]; // YYYY-MM-DD 형식
|
|
};
|
|
|
|
const closeModal = () => {
|
|
emit("close");
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* 모달 스타일 */
|
|
.modal-dialog {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
/* 스크롤 가능한 모달 */
|
|
.modal-content {
|
|
max-height: 60vh;
|
|
overflow-y: auto;
|
|
padding: 20px;
|
|
width: 75%;
|
|
background: white;
|
|
border-radius: 8px;
|
|
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
/* 닫기 버튼 */
|
|
.close-btn {
|
|
position: absolute;
|
|
top: 10px;
|
|
right: 10px;
|
|
background: none;
|
|
border: none;
|
|
font-size: 18px;
|
|
cursor: pointer;
|
|
font-weight: bold;
|
|
}
|
|
|
|
/* 리스트 기본 스타일 */
|
|
.vacation-list {
|
|
list-style-type: none;
|
|
padding-left: 0;
|
|
margin-top: 15px;
|
|
}
|
|
|
|
/* 리스트 아이템 */
|
|
.vacation-item {
|
|
display: flex;
|
|
align-items: center;
|
|
font-size: 16px;
|
|
font-weight: bold;
|
|
margin-bottom: 8px;
|
|
padding: 5px 10px;
|
|
border-radius: 5px;
|
|
background: #f9f9f9;
|
|
}
|
|
|
|
/* 인덱스 (연차 사용 개수) */
|
|
.vacation-index {
|
|
font-weight: bold;
|
|
font-size: 16px;
|
|
margin-right: 8px;
|
|
color: #333;
|
|
}
|
|
|
|
/* "-" 빨간색 */
|
|
.minus-symbol {
|
|
color: red;
|
|
font-weight: bold;
|
|
margin-right: 8px;
|
|
}
|
|
|
|
/* "+" 파란색 */
|
|
plus-symbol {
|
|
color: blue;
|
|
font-weight: bold;
|
|
margin-right: 8px;
|
|
}
|
|
|
|
/* 날짜 스타일 */
|
|
.vacation-date {
|
|
font-size: 16px;
|
|
color: #333;
|
|
}
|
|
|
|
/* 연차 유형 스타일 */
|
|
.vacation-type {
|
|
font-size: 14px;
|
|
font-weight: normal;
|
|
color: gray;
|
|
margin-left: 5px;
|
|
}
|
|
|
|
/* 연차 데이터 없음 */
|
|
.no-data {
|
|
text-align: center;
|
|
font-size: 14px;
|
|
color: gray;
|
|
margin-top: 10px;
|
|
}
|
|
</style>
|