feat(targets): wrap PriceTargets in Collapsible

사이드바 5번째(이자 마지막 정보성) 패널인 PriceTargets 도 공용 Collapsible
로 통일. SymbolSidebar(상단 종목 카드 — 자체 톤 유지가 맞음) 만 남기고
나머지 사이드 패널 5개(Orderbook / Targets / Alerts / Note / Related)가
모두 같은 토글/영속 패턴.

subtitle 설계 — 접힌 상태에서도 저장값 한눈에:
- 둘 다 저장됨: "목표 12,500 · 손절 9,800"
- 한쪽만: "목표 12,500" / "손절 9,800"
- 둘 다 없음: "비공개 · 브라우저 저장" (InvestmentNote 와 동일 톤)
- dirty 입력값이 아닌 saved 기준만 표시 — 토글 사이클 사이에 안내가
  깜빡이지 않게.

storageKey="targets" → panel-open:targets 영속.
defaultOpen=true — 입력값은 Collapsible 의 hidden 본문 덕에 토글에도
보존되지만, 처음 보는 사용자에겐 input 이 펴져 있어야 "여기서 적는다"
가 자명. 입력 흐름 우선.

기존 rounded-lg 는 Collapsible 기본 rounded-md 로 흡수 — 다른 사이드
패널과 모서리 톤 통일.

검증:
- npx tsc --noEmit clean
- npx next lint "✔ No ESLint warnings or errors"
This commit is contained in:
claude-owner
2026-06-01 10:40:04 +09:00
parent 70d56b14ec
commit b46f6f1b3a

View File

@@ -7,6 +7,7 @@
import { useEffect, useMemo, useState } from "react";
import { readTargets, writeTargets, type Targets } from "../lib/targets";
import { Collapsible } from "./Collapsible";
type Props = {
code: string;
@@ -69,12 +70,24 @@ export function PriceTargets({ code, current, onChange }: Props) {
const pctCls = (p: number | null): string =>
p == null ? "text-zinc-500" : p >= 0 ? "text-rose-400" : "text-sky-400";
// 접힌 상태에서도 유저가 어떤 값을 저장해뒀는지 한눈에 — 둘 다 없으면 InvestmentNote 와
// 같은 톤의 "비공개 · 브라우저 저장" 안내. 저장값(savedN)이 아닌 dirty 입력값을 보여주면
// 토글 사이클 사이에 안내가 깜빡여 혼란. saved 기준만 표시.
const fmtNum = (n: number): string =>
n.toLocaleString(undefined, { maximumFractionDigits: 0 });
const subtitle =
saved.target != null && saved.stop != null
? `목표 ${fmtNum(saved.target)} · 손절 ${fmtNum(saved.stop)}`
: saved.target != null
? `목표 ${fmtNum(saved.target)}`
: saved.stop != null
? `손절 ${fmtNum(saved.stop)}`
: "비공개 · 브라우저 저장";
return (
<div className="rounded-lg border border-zinc-800 bg-zinc-900/40 p-3">
<div className="mb-2 flex items-baseline justify-between">
<h3 className="text-xs font-semibold text-zinc-300"> </h3>
<span className="text-[10px] text-zinc-500"> · </span>
</div>
// defaultOpen=true — 입력 중인 텍스트는 Collapsible 의 hidden 본문 덕에 토글로 사라지지
// 않지만, 처음 보는 사용자에겐 input 이 펴져 있어야 "여기서 목표가를 적는다" 가 자명.
<Collapsible title="내 목표가" subtitle={subtitle} storageKey="targets">
<div className="space-y-2">
<Row
label="목표가"
@@ -114,7 +127,7 @@ export function PriceTargets({ code, current, onChange }: Props) {
{current == null && (
<div className="mt-1 text-[10px] text-zinc-500"> </div>
)}
</div>
</Collapsible>
);
}