import { useMemo, useState } from "react" import { Link } from "react-router-dom" import { Globe, RefreshCw, FileText, ShieldCheck } from "lucide-react" import type { GatewayInfo, HealthStatus } from "@/types" import { useGatewayReload, useCaddyfile } from "@/services/api/hooks" import { apiClient } from "@/services/api/client" import { HealthBadge } from "./HealthBadge" interface GatewayPanelProps { gateway: GatewayInfo statuses: HealthStatus[] } export function GatewayPanel({ gateway, statuses }: GatewayPanelProps) { const statusMap = new Map(statuses.map((s) => [s.id, s])) const { mutate: reload, isPending: reloading } = useGatewayReload() const [showCaddyfile, setShowCaddyfile] = useState(false) const { data: caddyfileData } = useCaddyfile(showCaddyfile) const multiNode = useMemo(() => { const nodes = new Set(gateway.routes.map((r) => r.node)) return nodes.size > 1 }, [gateway.routes]) return (
{/* Header */}

Gateway

{gateway.hostname} · port {gateway.port} · {gateway.routes.length} route{gateway.routes.length !== 1 ? "s" : ""}
{gateway.tls === "internal" && ( CA cert )}
{/* Route table — every gateway route, of every kind */} {gateway.routes.length > 0 && ( {multiNode && ( )} {gateway.routes.map((route) => { // Health applies to proxy/remote targets (a running service); // static targets are files on disk. const health = route.kind !== "static" && route.name ? statusMap.get(route.name) : undefined return ( {multiNode && ( )} ) })}
Address Kind TargetNodeHealth
{route.address} {route.name ? ( {route.kind === "static" ? shortDir(route.target) : route.target} ) : ( route.target )} {route.node} {route.kind === "static" ? ( ) : ( )}
)} {gateway.routes.length === 0 && (

No gateway routes configured.

)} {/* Caddyfile viewer */} {showCaddyfile && caddyfileData && (
            {caddyfileData.content}
          
)}
) } const KIND_STYLE: Record = { static: "bg-cyan-900/30 text-cyan-300 border-cyan-800", proxy: "bg-green-900/30 text-green-300 border-green-800", remote: "bg-purple-900/30 text-purple-300 border-purple-800", } /** Caddy serves static files; proxy/remote forward to a process. */ function KindBadge({ kind }: { kind: string }) { return ( {kind} ) } /** Show the tail of a serve directory (…/app/dist). */ function shortDir(path: string): string { const parts = path.split("/").filter(Boolean) return parts.length <= 2 ? path : "…/" + parts.slice(-2).join("/") }