diff --git a/public/css/custom.css b/public/css/custom.css index a5afec2..be038c6 100644 --- a/public/css/custom.css +++ b/public/css/custom.css @@ -3,7 +3,6 @@ /* 휴가 */ - /* 이벤트 선 없게 */ .fc-event { border: none; @@ -94,8 +93,72 @@ opacity: 0.6; /* 흐려 보이게 */ } -/* 본인 모달 */ -/* 닫기 버튼 */ +/* 휴가 모달 */ +.vac-modal-dialog { + background: none !important; + box-shadow: none !important; + display: flex; + align-items: flex-end; + justify-content: center; + width: 100%; + height: 100%; + padding-bottom: 20px; +} +.vac-modal-content { + background: #fff; + padding: 20px; + border-radius: 8px; + box-shadow: 0px -4px 10px rgba(0, 0, 0, 0.1); /* 위쪽 그림자만 적용 */ + max-width: 500px; + width: 100%; + position: relative; +} +.vac-modal-body { + max-height: 140px; + overflow-y: auto; + } +.vac-modal-text { + font-size: 14px; + text-align: center; + margin-bottom: 20px; +} +.count-container { + display: flex; + align-items: center; + justify-content: center; + gap: 6px; + margin-bottom: 10px; +} +.count-value { + font-size: 23px; + font-weight: bold; + min-width: 50px; + text-align: center; +} +.custom-button { + background: none; + border: none; + width: 55px; + height: 55px; + font-size: 26px; + color: white; + border-radius: 50%; + cursor: pointer; + transition: all 0.2s; +} +.vac-modal-title { + margin-bottom: 10px; +} +.vacation-item { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + margin-bottom: 8px; + padding: 5px 10px; + border-radius: 5px; + background: #f9f9f9; +} .close-btn { position: absolute; top: 10px; @@ -108,42 +171,6 @@ opacity: 0.6; /* 흐려 보이게 */ .close-btn:hover { color: #525252; } -/* 모달 배경 투명하게 */ -.vac-modal-dialog { - background: none !important; - box-shadow: none !important; - display: flex; - align-items: center; - justify-content: center; - width: 100%; - height: 100%; - } - - /* 모달 본문 스타일 */ - .vac-modal-content { - background: #fff; - border-radius: 8px; - box-shadow: 0px -4px 10px rgba(0, 0, 0, 0.1); /* 위쪽 그림자만 적용 */ - padding: 20px; - max-width: 500px; - width: 100%; - position: relative; - } -/* 리스트 아이템 */ -.vacation-item { - display: flex; - align-items: center; - font-size: 16px; - font-weight: bold; - margin-bottom: 8px; - padding: 5px 10px; - border-radius: 5px; - background: #f9f9f9; -} - - -/* 선물하기 모달 */ -/* 연차 개수 버튼 */ .count-btn { font-size: 18px; padding: 2px 10px; @@ -160,29 +187,179 @@ opacity: 0.6; /* 흐려 보이게 */ background: #cccccc; cursor: not-allowed; } -/* 버튼 컨테이너 (우측 정렬) */ .custom-button-container { display: flex; justify-content: flex-end; align-items: center; } -/* 버튼 기본 스타일 */ .custom-button { - background: none; /* 배경색 없음 */ - border: none; /* 테두리 없음 */ - padding: 10px; /* 크기 조정 */ - cursor: pointer; /* 클릭 가능하도록 변경 */ + background: none; + border: none; + padding: 10px; + cursor: pointer; } -/* 아이콘 색상 변경 (기본) */ .custom-button i { - color: #282538; /* 기본 아이콘 색상 */ - font-size: 25px; /* 아이콘 크기 */ + color: #282538; + font-size: 25px; } -/* 버튼 호버 효과 */ .custom-button:hover i { - color: #ff0800; /* 호버 시 아이콘 색상 변경 */ + color: #ff0800; } +/* 휴가 사원프로필 */ +.profile-list { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 10px; + padding: 0; +} +.profile-img { + transition: all 0.2s ease-in-out; +} + +/* 오전/오후반차,저장버튼 */ +/* 버튼 기본 스타일 */ +.vac-btn { + width: 50px; + height: 50px; + border-radius: 50%; + font-size: 20px; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease-in-out; + display: inline-block; + font-weight: 400; + line-height: 1.53; + color: #697a8d; + text-align: center; + vertical-align: middle; + cursor: pointer; + border: 1px solid transparent; +} +/* 마우스를 올렸을 때 */ + .vac-btn:hover { + filter: brightness(90%); + box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.2); + transform: scale(1.05); +} +/* 버튼이 눌렸을 때 */ + .vac-btn:active { + transform: scale(0.9); + box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.2); +} +/* 선택된 (눌린) 버튼 */ +.vac-btn.active { + border: 3px solid #ff0000; /* 붉은색 테두리 적용 */ + box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.3); + transform: scale(1.1); +} +.vac-btn-warning{ + color: #fff; + background-color: #ffab00; + border-color: #ffab00; + box-shadow: 0 0.125rem 0.25rem 0 rgba(255, 171, 0, 0.4); +} +/* AM 버튼 (선택된 상태) */ +.vac-btn-warning.active { + background-color: #ffca2c !important; + color: black; +} +.vac-btn-info { + color: #fff; + background-color: #03c3ec; + border-color: #03c3ec; + box-shadow: 0 0.125rem 0.25rem 0 rgba(3, 195, 236, 0.4); +} +/* PM 버튼 (선택된 상태) */ +.vac-btn-info.active { + background-color: #0b5ed7 !important; + color: white; +} +/* 버튼 기본 (비활성화일 때 기본 녹색) */ +.btn-success { + font-size: 24px; + width: 50px; + height: 50px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease-in-out; + background-color: #871919 !important; + color: white; + cursor: pointer; + border: 1px solid transparent; +} +/* 버튼 활성화 */ +.btn-success.active { + background-color: #ff0000 !important; + color: white !important; + border: 3px solid #eb9f9f !important; + box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.3); + transform: scale(1.1); +} +/* 버튼 비활성화 */ +.btn-success.disabled { + background-color: #bbb8b8 !important; + color: white !important; + cursor: not-allowed !important; + box-shadow: none; + transform: none; + opacity: 0.5; +} + +/* 작은 화면에서 버튼 크기 조정 */ +@media (max-width: 1600px) { + .count-btn { + width: 28px; + height: 28px; + font-size: 15px; + } + .count-container { + display: flex; + align-items: center; + justify-content: center; + gap: 0px; + margin-bottom: 8px; + } + .count-value { + font-size: 20px; + } + .custom-button { + width: 45px; + height: 45px; + font-size: 22px; + } + .vac-grant-modal-title { + font-size: 16px; + } + .vac-modal-text { + font-size: 11px; + } + .vac-modal-title { + font-size: 14px; + margin-bottom: 10px; + } + .vacation-item { + font-size: 12px; + text-align: center; + margin-bottom: 5px; + } + .vac-btn { + width: 40px; + height: 40px; + font-size: 18px; + } + .btn-success { + font-size: 20px; + width: 40px; + height: 40px; + } +} + + .grayscaleImg { filter: grayscale(100%); @@ -222,6 +399,9 @@ opacity: 0.6; /* 흐려 보이게 */ right: 1rem; z-index: 2; background-color: #fff !important; + border-radius: 0.5rem; + opacity: 1; + padding: 0.635rem; box-shadow: 0 0.125rem 0.25rem rgba(161, 172, 184, 0.4); transition: all 0.23s ease 0.1s; transform: translate(23px, -25px); @@ -233,7 +413,4 @@ opacity: 0.6; /* 흐려 보이게 */ transform: translate(20px, -20px); } -.end-project { - background-color: #ddd !important; -} /* project list end */ \ No newline at end of file diff --git a/src/components/button/HalfDayButtons.vue b/src/components/button/HalfDayButtons.vue index c4fa6ee..aeb2ed2 100644 --- a/src/components/button/HalfDayButtons.vue +++ b/src/components/button/HalfDayButtons.vue @@ -1,30 +1,28 @@ @@ -32,113 +30,37 @@ import { defineEmits, ref, defineProps, watch } from "vue"; const props = defineProps({ - isDisabled: Boolean, - selectedDate: String // 날짜 선택 값을 props로 받음 +isDisabled: Boolean, +selectedDate: String // 날짜 선택 값을 props로 받음 }); const emit = defineEmits(["toggleHalfDay", "addVacationRequests", "resetHalfDay"]); const halfDayType = ref(null); const toggleHalfDay = (type) => { - halfDayType.value = halfDayType.value === type ? null : type; - emit("toggleHalfDay", halfDayType.value); +halfDayType.value = halfDayType.value === type ? null : type; +emit("toggleHalfDay", halfDayType.value); }; // `selectedDate`가 변경되면 반차 선택 초기화 watch(() => props.selectedDate, (newDate) => { - if (newDate) { - resetHalfDay(); - } +if (newDate) { +resetHalfDay(); +} }); // 날짜 선택 후 반차 버튼 상태 초기화 const resetHalfDay = () => { - halfDayType.value = null; - emit("resetHalfDay"); +halfDayType.value = null; +emit("resetHalfDay"); }; const addVacationRequests = () => { - emit("addVacationRequests"); +emit("addVacationRequests"); }; defineExpose({ resetHalfDay }); diff --git a/src/components/modal/VacationGrantModal.vue b/src/components/modal/VacationGrantModal.vue index 82f8f72..ac977fd 100644 --- a/src/components/modal/VacationGrantModal.vue +++ b/src/components/modal/VacationGrantModal.vue @@ -1,129 +1,117 @@ - +}, { deep: true }); +onMounted(async () => { + if (props.isOpen && props.targetUser?.MEMBERSEQ) { + await fetchSentVacationCount(); + } +}); + diff --git a/src/components/modal/VacationModal.vue b/src/components/modal/VacationModal.vue index 22db837..2592d53 100644 --- a/src/components/modal/VacationModal.vue +++ b/src/components/modal/VacationModal.vue @@ -1,141 +1,122 @@ + + - diff --git a/src/components/vacation/ProfileList.vue b/src/components/vacation/ProfileList.vue index 9e06036..7fa0981 100644 --- a/src/components/vacation/ProfileList.vue +++ b/src/components/vacation/ProfileList.vue @@ -1,136 +1,115 @@ + - - // 프로필 크기 동적 조정: 사이드바 영역에 맞게 조금 더 축소 - const profileSize = computed(() => { - const totalUsers = userList.value.length; - if (totalUsers <= 10) return "68px"; // ~10명 - if (totalUsers <= 15) return "50px"; // ~20명 - return "30px"; // 20명 이상 - }); - - // 개별 유저 스타일 적용 - const getDynamicStyle = (user) => { - return { - width: profileSize.value, - height: profileSize.value, - borderWidth: "4px", - borderColor: user.usercolor || "#ccc", - borderStyle: "solid", - }; - }; - - - + diff --git a/src/layouts/NormalLayout.vue b/src/layouts/NormalLayout.vue index 08cef90..dd006b5 100644 --- a/src/layouts/NormalLayout.vue +++ b/src/layouts/NormalLayout.vue @@ -7,6 +7,7 @@
+
body @@ -14,6 +15,7 @@
+ @@ -27,6 +29,7 @@ import TheTop from './TheTop.vue'; import TheFooter from './TheFooter.vue'; import TheMenu from './TheMenu.vue'; + import TheChat from './TheChat.vue'; import { nextTick } from 'vue'; import { wait } from '@/common/utils'; @@ -45,4 +48,26 @@ loadScript('/js/main.js'); }); - + diff --git a/src/layouts/TheChat.vue b/src/layouts/TheChat.vue new file mode 100644 index 0000000..8102d8d --- /dev/null +++ b/src/layouts/TheChat.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/src/layouts/TheTop.vue b/src/layouts/TheTop.vue index 2e530ef..4c1d281 100644 --- a/src/layouts/TheTop.vue +++ b/src/layouts/TheTop.vue @@ -265,4 +265,5 @@ router.push('/login'); }; - + diff --git a/src/views/vacation/VacationManagement.vue b/src/views/vacation/VacationManagement.vue index d5fa758..d3c4fae 100644 --- a/src/views/vacation/VacationManagement.vue +++ b/src/views/vacation/VacationManagement.vue @@ -1,569 +1,517 @@ + - - + await fetchRemainingVacation(); + const currentYear = new Date().getFullYear(); + await fetchVacationHistory(currentYear); + window.addEventListener("beforeunload", preventUnsavedChanges); + // Flatpickr 초기화 (달 선택) + fpInstance = flatpickr(calendarDatepicker.value, { + dateFormat: "Y-m", + plugins: [ + new monthSelectPlugin({ + shorthand: true, + dateFormat: "Y-m", + altFormat: "F Y" + }) + ], + onChange: function(selectedDatesArr, dateStr) { + // 선택한 달의 첫날로 달력을 이동 + fullCalendarRef.value.getApi().gotoDate(dateStr + "-01"); + const [year, month] = dateStr.split("-"); + lastRemainingYear.value = parseInt(year, 10); + lastRemainingMonth.value = month; + loadCalendarData(lastRemainingYear.value, lastRemainingMonth.value); + }, + onClose: function() { + calendarDatepicker.value.style.display = "none"; + } + }); + // FullCalendar 년월월(.fc-toolbar-title) 클릭 시 데이트피커 열기 + nextTick(() => { + const titleEl = document.querySelector('.fc-toolbar-title'); + if (titleEl) { + titleEl.style.cursor = 'pointer'; + titleEl.addEventListener('click', () => { + const dpEl = calendarDatepicker.value; + dpEl.style.display = 'block'; + dpEl.style.position = 'fixed'; + dpEl.style.top = '25%'; + dpEl.style.left = '50%'; + dpEl.style.transform = 'translate(-50%, -50%)'; + dpEl.style.zIndex = '9999'; + dpEl.style.border = 'none'; + dpEl.style.outline = 'none'; + dpEl.style.backgroundColor = 'transparent'; + fpInstance.open(); + }); + } + }); +}) + +