보안 점검 및 대시보드 문구 수정
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { type FormEvent, useCallback, useEffect, useState } from "react";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useShallow } from "zustand/react/shallow";
|
||||
import { LoadingSpinner } from "@/components/ui/loading-spinner";
|
||||
import { useKisRuntimeStore } from "@/features/settings/store/use-kis-runtime-store";
|
||||
@@ -14,6 +14,7 @@ import { useKisTradeWebSocket } from "@/features/trade/hooks/useKisTradeWebSocke
|
||||
import { useStockOverview } from "@/features/trade/hooks/useStockOverview";
|
||||
import { useCurrentPrice } from "@/features/trade/hooks/useCurrentPrice";
|
||||
import { useTradeSearchPanel } from "@/features/trade/hooks/useTradeSearchPanel";
|
||||
import { useTradeNavigationStore } from "@/features/trade/store/use-trade-navigation-store";
|
||||
import type {
|
||||
DashboardStockOrderBookResponse,
|
||||
DashboardStockSearchItem,
|
||||
@@ -27,9 +28,10 @@ import type {
|
||||
* @see features/trade/hooks/useStockOverview.ts 선택 종목 상세 상태를 관리합니다.
|
||||
*/
|
||||
export function TradeContainer() {
|
||||
const searchParams = useSearchParams();
|
||||
const symbolParam = searchParams.get("symbol");
|
||||
const nameParam = searchParams.get("name");
|
||||
const router = useRouter();
|
||||
const consumePendingTarget = useTradeNavigationStore(
|
||||
(state) => state.consumePendingTarget,
|
||||
);
|
||||
|
||||
// [State] 호가 실시간 데이터 (체결 WS와 동일 소켓에서 수신)
|
||||
const [realtimeOrderBook, setRealtimeOrderBook] =
|
||||
@@ -60,28 +62,47 @@ export function TradeContainer() {
|
||||
useStockOverview();
|
||||
|
||||
/**
|
||||
* [Effect] URL 파라미터(symbol) 감지 시 자동 종목 로드
|
||||
* 대시보드 등 외부에서 종목 코드를 넘겨받아 트레이딩 페이지로 진입할 때 사용합니다.
|
||||
* [Effect] query string이 남아 들어온 경우 즉시 깨끗한 /trade URL로 정리합니다.
|
||||
* 과거 링크/브라우저 히스토리로 유입되는 query 오염을 제거하기 위한 방어 로직입니다.
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (symbolParam && isKisVerified && verifiedCredentials && _hasHydrated) {
|
||||
// 현재 선택된 종목과 파라미터가 다를 경우에만 자동 로드 수행
|
||||
if (selectedStock?.symbol !== symbolParam) {
|
||||
setKeyword(nameParam || symbolParam);
|
||||
appendSearchHistory({
|
||||
symbol: symbolParam,
|
||||
name: nameParam || symbolParam,
|
||||
market: "KOSPI", // 기본값 설정, loadOverview 이후 실제 데이터로 보완됨
|
||||
});
|
||||
loadOverview(symbolParam, verifiedCredentials);
|
||||
}
|
||||
if (typeof window === "undefined") return;
|
||||
if (!window.location.search) return;
|
||||
router.replace("/trade");
|
||||
}, [router]);
|
||||
|
||||
/**
|
||||
* [Effect] Dashboard에서 넘긴 종목을 1회 소비해 자동 로드합니다.
|
||||
* @remarks UI 흐름: Dashboard 종목 클릭 -> useTradeNavigationStore.setPendingTarget -> /trade -> consumePendingTarget -> loadOverview
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!isKisVerified || !verifiedCredentials || !_hasHydrated) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pendingTarget = consumePendingTarget();
|
||||
if (!pendingTarget) return;
|
||||
|
||||
if (selectedStock?.symbol === pendingTarget.symbol) {
|
||||
return;
|
||||
}
|
||||
|
||||
setKeyword(pendingTarget.name || pendingTarget.symbol);
|
||||
appendSearchHistory({
|
||||
symbol: pendingTarget.symbol,
|
||||
name: pendingTarget.name || pendingTarget.symbol,
|
||||
market: pendingTarget.market,
|
||||
});
|
||||
loadOverview(
|
||||
pendingTarget.symbol,
|
||||
verifiedCredentials,
|
||||
pendingTarget.market,
|
||||
);
|
||||
}, [
|
||||
symbolParam,
|
||||
nameParam,
|
||||
isKisVerified,
|
||||
verifiedCredentials,
|
||||
_hasHydrated,
|
||||
consumePendingTarget,
|
||||
selectedStock?.symbol,
|
||||
loadOverview,
|
||||
setKeyword,
|
||||
|
||||
Reference in New Issue
Block a user