feat: 뉴스 필터 트리 (신문사 → 분야) + ai_summary 우선 표시

- 좌측 필터: 신문사 펼침 → 분야별 필터 (News/경향신문/문화)
- API: source 파라미터 '신문사' 또는 '신문사/분야' 지원
- 리스트: ai_summary 있으면 우선, 없으면 extracted_text fallback

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-04-06 15:08:50 +09:00
parent 2eeed41f5c
commit 557165db11
2 changed files with 37 additions and 12 deletions

View File

@@ -20,18 +20,23 @@
let selectedArticle = $state(null);
let filterSource = $state('');
let showUnreadOnly = $state(false);
let sources = $state([]);
let sourceTree = $state({}); // { 경향신문: ['문화', '사회'], NYT: ['World'] }
let currentPage = $state(1);
let noteEditing = $state(false);
let noteText = $state('');
let expandedSources = $state({});
onMount(async () => {
try {
const srcData = await api('/news/sources');
// 신문사별 유니크
const names = new Set();
srcData.forEach(s => names.add(s.name.split(' ')[0]));
sources = [...names];
const tree = {};
srcData.forEach(s => {
const paper = s.name.split(' ')[0];
const cat = s.category || '';
if (!tree[paper]) tree[paper] = [];
if (cat && !tree[paper].includes(cat)) tree[paper].push(cat);
});
sourceTree = tree;
} catch (e) {}
loadArticles();
});
@@ -127,11 +132,26 @@
class="w-full text-left px-2 py-1.5 rounded text-sm mb-1 {filterSource === '' ? 'bg-[var(--accent)]/15 text-[var(--accent)]' : 'text-[var(--text-dim)] hover:bg-[var(--surface)]'}"
>📰 전체</button>
{#each sources as src}
<button
onclick={() => { filterSource = src; }}
class="w-full text-left px-2 py-1.5 rounded text-sm mb-0.5 {filterSource === src ? 'bg-[var(--accent)]/15 text-[var(--accent)]' : 'text-[var(--text-dim)] hover:bg-[var(--surface)]'}"
>{src}</button>
{#each Object.entries(sourceTree) as [paper, categories]}
<div class="mb-0.5">
<button
onclick={() => { filterSource = paper; expandedSources[paper] = !expandedSources[paper]; }}
class="w-full text-left px-2 py-1.5 rounded text-sm flex items-center justify-between
{filterSource === paper ? 'bg-[var(--accent)]/15 text-[var(--accent)]' : 'text-[var(--text-dim)] hover:bg-[var(--surface)]'}"
>
<span>{paper}</span>
<span class="text-[10px]">{expandedSources[paper] ? '▼' : '▶'}</span>
</button>
{#if expandedSources[paper] && categories.length > 0}
{#each categories as cat}
<button
onclick={() => { filterSource = `${paper}/${cat}`; }}
class="w-full text-left pl-6 pr-2 py-1 rounded text-xs
{filterSource === `${paper}/${cat}` ? 'bg-[var(--accent)]/15 text-[var(--accent)]' : 'text-[var(--text-dim)] hover:bg-[var(--surface)]'}"
>{cat}</button>
{/each}
{/if}
</div>
{/each}
<hr class="my-3 border-[var(--border)]">