From c998753eea506cf795e6fd67684b920a301651b6 Mon Sep 17 00:00:00 2001 From: gahusb Date: Sat, 23 May 2026 03:03:36 +0900 Subject: [PATCH] =?UTF-8?q?feat(insta):=20=EC=B9=B4=EB=93=9C=20=ED=83=AD?= =?UTF-8?q?=20=ED=8A=B8=EB=A0=8C=EB=94=A9=20=ED=82=A4=EC=9B=8C=EB=93=9C=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EC=A0=9C=EA=B1=B0=20+=2010=EA=B0=9C?= =?UTF-8?q?=EC=94=A9=20=ED=8E=98=EC=9D=B4=EC=A7=80=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit KeywordsPanel이 전체 목록을 세로로 길게 표시하던 것을, 동일 keyword 중복 제거(최고 score 유지)·score 내림차순 후 페이지당 10개만 렌더하고 이전(←)/다음(→) 페이저로 탐색하도록 변경. 카테고리 변경 시 첫 페이지 리셋. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/pages/insta/InstaCards.css | 12 ++++++ src/pages/insta/InstaCards.jsx | 75 ++++++++++++++++++++++++++-------- 2 files changed, 69 insertions(+), 18 deletions(-) diff --git a/src/pages/insta/InstaCards.css b/src/pages/insta/InstaCards.css index 1945aa0..50d0cb1 100644 --- a/src/pages/insta/InstaCards.css +++ b/src/pages/insta/InstaCards.css @@ -59,6 +59,18 @@ .ic-keyword-row__meta { font-size: 0.72rem; color: rgba(255,255,255,.35); white-space: nowrap; } .ic-keyword-row__score { font-size: 0.75rem; font-weight: 700; color: #ec4899; min-width: 36px; text-align: right; } +/* 키워드 페이저 (10개씩, 이전/다음) */ +.ic-keywords__pager { display: flex; align-items: center; justify-content: center; gap: 14px; margin-top: 12px; } +.ic-pager-btn { + display: inline-flex; align-items: center; justify-content: center; + width: 36px; height: 36px; border-radius: 99px; + border: 1px solid rgba(255,255,255,.12); background: rgba(255,255,255,.04); + color: rgba(255,255,255,.7); font-size: 1.1rem; cursor: pointer; transition: all .15s; +} +.ic-pager-btn:hover:not(:disabled) { background: rgba(236,72,153,.18); border-color: #ec4899; color: #ec4899; } +.ic-pager-btn:disabled { opacity: .3; cursor: not-allowed; } +.ic-pager-info { font-size: 0.8rem; font-weight: 600; color: rgba(255,255,255,.55); min-width: 48px; text-align: center; } + /* 슬레이트 그리드 — 모바일 2칸 강제, 데스크탑 auto-fill */ .ic-slates-grid { display: grid; diff --git a/src/pages/insta/InstaCards.jsx b/src/pages/insta/InstaCards.jsx index f4b3f9c..fa5231b 100644 --- a/src/pages/insta/InstaCards.jsx +++ b/src/pages/insta/InstaCards.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useCallback, useRef } from 'react'; +import React, { useState, useEffect, useCallback, useRef, useMemo } from 'react'; import PullToRefresh from '../../components/PullToRefresh'; import { getInstaStatus, @@ -521,11 +521,13 @@ function TriggerPanel() { /* ══════════════════════ 키워드 목록 ══════════════════════════════════════ */ const CATEGORIES = ['전체', 'economy', 'psychology', 'celebrity']; +const KEYWORDS_PER_PAGE = 10; function KeywordsPanel({ onCreateSlate }) { const [category, setCategory] = useState('전체'); const [keywords, setKeywords] = useState([]); const [creating, setCreating] = useState(null); // keyword_id being created + const [page, setPage] = useState(0); const load = useCallback(() => { const cat = category === '전체' ? undefined : category; @@ -533,6 +535,23 @@ function KeywordsPanel({ onCreateSlate }) { }, [category]); useEffect(() => { load(); }, [load]); + useEffect(() => { setPage(0); }, [category]); // 카테고리 변경 시 첫 페이지로 + + // 동일 keyword 중복 제거(최고 score 1개만 유지) + score 내림차순 + const deduped = useMemo(() => { + const best = new Map(); + for (const kw of keywords) { + const name = (kw.keyword || '').trim(); + if (!name) continue; + const prev = best.get(name); + if (!prev || (kw.score ?? 0) > (prev.score ?? 0)) best.set(name, kw); + } + return [...best.values()].sort((a, b) => (b.score ?? 0) - (a.score ?? 0)); + }, [keywords]); + + const totalPages = Math.max(1, Math.ceil(deduped.length / KEYWORDS_PER_PAGE)); + const safePage = Math.min(page, totalPages - 1); + const pageItems = deduped.slice(safePage * KEYWORDS_PER_PAGE, safePage * KEYWORDS_PER_PAGE + KEYWORDS_PER_PAGE); // 부모(InstaCards)의 handleCreateSlate에 위임 — progress 배너 + 스크롤 + 자동 미리보기 공통화 async function handleCreate(kw) { @@ -568,27 +587,47 @@ function KeywordsPanel({ onCreateSlate }) { {/* progress 표시는 상단 ic-slate-progress 배너에서 일괄 처리 */} - {keywords.length === 0 ? ( + {deduped.length === 0 ? (
키워드가 없습니다. 키워드 추출을 실행하세요.
) : ( -
- {keywords.map((kw) => ( -
- {kw.keyword} - - {kw.category} · {kw.articles_count ?? 0}건 - - {kw.score?.toFixed(1) ?? '-'} + <> +
+ {pageItems.map((kw) => ( +
+ {kw.keyword} + + {kw.category} · {kw.articles_count ?? 0}건 + + {kw.score?.toFixed(1) ?? '-'} + +
+ ))} +
+ + {totalPages > 1 && ( +
+ className="ic-pager-btn" + onClick={() => setPage((p) => Math.max(0, p - 1))} + disabled={safePage === 0} + aria-label="이전 키워드" + >← + {safePage + 1} / {totalPages} +
- ))} -
+ )} + )}
);