feat(alerts): 가격 알람 (localStorage + 60s 폴러 + 토스트)
- lib/alerts.ts: id/code/op(gte|lte)/target/triggered 저장소, watchlist/recent 와 동일 pub/sub - AlertsPanel: 종목 사이드바에 ≥/≤ 토글 + 목표가 입력 + 활성 알람 리스트(재무장/삭제) - AlertsToaster: layout 전역 마운트, 미발사 알람 코드만 폴링, 조건 충족시 markTriggered + 우측 하단 토스트(6s), Notification 권한 허용 시 브라우저 알림 병행
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
import Link from "next/link";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { AlertsPanel } from "../../components/AlertsPanel";
|
||||
import { CompositeScoreCard } from "../../components/CompositeScoreCard";
|
||||
import { DisclosuresPanel } from "../../components/DisclosuresPanel";
|
||||
import { MetricsPanel } from "../../components/MetricsPanel";
|
||||
@@ -145,6 +146,7 @@ export default function CodePage({ params }: { params: { code: string } }) {
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
<SymbolSidebar code={code} />
|
||||
<AlertsPanel code={code} name={chart?.name} current={current} />
|
||||
<RelatedStocks code={code} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import "./globals.css";
|
||||
import type { Metadata } from "next";
|
||||
import { AlertsToaster } from "../components/AlertsToaster";
|
||||
import { TopNav } from "../components/TopNav";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
@@ -13,6 +14,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
||||
<body className="min-h-screen">
|
||||
<TopNav />
|
||||
{children}
|
||||
<AlertsToaster />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user