- New lib/notes.ts: localStorage key `notes:<code>` storing { text, updatedAt },
2000-char cap, blank/whitespace removes the key.
- New InvestmentNote sidebar panel: textarea + character counter, save button
enabled only when dirty, "방금 전 / N분 전 / 오늘 HH:MM / YYYY-MM-DD"
relative timestamp on the last save, short save-confirmation toast.
- Mounted in [code]/page.tsx sidebar after AlertsPanel.
Also tightens writeTargets() to require strictly positive finite values,
matching the UI's parseNum() guard so the lib is safe under direct external
calls (reviewer's non-blocking note on a4a4a7f).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
51 lines
1.7 KiB
TypeScript
51 lines
1.7 KiB
TypeScript
// 종목별 목표가/손절가 저장 (브라우저 한정 — 비로그인 앱).
|
|
//
|
|
// 키: `targets:<code>` → { target?: number, stop?: number, savedAt: ISO }
|
|
// 차트 오버레이 라인과 손익 미리보기에 사용. 알림 없음 (그건 AlertsPanel 담당).
|
|
|
|
const PREFIX = "targets:";
|
|
|
|
export type Targets = {
|
|
target?: number | null; // 익절가 (선택)
|
|
stop?: number | null; // 손절가 (선택)
|
|
savedAt?: string;
|
|
};
|
|
|
|
export function readTargets(code: string): Targets {
|
|
if (typeof window === "undefined") return {};
|
|
try {
|
|
const raw = window.localStorage.getItem(`${PREFIX}${code}`);
|
|
return raw ? (JSON.parse(raw) as Targets) : {};
|
|
} catch {
|
|
return {};
|
|
}
|
|
}
|
|
|
|
export function writeTargets(code: string, t: Targets): void {
|
|
if (typeof window === "undefined") return;
|
|
// 둘 다 비어 있으면 키 자체를 지움 → 빈 객체 잔여물 제거.
|
|
// 양수 유한값만 통과. UI 가 이미 가드하지만 lib 자체도 방어 — 외부에서 직접 호출돼도 안전.
|
|
const cleaned: Targets = {};
|
|
if (t.target != null && Number.isFinite(t.target) && t.target > 0) cleaned.target = t.target;
|
|
if (t.stop != null && Number.isFinite(t.stop) && t.stop > 0) cleaned.stop = t.stop;
|
|
try {
|
|
if (cleaned.target == null && cleaned.stop == null) {
|
|
window.localStorage.removeItem(`${PREFIX}${code}`);
|
|
return;
|
|
}
|
|
cleaned.savedAt = new Date().toISOString();
|
|
window.localStorage.setItem(`${PREFIX}${code}`, JSON.stringify(cleaned));
|
|
} catch {
|
|
/* quota 초과 등 — 무시 */
|
|
}
|
|
}
|
|
|
|
export function clearTargets(code: string): void {
|
|
if (typeof window === "undefined") return;
|
|
try {
|
|
window.localStorage.removeItem(`${PREFIX}${code}`);
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
}
|