From a73658854be12759ee0dae2cebf22816e1cfb2be Mon Sep 17 00:00:00 2001 From: caadiq Date: Mon, 12 Jan 2026 18:05:29 +0900 Subject: [PATCH] =?UTF-8?q?PC=20=EA=B3=A1=20=EC=83=81=EC=84=B8:=20?= =?UTF-8?q?=EB=94=94=EC=9E=90=EC=9D=B8=20=EC=A0=95=EB=A6=AC=20(=EB=AE=A4?= =?UTF-8?q?=EB=B9=84=20embed,=20=ED=81=AC=EB=A0=88=EB=94=A7=20=EC=A4=84?= =?UTF-8?q?=EB=B0=94=EA=BF=88,=20=EA=B0=80=EC=82=AC=20=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A1=A4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/pc/public/TrackDetail.jsx | 263 ++++++++++--------- 1 file changed, 144 insertions(+), 119 deletions(-) diff --git a/frontend/src/pages/pc/public/TrackDetail.jsx b/frontend/src/pages/pc/public/TrackDetail.jsx index 8c6dd52..bf6d184 100644 --- a/frontend/src/pages/pc/public/TrackDetail.jsx +++ b/frontend/src/pages/pc/public/TrackDetail.jsx @@ -2,9 +2,29 @@ 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, Play, ExternalLink, ChevronRight, Disc3 } from 'lucide-react'; +import { Clock, User, Music, Mic2, Play, ExternalLink, ChevronRight } from 'lucide-react'; import { getTrack } from '../../../api/public/albums'; -import { formatDate } from '../../../utils/date'; + +// 유튜브 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() { @@ -18,6 +38,8 @@ function TrackDetail() { enabled: !!albumName && !!trackTitle, }); + const youtubeVideoId = useMemo(() => getYoutubeVideoId(track?.music_video_url), [track?.music_video_url]); + if (loading) { return ( - {/* 히어로 섹션 - 그라데이션 배경 */} -
-
- {/* 브레드크럼 네비게이션 */} -
- - 앨범 - - +
+ {/* 브레드크럼 네비게이션 */} +
+ + 앨범 + + + + {track.album?.title} + + + {track.title} +
+ + {/* 트랙 정보 헤더 */} +
+ {/* 앨범 커버 */} + navigate(`/album/${encodeURIComponent(track.album?.title || albumName)}`)} + > + {track.album?.title} + + + {/* 트랙 정보 */} + +
+ {track.is_title_track === 1 && ( + + TITLE + + )} + + Track {String(track.track_number).padStart(2, '0')} + +
+ +

{track.title}

+ + {/* 앨범 정보 */} - {track.album?.title} + +
+

{track.album?.album_type}

+

{track.album?.title}

+
- - {track.title} -
- {/* 트랙 정보 헤더 */} -
- {/* 앨범 커버 */} - -
navigate(`/album/${encodeURIComponent(track.album?.title || albumName)}`)} - > - {track.album?.title} + {/* 재생 시간 */} + {track.duration && ( +
+ + {track.duration}
- {/* 재생 느낌의 오버레이 */} -
- -
- - - {/* 트랙 정보 */} - -
- {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} -
- )} - {track.music_video_url && ( - - - 뮤직비디오 - - - )} -
-
-
+ )} +
-
- {/* 메인 콘텐츠 */} -
+ {/* 뮤직비디오 섹션 (유튜브 embed) */} + {youtubeVideoId && ( + +

+
+ 뮤직비디오 +

+
+