feat(targets): price target/stop simulator with chart overlay lines
- 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>
This commit is contained in:
@@ -38,11 +38,17 @@ function writeLogged(m: LoggedMap): void {
|
||||
}
|
||||
}
|
||||
|
||||
/** 오늘 처음 보는 code 면 true, 이미 봤으면 false. true 인 경우 mark 까지 수행. */
|
||||
export function shouldRecordView(code: string): boolean {
|
||||
/** 오늘 이미 카운트된 종목인지. POST 호출 전 dedupe 게이트. */
|
||||
export function wasRecordedToday(code: string): boolean {
|
||||
const today = kstToday();
|
||||
const logged = readLogged();
|
||||
return logged[code] === today;
|
||||
}
|
||||
|
||||
/** POST 성공 이후 호출. 실패 시 마크하지 않아 다음 방문에 재시도 가능. */
|
||||
export function markRecorded(code: string): void {
|
||||
const today = kstToday();
|
||||
const logged = readLogged();
|
||||
if (logged[code] === today) return false;
|
||||
logged[code] = today;
|
||||
// 한도: 너무 커지면 오래된 항목 제거. 단순히 100개로 잘라냄.
|
||||
const entries = Object.entries(logged);
|
||||
@@ -52,5 +58,4 @@ export function shouldRecordView(code: string): boolean {
|
||||
} else {
|
||||
writeLogged(logged);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user