docs(scanner): added in instructions on how to update the scanner

only test2 stage now commands for now.
This commit is contained in:
2026-05-12 20:26:19 -05:00
parent dc95e50a84
commit b0c7277a6c
17 changed files with 245 additions and 89 deletions

View File

@@ -1,4 +1,5 @@
import type { Express } from "express"; import type { Express } from "express";
import { featureCheck } from "../middleware/featureActive.middleware.js";
import available from "./availableScanIds.route.js"; import available from "./availableScanIds.route.js";
import downloads from "./downloadApps.route.js"; import downloads from "./downloadApps.route.js";
import lanes from "./laneCheck.js"; import lanes from "./laneCheck.js";
@@ -10,13 +11,13 @@ import version from "./version.route.js";
export const setupMobileRoutes = (baseUrl: string, app: Express) => { export const setupMobileRoutes = (baseUrl: string, app: Express) => {
//stats will be like this as we dont need to change this //stats will be like this as we dont need to change this
app.use(`${baseUrl}/api/mobile/version`, version); app.use(`${baseUrl}/api/mobile/version`, featureCheck("mobile"), version);
app.use(`${baseUrl}/api/mobile/apk`, downloads); app.use(`${baseUrl}/api/mobile/apk`, featureCheck("mobile"), downloads);
app.use(`${baseUrl}/api/mobile/logs`, logs); app.use(`${baseUrl}/api/mobile/logs`, featureCheck("mobile"), logs);
app.use(`${baseUrl}/api/mobile/auth`, authPin); app.use(`${baseUrl}/api/mobile/auth`, featureCheck("mobile"), authPin);
app.use(`${baseUrl}/api/mobile/pin`, newPin); app.use(`${baseUrl}/api/mobile/pin`, featureCheck("mobile"), newPin);
app.use(`${baseUrl}/api/mobile/laneCheck`, lanes); app.use(`${baseUrl}/api/mobile/laneCheck`, featureCheck("mobile"), lanes);
app.use(`${baseUrl}/api/mobile/available`, available); app.use(`${baseUrl}/api/mobile/available`, featureCheck("mobile"), available);
// all other system should be under /api/system/* // all other system should be under /api/system/*
}; };

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 613 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 KiB

Binary file not shown.

View File

@@ -1,11 +1,12 @@
import { useSuspenseQuery } from "@tanstack/react-query";
import { Link, useRouterState } from "@tanstack/react-router"; import { Link, useRouterState } from "@tanstack/react-router";
import { ChevronRight } from "lucide-react"; import { ChevronRight, ScrollText } from "lucide-react";
import { getSettings } from "../../lib/queries/getSettings";
import { import {
Collapsible, Collapsible,
CollapsibleContent, CollapsibleContent,
CollapsibleTrigger, CollapsibleTrigger,
} from "../ui/collapsible"; } from "../ui/collapsible";
import { import {
SidebarGroup, SidebarGroup,
SidebarGroupContent, SidebarGroupContent,
@@ -19,43 +20,55 @@ import {
useSidebar, useSidebar,
} from "../ui/sidebar"; } from "../ui/sidebar";
const docs = [
{
title: "Notifications",
url: "/intro",
//icon,
isActive: window.location.pathname.includes("notifications") ?? false,
items: [
{
title: "Reprints",
url: "/reprints",
},
{
title: "New Blocking order",
url: "/qualityBlocking",
},
],
},
{
title: "Mobile",
url: "/updateInstructions",
isActive: false,
items: [
{
title: "Settings",
url: "/mobile-settings",
},
],
},
];
export default function DocBar() { export default function DocBar() {
const { setOpen } = useSidebar(); const { setOpen } = useSidebar();
const { data: settings, isLoading } = useSuspenseQuery(getSettings());
const pathname = useRouterState({ const pathname = useRouterState({
select: (s) => s.location.pathname, select: (s) => s.location.pathname,
}); });
const isNotifications = pathname.includes("notifications"); const isNotifications = pathname.includes("notifications");
const docs = [
{
title: "Notifications",
url: "notifications/intro",
//icon,
isActive: true,
items: [
{
title: "Reprints",
icon: ScrollText,
url: "notifications/reprints",
},
{
title: "New Blocking order",
icon: ScrollText,
url: "notifications/qualityBlocking",
},
],
},
{
title: "Mobile",
url: "mobile/updateInstructions",
isActive:
!isLoading &&
settings.filter((n: any) => n.name === "mobile")[0].active,
items: [
{
title: "Update Instructions",
icon: ScrollText,
url: "mobile/updateInstructions",
},
// {
// title: "Settings",
// icon: ScrollText,
// url: "mobile/mobile-settings",
// },
],
},
];
return ( return (
<SidebarGroup> <SidebarGroup>
<SidebarGroupLabel>Docs</SidebarGroupLabel> <SidebarGroupLabel>Docs</SidebarGroupLabel>
@@ -72,42 +85,45 @@ export default function DocBar() {
</SidebarMenu> </SidebarMenu>
<SidebarMenu> <SidebarMenu>
{docs.map((item) => ( {docs.map((item) => (
<Collapsible <>
key={item.title} {item.isActive && (
asChild <Collapsible
defaultOpen={isNotifications} key={item.title}
className="group/collapsible" asChild
> defaultOpen={isNotifications}
<SidebarMenuItem> className="group/collapsible"
<CollapsibleTrigger asChild> >
<SidebarMenuButton tooltip={item.title}> <SidebarMenuItem>
<Link <CollapsibleTrigger asChild>
to={"/docs/$"} <SidebarMenuButton tooltip={item.title}>
params={{ _splat: `notifications${item.url}` }} <Link to={"/docs/$"} params={{ _splat: `${item.url}` }}>
> {item.title}
{item.title} </Link>
</Link> <ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
<ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" /> </SidebarMenuButton>
</SidebarMenuButton> </CollapsibleTrigger>
</CollapsibleTrigger> <CollapsibleContent>
<CollapsibleContent> <SidebarMenuSub>
<SidebarMenuSub> {item.items?.map((subItem) => (
{item.items?.map((subItem) => ( <SidebarMenuSubItem key={subItem.title}>
<SidebarMenuSubItem key={subItem.title}> <SidebarMenuSubButton asChild>
<SidebarMenuSubButton asChild> <Link
<Link to={"/docs/$"}
to={"/docs/$"} params={{ _splat: `${subItem.url}` }}
params={{ _splat: `notifications${subItem.url}` }} onClick={() => setOpen(false)}
> >
{subItem.title} <subItem.icon />
</Link> <span>{subItem.title}</span>
</SidebarMenuSubButton> </Link>
</SidebarMenuSubItem> </SidebarMenuSubButton>
))} </SidebarMenuSubItem>
</SidebarMenuSub> ))}
</CollapsibleContent> </SidebarMenuSub>
</SidebarMenuItem> </CollapsibleContent>
</Collapsible> </SidebarMenuItem>
</Collapsible>
)}
</>
))} ))}
</SidebarMenu> </SidebarMenu>
</SidebarGroupContent> </SidebarGroupContent>

View File

@@ -1,5 +1,5 @@
import { Link } from "@tanstack/react-router"; import { Link } from "@tanstack/react-router";
import { ScanText, ScrollText } from "lucide-react"; import { ScanText } from "lucide-react";
import { import {
SidebarGroup, SidebarGroup,
SidebarGroupContent, SidebarGroupContent,
@@ -10,14 +10,14 @@ import {
useSidebar, useSidebar,
} from "../ui/sidebar"; } from "../ui/sidebar";
export default function MobileBar({ session }: any) { export default function MobileBar() {
const { setOpen } = useSidebar(); const { setOpen } = useSidebar();
const items = [ const items = [
{ // {
title: "Update Instructions", // title: "Update Instructions",
url: "/", // url: "/",
icon: ScrollText, // icon: ScrollText,
}, // },
{ {
title: "Scan Log", title: "Scan Log",
url: "/", url: "/",

View File

@@ -1,3 +1,4 @@
import { useSuspenseQuery } from "@tanstack/react-query";
import { import {
Sidebar, Sidebar,
SidebarContent, SidebarContent,
@@ -6,12 +7,14 @@ import {
SidebarMenuItem, SidebarMenuItem,
} from "@/components/ui/sidebar"; } from "@/components/ui/sidebar";
import { useSession } from "@/lib/auth-client"; import { useSession } from "@/lib/auth-client";
import { getSettings } from "../../lib/queries/getSettings";
import AdminSidebar from "./AdminBar"; import AdminSidebar from "./AdminBar";
import DocBar from "./DocBar"; import DocBar from "./DocBar";
import MobileBar from "./MobileBar"; import MobileBar from "./MobileBar";
export function AppSidebar() { export function AppSidebar() {
const { data: session } = useSession(); const { data: session } = useSession();
const { data: settings, isLoading } = useSuspenseQuery(getSettings());
return ( return (
<Sidebar <Sidebar
@@ -24,7 +27,11 @@ export function AppSidebar() {
<SidebarMenuItem> <SidebarMenuItem>
<SidebarContent> <SidebarContent>
<DocBar /> <DocBar />
<MobileBar session={session} /> {!isLoading &&
settings.filter((n: any) => n.name === "mobile")[0].active && (
<MobileBar />
)}
{session && {session &&
(session.user.role === "admin" || (session.user.role === "admin" ||
session.user.role === "systemAdmin" || session.user.role === "systemAdmin" ||

View File

@@ -0,0 +1,137 @@
import { useMutation } from "@tanstack/react-query";
import { Button } from "../../components/ui/button";
import { Separator } from "../../components/ui/separator";
export default function UpdateInstructions() {
const getFile = useMutation({
mutationFn: async () => {
// 1. Fetch the file from the public folder
const response = await fetch(
`/lst/app/stage-now/${window.LST_CONFIG?.server}-stageNow.pdf`,
);
if (!response.ok) throw new Error("Network response was not ok");
// 2. Convert to blob
return await response.blob();
},
onSuccess: (blob) => {
// 3. Create a temporary anchor element to trigger download
const url = window.URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = `${window.LST_CONFIG?.server}-stageNow.pdf`; // Desired filename
document.body.appendChild(a);
a.click();
// 4. Cleanup
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
},
});
return (
<div className="flex flex-row gap-2">
<div className="w-1/2">
<div className="flex flex-col gap-1 justify-center">
<div>
<p className="text-center text-3xl">
Updating the lst mobile scanner app
</p>
<p className="text-center text-sm">
NOTE: LST Mobile only works on TC8300
</p>
</div>
<div className="flex justify-center">
<Button
onClick={() => getFile.mutate()}
disabled={getFile.isPending}
>
{getFile.isPending ? "Downloading..." : "Get StageNow Codes"}
</Button>
</div>
</div>
<Separator className="m-3" />
<div>
<p className="text-2xl text-center">
How to know the scanner has an update?
</p>
<p>
The bottom part of the scanner will show a red or orange bar
indicating there is an update. As shown below
</p>
<div className="flex flex-row gap-2 justify-center">
<div className="w-1/2">
<img
src="/lst/app/imgs/docs/mobile/critical_update.png"
alt="Home"
className="max-w-[50%] h-auto"
/>
</div>
<div className="w-1/2">
<img
src="/lst/app/imgs/docs/mobile/update.png"
alt="Home"
className="max-w-[50%] h-auto"
/>
</div>
</div>
</div>
<Separator className="m-3" />
<div>
<p className="text-2xl text-center">
To update the scanner follow the below steps.
</p>
<p>Step 1) Tap the 3 dots top right of the home screen</p>
<img
src="/lst/app/imgs/docs/mobile/ehs_homeScreen.png"
alt="Home"
className="max-w-[25%] h-auto m-3"
/>
<p>Step 2) Tap tools</p>
<img
src="/lst/app/imgs/docs/mobile/ehs_menu.png"
alt="Home"
className="max-w-[25%] h-auto m-3"
/>
<p>Step 3) Tap Stage Now</p>
<img
src="/lst/app/imgs/docs/mobile/tools.png"
alt="Home"
className="max-w-[25%] h-auto m-3"
/>
<p>
Step 4) Scan the 3 barcode's to the right or from the printed sheet
</p>
<img
src="/lst/app/imgs/docs/mobile/stagenow.png"
alt="Home"
className="max-w-[25%] h-auto m-3"
/>
</div>
</div>
<div className="w-1/2">
<p>Scan Commands</p>
<Separator className="m-3" />
<div className="flex flex-col justify-center">
<img
src={`/lst/app/imgs/docs/mobile/${window.LST_CONFIG?.server}-1.png`}
alt="Home"
className="m-3"
/>
<img
src={`/lst/app/imgs/docs/mobile/${window.LST_CONFIG?.server}-2.png`}
alt="Home"
className="m-3"
/>
<img
src={`/lst/app/imgs/docs/mobile/${window.LST_CONFIG?.server}-3.png`}
alt="Home"
className="m-3"
/>
</div>
</div>
</div>
);
}

View File

@@ -1,3 +0,0 @@
export default function updateInstructions() {
return <div>updateInstructions</div>;
}

View File

@@ -13,9 +13,7 @@ const docsMap: Record<string, ComponentType> = {};
for (const path in modules) { for (const path in modules) {
const mod = modules[path] as DocModule; const mod = modules[path] as DocModule;
const slug = path const slug = path.replace("../docs/", "").replace(".tsx", "");
.replace("../docs/", "")
.replace(".tsx", "");
// "notifications/intro" // "notifications/intro"
docsMap[slug] = mod.default; docsMap[slug] = mod.default;