182 lines
5.1 KiB
Vue
182 lines
5.1 KiB
Vue
<template>
|
||
<div class="vacation-management">
|
||
<div class="container-xxl flex-grow-1 container-p-y">
|
||
<div class="save-button-container">
|
||
<button class="btn btn-success" @click="addVacationRequest">✔</button>
|
||
</div>
|
||
<div class="card app-calendar-wrapper">
|
||
<div class="row g-0">
|
||
<div class="col app-calendar-content">
|
||
<div class="card shadow-none border-0">
|
||
<div class="card-body pb-0">
|
||
<full-calendar
|
||
ref="fullCalendarRef"
|
||
:events="calendarEvents"
|
||
:options="calendarOptions"
|
||
defaultView="dayGridMonth"
|
||
class="flatpickr-calendar-only"
|
||
>
|
||
</full-calendar>
|
||
</div>
|
||
</div>
|
||
<div class="half-day-buttons">
|
||
<button class="btn btn-info" :class="{ active: halfDayType === 'AM' }" @click="toggleHalfDay('AM')">☀️ 오전반차</button>
|
||
<button class="btn btn-warning" :class="{ active: halfDayType === 'PM' }" @click="toggleHalfDay('PM')">🌙 오후반차</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import FullCalendar from '@fullcalendar/vue3';
|
||
import dayGridPlugin from '@fullcalendar/daygrid';
|
||
import interactionPlugin from '@fullcalendar/interaction';
|
||
import 'flatpickr/dist/flatpickr.min.css';
|
||
import '@/assets/css/app-calendar.css';
|
||
import { reactive, ref } from 'vue';
|
||
|
||
const fullCalendarRef = ref(null);
|
||
const calendarEvents = ref([]);
|
||
const selectedDates = ref([]);
|
||
const halfDayType = ref(null); // 오전/오후 반차 선택
|
||
|
||
const calendarOptions = reactive({
|
||
plugins: [dayGridPlugin, interactionPlugin],
|
||
initialView: 'dayGridMonth',
|
||
headerToolbar: {
|
||
left: 'today',
|
||
center: 'title',
|
||
right: 'prev,next',
|
||
},
|
||
locale: 'ko',
|
||
selectable: true,
|
||
dateClick: handleDateClick,
|
||
});
|
||
|
||
function handleDateClick(info) {
|
||
const date = info.dateStr;
|
||
const dayElement = info.dayEl;
|
||
|
||
if (!selectedDates.value.includes(date)) {
|
||
selectedDates.value.push(date);
|
||
if (halfDayType.value === 'AM') {
|
||
dayElement.style.backgroundImage = 'linear-gradient(to bottom, #ade3ff 50%, transparent 50%)';
|
||
} else if (halfDayType.value === 'PM') {
|
||
dayElement.style.backgroundImage = 'linear-gradient(to top, #ade3ff 50%, transparent 50%)';
|
||
} else {
|
||
dayElement.style.backgroundColor = '#ade3ff';
|
||
}
|
||
} else {
|
||
selectedDates.value = selectedDates.value.filter((d) => d !== date);
|
||
dayElement.style.backgroundColor = '';
|
||
dayElement.style.backgroundImage = '';
|
||
}
|
||
|
||
halfDayType.value = null; // 날짜 클릭 후 반차 선택 초기화
|
||
}
|
||
|
||
function toggleHalfDay(type) {
|
||
halfDayType.value = halfDayType.value === type ? null : type;
|
||
}
|
||
|
||
function addVacationRequest() {
|
||
if (selectedDates.value.length === 0) {
|
||
alert('Please select at least one date.');
|
||
return;
|
||
}
|
||
|
||
const newEvents = selectedDates.value.map((date) => ({
|
||
title: halfDayType.value ? `${halfDayType.value} Half Day Vacation` : 'Vacation',
|
||
start: date,
|
||
allDay: true,
|
||
}));
|
||
|
||
calendarEvents.value = [...calendarEvents.value, ...newEvents];
|
||
alert(`Vacation added for dates: ${selectedDates.value.join(', ')} as ${halfDayType.value || 'Full Day'}`);
|
||
selectedDates.value = [];
|
||
halfDayType.value = null;
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.vacation-management {
|
||
padding: 20px;
|
||
}
|
||
|
||
.save-button-container {
|
||
position: fixed;
|
||
top: 900px; /* 탑바 아래로 간격 조정 */
|
||
right: 400px;
|
||
z-index: 1050; /* 탑바보다 높은 값 */
|
||
background-color: white;
|
||
padding: 10px;
|
||
border-radius: 5px;
|
||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.save-button-container {
|
||
top: 70px; /* 모바일에서 탑바 아래 간격 조정 */
|
||
right: 5px;
|
||
left: 5px;
|
||
width: calc(100% - 10px); /* 모바일 화면에 맞게 크기 조정 */
|
||
text-align: center;
|
||
}
|
||
}
|
||
|
||
|
||
.half-day-buttons {
|
||
display: flex;
|
||
justify-content: center;
|
||
gap: 10px;
|
||
margin-top: 20px;
|
||
}
|
||
|
||
.fc-day-sun .fc-col-header-cell-cushion,
|
||
.fc-day-sun a {
|
||
color: red;
|
||
}
|
||
|
||
.fc-day-sat .fc-col-header-cell-cushion,
|
||
.fc-day-sat a {
|
||
color: blue;
|
||
}
|
||
|
||
.flatpickr-calendar-only input.flatpickr-input {
|
||
display: none;
|
||
}
|
||
|
||
.flatpickr-input {
|
||
display: none;
|
||
}
|
||
|
||
.pt-2.px-3 {
|
||
position: relative;
|
||
}
|
||
|
||
.flatpickr-calendar {
|
||
position: relative !important;
|
||
display: block !important;
|
||
width: 100% !important;
|
||
height: auto !important;
|
||
z-index: 1;
|
||
}
|
||
|
||
.btn-info {
|
||
background-color: #17a2b8;
|
||
color: white;
|
||
}
|
||
|
||
.btn-warning {
|
||
background-color: #ffc107;
|
||
color: white;
|
||
}
|
||
|
||
button.active {
|
||
opacity: 0.7;
|
||
}
|
||
</style>
|