일정 관리
fromis_9의 일정을 관리합니다
카테고리
{selectedCategory === 'all' ? '전체 일정' : categories.find(c => c.id === selectedCategory)?.name}
{filteredSchedules.length}개의 일정등록된 일정이 없습니다
{schedule.title}
{schedule.description}
import { useState, useEffect, useRef } from 'react'; import { useNavigate, Link } from 'react-router-dom'; import { motion, AnimatePresence } from 'framer-motion'; import { LogOut, Home, ChevronRight, Calendar, Plus, Edit2, Trash2, ChevronLeft, Search, ChevronDown } from 'lucide-react'; import Toast from '../../../components/Toast'; function AdminSchedule() { const navigate = useNavigate(); const [loading, setLoading] = useState(false); const [user, setUser] = useState(null); const [toast, setToast] = useState(null); const [searchTerm, setSearchTerm] = useState(''); const [selectedCategory, setSelectedCategory] = useState('all'); const [selectedDate, setSelectedDate] = useState(null); const [currentDate, setCurrentDate] = useState(new Date()); const [slideDirection, setSlideDirection] = useState(0); // 년월 선택 관련 (Schedule.jsx와 동일한 패턴) const [showYearMonthPicker, setShowYearMonthPicker] = useState(false); const [viewMode, setViewMode] = useState('yearMonth'); // 'yearMonth' | 'months' const pickerRef = useRef(null); // 달력 관련 const year = currentDate.getFullYear(); const month = currentDate.getMonth(); const firstDay = new Date(year, month, 1).getDay(); const daysInMonth = new Date(year, month + 1, 0).getDate(); const days = ['일', '월', '화', '수', '목', '금', '토']; const monthNames = ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월']; // 년도 범위 (현재 년도 기준 10년 단위 - Schedule.jsx와 동일) const startYear = Math.floor(year / 10) * 10 - 1; const yearRange = Array.from({ length: 12 }, (_, i) => startYear + i); // 현재 년도/월 확인 함수 const isCurrentYear = (y) => new Date().getFullYear() === y; const isCurrentMonth = (m) => { const today = new Date(); return today.getFullYear() === year && today.getMonth() === m; }; const getDaysInMonth = (y, m) => new Date(y, m + 1, 0).getDate(); // 카테고리 목록 const categories = [ { id: 'all', name: '전체', color: 'gray' }, { id: 'broadcast', name: '방송', color: 'blue' }, { id: 'event', name: '이벤트', color: 'green' }, { id: 'release', name: '발매', color: 'purple' }, { id: 'concert', name: '콘서트', color: 'red' }, { id: 'fansign', name: '팬사인회', color: 'pink' }, ]; // 더미 일정 데이터 (UI용) const dummySchedules = [ { id: 1, title: 'SBS 인기가요 출연', date: '2026-01-05', time: '15:30', category: 'broadcast', description: '컴백 무대' }, { id: 2, title: '유튜브 라이브', date: '2026-01-05', time: '19:00', category: 'broadcast', description: '팬들과 소통 시간' }, { id: 3, title: '팬미팅', date: '2026-01-10', time: '18:00', category: 'event', description: '서울 올림픽홀' }, { id: 4, title: '신곡 발매', date: '2026-01-15', time: '18:00', category: 'release', description: '미니앨범 8집' }, { id: 5, title: '콘서트 투어', date: '2026-01-20', time: '19:00', category: 'concert', description: '부산 벡스코' }, { id: 6, title: '온라인 팬사인회', date: '2026-01-25', time: '17:00', category: 'fansign', description: '위버스 진행' }, ]; // 카테고리별 색상 const getCategoryColor = (categoryId) => { const colors = { broadcast: 'bg-blue-100 text-blue-700', event: 'bg-green-100 text-green-700', release: 'bg-purple-100 text-purple-700', concert: 'bg-red-100 text-red-700', fansign: 'bg-pink-100 text-pink-700', }; return colors[categoryId] || 'bg-gray-100 text-gray-700'; }; // 카테고리별 도트 색상 const getCategoryDotColor = (categoryId) => { const colors = { broadcast: 'bg-blue-500', event: 'bg-green-500', release: 'bg-purple-500', concert: 'bg-red-500', fansign: 'bg-pink-500', }; return colors[categoryId] || 'bg-gray-500'; }; // 해당 날짜에 일정이 있는지 확인 const hasSchedule = (day) => { const dateStr = `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`; return dummySchedules.some(s => s.date === dateStr); }; // Toast 자동 숨김 useEffect(() => { if (toast) { const timer = setTimeout(() => setToast(null), 3000); return () => clearTimeout(timer); } }, [toast]); useEffect(() => { const token = localStorage.getItem('adminToken'); const userData = localStorage.getItem('adminUser'); if (!token || !userData) { navigate('/admin'); return; } setUser(JSON.parse(userData)); }, [navigate]); // 외부 클릭 시 피커 닫기 useEffect(() => { const handleClickOutside = (event) => { if (pickerRef.current && !pickerRef.current.contains(event.target)) { setShowYearMonthPicker(false); setViewMode('yearMonth'); } }; if (showYearMonthPicker) { document.addEventListener('mousedown', handleClickOutside); } return () => document.removeEventListener('mousedown', handleClickOutside); }, [showYearMonthPicker]); const handleLogout = () => { localStorage.removeItem('adminToken'); localStorage.removeItem('adminUser'); navigate('/admin'); }; // 월 이동 const prevMonth = () => { setSlideDirection(-1); setCurrentDate(new Date(year, month - 1, 1)); }; const nextMonth = () => { setSlideDirection(1); setCurrentDate(new Date(year, month + 1, 1)); }; // 년도 범위 이동 const prevYearRange = () => setCurrentDate(new Date(year - 10, month, 1)); const nextYearRange = () => setCurrentDate(new Date(year + 10, month, 1)); // 년도 선택 시 월 선택 모드로 전환 const selectYear = (newYear) => { setCurrentDate(new Date(newYear, month, 1)); setViewMode('months'); }; // 월 선택 시 적용 후 닫기 const selectMonth = (newMonth) => { setCurrentDate(new Date(year, newMonth, 1)); setShowYearMonthPicker(false); setViewMode('yearMonth'); }; // 날짜 선택 const selectDate = (day) => { const dateStr = `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`; setSelectedDate(selectedDate === dateStr ? null : dateStr); }; // 필터링된 일정 const filteredSchedules = dummySchedules.filter(schedule => { const matchesSearch = schedule.title.toLowerCase().includes(searchTerm.toLowerCase()); const matchesCategory = selectedCategory === 'all' || schedule.category === selectedCategory; return matchesSearch && matchesCategory; }); return (
fromis_9의 일정을 관리합니다
등록된 일정이 없습니다
{schedule.description}