More messing about, and learning how it all works. Added time to header. Changed some padding. Changed video to preview not target detection. Added TODO list.
This commit is contained in:
@@ -10,7 +10,7 @@ const Card = ({ children, className }: CardProps) => {
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"bg-[#253445] rounded-lg mt-4 mx-4 px-4 py-4 shadow-2xl overflow-y-auto md:row-span-1",
|
||||
"bg-[#253445] rounded-lg mt-4 mx-2 px-4 py-4 shadow-2xl overflow-y-auto md:row-span-1",
|
||||
className
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -1,10 +1,60 @@
|
||||
import * as React from "react";
|
||||
import { Link } from "react-router";
|
||||
import Logo from "/MAV.svg";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faGear } from "@fortawesome/free-solid-svg-icons";
|
||||
import { faListCheck } from "@fortawesome/free-solid-svg-icons";
|
||||
import { faGear, faListCheck } from "@fortawesome/free-solid-svg-icons";
|
||||
import type { VersionFieldType } from "../../types/types";
|
||||
|
||||
async function fetchVersions(signal?: AbortSignal): Promise<VersionFieldType> {
|
||||
const res = await fetch("http://192.168.75.11/api/versions", { signal });
|
||||
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
||||
return res.json();
|
||||
}
|
||||
|
||||
const pad = (n: number) => String(n).padStart(2, "0");
|
||||
const normalizeToMs = (ts: number) => (ts < 1e12 ? ts * 1000 : ts); // seconds → ms if needed
|
||||
|
||||
function formatFromMs(ms: number, tz: "local" | "utc" = "local") {
|
||||
const d = new Date(ms);
|
||||
const h = tz === "utc" ? d.getUTCHours() : d.getHours();
|
||||
const m = tz === "utc" ? d.getUTCMinutes() : d.getMinutes();
|
||||
const s = tz === "utc" ? d.getUTCSeconds() : d.getSeconds();
|
||||
const day = tz === "utc" ? d.getUTCDate() : d.getDate();
|
||||
const month = (tz === "utc" ? d.getUTCMonth() : d.getMonth()) + 1;
|
||||
const year = tz === "utc" ? d.getUTCFullYear() : d.getFullYear();
|
||||
return `${pad(h)}:${pad(m)}:${pad(s)} ${pad(day)}-${pad(month)}-${year}`;
|
||||
}
|
||||
|
||||
export default function Header() {
|
||||
const [offsetMs, setOffsetMs] = React.useState<number | null>(null);
|
||||
const [nowMs, setNowMs] = React.useState<number>(Date.now());
|
||||
|
||||
React.useEffect(() => {
|
||||
const ac = new AbortController();
|
||||
fetchVersions(ac.signal)
|
||||
.then((data) => {
|
||||
const serverMs = normalizeToMs(data.timeStamp);
|
||||
setOffsetMs(serverMs - Date.now());
|
||||
})
|
||||
return () => ac.abort();
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
let timer: number;
|
||||
const schedule = () => {
|
||||
const now = Date.now();
|
||||
setNowMs(now);
|
||||
const delay = 1000 - (now % 1000);
|
||||
timer = window.setTimeout(schedule, delay);
|
||||
};
|
||||
schedule();
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
const serverNowMs = offsetMs == null ? nowMs : nowMs + offsetMs;
|
||||
const localStr = formatFromMs(serverNowMs, "local");
|
||||
const utcStr = formatFromMs(serverNowMs, "utc");
|
||||
|
||||
const Header = () => {
|
||||
return (
|
||||
<div className="relative bg-[#253445] border-b border-gray-500 items-center mx-auto px-2 sm:px-6 lg:px-8 p-4 flex flex-row justify-between">
|
||||
{/* Left: Logo */}
|
||||
@@ -13,17 +63,20 @@ const Header = () => {
|
||||
<img src={Logo} alt="Logo" width={150} height={150} />
|
||||
</Link>
|
||||
</div>
|
||||
<div className="flex items-center space-x-8">
|
||||
{/* Right: Texts stacked + icons */}
|
||||
<div className="flex items-center space-x-12">
|
||||
<div className="flex flex-col leading-tight text-white text-sm tabular-nums">
|
||||
<h2>Local: {localStr}</h2>
|
||||
<h2>UTC: {utcStr}</h2>
|
||||
</div>
|
||||
|
||||
<Link to={"/session-settings"}>
|
||||
<FontAwesomeIcon icon={faListCheck} />
|
||||
<FontAwesomeIcon className="text-white" icon={faListCheck} />
|
||||
</Link>
|
||||
<Link to={"/system-settings"}>
|
||||
<FontAwesomeIcon icon={faGear} />
|
||||
<FontAwesomeIcon className="text-white" icon={faGear} />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default Header;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ const NavigationArrow = ({ side, settingsPage }: NavigationArrowProps) => {
|
||||
if (settingsPage) {
|
||||
return (
|
||||
<>
|
||||
{side === "TargetDetectionFront" ? (
|
||||
{side === "CameraFront" ? (
|
||||
<FontAwesomeIcon
|
||||
icon={faArrowRight}
|
||||
className="absolute top-[50%] right-[2%] backdrop-blur-md hover:cursor-pointer animate-bounce"
|
||||
|
||||
Reference in New Issue
Block a user