import { motion, AnimatePresence } from 'framer-motion'; import { useState, useEffect, useCallback } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { ArrowLeft, Play, Calendar, Music2, Clock, X, ChevronLeft, ChevronRight, Download } from 'lucide-react'; import { getAlbumByName } from '../../../api/public/albums'; import { formatDate } from '../../../utils/date'; // 모바일 앨범 상세 페이지 function MobileAlbumDetail() { const { name } = useParams(); const navigate = useNavigate(); const [album, setAlbum] = useState(null); const [loading, setLoading] = useState(true); const [lightbox, setLightbox] = useState({ open: false, images: [], index: 0 }); const [imageLoaded, setImageLoaded] = useState(false); // 라이트박스 네비게이션 const goToPrev = useCallback(() => { if (lightbox.images.length <= 1) return; setImageLoaded(false); setLightbox(prev => ({ ...prev, index: (prev.index - 1 + prev.images.length) % prev.images.length })); }, [lightbox.images.length]); const goToNext = useCallback(() => { if (lightbox.images.length <= 1) return; setImageLoaded(false); setLightbox(prev => ({ ...prev, index: (prev.index + 1) % prev.images.length })); }, [lightbox.images.length]); const closeLightbox = useCallback(() => { setLightbox(prev => ({ ...prev, open: false })); }, []); // 이미지 다운로드 const downloadImage = useCallback(async () => { const imageUrl = lightbox.images[lightbox.index]; if (!imageUrl) return; try { const response = await fetch(imageUrl); const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = `fromis9_photo_${String(lightbox.index + 1).padStart(2, '0')}.webp`; document.body.appendChild(link); link.click(); document.body.removeChild(link); window.URL.revokeObjectURL(url); } catch (error) { console.error('다운로드 오류:', error); } }, [lightbox.images, lightbox.index]); // 라이트박스 body 스크롤 방지 useEffect(() => { if (lightbox.open) { document.body.style.overflow = 'hidden'; } else { document.body.style.overflow = ''; } return () => { document.body.style.overflow = ''; }; }, [lightbox.open]); useEffect(() => { getAlbumByName(name) .then(data => { setAlbum(data); setLoading(false); }) .catch(error => { console.error('앨범 로드 오류:', error); setLoading(false); }); }, [name]); // 총 재생 시간 계산 const getTotalDuration = () => { if (!album?.tracks) return ''; let totalSeconds = 0; album.tracks.forEach(track => { if (track.duration) { const parts = track.duration.split(':'); totalSeconds += parseInt(parts[0]) * 60 + parseInt(parts[1]); } }); const mins = Math.floor(totalSeconds / 60); const secs = totalSeconds % 60; return `${mins}:${String(secs).padStart(2, '0')}`; }; if (loading) { return (
); } if (!album) { return (

앨범을 찾을 수 없습니다

); } // 모든 컨셉 포토를 하나의 배열로 const allPhotos = album.conceptPhotos ? Object.values(album.conceptPhotos).flat() : []; return ( <>
{/* 헤더 */}
{album.title}
{/* 앨범 정보 섹션 */}
{/* 앨범 커버 */} setLightbox({ open: true, images: [album.cover_original_url || album.cover_medium_url], index: 0 })} > {album.cover_medium_url && ( {album.title} )} {/* 앨범 정보 */} {album.album_type}

{album.title}

{/* 메타 정보 */}
{formatDate(album.release_date, 'YYYY.MM.DD')}
{album.tracks?.length || 0}곡
{getTotalDuration()}
{/* 티저 포토 */} {album.teasers && album.teasers.length > 0 && (

티저 포토

{album.teasers.map((teaser, index) => (
setLightbox({ open: true, images: album.teasers.map(t => t.original_url), index, teasers: album.teasers })} className="w-20 h-20 flex-shrink-0 bg-gray-200 rounded-xl overflow-hidden relative" > {teaser.media_type === 'video' ? ( <>
))}
)} {/* 수록곡 */} {album.tracks && album.tracks.length > 0 && (

수록곡

{album.tracks.map((track, index) => (
{String(track.track_number).padStart(2, '0')}

{track.title}

{track.is_title_track === 1 && ( TITLE )}
{track.duration || '-'} {track.music_video_url && ( )}
))}
)} {/* 컨셉 포토 */} {allPhotos.length > 0 && (

컨셉 포토

{allPhotos.slice(0, 6).map((photo, idx) => (
setLightbox({ open: true, images: allPhotos.map(p => p.original_url), index: idx })} className="aspect-square bg-gray-200 rounded-xl overflow-hidden" > {`컨셉
))}
)} {/* 설명 */} {album.description && (

소개

{album.description}

)}
{/* 라이트박스 */} {lightbox.open && ( {/* 상단 버튼 */}
{/* 이전 버튼 */} {lightbox.images.length > 1 && ( )} {/* 로딩 스피너 */} {!imageLoaded && (
)} {/* 이미지/비디오 */} {lightbox.teasers?.[lightbox.index]?.media_type === 'video' ? (