summaryrefslogtreecommitdiff
path: root/frontend/components/prism/TickerHeader.tsx
blob: 804ffc08b3f42696583b60a9db2c2aa94f25bbe7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import { deltaClass, fmtCurrency, fmtPct } from "@/lib/format";
import { rangePercent } from "@/lib/overview";
import type { TickerOverview } from "@/types/api";

type Props = {
  overview: TickerOverview;
  onToggleWatchlist: () => void;
  isSaved: boolean;
};

export function TickerHeader({ overview, onToggleWatchlist, isSaved }: Props) {
  const pct = rangePercent(overview);
  const lastSource = overview.meta.sources["quote.price"];

  return (
    <header className="psm-ticker-head">
      <div className="psm-header-left">
        {overview.profile.sector && (
          <span className="psm-sector-label">{overview.profile.sector}</span>
        )}
        <div className="psm-heading-row">
          <span className="psm-company-sym">{overview.profile.symbol}</span>
          <span className="psm-company-name">{overview.profile.name || "Name unavailable"}</span>
        </div>
        <div className="psm-head-meta">
          {overview.profile.exchange ? <span className="psm-tag">{overview.profile.exchange}</span> : null}
          {overview.meta.is_partial ? <span className="psm-partial-chip">Partial Data</span> : null}
        </div>
      </div>

      <div className="psm-range">
        <div className="psm-eyebrow">52 Week Range</div>
        <div className="psm-range-values">
          <span>{fmtCurrency(overview.range_52w.low)}</span>
          <span className="psm-range-spot">{fmtCurrency(overview.range_52w.price ?? overview.quote.price)}</span>
          <span>{fmtCurrency(overview.range_52w.high)}</span>
        </div>
        <div className="psm-range-rail" aria-hidden>
          {pct != null ? <span className="psm-range-indicator" style={{ left: `${pct}%` }} /> : null}
        </div>
        <div className="psm-range-caption">{pct == null ? "Range unavailable" : `${pct.toFixed(0)}% through the annual range`}</div>
      </div>

      <div className="psm-price-stack">
        <span className="psm-price">{fmtCurrency(overview.quote.price)}</span>
        <span className={`psm-change ${deltaClass(overview.quote.change_pct)}`}>
          {fmtCurrency(overview.quote.change)} · {fmtPct(overview.quote.change_pct, 2, true)}
        </span>
        <span className="psm-quote-line">Prev close {fmtCurrency(overview.quote.prev_close)}</span>
        {lastSource ? <span className="psm-quote-line">Source {lastSource.replaceAll("_", " ")}</span> : null}
        <button type="button" className={`psm-primary-action${isSaved ? " subtle" : ""}`} onClick={onToggleWatchlist}>
          {isSaved ? "Remove From Watchlist" : "Save To Watchlist"}
        </button>
      </div>
    </header>
  );
}