Files
lst_v3/lstMobile/src/components/LSTScanner.tsx
Blake Matthes db28635c8c
All checks were successful
Build and Push LST Docker Image / docker (push) Successful in 3m1s
fix(mobile): ui over lapping
the ui elements would over lap and cause visual issues with the scanning and seeing the old labels

closes #25
2026-05-27 20:57:49 -05:00

257 lines
6.6 KiB
TypeScript

import axios from "axios";
import { format } from "date-fns-tz";
import Constants from "expo-constants";
import { Redirect, useFocusEffect, useRouter } from "expo-router";
import { useCallback, useEffect, useState } from "react";
import { Alert, Button, 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";
import { Separator } from "./ui/separator";
const STX = "\x02";
const ETX = "\x03";
const formatName = (name?: string) =>
name ? name.charAt(0).toUpperCase() + name.slice(1).toLowerCase() : "";
export default function LSTScanner() {
const user = useMobileAuthStore((s) => s.user);
const logout = useMobileAuthStore((s) => s.logout);
const router = useRouter();
// TODO : move to off tcp stuff after od
const lastScan = useScannerStore((s) => s.lastScan);
const setLastScan = useScannerStore((s) => s.setLastScan);
const [tagScans, setTagScans] = useState<any>([]);
const serverIp = useAppStore((s) => s.serverIp);
const [bgColor, setBGColor] = useState<string | null>(null);
const build = Constants.expoConfig?.android?.versionCode ?? 1;
const handleScan = useCallback(
async (scan: ZebraScanResult) => {
await scannerFeedback({
type: "scan",
sound: true,
vibrate: true,
led: true,
});
const isAlphaStart = /^[a-zA-Z]/.test(scan.data);
const isExcluded = (user?.excludedCommand ?? []).some((cmd) =>
scan.data.toLowerCase().includes(cmd.toLowerCase()),
);
console.log(user?.excludedCommand);
if (isAlphaStart && isExcluded) {
Alert.alert(
"Command not allowed",
`Command: ${scan.data}\n\nPlease contact logistics if this is an error`,
);
return;
}
let commandToSend = `${STX}${user?.scannerId}@${scan.data}${ETX}`;
// if we are sscc we need to scan like this .... <STX>98@]C100090087710038712256<ETX>
if (scan.data.startsWith("000")) {
commandToSend = `${STX}${user?.scannerId}@]C1${scan.data}${ETX}`;
setTagScans((prev: any) => [
{
label: parseInt(scan.data.slice(10, -1) || "000", 10).toString(),
date: format(new Date(Date.now()), "HH:mm"),
},
...prev,
]);
}
const scanned = (await sendTcpMessage(
commandToSend,
serverIp,
50004,
)) as any;
// send the logs to lst but allow it to time out if it dose not exist just bc.
try {
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()
: scan.data.startsWith("loc")
? scan.data
: "0",
scannerVersion: build,
});
} catch (error) {
console.log(error);
}
// const response = await sendTcpMessage(tcpMessage);
console.log(scanned.data);
if (scanned.data.status !== "error") {
await scannerFeedback({
type: "good",
sound: true,
vibrate: true,
led: true,
});
setBGColor("bg-green-500");
// version check
versionCheck();
// auth update
useMobileAuthStore.getState().updateLastScan();
setTimeout(() => {
setBGColor(null);
}, 1 * 1000);
}
if (scanned.data.status === "error") {
await scannerFeedback({
type: scanned.data.status === "error" ? "bad" : "good",
sound: true,
vibrate: true,
led: true,
});
setBGColor("bg-red-500");
setTimeout(() => {
setBGColor(null);
}, 1 * 1000);
}
setLastScan(scanned.data);
// if we change commands we want to zero out the last scanned labels
if (isAlphaStart) {
setTagScans([]);
}
},
[
serverIp,
setLastScan,
user?.scannerId,
user?.name,
user?.excludedCommand?.some,
user?.excludedCommand,
build,
],
);
const clearScans = () => {
setTagScans([]);
};
const logoutScanner = () => {
setTagScans([]);
setLastScan(null);
logout();
router.replace("/");
};
//console.log(lastScan);
useFocusEffect(
useCallback(() => {
zebraScanner.startListening();
const sub = zebraScanner.addScanListener((scan) => {
//console.log("SCAN:", scan);
handleScan(scan);
});
return () => {
sub.remove();
zebraScanner.stopListening();
};
}, [handleScan]),
);
return (
<View className={`${bgColor ?? ""} flex-1 w-full`}>
<View className="flex gap-2 items-center">
<View className="flex flex-col gap-2 items-center">
<Text style={{ fontSize: 14, fontWeight: "600" }}>
Lst user: {formatName(user?.name ?? "")}
</Text>
{/* <Text style={{ fontSize: 14, fontWeight: "600" }}>
LST Scanner id: {user?.scannerId}
</Text> */}
</View>
<View
style={{
marginTop: 5,
alignItems: "center",
}}
>
{!lastScan ? (
<View style={{ marginTop: 2, alignItems: "center" }}>
<Text className="text-lg font-bold">Ready to scan</Text>
<Text>Please Scan a command to start scanning...</Text>
<Text className="text-sm">
Scanning a label could cause errors due to incorrect previous
command scanned
</Text>
</View>
) : (
<View
style={{
marginTop: 2,
alignItems: "center",
}}
>
{lastScan.lines
?.filter((line) => !/^\d+@$/.test(line))
.map((i) => {
return (
<View
style={{ marginTop: 2, alignItems: "center" }}
key={i}
>
<Text style={{ fontSize: 12, fontWeight: "600" }}>
{i}
</Text>
</View>
);
})}
</View>
)}
</View>
</View>
<Separator className="m-2" />
<View className="flex-1 w-full px-4">
<ScannedLabelBox
labels={tagScans}
color={bgColor}
clearScan={clearScans}
/>
<GlobalFooter />
</View>
{/* <View className="m-2">
{user && (
<View className="items-center">
<Button title="Logout" onPress={logoutScanner} />
</View>
)}
</View> */}
{/* <View style={{ maxHeight: 75 }} className="flex-1 bg-slate-500"></View> */}
</View>
);
}