"use client"; // 종목 페이지의 가격 알람 패널. // 현재 종목의 활성 알람 리스트 + 새 알람 추가 폼 (≥ / ≤ + 가격). // 발사 자체는 AlertsToaster 가 글로벌로 처리. 여기는 입력/표시만. // Collapsible 본문은 hidden 으로만 가리므로 접어도 op/target partial 입력 유지. import { useEffect, useState } from "react"; import { alerts, type Alert, type AlertOp } from "../lib/alerts"; import { Collapsible } from "./Collapsible"; type Props = { code: string; name?: string | null; // 현재가 — 폼 placeholder 와 기본값으로 사용. current?: number | null; }; export function AlertsPanel({ code, name, current }: Props) { const [items, setItems] = useState([]); const [op, setOp] = useState("gte"); const [target, setTarget] = useState(""); useEffect(() => { const refresh = () => setItems(alerts.listForCode(code)); refresh(); return alerts.subscribe(refresh); }, [code]); const onAdd = () => { const n = Number(target.replace(/[, ]/g, "")); if (!Number.isFinite(n) || n <= 0) return; alerts.add({ code, name: name ?? undefined, op, target: n }); setTarget(""); }; const subtitle = current != null ? `현재가 ${current.toLocaleString()}원` : undefined; return (
setTarget(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") onAdd(); }} placeholder={current != null ? String(Math.round(current)) : "목표가"} className="w-28 rounded-md border border-zinc-700 bg-zinc-900 px-2 py-1 text-xs text-zinc-100 outline-none focus:border-zinc-500" />
{items.length === 0 ? (
설정된 알람이 없습니다. 임계값을 추가하세요.
) : (
    {items.map((a) => (
  • {a.op === "gte" ? "≥" : "≤"} {a.target.toLocaleString()} {a.triggered && ( 발사됨 )}
    {a.triggered && ( )}
  • ))}
)}
); }