import React, { useState, useEffect } from 'react'; import { Newspaper, MessageCircle, ExternalLink, Clock, User, TrendingUp, Calendar, RefreshCw } from 'lucide-react'; import { stockApi, NewsSocialRequest, NewsSocialResponse, NewsArticle, SocialPost, formatDate } from '@/lib/api'; interface NewsSocialDisplayProps { ticker: string; } const NewsSocialDisplay: React.FC = ({ ticker }) => { const [data, setData] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [activeTab, setActiveTab] = useState<'all' | 'news' | 'social'>('all'); const [settings, setSettings] = useState({ ticker: ticker, days_back: 7, max_articles: 15, max_social_posts: 10, include_social: true, }); // Update ticker when prop changes and clear previous data useEffect(() => { // Clear previous data immediately when ticker changes if (settings.ticker !== ticker) { setData(null); setError(null); setLoading(false); setSettings(prev => ({ ...prev, ticker: ticker })); } }, [ticker, settings.ticker]); // Auto-fetch when settings change (but not on initial ticker update) useEffect(() => { if (ticker && ticker.length > 0 && settings.ticker === ticker) { fetchNewsSocialData(); } }, [settings.ticker, settings.days_back, settings.max_articles, settings.max_social_posts, settings.include_social]); const fetchNewsSocialData = async () => { if (!ticker) return; setLoading(true); setError(null); // Clear previous data when starting new fetch setData(null); try { const result = await stockApi.getNewsSocialData(settings); setData(result); } catch (err) { console.error('News/Social data fetch error:', err); setError(err instanceof Error ? err.message : '뉴스 및 소셜 미디어 데이터를 가져오는데 실패했습니다.'); } finally { setLoading(false); } }; const formatTimeAgo = (publishedAt?: string) => { if (!publishedAt) return ''; const now = new Date(); const published = new Date(publishedAt); const diffInHours = Math.floor((now.getTime() - published.getTime()) / (1000 * 60 * 60)); if (diffInHours < 1) return '방금 전'; if (diffInHours < 24) return `${diffInHours}시간 전`; const diffInDays = Math.floor(diffInHours / 24); if (diffInDays < 7) return `${diffInDays}일 전`; return formatDate(publishedAt); }; const NewsCard: React.FC<{ article: NewsArticle }> = ({ article }) => (
{article.source} {article.published_at && ( <> {formatTimeAgo(article.published_at)} )}

{article.title}

{article.summary && (

{article.summary}

)}
{article.author && ( <> {article.author} )}
읽기
); const SocialCard: React.FC<{ post: SocialPost }> = ({ post }) => (
{post.platform} {post.subreddit && ( r/{post.subreddit} )} {post.published_at && ( <> {formatTimeAgo(post.published_at)} )}
{typeof post.score === 'number' && (
{post.score}
)}

{post.title}

{post.content && post.content.length > 0 && (

{post.content}

)}
{post.author} {typeof post.comments_count === 'number' && post.comments_count > 0 && ( <> {post.comments_count} 댓글 )}
보기
); if (!ticker) { return (

종목을 선택하면 관련 뉴스와 소셜 미디어 데이터를 확인할 수 있습니다.

); } return (
{/* 헤더 및 설정 */}

뉴스 & 소셜 미디어 ({ticker})

{/* 설정 옵션 */}
{/* 탭 */}
{/* 로딩 상태 */} {loading && (

데이터를 불러오는 중...

)} {/* 오류 상태 */} {error && !loading && (

{error}

)} {/* 데이터 표시 - 로딩 중이 아니고 에러도 없을 때만 */} {!loading && !error && data && ( <> {/* 요약 정보 - 데이터가 있을 때만 표시 */} {data.summary.total_items > 0 && (
{data.news.total_articles}
뉴스 기사
{data.social_media.total_posts}
소셜 포스트
{data.summary.total_items}
전체 항목
{data.summary.time_range_days}
조회 일수
)} {/* 콘텐츠 표시 */} {(activeTab === 'all' || activeTab === 'news') && data.news.articles.length > 0 && (
{activeTab === 'all' &&

뉴스 기사

}
{data.news.articles.map((article, index) => ( ))}
)} {(activeTab === 'all' || activeTab === 'social') && data.social_media.posts.length > 0 && (
{activeTab === 'all' &&

소셜 미디어

}
{data.social_media.posts.map((post, index) => ( ))}
)} {/* 데이터 없음 메시지 */} {data.summary.total_items === 0 && (

{ticker}에 대한 뉴스가 없습니다.

다른 기간을 선택하거나 다른 종목을 검색해 보세요.

)} )}
); }; export default NewsSocialDisplay;