From d5c5e9b9d0c2c9af7df1c4a3b204d29e317605de Mon Sep 17 00:00:00 2001 From: beatz174-bit Date: Fri, 21 Nov 2025 18:29:20 +1000 Subject: [PATCH] Add modal barcode scanning flow and product link --- src/screens/BarcodeScannerScreen.tsx | 67 ++++++++++++++++++++++++++-- src/screens/ManageProductsScreen.tsx | 10 ++++- 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/src/screens/BarcodeScannerScreen.tsx b/src/screens/BarcodeScannerScreen.tsx index 2d7c056..e29231a 100644 --- a/src/screens/BarcodeScannerScreen.tsx +++ b/src/screens/BarcodeScannerScreen.tsx @@ -1,6 +1,20 @@ -import { Alert, Card, CardContent, Chip, Container, Divider, Stack, Typography } from '@mui/material'; +import { + Alert, + Button, + Card, + CardContent, + Chip, + Container, + Dialog, + DialogContent, + DialogTitle, + Divider, + Stack, + Typography, +} from '@mui/material'; import { liveQuery } from 'dexie'; import { useEffect, useMemo, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; import { BarcodeScannerView } from '../components/BarcodeScannerView'; import { useDatabase } from '../context/DBProvider'; import { Area } from '../models/Area'; @@ -14,8 +28,10 @@ interface ProductLookup { export const BarcodeScannerScreen = () => { const db = useDatabase(); + const navigate = useNavigate(); const [lastCode, setLastCode] = useState(''); const [lookup, setLookup] = useState({ pickLists: [] }); + const [scannerOpen, setScannerOpen] = useState(false); useEffect(() => { if (!lastCode) { @@ -54,13 +70,45 @@ export const BarcodeScannerScreen = () => { const hasProduct = useMemo(() => lookup.product && lookup.product !== null, [lookup.product]); + const handleDetected = (code: string) => { + setLastCode(code); + setScannerOpen(false); + }; + + const handleAddProduct = () => { + if (!lastCode) return; + navigate('/products', { state: { newBarcode: lastCode } }); + }; + return ( Barcode Scanner - setLastCode(code)} /> + + + + + Scan barcodes + + Open the camera in a popup to keep scanned details easy to read. + + + + + {lastCode ? ( + + ) : null} + + + + + {lastCode ? ( @@ -77,7 +125,14 @@ export const BarcodeScannerScreen = () => { {lookup.product === null ? ( - This barcode is not present in the product list. + + + This barcode is not present in the product list. + + + ) : null} @@ -129,6 +184,12 @@ export const BarcodeScannerScreen = () => { ) : null} + setScannerOpen(false)} fullWidth> + Scan a barcode + + + + ); }; diff --git a/src/screens/ManageProductsScreen.tsx b/src/screens/ManageProductsScreen.tsx index f55ff81..11f6ebf 100644 --- a/src/screens/ManageProductsScreen.tsx +++ b/src/screens/ManageProductsScreen.tsx @@ -11,7 +11,7 @@ import { DialogContent, } from '@mui/material'; import SearchIcon from '@mui/icons-material/Search'; -import { Link as RouterLink } from 'react-router-dom'; +import { Link as RouterLink, useLocation } from 'react-router-dom'; import { useEffect, useMemo, useState } from 'react'; import { v4 as uuidv4 } from 'uuid'; import { ProductRow } from '../components/ProductRow'; @@ -24,6 +24,7 @@ export const ManageProductsScreen = () => { const db = useDatabase(); const products = useProducts(); const categories = useCategories(); + const location = useLocation(); const [search, setSearch] = useState(''); const [name, setName] = useState(''); const [category, setCategory] = useState(''); @@ -51,6 +52,13 @@ export const ManageProductsScreen = () => { [products, search], ); + useEffect(() => { + const state = location.state as { newBarcode?: string } | null; + if (state?.newBarcode) { + setBarcode(state.newBarcode); + } + }, [location.state]); + const addProduct = async () => { if (!name || !category) return; await db.products.add({