사이드바 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"
- New lib/targets.ts: per-code localStorage (key `targets:<code>`) with
read/write/clear; rejects non-positive/non-finite values.
- New PriceTargets sidebar panel: 목표가/손절가 inputs, live %-from-current
preview (rose=up, sky=down), save/clear actions.
- StockChart accepts optional `targets` prop and draws dashed horizontal
price lines on the candle series (rose=target, sky=stop) with axis labels.
- Page loads saved targets on mount/code-change and re-renders chart on save.
Also fixes view-counter dedupe caveat from reviewer: split into
wasRecordedToday() + markRecorded(); the page now marks localStorage only
after POST /api/views succeeds, so a failed POST stays retryable on the
next visit instead of being silently swallowed for the day.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>