import Link from "next/link"; import { Activity, RefreshCcw, Settings2, Wifi } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import type { DashboardBalanceSummary } from "@/features/dashboard/types/dashboard.types"; import { formatCurrency, formatSignedCurrency, formatSignedPercent, getChangeToneClass, } from "@/features/dashboard/utils/dashboard-format"; import { cn } from "@/lib/utils"; interface StatusHeaderProps { summary: DashboardBalanceSummary | null; isKisRestConnected: boolean; isWebSocketReady: boolean; isRealtimePending: boolean; isProfileVerified: boolean; verifiedAccountNo: string | null; isRefreshing: boolean; lastUpdatedAt: string | null; onRefresh: () => void; } /** * @description 대시보드 상단 상태 헤더(총자산/손익/연결상태/빠른액션) 컴포넌트입니다. * @see features/dashboard/components/DashboardContainer.tsx 대시보드 루트에서 상태 값을 전달받아 렌더링합니다. */ export function StatusHeader({ summary, isKisRestConnected, isWebSocketReady, isRealtimePending, isProfileVerified, verifiedAccountNo, isRefreshing, lastUpdatedAt, onRefresh, }: StatusHeaderProps) { const toneClass = getChangeToneClass(summary?.totalProfitLoss ?? 0); const updatedLabel = lastUpdatedAt ? new Date(lastUpdatedAt).toLocaleTimeString("ko-KR", { hour12: false, }) : "--:--:--"; const hasApiTotalAmount = Boolean(summary) && (summary?.apiReportedTotalAmount ?? 0) > 0; const hasApiNetAssetAmount = Boolean(summary) && (summary?.apiReportedNetAssetAmount ?? 0) > 0; const isApiTotalAmountDifferent = Boolean(summary) && Math.abs( (summary?.apiReportedTotalAmount ?? 0) - (summary?.totalAmount ?? 0), ) >= 1; const realtimeStatusLabel = isWebSocketReady ? isRealtimePending ? "수신 대기중" : "연결됨" : "미연결"; return ( {/* ========== BACKGROUND DECORATION ========== */}
{/* ========== TOTAL ASSET ========== */}

내 자산 (순자산 실시간)

{summary ? `${formatCurrency(summary.totalAmount)}원` : "-"}

현금(예수금) {summary ? `${formatCurrency(summary.cashBalance)}원` : "-"}

주식 평가금{" "} {summary ? `${formatCurrency(summary.evaluationAmount)}원` : "-"}

총예수금(KIS){" "} {summary ? `${formatCurrency(summary.totalDepositAmount)}원` : "-"}

총예수금은 결제 대기 금액이 포함될 수 있어 체감 현금과 다를 수 있습니다.

순자산(대출 반영){" "} {summary ? `${formatCurrency(summary.netAssetAmount)}원` : "-"}

{hasApiTotalAmount && isApiTotalAmountDifferent ? (

KIS 집계 총자산 {formatCurrency(summary?.apiReportedTotalAmount ?? 0)}원

) : null} {hasApiNetAssetAmount ? (

KIS 집계 순자산 {formatCurrency(summary?.apiReportedNetAssetAmount ?? 0)}원

) : null}
{/* ========== PROFIT/LOSS ========== */}

현재 손익

{summary ? `${formatSignedCurrency(summary.totalProfitLoss)}원` : "-"}

{summary ? formatSignedPercent(summary.totalProfitRate) : "-"}

현재 평가금액{" "} {summary ? `${formatCurrency(summary.evaluationAmount)}원` : "-"}

총 매수금액{" "} {summary ? `${formatCurrency(summary.purchaseAmount)}원` : "-"}

{/* ========== CONNECTION STATUS ========== */}

연결 상태

서버 {isKisRestConnected ? "연결됨" : "연결 끊김"} 실시간 시세 {realtimeStatusLabel} 계좌 인증 {isProfileVerified ? "완료" : "미완료"}

마지막 업데이트 {updatedLabel}

계좌 {maskAccountNo(verifiedAccountNo)}

대출금 {summary ? `${formatCurrency(summary.loanAmount)}원` : "-"}

{/* ========== QUICK ACTIONS ========== */}
); } /** * @description 계좌번호를 마스킹해 표시합니다. * @param value 계좌번호(8-2) * @returns 마스킹 문자열 * @see features/dashboard/components/StatusHeader.tsx 시스템 상태 영역 계좌 표시 */ function maskAccountNo(value: string | null) { if (!value) return "-"; const digits = value.replace(/\D/g, ""); if (digits.length !== 10) return "********"; return "********-**"; }