fix(music): TrendsTab 로딩상태·에러피드백·메타데이터 수정

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-01 15:01:38 +09:00
parent 0f0ca8610d
commit 1847771ad2

View File

@@ -10,6 +10,7 @@ const FLAG = { BR: '🇧🇷', US: '🇺🇸', ID: '🇮🇩', MX: '🇲🇽', K
function fmtDateTime(iso) {
if (!iso) return null;
const d = new Date(iso);
if (isNaN(d.getTime())) return iso.slice(0, 10);
const today = new Date().toDateString();
if (d.toDateString() === today) {
return `오늘 ${d.getHours().toString().padStart(2, '0')}:${d.getMinutes().toString().padStart(2, '0')}`;
@@ -24,16 +25,25 @@ export default function TrendsTab() {
const [selectedReport, setSelectedReport] = useState(null);
const [researching, setResearching] = useState(false);
const [copiedIdx, setCopiedIdx] = useState(null);
const [loading, setLoading] = useState(true);
const [researchMsg, setResearchMsg] = useState('');
const loadAll = async () => {
const [latest, rpts, sugg] = await Promise.all([
getLatestTrendReport().catch(() => null),
getTrendReports().catch(() => []),
getMarketSuggestions().catch(() => []),
]);
setLatestReport(latest);
setReports(Array.isArray(rpts) ? rpts : rpts.reports ?? []);
setSuggestions(Array.isArray(sugg) ? sugg : sugg.suggestions ?? []);
setLoading(true);
try {
const [latest, rpts, sugg] = await Promise.all([
getLatestTrendReport().catch(() => null),
getTrendReports().catch(() => []),
getMarketSuggestions().catch(() => []),
]);
setLatestReport(latest);
setReports(Array.isArray(rpts) ? rpts : rpts.reports ?? []);
setSuggestions(Array.isArray(sugg) ? sugg : sugg.suggestions ?? []);
} catch (e) {
console.error('loadAll:', e);
} finally {
setLoading(false);
}
};
useEffect(() => { loadAll(); }, []);
@@ -42,6 +52,8 @@ export default function TrendsTab() {
setResearching(true);
try {
await triggerYoutubeResearch();
setResearchMsg('수집이 시작되었습니다. 잠시 후 새로고침하세요.');
setTimeout(() => setResearchMsg(''), 4000);
} catch (e) {
console.error('triggerYoutubeResearch:', e);
} finally {
@@ -66,6 +78,8 @@ export default function TrendsTab() {
? (selectedReport.recommended_styles ?? [])
: suggestions;
if (loading) return <div className="yt-content"><p className="yt-empty">데이터 로딩 ...</p></div>;
return (
<div className="yt-content">
{/* 수집 상태 바 */}
@@ -85,6 +99,7 @@ export default function TrendsTab() {
>
{researching ? '수집 중...' : '↻ 수동 수집'}
</button>
{researchMsg && <p className="yt-empty" style={{ color: '#22c55e', marginTop: 4 }}>{researchMsg}</p>}
</div>
{/* 인기 장르 Top 5 */}
@@ -168,9 +183,10 @@ export default function TrendsTab() {
<div
key={r.id ?? r.report_date}
className={`yt-report-row ${selectedReport?.report_date === r.report_date ? 'is-selected' : ''}`}
onClick={() => setSelectedReport(
selectedReport?.report_date === r.report_date ? null : r
)}
onClick={() => {
setSelectedReport(selectedReport?.report_date === r.report_date ? null : r);
setCopiedIdx(null);
}}
>
<span className="yt-report-row__date">
{r.report_date}
@@ -179,7 +195,7 @@ export default function TrendsTab() {
)}
</span>
<span className="yt-report-row__meta">
{r.top_genres?.length ?? 0} 장르 · {r.recommended_styles?.length ?? 0} 추천
{r.insights ? r.insights.slice(0, 60) + (r.insights.length >= 60 ? '…' : '') : ''}
</span>
<span className="yt-report-row__action">보기 </span>
</div>