diff --git a/.gitignore b/.gitignore index 9e8d69f..e8a3934 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,6 @@ controllerBuilds # ignoring the old app that will be built into this one to make deploying faster and more easy as we do the migration lstV2/frontend/.tanstack -mobileLst keys # Logs logs diff --git a/mobileLst/.gitignore b/mobileLst/.gitignore new file mode 100644 index 0000000..f8c6c2e --- /dev/null +++ b/mobileLst/.gitignore @@ -0,0 +1,43 @@ +# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files + +# dependencies +node_modules/ + +# Expo +.expo/ +dist/ +web-build/ +expo-env.d.ts + +# Native +.kotlin/ +*.orig.* +*.jks +*.p8 +*.p12 +*.key +*.mobileprovision + +# Metro +.metro-health-check* + +# debug +npm-debug.* +yarn-debug.* +yarn-error.* + +# macOS +.DS_Store +*.pem + +# local env files +.env*.local + +# typescript +*.tsbuildinfo + +app-example + +# generated native folders +/ios +/android diff --git a/mobileLst/README.md b/mobileLst/README.md new file mode 100644 index 0000000..48dd63f --- /dev/null +++ b/mobileLst/README.md @@ -0,0 +1,50 @@ +# Welcome to your Expo app 👋 + +This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app). + +## Get started + +1. Install dependencies + + ```bash + npm install + ``` + +2. Start the app + + ```bash + npx expo start + ``` + +In the output, you'll find options to open the app in a + +- [development build](https://docs.expo.dev/develop/development-builds/introduction/) +- [Android emulator](https://docs.expo.dev/workflow/android-studio-emulator/) +- [iOS simulator](https://docs.expo.dev/workflow/ios-simulator/) +- [Expo Go](https://expo.dev/go), a limited sandbox for trying out app development with Expo + +You can start developing by editing the files inside the **app** directory. This project uses [file-based routing](https://docs.expo.dev/router/introduction). + +## Get a fresh project + +When you're ready, run: + +```bash +npm run reset-project +``` + +This command will move the starter code to the **app-example** directory and create a blank **app** directory where you can start developing. + +## Learn more + +To learn more about developing your project with Expo, look at the following resources: + +- [Expo documentation](https://docs.expo.dev/): Learn fundamentals, or go into advanced topics with our [guides](https://docs.expo.dev/guides). +- [Learn Expo tutorial](https://docs.expo.dev/tutorial/introduction/): Follow a step-by-step tutorial where you'll create a project that runs on Android, iOS, and the web. + +## Join the community + +Join our community of developers creating universal apps. + +- [Expo on GitHub](https://github.com/expo/expo): View our open source platform and contribute. +- [Discord community](https://chat.expo.dev): Chat with Expo users and ask questions. diff --git a/mobileLst/app.json b/mobileLst/app.json new file mode 100644 index 0000000..1d4db5f --- /dev/null +++ b/mobileLst/app.json @@ -0,0 +1,71 @@ +{ + "expo": { + "name": "LSTScanner", + "slug": "lst-scanner-app", + "version": "1.0.0", + "orientation": "portrait", + "icon": "./assets/icon.png", + "scheme": "lstscanner", + "userInterfaceStyle": "automatic", + "newArchEnabled": true, + "ios": { + "supportsTablet": true + }, + "updates": { + "enabled": true, + "url": "http://10.193.0.56:4000/api/mobile/updates", + "fallbackToCacheTimeout": 30000, + "codeSigningCertificate": "./certs/certificate.pem", + "codeSigningMetadata": { + "keyid": "self-hosted", + "alg": "rsa-v1_5-sha256" + } + }, + "runtimeVersion": "1.0.0", + "android": { + "adaptiveIcon": { + "backgroundColor": "#E6F4FE", + "foregroundImage": "./assets/images/android-icon-foreground.png", + "backgroundImage": "./assets/images/android-icon-background.png", + "monochromeImage": "./assets/images/android-icon-monochrome.png" + }, + "package": "com.company.lstscanner", + "versionCode": 1, + "edgeToEdgeEnabled": true, + "predictiveBackGestureEnabled": false + }, + "web": { + "output": "static", + "favicon": "./assets/images/favicon.png" + }, + "plugins": [ + "expo-router", + "./plugins/androidCustomizations", + [ + "expo-splash-screen", + { + "image": "./assets/icon.png", + "imageWidth": 200, + "resizeMode": "contain", + "backgroundColor": "#ffffff", + "dark": { + "backgroundColor": "#000000" + } + } + ], + [ + "expo-build-properties", + { + "android": { + "usesCleartextTraffic": true + }, + "ios": {} + } + ] + ], + "experiments": { + "typedRoutes": true, + "reactCompiler": true + } + } +} diff --git a/mobileLst/app/_layout.tsx b/mobileLst/app/_layout.tsx new file mode 100644 index 0000000..d2a8b0b --- /dev/null +++ b/mobileLst/app/_layout.tsx @@ -0,0 +1,5 @@ +import { Stack } from "expo-router"; + +export default function RootLayout() { + return ; +} diff --git a/mobileLst/app/index.tsx b/mobileLst/app/index.tsx new file mode 100644 index 0000000..cecf889 --- /dev/null +++ b/mobileLst/app/index.tsx @@ -0,0 +1,122 @@ +import React, { useState } from "react"; +import { + Button, + FlatList, + Pressable, + StyleSheet, + Text, + TextInput, + View, +} from "react-native"; +import * as Updates from 'expo-updates'; + +export default function App() { + const [buffer, setBuffer] = useState(""); + const [items, setItems] = useState([]); + const [status, setStatus] = useState(""); + + const [updates, setUpdates] = useState("") + + const handleChange = (text: string) => { + // Scanner "types" characters then appends Enter (\n) + if (text.endsWith("\n")) { + const code = text.trim(); // Remove newline + handleScan(code); + setBuffer(""); // Reset for next scan + } else { + setBuffer(text); + } + }; + +async function checkServerUpdate() { + setUpdates('Checking for updates...'); + try { + const res = await Updates.checkForUpdateAsync(); + if (res.isAvailable) { + setUpdates('Update available! Fetching and reloading...'); + await Updates.fetchUpdateAsync(); + await Updates.reloadAsync(); + } else { + setUpdates('No new update available.'); + } + } catch (e:any) { + setUpdates(`Update check failed: ${e.message}`); + } +} + + const handleScan = (code: string) => { + //console.log("Scanned:", code); + + if (code.toUpperCase().startsWith("LOC")) { + console.log("Triggered relocate to lane"); + performRelocate(code); + } else { + setItems((prev) => [...prev, code]); + setStatus(`Added: ${code}`); + } + }; + + const performRelocate = (locationCode: string) => { + if (items.length === 0) { + setStatus(`Relocate to ${locationCode} requested, but no items`); + return; + } + + // Do your API call or whatever the "relocate" means + console.log("Relocating", items, "to", locationCode); + + setStatus(`Moved ${items.length} items to ${locationCode}`); + setItems([]); + }; + + return ( + +