import { useState, useEffect } from 'react'; import { useNavigate, Link } from 'react-router-dom'; import { motion, AnimatePresence } from 'framer-motion'; import { Plus, Search, Edit2, Trash2, Image, Music, Home, ChevronRight, LogOut, Calendar, AlertTriangle, X } from 'lucide-react'; import Toast from '../../../components/Toast'; function AdminAlbums() { const navigate = useNavigate(); const [albums, setAlbums] = useState([]); const [loading, setLoading] = useState(true); const [searchQuery, setSearchQuery] = useState(''); const [user, setUser] = useState(null); const [toast, setToast] = useState(null); const [deleteDialog, setDeleteDialog] = useState({ show: false, album: null }); const [deleting, setDeleting] = useState(false); // 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)); fetchAlbums(); }, [navigate]); const fetchAlbums = () => { fetch('/api/albums') .then(res => res.json()) .then(data => { setAlbums(data); setLoading(false); }) .catch(error => { console.error('앨범 로드 오류:', error); setLoading(false); }); }; const handleLogout = () => { localStorage.removeItem('adminToken'); localStorage.removeItem('adminUser'); navigate('/admin'); }; const handleDelete = async () => { if (!deleteDialog.album) return; setDeleting(true); try { const token = localStorage.getItem('adminToken'); const response = await fetch(`/api/admin/albums/${deleteDialog.album.id}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${token}`, }, }); if (!response.ok) { throw new Error('삭제 실패'); } setToast({ message: `"${deleteDialog.album.title}" 앨범이 삭제되었습니다.`, type: 'success' }); setDeleteDialog({ show: false, album: null }); fetchAlbums(); // 목록 새로고침 } catch (error) { console.error('삭제 오류:', error); setToast({ message: '앨범 삭제 중 오류가 발생했습니다.', type: 'error' }); } finally { setDeleting(false); } }; // 날짜 포맷팅 const formatDate = (dateStr) => { if (!dateStr) return ''; const date = new Date(dateStr); return `${date.getFullYear()}.${String(date.getMonth() + 1).padStart(2, '0')}.${String(date.getDate()).padStart(2, '0')}`; }; // 검색 필터링 const filteredAlbums = albums.filter(album => album.title.toLowerCase().includes(searchQuery.toLowerCase()) ); return (
{/* Toast */} setToast(null)} /> {/* 삭제 확인 다이얼로그 */} {deleteDialog.show && ( !deleting && setDeleteDialog({ show: false, album: null })} > e.stopPropagation()} >

앨범 삭제

"{deleteDialog.album?.title}" 앨범을 삭제하시겠습니까?
이 작업은 되돌릴 수 없으며, 모든 트랙과 커버 이미지가 함께 삭제됩니다.

)}
{/* 헤더 */}
fromis_9 Admin
안녕하세요, {user?.username}
{/* 메인 콘텐츠 */}
{/* 브레드크럼 */}
앨범 관리
{/* 타이틀 & 액션 */}

앨범 관리

앨범, 트랙, 사진을 관리합니다

{/* 검색 */}
setSearchQuery(e.target.value)} placeholder="앨범 검색..." className="w-full pl-10 pr-4 py-2 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent" />
{/* 앨범 목록 */} {loading ? (
) : (
{filteredAlbums.map((album, index) => ( ))}
앨범 타입 발매일 트랙 관리
{album.title}

{album.title}

{album.album_type}
{formatDate(album.release_date)}
{album.tracks?.length || 0}곡
{filteredAlbums.length === 0 && (
{searchQuery ? '검색 결과가 없습니다.' : '등록된 앨범이 없습니다.'}
)}
)}
); } export default AdminAlbums;