File size: 3,036 Bytes
4083225
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import { Menu, PanelLeftClose, Pencil } from "lucide-react";
import "./TopBar.css";
import { getNewsTimeframeLabel } from "../constants/timeframes.js";

function fmt(n) {
  if (n == null) return "—";
  if (n >= 1000) return new Intl.NumberFormat("en-US").format(n);
  return String(n);
}

function fmtTime(iso) {
  if (!iso) return "—";
  const d = new Date(iso);
  return d.toLocaleString("en-GB", {
    year: "numeric",
    month: "short",
    day: "2-digit",
    hour: "2-digit",
    minute: "2-digit",
  });
}

function divLabel(d) {
  if (d == null) return { text: "—", tone: "" };
  if (d > 0.7) return { text: "high", tone: "danger" };
  if (d > 0.45) return { text: "moderate", tone: "warn" };
  return { text: "low", tone: "neutral" };
}

export default function TopBar({
  query,
  meta,
  metaLoading,
  menuOpen,
  onToggleMenu,
  onEditTopic,
}) {
  const div = divLabel(meta?.divergenceIndex);

  return (
    <div className="topbar">
      <button
        className="topbar__menu-btn"
        onClick={onToggleMenu}
        aria-label="Toggle visualization menu"
        title="Toggle visualization menu"
      >
        {menuOpen ? <PanelLeftClose size={15} /> : <Menu size={15} />}
        <span>views</span>
      </button>

      <div className="topbar__topic">
        <div className="label">Topic</div>
        <button
          className="topbar__topic-button"
          onClick={onEditTopic}
          title="Change topic"
        >
          <span className="topbar__topic-block">
            <span className="topbar__topic-text">
              {query.topic || "Untitled"}
            </span>
            <span className="topbar__topic-meta">
              {getNewsTimeframeLabel(query.newsTimeframe)}
            </span>
          </span>
          <Pencil size={14} strokeWidth={1.5} className="topbar__topic-icon" />
        </button>
      </div>

      <div className="topbar__metrics" aria-busy={metaLoading || undefined}>
        <Metric label="Articles"    value={fmt(meta?.totalArticles)} />
        <Metric label="Sources"     value={fmt(meta?.totalSources)} />
        <Metric label="Countries"   value={fmt(meta?.countriesCovered)} />
        <Metric label="Languages"   value={fmt(meta?.languagesCovered)} />
        <Metric
          label="Divergence"
          value={
            meta?.divergenceIndex != null
              ? meta.divergenceIndex.toFixed(2)
              : "—"
          }
          accent={div.tone}
          suffix={div.text}
        />
        <Metric
          label="Updated"
          value={fmtTime(meta?.lastUpdated)}
          tight
        />
      </div>
    </div>
  );
}

function Metric({ label, value, accent = "", suffix, tight = false }) {
  return (
    <div className={`metric ${tight ? "metric--tight" : ""}`}>
      <div className="label metric__label">{label}</div>
      <div className={`metric__value metric__value--${accent}`}>
        {value}
        {suffix && <span className="metric__suffix">{suffix}</span>}
      </div>
    </div>
  );
}