diff --git a/components/StockDetails.tsx b/components/StockDetails.tsx index ecd37fa..f662c3b 100644 --- a/components/StockDetails.tsx +++ b/components/StockDetails.tsx @@ -8,7 +8,7 @@ import { Check, ChevronDown, ChevronLeft, Heart } from 'lucide-react'; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { TrendingUp, TrendingDown } from "lucide-react" -import { useGetOverallPortfolioQuery, useGetWalletQuery } from "@/lib/api"; +import { useGetOverallPortfolioQuery, useGetWalletQuery } from "@/lib/api"; import { mutate } from 'swr'; // 주식 상세 정보를 보여주는 컴포넌트(종목정보 상세, 내 계좌, AI 추천 탭) @@ -32,8 +32,8 @@ export default function StockDetails({ symbol, activeTab, onTabChange, favoriteS const [aiSubmitted, setAiSubmitted] = useState(false); const [isHeartFilled, setIsHeartFilled] = useState(false); - const { data: portfolioData, isLoading: isPortfolioLoading } = useGetOverallPortfolioQuery(); - const { data: walletData, isLoading: isWalletLoading } = useGetWalletQuery(); + const { data: portfolioData, isLoading: isPortfolioLoading, refetch: refetchPortfolio } = useGetOverallPortfolioQuery(); + const { data: walletData, isLoading: isWalletLoading, refetch: refetchWallet } = useGetWalletQuery(); const [selectedRiskLevel, setSelectedRiskLevel] = useState(null); const [selectedStrategies, setSelectedStrategies] = useState([]); @@ -79,7 +79,7 @@ export default function StockDetails({ symbol, activeTab, onTabChange, favoriteS useEffect(() => { const fetchData = async () => { if (!symbol) return; // symbol이 없으면 실행하지 않음 - + setIsLoading(true); setError(null); try { @@ -90,8 +90,8 @@ export default function StockDetails({ symbol, activeTab, onTabChange, favoriteS if (response.data) { const price = response.data.currentPrice; const lastPrice = response.data.lastPrice; - const change = lastPrice !== 0 && lastPrice !== undefined && lastPrice !== null - ? ((price - lastPrice) / lastPrice) * 100 + const change = lastPrice !== 0 && lastPrice !== undefined && lastPrice !== null + ? ((price - lastPrice) / lastPrice) * 100 : 0; onTabChange(activeTab); // 탭 변경을 통해 상위 컴포넌트에 데이터 업데이트 알림 } @@ -113,7 +113,7 @@ export default function StockDetails({ symbol, activeTab, onTabChange, favoriteS useEffect(() => { const fetchUserPreference = async () => { if (!isLoggedIn) return; - + setIsLoadingPreference(true); try { const response = await getUserPreference(); @@ -127,7 +127,13 @@ export default function StockDetails({ symbol, activeTab, onTabChange, favoriteS fetchUserPreference(); }, [isLoggedIn]); - + //내계좌 누를대마다 리패치하기 + useEffect(() => { + if (activeTab === '내 계좌') { + refetchPortfolio(); + refetchWallet(); + } + }, [activeTab]); // AI 추천 종목 데이터 가져오기 useEffect(() => { const fetchAiRecommendations = async () => { @@ -168,7 +174,7 @@ export default function StockDetails({ symbol, activeTab, onTabChange, favoriteS }; const handleStrategyClick = (strategy: PreferredStrategy) => { - setSelectedStrategies(prev => + setSelectedStrategies(prev => prev.includes(strategy) ? prev.filter(s => s !== strategy) : [...prev, strategy] @@ -176,7 +182,7 @@ export default function StockDetails({ symbol, activeTab, onTabChange, favoriteS }; const handleSectorClick = (sector: PreferredSector) => { - setSelectedSectors(prev => + setSelectedSectors(prev => prev.includes(sector) ? prev.filter(s => s !== sector) : [...prev, sector] @@ -218,11 +224,11 @@ export default function StockDetails({ symbol, activeTab, onTabChange, favoriteS console.log('API 요청 데이터:', requestData); const response = await saveUserPreference(requestData); console.log('API 응답 데이터:', response); - + // 선호도 저장 후 데이터 다시 가져오기 const updatedPreference = await getUserPreference(); setUserPreference(updatedPreference); - + setShowResult(true); } catch (error) { console.error('API 에러:', error); @@ -233,9 +239,9 @@ export default function StockDetails({ symbol, activeTab, onTabChange, favoriteS }; // 추천 이유 파싱 함수 - const parseAiReason = (reasons: any[]): { - portfolio: string; - industry: string; + const parseAiReason = (reasons: any[]): { + portfolio: string; + industry: string; ai: string; portfolioStrategy: string; industryStrategy: string; @@ -297,9 +303,8 @@ export default function StockDetails({ symbol, activeTab, onTabChange, favoriteS onTabChange(tab); setShowReasonDetail(false); }} - className={`px-2 md:px-4 py-2 rounded-xl font-medium text-xs md:text-sm whitespace-nowrap transition-colors ${ - activeTab === tab ? 'bg-[#f5f7f9]' : 'bg-[#f5f7f9] hover:bg-gray-200' - }`} + className={`px-2 md:px-4 py-2 rounded-xl font-medium text-xs md:text-sm whitespace-nowrap transition-colors ${activeTab === tab ? 'bg-[#f5f7f9]' : 'bg-[#f5f7f9] hover:bg-gray-200' + }`} > {tab} @@ -325,9 +330,8 @@ export default function StockDetails({ symbol, activeTab, onTabChange, favoriteS onTabChange(tab); setShowReasonDetail(false); }} - className={`px-2 md:px-4 py-2 rounded-xl font-medium text-xs md:text-sm whitespace-nowrap transition-colors ${ - activeTab === tab ? 'bg-[#f5f7f9]' : 'bg-[#f5f7f9] hover:bg-gray-200' - }`} + className={`px-2 md:px-4 py-2 rounded-xl font-medium text-xs md:text-sm whitespace-nowrap transition-colors ${activeTab === tab ? 'bg-[#f5f7f9]' : 'bg-[#f5f7f9] hover:bg-gray-200' + }`} > {tab} @@ -420,9 +424,8 @@ export default function StockDetails({ symbol, activeTab, onTabChange, favoriteS onTabChange(tab); setAiSubmitted(false); }} - className={`px-2 md:px-4 py-2 rounded-xl font-medium text-xs md:text-sm whitespace-nowrap transition-colors ${ - activeTab === tab ? 'bg-[#f5f7f9]' : 'bg-[#f5f7f9] hover:bg-gray-200' - }`} + className={`px-2 md:px-4 py-2 rounded-xl font-medium text-xs md:text-sm whitespace-nowrap transition-colors ${activeTab === tab ? 'bg-[#f5f7f9]' : 'bg-[#f5f7f9] hover:bg-gray-200' + }`} > {tab} @@ -464,55 +467,55 @@ export default function StockDetails({ symbol, activeTab, onTabChange, favoriteS
투자금액
- $ - - {portfolioData?.data?.investedAmount?.toLocaleString("en-US", { - minimumFractionDigits: 2, - maximumFractionDigits: 2, - }) ?? '-'} - -
+ $ + + {portfolioData?.data?.investedAmount?.toLocaleString("en-US", { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + }) ?? '-'} + +
{/* Unrealized P&L */}
평가손익 -
= 0 - ? "text-[#41c3a9] group-hover:text-[#4caf50]" - : "text-[#e74c3c] group-hover:text-[#a73d2a]"} +
= 0 + ? "text-[#41c3a9] group-hover:text-[#4caf50]" + : "text-[#e74c3c] group-hover:text-[#a73d2a]"} `} - > - $ - - {(portfolioData?.data?.evalGain ?? 0) >= 0 ? "+" : "-"} - {Math.abs(portfolioData?.data?.evalGain ?? 0).toLocaleString("en-US", { - minimumFractionDigits: 2, - maximumFractionDigits: 2, - })} - -
+ > + $ + + {(portfolioData?.data?.evalGain ?? 0) >= 0 ? "+" : "-"} + {Math.abs(portfolioData?.data?.evalGain ?? 0).toLocaleString("en-US", { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + })} + +
{/* Return Rate */}
수익률
= 0 - ? "text-[#41c3a9] group-hover:text-[#4caf50]" - : "text-[#e74c3c] group-hover:text-[#a73d2a]"} + className={`text-xl font-bold transition-colors flex items-center gap-1 + ${(portfolioData?.data?.returnRate ?? 0) >= 0 + ? "text-[#41c3a9] group-hover:text-[#4caf50]" + : "text-[#e74c3c] group-hover:text-[#a73d2a]"} `} > {(portfolioData?.data?.returnRate ?? 0) >= 0 ? ( - - ) : ( - - )} - {(portfolioData?.data?.returnRate ?? 0) >= 0 ? "+" : "-"} - {Math.abs((portfolioData?.data?.returnRate ?? 0)*1000).toFixed(2)}% - -
+ + ) : ( + + )} + {(portfolioData?.data?.returnRate ?? 0) >= 0 ? "+" : "-"} + {Math.abs((portfolioData?.data?.returnRate ?? 0) * 1000).toFixed(2)}% + +
@@ -539,10 +542,9 @@ export default function StockDetails({ symbol, activeTab, onTabChange, favoriteS

당신의 투자 성향

- - )} @@ -844,7 +839,7 @@ export default function StockDetails({ symbol, activeTab, onTabChange, favoriteS
ROE - {details.roe !== undefined ? `${(details.roe*100).toFixed(2)}%` : '-'} + {details.roe !== undefined ? `${(details.roe * 100).toFixed(2)}%` : '-'}
EPS