123 lines
3.7 KiB
Vue
123 lines
3.7 KiB
Vue
<template>
|
|
<div v-if="isOpen" class="vac-modal-dialog" @click.self="closeModal">
|
|
<div class="vac-modal-content p-5 modal-scroll">
|
|
<h5 class="vac-modal-title">📅 내 연차 상세 내역</h5>
|
|
<button class="close-btn" @click="closeModal">✖</button>
|
|
<!-- 연차 목록 -->
|
|
<div class="vac-modal-body" v-if="mergedVacations.length > 0">
|
|
<ol class="list-group-numbered px-0 mt-4">
|
|
<li
|
|
v-for="(vac, index) in mergedVacations"
|
|
:key="vac._expandIndex"
|
|
class="vacation-item"
|
|
>
|
|
<span v-if="vac.category === 'used'" class="fw-bold text-dark me-2">
|
|
{{ usedVacationIndexMap[vac._expandIndex] }})
|
|
</span>
|
|
<span :class="vac.category === 'used' ? 'fw-bold text-danger me-2' : 'fw-bold text-primary me-2'">
|
|
{{ vac.category === 'used' ? '-' : '+' }}
|
|
</span>
|
|
<span
|
|
:style="{ color: userColors[vac.senderId || vac.receiverId] || '#000' }"
|
|
>
|
|
{{ formatDate(vac.date) }}
|
|
</span>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<!-- 연차 데이터 없음 -->
|
|
<p v-else class="text-sm-center mt-10 text-gray vac-modal-title">
|
|
🚫 연차 내역이 없습니다.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { defineProps, defineEmits, computed } from "vue";
|
|
import { formatDate } from '@/common/formattedDate.js';
|
|
|
|
const props = defineProps({
|
|
isOpen: Boolean,
|
|
myVacations: {
|
|
type: Array,
|
|
default: () => [],
|
|
},
|
|
receivedVacations: {
|
|
type: Array,
|
|
default: () => [],
|
|
},
|
|
userColors: {
|
|
type: Object,
|
|
default: () => ({}),
|
|
},
|
|
});
|
|
|
|
const emit = defineEmits(["close"]);
|
|
|
|
// 사용한 휴가(선물,연차사용)
|
|
let globalCounter = 0;
|
|
const usedVacations = computed(() => {
|
|
const result = [];
|
|
props.myVacations.forEach((v) => {
|
|
const count = v.used_quota || 1;
|
|
for (let i = 0; i < count; i++) {
|
|
result.push({
|
|
...v,
|
|
category: "used",
|
|
code: v.LOCVACTYP,
|
|
_expandIndex: globalCounter++,
|
|
});
|
|
}
|
|
});
|
|
return result;
|
|
});
|
|
|
|
// 받은 휴가
|
|
const receivedVacations = computed(() =>
|
|
props.receivedVacations.map((v) => ({
|
|
...v,
|
|
category: "received",
|
|
}))
|
|
);
|
|
|
|
// 필터링
|
|
const sortedUsedVacationsAsc = computed(() => {
|
|
return [...usedVacations.value].sort((a, b) => {
|
|
return new Date(a.date) - new Date(b.date) || (a._expandIndex - b._expandIndex);
|
|
});
|
|
});
|
|
|
|
// 누적 인덱스 계산 type === "700103"이면 +1 그 외이면 +0.5
|
|
const usedVacationIndexMap = computed(() => {
|
|
let cumulative = 0;
|
|
const map = {};
|
|
sortedUsedVacationsAsc.value.forEach((item) => {
|
|
const increment = item.type === "700103" ? 1 : 0.5;
|
|
cumulative += increment;
|
|
map[item._expandIndex] = cumulative;
|
|
});
|
|
return map;
|
|
});
|
|
|
|
// 최종 표시할 merged 리스트 (Used + Received) 날짜 내림차순 정렬 (최신 → 과거)
|
|
const mergedVacations = computed(() => {
|
|
const all = [...usedVacations.value, ...receivedVacations.value];
|
|
// 날짜 내림차순 + 확장 인덱스 내림차순
|
|
all.sort((a, b) => {
|
|
const dateDiff = new Date(b.date) - new Date(a.date);
|
|
if (dateDiff !== 0) return dateDiff;
|
|
return b._expandIndex - a._expandIndex;
|
|
});
|
|
return all;
|
|
});
|
|
|
|
// 모달 닫기
|
|
const closeModal = () => {
|
|
emit("close");
|
|
};
|
|
</script>
|
|
<style scoped>
|
|
</style>
|
|
|