휴가 여려년도 삭제 수정
This commit is contained in:
parent
9c01a84749
commit
3ac834dd4a
@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
/* 휴가 */
|
/* 휴가 */
|
||||||
|
|
||||||
|
.fc-daygrid-event {
|
||||||
|
pointer-events: none !important;
|
||||||
|
}
|
||||||
/* 이벤트 선 없게 */
|
/* 이벤트 선 없게 */
|
||||||
.fc-event {
|
.fc-event {
|
||||||
border: none;
|
border: none;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="isOpen" class="vac-modal-dialog" @click.self="closeModal">
|
<div v-if="isOpen" class="vac-modal-dialog" @click.self="closeModal">
|
||||||
<div class="vac-modal-content p-5 modal-scroll">
|
<div class="vac-modal-content p-5 modal-scroll">
|
||||||
<h5 class="vac-modal-title">📅 내 연차 사용 내역</h5>
|
<h5 class="vac-modal-title">📅 내 연차 상세 내역</h5>
|
||||||
<button class="close-btn" @click="closeModal">✖</button>
|
<button class="close-btn" @click="closeModal">✖</button>
|
||||||
<!-- 연차 목록 -->
|
<!-- 연차 목록 -->
|
||||||
<div class="vac-modal-body" v-if="mergedVacations.length > 0">
|
<div class="vac-modal-body" v-if="mergedVacations.length > 0">
|
||||||
@ -26,8 +26,8 @@
|
|||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
<!-- 연차 데이터 없음 -->
|
<!-- 연차 데이터 없음 -->
|
||||||
<p v-else class="text-sm-center mt-10 text-gray">
|
<p v-else class="text-sm-center mt-10 text-gray vac-modal-title">
|
||||||
🚫 사용한 연차가 없습니다.
|
🚫 연차 내역이 없습니다.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -114,7 +114,7 @@ const mergedVacations = computed(() => {
|
|||||||
|
|
||||||
// 모달 닫기
|
// 모달 닫기
|
||||||
const closeModal = () => {
|
const closeModal = () => {
|
||||||
emit("close");
|
emit("close");
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@ -69,12 +69,18 @@ nextTick(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const sortedUserList = computed(() => {
|
const sortedUserList = computed(() => {
|
||||||
if (!employeeId.value) return userList.value;
|
if (!employeeId.value) return [];
|
||||||
const myProfile = userList.value.find(user => user.MEMBERSEQ === employeeId.value);
|
|
||||||
const otherUsers = userList.value.filter(user => user.MEMBERSEQ !== employeeId.value);
|
// 관리자가 아닌 사용자만 필터링
|
||||||
return myProfile ? [myProfile, ...otherUsers] : userList.value;
|
const nonAdminUsers = userList.value.filter(user => user.MEMBERROL !== "ROLE_ADMIN");
|
||||||
|
|
||||||
|
const myProfile = nonAdminUsers.find(user => user.MEMBERSEQ === employeeId.value);
|
||||||
|
const otherUsers = nonAdminUsers.filter(user => user.MEMBERSEQ !== employeeId.value);
|
||||||
|
|
||||||
|
return myProfile ? [myProfile, ...otherUsers] : otherUsers;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const getUserProfileImage = (profilePath) =>
|
const getUserProfileImage = (profilePath) =>
|
||||||
profilePath && profilePath.trim() ? `${baseUrl}upload/img/profile/${profilePath}` : defaultProfile;
|
profilePath && profilePath.trim() ? `${baseUrl}upload/img/profile/${profilePath}` : defaultProfile;
|
||||||
|
|
||||||
|
|||||||
@ -142,7 +142,7 @@ const calendarOptions = reactive({
|
|||||||
datesSet: handleMonthChange,
|
datesSet: handleMonthChange,
|
||||||
events: calendarEvents,
|
events: calendarEvents,
|
||||||
});
|
});
|
||||||
// 캘린더 월 변경경
|
// 캘린더 월 변경
|
||||||
function handleMonthChange(viewInfo) {
|
function handleMonthChange(viewInfo) {
|
||||||
const currentDate = viewInfo.view.currentStart;
|
const currentDate = viewInfo.view.currentStart;
|
||||||
const year = currentDate.getFullYear();
|
const year = currentDate.getFullYear();
|
||||||
@ -154,16 +154,17 @@ function handleDateClick(info) {
|
|||||||
const clickedDateStr = info.dateStr;
|
const clickedDateStr = info.dateStr;
|
||||||
const clickedDate = info.date;
|
const clickedDate = info.date;
|
||||||
const todayStr = new Date().toISOString().split("T")[0];
|
const todayStr = new Date().toISOString().split("T")[0];
|
||||||
|
|
||||||
if (
|
if (
|
||||||
clickedDate.getDay() === 0 ||
|
clickedDate.getDay() === 0 ||
|
||||||
clickedDate.getDay() === 6 ||
|
clickedDate.getDay() === 6 ||
|
||||||
holidayDates.value.has(clickedDateStr) ||
|
holidayDates.value.has(clickedDateStr) ||
|
||||||
clickedDateStr < todayStr
|
clickedDateStr < todayStr
|
||||||
){
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const isMyVacation = myVacations.value.some(vac => {
|
const isMyVacation = myVacations.value.some(vac => {
|
||||||
const vacDate = vac.date ? String(vac.date).substring(0, 10) : "";
|
const vacDate = vac.date ? vac.date.substring(0, 10) : "";
|
||||||
return vacDate === clickedDateStr && !vac.receiverId;
|
return vacDate === clickedDateStr && !vac.receiverId;
|
||||||
});
|
});
|
||||||
if (isMyVacation) {
|
if (isMyVacation) {
|
||||||
@ -186,7 +187,6 @@ function handleDateClick(info) {
|
|||||||
selectedDates.value.set(clickedDateStr, type);
|
selectedDates.value.set(clickedDateStr, type);
|
||||||
halfDayType.value = null;
|
halfDayType.value = null;
|
||||||
updateCalendarEvents();
|
updateCalendarEvents();
|
||||||
// 날짜 선택 후 반차버튼 초기화
|
|
||||||
if (halfDayButtonsRef.value) {
|
if (halfDayButtonsRef.value) {
|
||||||
halfDayButtonsRef.value.resetHalfDay();
|
halfDayButtonsRef.value.resetHalfDay();
|
||||||
}
|
}
|
||||||
@ -266,15 +266,24 @@ const handleProfileClick = async (user) => {
|
|||||||
const fetchUserList = async () => {
|
const fetchUserList = async () => {
|
||||||
try {
|
try {
|
||||||
await userListStore.fetchUserList();
|
await userListStore.fetchUserList();
|
||||||
userList.value = userListStore.userList;
|
|
||||||
|
// "ROLE_ADMIN"을 제외하고 필터링
|
||||||
|
const filteredUsers = userListStore.userList.filter(user => user.MEMBERROL !== "ROLE_ADMIN");
|
||||||
|
|
||||||
|
// 필터링된 리스트를 userList에 반영
|
||||||
|
userList.value = [...filteredUsers];
|
||||||
|
|
||||||
if (!userList.value.length) {
|
if (!userList.value.length) {
|
||||||
console.warn("📌 사용자 목록이 비어 있음!");
|
console.warn("📌 사용자 목록이 비어 있음!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 사용자별 색상 저장
|
||||||
userColors.value = {};
|
userColors.value = {};
|
||||||
userList.value.forEach((user) => {
|
userList.value.forEach((user) => {
|
||||||
userColors.value[user.MEMBERSEQ] = user.usercolor;
|
userColors.value[user.MEMBERSEQ] = user.usercolor;
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("📌 사용자 목록 불러오기 오류:", error);
|
console.error("📌 사용자 목록 불러오기 오류:", error);
|
||||||
}
|
}
|
||||||
@ -310,47 +319,54 @@ const filteredReceivedVacations = computed(() => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* 휴가 저장 */
|
||||||
/* 휴가 변경사항 저장 */
|
// 휴가 변경사항 저장
|
||||||
async function saveVacationChanges() {
|
async function saveVacationChanges() {
|
||||||
if (!hasChanges.value) return;
|
if (!hasChanges.value) return;
|
||||||
|
|
||||||
const selectedDatesArray = Array.from(selectedDates.value);
|
const selectedDatesArray = Array.from(selectedDates.value);
|
||||||
const vacationsToAdd = selectedDatesArray
|
|
||||||
.filter(([date, type]) => type !== "delete")
|
const vacationChangesByYear = selectedDatesArray.reduce((acc, [date, type]) => {
|
||||||
.filter(([date, type]) =>
|
const year = date.split("-")[0]; // YYYY-MM-DD에서 YYYY 추출
|
||||||
!myVacations.value.some(vac => vac.date && vac.date.startsWith(date)) ||
|
if (!acc[year]) acc[year] = { add: [], delete: [] };
|
||||||
myVacations.value.some(vac => vac.date && vac.date.startsWith(date) && vac.receiverId)
|
|
||||||
)
|
if (type !== "delete") {
|
||||||
.map(([date, type]) => ({ date, type }));
|
acc[year].add.push({ date, type });
|
||||||
const vacationsToDelete = myVacations.value
|
|
||||||
.filter(vac => {
|
|
||||||
if (!vac.date) return false;
|
|
||||||
const date = vac.date.split("T")[0];
|
|
||||||
return selectedDates.value.get(date) === "delete" && !vac.receiverId;
|
|
||||||
})
|
|
||||||
.map(vac => {
|
|
||||||
const id = vac.id;
|
|
||||||
return typeof id === "number" ? Number(id) : id;
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
const response = await axios.post("vacation/batchUpdate", {
|
|
||||||
add: vacationsToAdd,
|
|
||||||
delete: vacationsToDelete
|
|
||||||
});
|
|
||||||
if (response.data && response.data.status === "OK") {
|
|
||||||
toastStore.onToast('휴가 변경 사항이 저장되었습니다.', 's');
|
|
||||||
await fetchVacationHistory(lastRemainingYear.value);
|
|
||||||
await fetchRemainingVacation();
|
|
||||||
if (isModalOpen.value) {
|
|
||||||
await fetchVacationHistory(lastRemainingYear.value);
|
|
||||||
}
|
|
||||||
const currentDate = fullCalendarRef.value.getApi().getDate();
|
|
||||||
await loadCalendarData(currentDate.getFullYear(), currentDate.getMonth() + 1);
|
|
||||||
selectedDates.value.clear();
|
|
||||||
updateCalendarEvents();
|
|
||||||
} else {
|
} else {
|
||||||
toastStore.onToast('휴가 저장 중 오류가 발생했습니다.', 'e');
|
acc[year].delete.push(date);
|
||||||
}
|
}
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
try {
|
||||||
|
for (const year of Object.keys(vacationChangesByYear)) {
|
||||||
|
const vacationsToAdd = vacationChangesByYear[year].add;
|
||||||
|
|
||||||
|
const vacationsToDeleteForYear = myVacations.value
|
||||||
|
.filter(vac => {
|
||||||
|
if (!vac.date) return false;
|
||||||
|
const vacDate = vac.date.split("T")[0];
|
||||||
|
return vacationChangesByYear[year].delete.includes(vacDate);
|
||||||
|
})
|
||||||
|
.map(vac => vac.id);
|
||||||
|
if (vacationsToAdd.length > 0 || vacationsToDeleteForYear.length > 0) {
|
||||||
|
const response = await axios.post("vacation/batchUpdate", {
|
||||||
|
add: vacationsToAdd,
|
||||||
|
delete: vacationsToDeleteForYear,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.data && response.data.status === "OK") {
|
||||||
|
toastStore.onToast(`휴가 변경 사항이 저장되었습니다.`, 's');
|
||||||
|
await fetchVacationHistory(year);
|
||||||
|
} else {
|
||||||
|
toastStore.onToast(`휴가 변경 중 오류가 발생했습니다.`, 'e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await fetchRemainingVacation();
|
||||||
|
selectedDates.value.clear();
|
||||||
|
updateCalendarEvents();
|
||||||
|
const currentDate = fullCalendarRef.value.getApi().getDate();
|
||||||
|
await loadCalendarData(currentDate.getFullYear(), currentDate.getMonth() + 1);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("🚨 휴가 변경 저장 실패:", error);
|
console.error("🚨 휴가 변경 저장 실패:", error);
|
||||||
toastStore.onToast('휴가 저장 요청에 실패했습니다.', 'e');
|
toastStore.onToast('휴가 저장 요청에 실패했습니다.', 'e');
|
||||||
@ -363,15 +379,11 @@ async function fetchVacationHistory(year) {
|
|||||||
try {
|
try {
|
||||||
const response = await axios.get(`vacation/history?year=${year}`);
|
const response = await axios.get(`vacation/history?year=${year}`);
|
||||||
if (response.status === 200 && response.data) {
|
if (response.status === 200 && response.data) {
|
||||||
myVacations.value = response.data.data.usedVacations || [];
|
// 기존 데이터 유지 + 새로운 연도 데이터 추가
|
||||||
receivedVacations.value = response.data.data.receivedVacations || [];
|
myVacations.value = [...myVacations.value, ...response.data.data.usedVacations || []];
|
||||||
} else {
|
|
||||||
console.warn("❌ 연차 내역을 불러오지 못했습니다.");
|
|
||||||
myVacations.value = [];
|
|
||||||
receivedVacations.value = [];
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("🚨 연차 데이터 불러오기 실패:", error);
|
console.error(`🚨 ${year}년 휴가 데이터 불러오기 실패:`, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 모든 사원 연차 내역 및 그래프화
|
// 모든 사원 연차 내역 및 그래프화
|
||||||
@ -480,8 +492,10 @@ function preventUnsavedChanges(event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* watch */
|
/* watch */
|
||||||
watch(lastRemainingYear, async (newYear, oldYear) => {
|
watch(() => lastRemainingYear.value, async (newYear, oldYear) => {
|
||||||
await fetchVacationHistory(newYear);
|
if (newYear !== oldYear) {
|
||||||
|
await fetchVacationHistory(newYear);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
// `selectedDates` 변경 시 반차 버튼 초기화
|
// `selectedDates` 변경 시 반차 버튼 초기화
|
||||||
watch(
|
watch(
|
||||||
@ -551,17 +565,17 @@ onMounted(async () => {
|
|||||||
if (titleEl) {
|
if (titleEl) {
|
||||||
titleEl.style.cursor = 'pointer';
|
titleEl.style.cursor = 'pointer';
|
||||||
titleEl.addEventListener('click', () => {
|
titleEl.addEventListener('click', () => {
|
||||||
const dpEl = calendarDatepicker.value;
|
const dpEl = calendarDatepicker.value;
|
||||||
dpEl.style.display = 'block';
|
dpEl.style.display = 'block';
|
||||||
dpEl.style.position = 'fixed';
|
dpEl.style.position = 'fixed';
|
||||||
dpEl.style.top = '25%';
|
dpEl.style.top = '25%';
|
||||||
dpEl.style.left = '50%';
|
dpEl.style.left = '50%';
|
||||||
dpEl.style.transform = 'translate(-50%, -50%)';
|
dpEl.style.transform = 'translate(-50%, -50%)';
|
||||||
dpEl.style.zIndex = '9999';
|
dpEl.style.zIndex = '9999';
|
||||||
dpEl.style.border = 'none';
|
dpEl.style.border = 'none';
|
||||||
dpEl.style.outline = 'none';
|
dpEl.style.outline = 'none';
|
||||||
dpEl.style.backgroundColor = 'transparent';
|
dpEl.style.backgroundColor = 'transparent';
|
||||||
fpInstance.open();
|
fpInstance.open();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user