Add lat long. Refactor.

This commit is contained in:
James Pace 2026-03-07 21:47:10 +00:00
parent 99b148cdc5
commit 86870c4d2a
5 changed files with 112 additions and 67 deletions

View File

@ -2,8 +2,9 @@ import { useState } from "react";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { Provider as JotaiProvider } from "jotai";
import { Home } from "./Home.tsx";
import { Autonomy } from "./Autonomy.tsx";
import { Version } from "./Version.tsx";
import { Network } from "./Network.tsx";
import { WhoAmI } from "./WhoAmI.tsx";
import "./App.css";
function App() {
@ -26,13 +27,17 @@ const router = createBrowserRouter([
element: <Home />,
},
{
path: "/network",
element: <Network />,
path: "/whoami",
element: <WhoAmI />,
},
{
path: "/version",
element: <Version />,
},
{
path: "/autonomy",
element: <Autonomy />,
},
]);
export default App;

View File

@ -17,8 +17,11 @@ export function AppNav() {
<Nav.Link as={Link} to="/version">
Version
</Nav.Link>
<Nav.Link as={Link} to="/network">
Network
<Nav.Link as={Link} to="/whoami">
WhoAmI
</Nav.Link>
<Nav.Link as={Link} to="/autonomy">
Autonomy
</Nav.Link>
</Nav>
</Navbar.Collapse>

97
src/Autonomy.tsx Normal file
View File

@ -0,0 +1,97 @@
import { AppNav, Footer } from "./AppNav.tsx";
import { Container, Row, Col, Image, Card } from "react-bootstrap";
import { atom, useAtomValue } from "jotai";
import { atomWithQuery } from "jotai-tanstack-query";
const costmapImageQuery = async () => {
const resp = await fetch("api/costmap_image");
if (!resp.ok) {
throw new Error("Network response was not ok");
}
const blob = await resp.blob();
return URL.createObjectURL(blob);
};
const costmapImageQueryAtom = atomWithQuery(() => ({
queryKey: ["costmap_image"],
queryFn: costmapImageQuery,
refetchInterval: 1000, // 1s
}));
const costmapImageAtom = atom((get) => {
const response = get(costmapImageQueryAtom);
if (response.isPending) {
return <p>"Loading..."</p>;
}
if (response.isError) {
return <p>"Error loading!"</p>;
}
const costmapStyle = {
minHeight: "65svb",
};
return <Image src={response.data} fluid style={costmapStyle} />;
});
const statusStringQuery = async () => {
const resp = await fetch("api/status");
if (!resp.ok) {
throw new Error("Network response was not ok");
}
return resp.json();
};
const statusStringQueryAtom = atomWithQuery(() => ({
queryKey: ["status_string"],
queryFn: statusStringQuery,
refetchInterval: 500, // 0.5s
}));
const statusStringAtom = atom((get) => {
const response = get(statusStringQueryAtom);
if (response.isPending || response.isError || !response.data.status) {
return "N/A";
}
return response.data.message;
});
const latLongQuery = async () => {
const resp = await fetch("api/position");
if (!resp.ok) {
throw new Error("Network response was not ok");
}
return resp.json();
};
const latLongQueryAtom = atomWithQuery(() => ({
queryKey: ["latlong"],
queryFn: latLongQuery,
refetchInterval: 500, // 0.5s
}));
const latLongAtom = atom((get) => {
const response = get(latLongQueryAtom);
if (response.isPending || response.isError || !response.data.status) {
return "N/A";
}
return `(${response.data.latitude}, ${response.data.longitude})`;
});
export function Autonomy() {
const costmapImage = useAtomValue(costmapImageAtom);
const statusString = useAtomValue(statusStringAtom);
const latLong = useAtomValue(latLongAtom);
return (
<div>
<AppNav />
<Container className="vert-padded">
<Card className="padded">
<Row>
<Col lg={8}>{costmapImage}</Col>
<Col lg={4}>
<p>Status:</p>
<pre>{statusString}</pre>
<p>Latitude, Longitude:</p>
<pre>{latLong}</pre>
</Col>
</Row>
</Card>
</Container>
<Footer />
</div>
);
}

View File

@ -3,74 +3,14 @@ import { Container, Row, Col, Image, Card } from "react-bootstrap";
import { atom, useAtomValue } from "jotai";
import { atomWithQuery } from "jotai-tanstack-query";
const costmapImageQuery = async () => {
const resp = await fetch("api/costmap_image");
if (!resp.ok) {
throw new Error("Network response was not ok");
}
const blob = await resp.blob();
return URL.createObjectURL(blob);
};
const costmapImageQueryAtom = atomWithQuery(() => ({
queryKey: ["costmap_image"],
queryFn: costmapImageQuery,
refetchInterval: 1000, // 1s
}));
const costmapImageAtom = atom((get) => {
const response = get(costmapImageQueryAtom);
if (response.isPending) {
return <p>"Loading..."</p>;
}
if (response.isError) {
return <p>"Error loading!"</p>;
}
const costmapStyle = {
minHeight: "65svb",
};
return <Image src={response.data} fluid style={costmapStyle} />;
});
const statusStringQuery = async () => {
const resp = await fetch("api/status");
if (!resp.ok) {
throw new Error("Network response was not ok");
}
return resp.json();
};
const statusStringQueryAtom = atomWithQuery(() => ({
queryKey: ["status_string"],
queryFn: statusStringQuery,
refetchInterval: 500, // 0.5s
}));
const statusStringAtom = atom((get) => {
const response = get(statusStringQueryAtom);
if (response.isPending) {
return "Loading...";
}
if (response.isError) {
return "Error loading!";
}
if (!response.data.status) {
return "N/A";
}
return response.data.message;
});
export function Home() {
const costmapImage = useAtomValue(costmapImageAtom);
const statusString = useAtomValue(statusStringAtom);
return (
<div>
<AppNav />
<Container className="vert-padded">
<Card className="padded">
<Row>
<Col lg={8}>{costmapImage}</Col>
<Col lg={4}>
<p>Status:</p>
<pre>{statusString}</pre>
</Col>
<p>Hello World!</p>
</Row>
</Card>
</Container>

View File

@ -1,7 +1,7 @@
import { AppNav, Footer } from "./AppNav.tsx";
import { Container, Row, Col, Image } from "react-bootstrap";
export function Network() {
export function WhoAmI() {
return (
<div>
<AppNav />