import { useState, useMemo } from 'react'; import { useParams, useNavigate, Link } from 'react-router-dom'; import { useQuery } from '@tanstack/react-query'; import { motion } from 'framer-motion'; import { Clock, User, Music, Mic2, ChevronRight } from 'lucide-react'; import { getTrack } from '../../../api/public/albums'; // 유튜브 URL에서 비디오 ID 추출 const getYoutubeVideoId = (url) => { if (!url) return null; const patterns = [ /(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&\n?#]+)/, ]; for (const pattern of patterns) { const match = url.match(pattern); if (match) return match[1]; } return null; }; // 쉼표 기준 줄바꿈 처리 const formatCredit = (text) => { if (!text) return null; return text.split(',').map((item, index) => ( {item.trim()} )); }; // PC 곡 상세 페이지 function TrackDetail() { const { name: albumName, trackTitle } = useParams(); const navigate = useNavigate(); // useQuery로 트랙 데이터 로드 const { data: track, isLoading: loading, error } = useQuery({ queryKey: ['track', albumName, trackTitle], queryFn: () => getTrack(albumName, trackTitle), enabled: !!albumName && !!trackTitle, }); const youtubeVideoId = useMemo(() => getYoutubeVideoId(track?.music_video_url), [track?.music_video_url]); if (loading) { return (
); } if (error || !track) { return (

트랙을 찾을 수 없습니다.

); } return (
{/* 브레드크럼 네비게이션 */}
앨범 {track.album?.title} {track.title}
{/* 트랙 정보 헤더 */}
{/* 앨범 커버 */} {track.album?.title} {/* 트랙 정보 */}
{track.is_title_track === 1 && ( TITLE )} Track {String(track.track_number).padStart(2, '0')}

{track.title}

{/* 앨범 정보 (텍스트만) */} {track.album?.album_type} · {track.album?.title} {/* 재생 시간 */} {track.duration && (
{track.duration}
)}
{/* 뮤직비디오 섹션 (유튜브 embed) */} {youtubeVideoId && (

뮤직비디오