From 12412536d10981013053c39d156c6c9cb0babd11 Mon Sep 17 00:00:00 2001 From: Blake Matthes Date: Wed, 6 May 2026 12:09:47 -0500 Subject: [PATCH] refactor(scanner): finished login stuff for current routes --- backend/mobile/mobileAuth.route.ts | 4 +++ lstMobile/app.json | 4 +-- lstMobile/src/app/(tabs)/_layout.tsx | 8 +++-- lstMobile/src/app/login.tsx | 5 ++-- lstMobile/src/app/setup.tsx | 2 ++ lstMobile/src/components/LSTScanner.tsx | 37 +++++++++++++++++++----- lstMobile/src/components/ProdScanner.tsx | 18 ++++++++++-- lstMobile/src/hooks/useAppStartup.tsx | 28 ++---------------- lstMobile/src/hooks/useMobileAuth.ts | 31 +++++++++++++++++--- 9 files changed, 91 insertions(+), 46 deletions(-) diff --git a/backend/mobile/mobileAuth.route.ts b/backend/mobile/mobileAuth.route.ts index 017443b..76da6f8 100644 --- a/backend/mobile/mobileAuth.route.ts +++ b/backend/mobile/mobileAuth.route.ts @@ -263,6 +263,10 @@ r.patch("/user/:id", requireAuth, async (req, res) => { updates.active = req.body.active; } + if (req.body?.excludedCommand !== undefined) { + updates.excludedCommand = req.body.excludedCommand; + } + if (req.body?.role !== undefined) { updates.role = req.body.role; } diff --git a/lstMobile/app.json b/lstMobile/app.json index 42d4d41..d1a0261 100644 --- a/lstMobile/app.json +++ b/lstMobile/app.json @@ -15,8 +15,8 @@ "foregroundImage": "./assets/adaptive-icon-white.png", "backgroundColor": "#ffffff" }, - "versionCode": 24, - "minSupportedVersionCode": 21, + "versionCode": 30, + "minSupportedVersionCode": 26, "predictiveBackGestureEnabled": false, "package": "net.alpla.lst.mobile" }, diff --git a/lstMobile/src/app/(tabs)/_layout.tsx b/lstMobile/src/app/(tabs)/_layout.tsx index bcdeb4f..98eca0b 100644 --- a/lstMobile/src/app/(tabs)/_layout.tsx +++ b/lstMobile/src/app/(tabs)/_layout.tsx @@ -15,9 +15,11 @@ export default function TabsLayout() { const isUnlocked = useMobileAuthStore((s) => s.isUnlocked); const port = parseInt(serverPort || "0", 10) >= 50000; - - if (!user || (!isUnlocked && !port)) { - return ; + console.log(port); + if (!port) { + if (!user || !isUnlocked) { + return ; + } } const isNormalScanner = parseInt(serverPort || "0", 10) >= 50000; diff --git a/lstMobile/src/app/login.tsx b/lstMobile/src/app/login.tsx index a4dd642..4890f35 100644 --- a/lstMobile/src/app/login.tsx +++ b/lstMobile/src/app/login.tsx @@ -2,7 +2,7 @@ import axios from "axios"; import { useRouter } from "expo-router"; import { useState } from "react"; -import { Button, Text, View } from "react-native"; +import { Alert, Button, Text, View } from "react-native"; import { Input } from "../components/ui/input"; import { useAppStore } from "../hooks/useAppStore"; import { useMobileAuthStore } from "../hooks/useMobileAuth"; @@ -38,6 +38,7 @@ export default function Login() { } } catch (error) { console.log(error); + Alert.alert("Login Error", `Invalid pin please try again`); } }; @@ -70,7 +71,7 @@ export default function Login() { - + Warning: If you are logged into another scanner you will encounter scan errors, please do not try to log into more than 1 scanner at a time. diff --git a/lstMobile/src/app/setup.tsx b/lstMobile/src/app/setup.tsx index 7c672cb..8f081ca 100644 --- a/lstMobile/src/app/setup.tsx +++ b/lstMobile/src/app/setup.tsx @@ -25,6 +25,8 @@ export default function Setup() { const server = useServerStore((s) => s.serverVersion); + // TODO: if on lst version and the user is manager or admin just login + const authCheck = () => { if (pin === "6971") { setAuth(true); diff --git a/lstMobile/src/components/LSTScanner.tsx b/lstMobile/src/components/LSTScanner.tsx index c621ab0..0c3d981 100644 --- a/lstMobile/src/components/LSTScanner.tsx +++ b/lstMobile/src/components/LSTScanner.tsx @@ -7,6 +7,7 @@ import { useMobileAuthStore } from "../hooks/useMobileAuth"; import { useScannerStore } from "../hooks/useScannerStore"; import { scannerFeedback } from "../lib/feedbackScan"; import { sendTcpMessage } from "../lib/tcpScan"; +import { versionCheck } from "../lib/versionValidation"; import { type ZebraScanResult, zebraScanner } from "../lib/ZebraScanner"; import { ScannedLabelBox } from "./ScannedLabels"; import { GlobalFooter } from "./UpdateFooter"; @@ -45,10 +46,15 @@ export default function LSTScanner() { scan.data.toLowerCase().includes(cmd.toLowerCase()), ); + console.log(user?.excludedCommand); + if (isAlphaStart && isExcluded) { Alert.alert( - `Command: ${scan.data} is not allowed to be used, please contact logistics if this is an error`, + "Command not allowed", + `Command: ${scan.data}\n\nPlease contact logistics if this is an error`, ); + + return; } let commandToSend = `${STX}${user?.scannerId}@${scan.data}${ETX}`; @@ -68,16 +74,24 @@ export default function LSTScanner() { const scanned = (await sendTcpMessage( commandToSend, serverIp, - parseInt(serverPort || "0", 10), + 50004, )) as any; + // send the logs to lst but allow it to time out if it dose not exist just bc. - const logInfo = { ...scanned, user: user?.name }; try { - await axios.post( - `http://${serverIp.trim()}:3000/lst/api/mobile/logs`, - logInfo, - ); + await axios.post(`http://${serverIp.trim()}:3000/lst/api/mobile/logs`, { + scannerId: user?.scannerId ?? "0", + message: scanned.data.message, + prompt: scanned.data.prompt, + commandDescription: scanned.data.commandDescription, + status: scanned.data.status, + lines: scanned.data.lines, + user: user?.name ?? "prodScan", + runningNumber: scan.data.startsWith("000") + ? parseInt(scan.data.slice(10, -1) || "000", 10).toString() + : "0", + }); } catch (error) { console.log(error); } @@ -90,7 +104,15 @@ export default function LSTScanner() { vibrate: true, led: true, }); + setBGColor("bg-green-500"); + + // version check + versionCheck(); + + // auth update + useMobileAuthStore.getState().updateLastScan(); + setTimeout(() => { setBGColor(null); }, 1 * 1000); @@ -117,7 +139,6 @@ export default function LSTScanner() { }, [ serverIp, - serverPort, setLastScan, user?.scannerId, user?.name, diff --git a/lstMobile/src/components/ProdScanner.tsx b/lstMobile/src/components/ProdScanner.tsx index f3ba186..d56fcc4 100644 --- a/lstMobile/src/components/ProdScanner.tsx +++ b/lstMobile/src/components/ProdScanner.tsx @@ -3,9 +3,11 @@ import { format } from "date-fns-tz"; import { useCallback, useEffect, useState } from "react"; import { Text, View } from "react-native"; import { useAppStore } from "../hooks/useAppStore"; +import { useMobileAuthStore } from "../hooks/useMobileAuth"; import { useScannerStore } from "../hooks/useScannerStore"; import { scannerFeedback } from "../lib/feedbackScan"; import { sendTcpMessage } from "../lib/tcpScan"; +import { versionCheck } from "../lib/versionValidation"; import { type ZebraScanResult, zebraScanner } from "../lib/ZebraScanner"; import { ScannedLabelBox } from "./ScannedLabels"; import { GlobalFooter } from "./UpdateFooter"; @@ -52,11 +54,16 @@ export default function ProdScanner() { parseInt(serverPort || "0", 10), )) as any; // send the logs to lst but allow it to time out if it dose not exist just bc. - + const data = { + ...scanned.data, + runningNumber: scan.data.startsWith("000") + ? parseInt(scan.data.slice(10, -1) || "000", 10).toString() + : "0", + }; try { await axios.post( `http://${serverIp.trim()}:3000/lst/api/mobile/logs`, - scanned, + data, ); } catch (error) { console.log(error); @@ -71,6 +78,13 @@ export default function ProdScanner() { led: true, }); setBGColor("bg-green-500"); + + // version check + versionCheck(); + + // auth update + useMobileAuthStore.getState().updateLastScan(); + setTimeout(() => { setBGColor(null); }, 1 * 1000); diff --git a/lstMobile/src/hooks/useAppStartup.tsx b/lstMobile/src/hooks/useAppStartup.tsx index 1d7a50b..b509ab0 100644 --- a/lstMobile/src/hooks/useAppStartup.tsx +++ b/lstMobile/src/hooks/useAppStartup.tsx @@ -2,6 +2,7 @@ import axios from "axios"; import Constants from "expo-constants"; import { useEffect, useRef, useState } from "react"; import { devDelay } from "../lib/devMode"; +import { versionCheck } from "../lib/versionValidation"; import { useAppStore } from "./useAppStore"; import { useServerStore } from "./useServerCheck"; @@ -24,7 +25,6 @@ export function useAppStartup() { const hasHydrated = useAppStore((s) => s.hasHydrated); const serverPort = useAppStore((s) => s.serverPort); const serverIp = useAppStore((s) => s.serverIp); - const setServerVersion = useServerStore((s) => s.setServerVersion); useEffect(() => { if (!hasHydrated) { @@ -62,29 +62,7 @@ export function useAppStartup() { return; } - const port = - parseInt(serverPort || "0", 10) >= 50000 ? "3000" : serverPort; - - try { - const res = await axios.get( - `http://${serverIp}:${port}/lst/api/mobile/version`, - { timeout: 5000 }, - ); - - if (res.status === 200) { - setServerVersion(res.data); - } - - const build = Constants.expoConfig?.android?.versionCode ?? 1; - - if (build < res.data.minSupportedVersionCode) { - setStartupRoute("/updateScreen"); - setReady(true); - return; - } - } catch (error) { - console.log("Version check error:", error); - } + await versionCheck(); setStatus("scannerMode"); await devDelay(1500); @@ -123,7 +101,7 @@ export function useAppStartup() { return () => { cancelled = true; }; - }, [hasHydrated, serverIp, serverPort, setServerVersion]); + }, [hasHydrated, serverIp, serverPort]); return { ready, diff --git a/lstMobile/src/hooks/useMobileAuth.ts b/lstMobile/src/hooks/useMobileAuth.ts index 8652f08..a5f8961 100644 --- a/lstMobile/src/hooks/useMobileAuth.ts +++ b/lstMobile/src/hooks/useMobileAuth.ts @@ -1,5 +1,7 @@ import { create } from "zustand"; +const ONE_HOUR = 1000 * 60 * 60; + type MobileUser = { id: string; name: string; @@ -11,19 +13,40 @@ type MobileUser = { type AuthState = { user: MobileUser | null; isUnlocked: boolean; + lastScanAt: number | null; setUser: (user: MobileUser) => void; + updateLastScan: () => void; lock: () => void; logout: () => void; + shouldLockForIdle: () => boolean; }; -export const useMobileAuthStore = create((set) => ({ +export const useMobileAuthStore = create((set, get) => ({ user: null, isUnlocked: false, + lastScanAt: null, - setUser: (user) => set({ user, isUnlocked: true }), - + setUser: (user) => + set({ + user, + isUnlocked: true, + lastScanAt: Date.now(), + }), + updateLastScan: () => set({ lastScanAt: Date.now() }), lock: () => set({ isUnlocked: false }), - logout: () => set({ user: null, isUnlocked: false }), + logout: () => + set({ + user: null, + isUnlocked: false, + lastScanAt: null, + }), + shouldLockForIdle: () => { + const lastScanAt = get().lastScanAt; + + if (!lastScanAt) return true; + + return Date.now() - lastScanAt > ONE_HOUR; + }, }));