108 lines
2.9 KiB
TypeScript
108 lines
2.9 KiB
TypeScript
import { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
|
|
import { Outlet, json, useLoaderData, useRevalidator } from "@remix-run/react";
|
|
import { useEffect, useRef, useState } from "react";
|
|
import Header, { HeaderData } from "~/components/header";
|
|
import { enhance } from "~/utils/db.server";
|
|
|
|
export async function loader({
|
|
request,
|
|
}: LoaderFunctionArgs) {
|
|
const {dbe, session} = await enhance(request);
|
|
|
|
let sessiondata : HeaderData = {loggedin: false};
|
|
|
|
if(session.has("user_id")){
|
|
sessiondata.user = session.get("user");
|
|
sessiondata.loggedin = true;
|
|
}
|
|
|
|
const numCheckouts = await dbe.history.count({});
|
|
|
|
return json({sessiondata, checkouts: numCheckouts});
|
|
}
|
|
|
|
|
|
export const meta: MetaFunction = ({}) => {
|
|
return [{ title: "Inventory | K-FRIDGE" }];
|
|
};
|
|
|
|
export default function InventoryLayout() {
|
|
let data = useLoaderData<typeof loader>();
|
|
let revalidator = useRevalidator();
|
|
|
|
const [checkouts, setCheckouts] = useState(data.checkouts);
|
|
const shouldFetchRef = useRef(true);
|
|
|
|
// User has switched back to the tab
|
|
const onFocus = () => {
|
|
shouldFetchRef.current = true;
|
|
};
|
|
|
|
// User has switched away from the tab (AKA tab is hidden)
|
|
const onBlur = () => {
|
|
shouldFetchRef.current = false;
|
|
};
|
|
|
|
useEffect(() => {
|
|
window.addEventListener("focus", onFocus);
|
|
window.addEventListener("blur", onBlur);
|
|
// Calls onFocus when the window first loads
|
|
onFocus();
|
|
// Specify how to clean up after this effect:
|
|
return () => {
|
|
window.removeEventListener("focus", onFocus);
|
|
window.removeEventListener("blur", onBlur);
|
|
};
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const pollCheckouts = async () => {
|
|
if (!shouldFetchRef.current) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await fetch("/resource/checkouts", { credentials: "same-origin" });
|
|
if (!response.ok) {
|
|
return;
|
|
}
|
|
|
|
const payload = await response.json() as { checkouts?: number | string | null };
|
|
const newCheckouts = Number(payload.checkouts);
|
|
|
|
if (!Number.isFinite(newCheckouts)) {
|
|
return;
|
|
}
|
|
|
|
if (newCheckouts !== checkouts) {
|
|
setCheckouts(newCheckouts);
|
|
|
|
if (revalidator.state === "idle") {
|
|
revalidator.revalidate();
|
|
}
|
|
}
|
|
} catch {
|
|
// Ignore transient network errors while the connection is down.
|
|
}
|
|
};
|
|
|
|
const timer = window.setInterval(() => {
|
|
void pollCheckouts();
|
|
}, 5000);
|
|
|
|
void pollCheckouts();
|
|
|
|
return () => window.clearInterval(timer);
|
|
}, [checkouts, revalidator]);
|
|
|
|
return (
|
|
<>
|
|
<header>
|
|
<Header data={data.sessiondata}></Header>
|
|
</header>
|
|
<main>
|
|
<Outlet />
|
|
</main>
|
|
</>
|
|
);
|
|
} |