| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- <template>
- <div class="admin--datepicker">
- <input
- ref="dateInput"
- type="text"
- :value="modelValue"
- :placeholder="placeholder"
- :class="['admin--form-input', { 'is-required': required }]"
- :required="required"
- readonly
- >
- </div>
- </template>
- <script setup>
- import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
- import flatpickr from 'flatpickr'
- import { Korean } from 'flatpickr/dist/l10n/ko'
- import 'flatpickr/dist/flatpickr.min.css'
- import 'flatpickr/dist/themes/dark.css'
- const props = defineProps({
- modelValue: {
- type: String,
- default: ''
- },
- placeholder: {
- type: String,
- default: '날짜 선택'
- },
- required: {
- type: Boolean,
- default: false
- },
- mode: {
- type: String,
- default: 'single', // single, range
- validator: (value) => ['single', 'range'].includes(value)
- },
- minDate: {
- type: String,
- default: null
- },
- maxDate: {
- type: String,
- default: null
- }
- })
- const emit = defineEmits(['update:modelValue'])
- const dateInput = ref(null)
- let flatpickrInstance = null
- onMounted(() => {
- flatpickrInstance = flatpickr(dateInput.value, {
- locale: Korean,
- dateFormat: 'Y-m-d',
- mode: props.mode,
- minDate: props.minDate,
- maxDate: props.maxDate,
- defaultDate: props.modelValue || null,
- onChange: (_selectedDates, dateStr) => {
- emit('update:modelValue', dateStr)
- },
- // 다크 테마 설정
- theme: 'dark',
- // 월/년 선택 드롭다운 활성화
- monthSelectorType: 'dropdown',
- // 시간 선택 비활성화
- enableTime: false,
- // 주말 강조
- onDayCreate: (_dObj, _dStr, _fp, dayElem) => {
- const day = dayElem.dateObj.getDay()
- if (day === 0) {
- dayElem.classList.add('weekend-sunday')
- } else if (day === 6) {
- dayElem.classList.add('weekend-saturday')
- }
- }
- })
- })
- // modelValue 변경 감지
- watch(() => props.modelValue, (newValue) => {
- if (flatpickrInstance && newValue !== flatpickrInstance.input.value) {
- flatpickrInstance.setDate(newValue || null, false)
- }
- })
- // minDate, maxDate 변경 감지
- watch([() => props.minDate, () => props.maxDate], ([newMinDate, newMaxDate]) => {
- if (flatpickrInstance) {
- flatpickrInstance.set('minDate', newMinDate)
- flatpickrInstance.set('maxDate', newMaxDate)
- }
- })
- onBeforeUnmount(() => {
- if (flatpickrInstance) {
- flatpickrInstance.destroy()
- }
- })
- </script>
- <style scoped>
- .admin--datepicker {
- position: relative;
- }
- .admin--datepicker .admin--form-input {
- cursor: pointer;
- background: var(--admin-bg-tertiary, #252525);
- color: var(--admin-text-primary, #ffffff) !important;
- border: 1px solid var(--admin-border-color, #333333);
- }
- .admin--datepicker .admin--form-input:read-only {
- background: var(--admin-bg-tertiary, #252525);
- color: var(--admin-text-primary, #ffffff) !important;
- }
- .admin--datepicker .admin--form-input::placeholder {
- color: var(--admin-text-muted, #666666);
- }
- .admin--datepicker .admin--form-input:focus {
- outline: none;
- border-color: var(--admin-accent-primary, #bb0a30);
- box-shadow: 0 0 0 3px rgba(187, 10, 48, 0.1);
- }
- /* 다크 테마 커스터마이징 */
- :deep(.flatpickr-calendar.dark) {
- background: #2c3e50;
- border-color: #34495e;
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
- }
- :deep(.flatpickr-calendar.dark .flatpickr-months) {
- background: #34495e;
- }
- :deep(.flatpickr-calendar.dark .flatpickr-current-month .flatpickr-monthDropdown-months) {
- background: #2c3e50;
- color: #ecf0f1;
- }
- :deep(.flatpickr-calendar.dark .flatpickr-day.selected) {
- background: #3498db;
- border-color: #2980b9;
- }
- :deep(.flatpickr-calendar.dark .flatpickr-day.selected:hover) {
- background: #2980b9;
- }
- :deep(.flatpickr-calendar.dark .flatpickr-day:hover) {
- background: #34495e;
- }
- :deep(.flatpickr-calendar.dark .flatpickr-day.today) {
- border-color: #3498db;
- }
- :deep(.flatpickr-calendar.dark .flatpickr-day.today:hover) {
- background: #34495e;
- border-color: #3498db;
- }
- /* 주말 색상 */
- :deep(.flatpickr-day.weekend-sunday) {
- color: #e74c3c !important;
- }
- :deep(.flatpickr-day.weekend-saturday) {
- color: #3498db !important;
- }
- :deep(.flatpickr-day.weekend-sunday.selected),
- :deep(.flatpickr-day.weekend-saturday.selected) {
- color: #fff !important;
- }
- /* Range 모드 스타일 */
- :deep(.flatpickr-day.inRange) {
- background: rgba(52, 152, 219, 0.2);
- border-color: transparent;
- box-shadow: -5px 0 0 rgba(52, 152, 219, 0.2), 5px 0 0 rgba(52, 152, 219, 0.2);
- }
- :deep(.flatpickr-day.startRange),
- :deep(.flatpickr-day.endRange) {
- background: #3498db;
- color: #fff;
- }
- </style>
|