File size: 1,916 Bytes
a8f12e6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { useEffect, useRef, useState } from "react";
import { checkHealth } from "../services/api";

const POLL_INTERVAL_MS = 10000;

export default function StatusBadge() {
  const [health, setHealth] = useState(null);
  const [phase, setPhase] = useState("checking"); // 'checking' | 'online' | 'offline'
  const mountedRef = useRef(true);

  useEffect(() => {
    mountedRef.current = true;
    let cancelled = false;

    const poll = async () => {
      const result = await checkHealth();
      if (cancelled || !mountedRef.current) return;
      if (result?.model_loaded) {
        setHealth(result);
        setPhase("online");
      } else {
        setHealth(result);
        setPhase("offline");
      }
    };

    poll();
    const interval = setInterval(poll, POLL_INTERVAL_MS);

    const onFocus = () => poll();
    window.addEventListener("focus", onFocus);

    return () => {
      cancelled = true;
      mountedRef.current = false;
      clearInterval(interval);
      window.removeEventListener("focus", onFocus);
    };
  }, []);

  if (phase === "checking") {
    return (
      <div className="inline-flex items-center gap-2 px-3 py-1 bg-gray-700 text-gray-300 rounded-full text-sm">
        <div className="w-2 h-2 bg-gray-500 rounded-full animate-pulse" />
        Checking...
      </div>
    );
  }

  const isOnline = phase === "online";
  const statusColor = isOnline ? "bg-green-500" : "bg-red-500";
  const statusText = isOnline ? "Backend online" : "Backend offline";

  return (
    <div className="inline-flex items-center gap-2 px-3 py-1 bg-gray-900 border border-gray-700 rounded-full text-sm">
      <div className={`w-2 h-2 ${statusColor} rounded-full`} />
      <span className="text-gray-300">{statusText}</span>
      {health?.api_version && (
        <span className="text-gray-500 text-xs ml-1">
          v{health.api_version}
        </span>
      )}
    </div>
  );
}