+
+
+ {cfg.label}
+
+ {h.name || h.ticker}
+ {h.ticker}
+ {h.close != null && (
+ {h.close.toLocaleString()}원
+ )}
+ = 0 ? 'is-up' : 'is-down'}`}>
+ {fmtRate(h.pnl_rate)}
+
+
+ {h.reasons && (
+
{h.reasons}
+ )}
+ {h.tech_score != null && (
+
+ 기술강도 {h.tech_score.toFixed(0)}
+
+
+ )}
+ {issues.length > 0 && (
+
+ {issues.map((iss, i) => (
+
+
+ {iss.summary}
+
+ ))}
+
+ )}
+
+ );
+};
+
+/* ── main component ───────────────────────────────────────────────── */
+const HoldingsIntelTab = () => {
+ const [data, setData] = useState(null);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState('');
+
+ useEffect(() => {
+ setLoading(true);
+ setError('');
+ stockHoldingsIntel()
+ .then(setData)
+ .catch((err) => setError(err?.message ?? String(err)))
+ .finally(() => setLoading(false));
+ }, []);
+
+ const ph = data?.portfolio_health ?? {};
+ const holdings = data?.holdings ?? [];
+
+ return (
+