diff --git a/src/frontend/src/components/items/BarcodeInput.tsx b/src/frontend/src/components/items/BarcodeInput.tsx new file mode 100644 index 0000000000..2ae2200cf3 --- /dev/null +++ b/src/frontend/src/components/items/BarcodeInput.tsx @@ -0,0 +1,59 @@ +import { t } from '@lingui/macro'; +import { ActionIcon, Box, Button, Divider, TextInput } from '@mantine/core'; +import { IconQrcode } from '@tabler/icons-react'; +import React, { useState } from 'react'; + +import { InputImageBarcode } from '../../pages/Index/Scan'; + +type BarcodeInputProps = { + onScan: (decodedText: string) => void; + value?: string; + onChange?: (event: React.ChangeEvent) => void; + onAction?: () => void; + placeholder?: string; + label?: string; + actionText?: string; +}; + +export function BarcodeInput({ + onScan, + value, + onChange, + onAction, + placeholder = t`Scan barcode data here using barcode scanner`, + label = t`Barcode`, + actionText = t`Scan` +}: Readonly) { + const [isScanning, setIsScanning] = useState(false); + + return ( + + {isScanning && ( + <> + + + + )} + setIsScanning(!isScanning)} + > + + + } + w="100%" + /> + {onAction ? ( + + ) : null} + + ); +} diff --git a/src/frontend/src/components/items/QRCode.tsx b/src/frontend/src/components/items/QRCode.tsx index 030fffea55..627dcfa459 100644 --- a/src/frontend/src/components/items/QRCode.tsx +++ b/src/frontend/src/components/items/QRCode.tsx @@ -1,35 +1,29 @@ import { Trans, t } from '@lingui/macro'; import { - ActionIcon, Alert, Box, Button, Code, - Divider, - Flex, Group, Image, Select, Skeleton, Stack, - Text, - TextInput + Text } from '@mantine/core'; import { useDisclosure } from '@mantine/hooks'; import { modals } from '@mantine/modals'; -import { IconQrcode } from '@tabler/icons-react'; import { useQuery } from '@tanstack/react-query'; import QR from 'qrcode'; import { useEffect, useMemo, useState } from 'react'; -import { set } from 'react-hook-form'; import { api } from '../../App'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; -import { InputImageBarcode, ScanItem } from '../../pages/Index/Scan'; import { apiUrl } from '../../states/ApiState'; import { useGlobalSettingsState } from '../../states/SettingsState'; import { CopyButton } from '../buttons/CopyButton'; import { QrCodeType } from './ActionDropdown'; +import { BarcodeInput } from './BarcodeInput'; type QRCodeProps = { ecl?: 'L' | 'M' | 'Q' | 'H'; @@ -162,37 +156,22 @@ export const QRCodeLink = ({ mdl_prop }: { mdl_prop: QrCodeType }) => { location.reload(); }); } - const actionSubmit = (data: ScanItem[]) => { - linkBarcode(data[0].data); + const actionSubmit = (decodedText: string) => { + linkBarcode(decodedText); }; + + const handleLinkBarcode = () => { + linkBarcode(barcode); + }; + return ( - - {isScanning ? ( - <> - - - - ) : null} - setBarcode(event.currentTarget.value)} - placeholder={t`Scan barcode data here using barcode scanner`} - leftSection={ - - - - } - w="100%" - /> - - + setBarcode(event.currentTarget.value)} + onScan={actionSubmit} + onAction={handleLinkBarcode} + actionText={t`Link`} + /> ); }; diff --git a/src/frontend/src/components/modals/QrCodeModal.tsx b/src/frontend/src/components/modals/QrCodeModal.tsx index 5d656b5778..061609eb81 100644 --- a/src/frontend/src/components/modals/QrCodeModal.tsx +++ b/src/frontend/src/components/modals/QrCodeModal.tsx @@ -1,69 +1,21 @@ import { Trans, t } from '@lingui/macro'; -import { - Badge, - Button, - Container, - Group, - ScrollArea, - Space, - Stack, - Text -} from '@mantine/core'; -import { - useDocumentVisibility, - useListState, - useLocalStorage -} from '@mantine/hooks'; +import { Button, ScrollArea, Stack, Text } from '@mantine/core'; +import { useListState } from '@mantine/hooks'; import { ContextModalProps } from '@mantine/modals'; import { showNotification } from '@mantine/notifications'; -import { IconX } from '@tabler/icons-react'; -import { Html5Qrcode } from 'html5-qrcode'; -import { CameraDevice } from 'html5-qrcode/camera/core'; -import { Html5QrcodeResult } from 'html5-qrcode/core'; -import { useEffect, useState } from 'react'; import { api } from '../../App'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { apiUrl } from '../../states/ApiState'; +import { BarcodeInput } from '../items/BarcodeInput'; export function QrCodeModal({ context, id -}: ContextModalProps<{ modalBody: string }>) { - const [qrCodeScanner, setQrCodeScanner] = useState(null); - const [camId, setCamId] = useLocalStorage({ - key: 'camId', - defaultValue: null - }); - const [scanningEnabled, setScanningEnabled] = useState(false); - const [wasAutoPaused, setWasAutoPaused] = useState(false); - const documentState = useDocumentVisibility(); - +}: Readonly>) { const [values, handlers] = useListState([]); - // Mount QR code once we are loaded - useEffect(() => { - setQrCodeScanner(new Html5Qrcode('reader')); - }, []); - - // Stop/star when leaving or reentering page - useEffect(() => { - if (scanningEnabled && documentState === 'hidden') { - stopScanning(); - setWasAutoPaused(true); - } else if (wasAutoPaused && documentState === 'visible') { - startScanning(); - setWasAutoPaused(false); - } - }, [documentState]); - - // Scanner functions - function onScanSuccess( - decodedText: string, - decodedResult: Html5QrcodeResult - ) { - qrCodeScanner?.pause(); - + function onScanAction(decodedText: string) { handlers.append(decodedText); api .post(apiUrl(ApiEndpoints.barcode), { barcode: decodedText }) @@ -77,124 +29,28 @@ export function QrCodeModal({ window.location.href = response.data.url; } }); - - qrCodeScanner?.resume(); - } - - function onScanFailure(error: string) { - if ( - error != - 'QR code parse error, error = NotFoundException: No MultiFormat Readers were able to detect the code.' - ) { - console.warn(`Code scan error = ${error}`); - } - } - - function selectCamera() { - Html5Qrcode.getCameras() - .then((devices) => { - if (devices?.length) { - setCamId(devices[0]); - } - }) - .catch((err) => { - showNotification({ - title: t`Error while getting camera`, - message: err, - color: 'red', - icon: - }); - }); - } - - function startScanning() { - if (camId && qrCodeScanner) { - qrCodeScanner - .start( - camId.id, - { fps: 10, qrbox: { width: 250, height: 250 } }, - (decodedText, decodedResult) => { - onScanSuccess(decodedText, decodedResult); - }, - (errorMessage) => { - onScanFailure(errorMessage); - } - ) - .catch((err: string) => { - showNotification({ - title: t`Error while scanning`, - message: err, - color: 'red', - icon: - }); - }); - setScanningEnabled(true); - } - } - - function stopScanning() { - if (qrCodeScanner && scanningEnabled) { - qrCodeScanner.stop().catch((err: string) => { - showNotification({ - title: t`Error while stopping`, - message: err, - color: 'red', - icon: - }); - }); - setScanningEnabled(false); - } } return ( - - - {camId?.label} - - {scanningEnabled ? t`Scanning` : t`Not scanning`} - - - {!camId ? ( - + + + {values.length == 0 ? ( + + No scans yet! + ) : ( - <> - - - - - {values.length == 0 ? ( - - No scans yet! - - ) : ( - - {values.map((value, index) => ( -
{value}
- ))} -
- )} - + + {values.map((value, index) => ( +
{value}
+ ))} +
)}