import { useQuery } from "@tanstack/react-query" import { createFileRoute } from "@tanstack/react-router" import { useState } from "react" import { byRecency, DashboardMosaic } from "@/components/Common/DashboardMosaic" import { DEFAULT_RANGE } from "@/components/Common/RangePicker" import { dashboardsQueryOptions } from "@/components/Dashboard/queries" import { BrainView } from "@/components/Flow/BrainView" import { flowsQueryOptions } from "@/components/Flow/queries" import { FlowTable } from "@/components/Health/FlowTable" import { HealthActivity } from "@/components/Health/HealthActivity" import { HealthOverview } from "@/components/Health/HealthOverview" import { LiveIndicator } from "@/components/Health/LiveIndicator" import { Card } from "@/components/ui/card" export const Route = createFileRoute("/_layout/")({ component: Home, head: () => ({ meta: [ { title: "Home - Fluksio", }, ], }), }) /** DESIGN-GUIDELINES.md → Typography, the canonical section header. */ const HEADER = "text-xs font-medium uppercase tracking-[0.5px] text-muted-foreground" /** * The one overview: what the engine is wired up as, what is running, and how * it has been doing. The brain and the health screens compose in here rather * than living at routes of their own. * * Top to bottom it is a widening lens: the whole installation as a graph, what * has been built on it, whether it is well, then flow by flow and finally * moment by moment. */ function Home() { // The health block's window: one choice, read by the tiles, the flow table, // the charts and the lists under them. const [range, setRange] = useState(DEFAULT_RANGE) const boards = useQuery(dashboardsQueryOptions()) // Only to know whether the brain has anything to draw; the table below runs // its own copy of the same query. const { data } = useQuery(flowsQueryOptions()) const flows = data?.data ?? [] const dashboards = [...(boards.data?.data ?? [])].sort(byRecency) return ( // `[&>*]:min-w-0`: a grid item's automatic minimum is its content, so one // long name or wide table widens the whole column and the page with it. // Every section here is free to shrink instead. See DESIGN-GUIDELINES.md // → Responsive.
{/* Nothing at all while the socket is up. Everything below is polled, so a dead socket would otherwise look like an engine that went quiet. */} {/* Nothing wired up yet means nothing to draw, and the band would still hold a screenful of empty space above the flows table. Node count rather than flow count: a flow made a minute ago has none. */} {flows.some((flow) => (flow.node_count ?? 0) > 0) ? : null} {/* One row across the full width rather than a column beside the flows: a dashboard tile is a picture, and a picture wants to be wide. Past what fits, the strip scrolls sideways on its own — the page must not, which is what the `min-w-0` above is holding. */}

Dashboards

{/* `min-w-0`: the strip inside scrolls, but this card is a grid item whose automatic minimum is its content — without this the tiles widen it, and the page with it. */}
) }