diff --git a/frontend/src/components/pc/admin/bot/YouTubeBotDialog.jsx b/frontend/src/components/pc/admin/bot/YouTubeBotDialog.jsx index b64cb34..07acf22 100644 --- a/frontend/src/components/pc/admin/bot/YouTubeBotDialog.jsx +++ b/frontend/src/components/pc/admin/bot/YouTubeBotDialog.jsx @@ -1,10 +1,10 @@ /** * YouTube 봇 추가/수정 다이얼로그 */ -import { useState, useEffect } from 'react'; +import { useState, useEffect, useRef } from 'react'; import { createPortal } from 'react-dom'; import { motion, AnimatePresence } from 'framer-motion'; -import { Youtube, Search, X, ChevronDown, ChevronUp } from 'lucide-react'; +import { Youtube, Search, X, ChevronDown, ChevronUp, Clock } from 'lucide-react'; // 동기화 간격 옵션 const INTERVAL_OPTIONS = [ @@ -27,6 +27,79 @@ const DAY_OPTIONS = [ { value: 6, label: '토요일' }, ]; +// 시간 옵션 (00:00 ~ 23:00) +const TIME_OPTIONS = Array.from({ length: 24 }, (_, i) => ({ + value: `${String(i).padStart(2, '0')}:00`, + label: `${String(i).padStart(2, '0')}:00`, +})); + +/** + * 커스텀 드롭다운 컴포넌트 + */ +function Dropdown({ value, options, onChange, placeholder = '선택', className = '' }) { + const [isOpen, setIsOpen] = useState(false); + const dropdownRef = useRef(null); + + useEffect(() => { + const handleClickOutside = (event) => { + if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { + setIsOpen(false); + } + }; + + if (isOpen) { + document.addEventListener('mousedown', handleClickOutside); + } + return () => document.removeEventListener('mousedown', handleClickOutside); + }, [isOpen]); + + const selectedOption = options.find((opt) => opt.value === value); + + return ( +
+ + + {isOpen && ( + + {options.map((opt) => ( + + ))} + + )} + +
+ ); +} + function YouTubeBotDialog({ isOpen, onClose, bot = null, onSubmit }) { const isEdit = !!bot; @@ -202,17 +275,12 @@ function YouTubeBotDialog({ isOpen, onClose, bot = null, onSubmit }) { - + options={INTERVAL_OPTIONS} + onChange={setInterval} + placeholder="간격 선택" + /> {/* 예정 일정 자동 생성 */} @@ -244,25 +312,20 @@ function YouTubeBotDialog({ isOpen, onClose, bot = null, onSubmit }) {
- + options={DAY_OPTIONS} + onChange={setScheduleDayOfWeek} + placeholder="요일 선택" + />
- setScheduleTime(e.target.value)} - className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-red-500/20 focus:border-red-500" + options={TIME_OPTIONS} + onChange={setScheduleTime} + placeholder="시간 선택" />
@@ -285,17 +348,12 @@ function YouTubeBotDialog({ isOpen, onClose, bot = null, onSubmit }) { {/* 마감 요일 */}
- + options={DAY_OPTIONS} + onChange={setDeadlineDayOfWeek} + placeholder="요일 선택" + />

이 요일까지 영상이 없으면 예정 일정을 삭제합니다

diff --git a/frontend/src/components/pc/admin/schedule/WordItem.jsx b/frontend/src/components/pc/admin/schedule/WordItem.jsx index 8c7e4f2..35a6f82 100644 --- a/frontend/src/components/pc/admin/schedule/WordItem.jsx +++ b/frontend/src/components/pc/admin/schedule/WordItem.jsx @@ -126,7 +126,7 @@ function WordItem({ id, word, pos, index, onUpdate, onDelete }) { initial={{ opacity: 0, y: -5 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -5 }} - className="absolute top-full left-0 mt-1 w-64 bg-white rounded-xl shadow-lg border border-gray-200 py-1 z-20" + className="absolute top-full left-0 mt-1 w-64 bg-white rounded-xl shadow-lg border border-gray-200 py-1 z-40" > {POS_TAGS.map((tag) => (