diff --git a/package.json b/package.json index 5d4b888..8c3ffbc 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "type": "module", "scripts": { - "dev": "vite", + "dev": "vite --host", "build": "vite build", "test": "vitest", "preview": "vite preview" @@ -13,6 +13,7 @@ "@directus/sdk": "^15.0.1", "classnames": "^2.5.1", "jotai": "^2.7.0", + "quagga": "^0.12.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.22.2" @@ -23,6 +24,7 @@ "@testing-library/user-event": "^14.5.2", "@types/react": "^18.2.56", "@types/react-dom": "^18.2.19", + "@vitejs/plugin-basic-ssl": "^1.1.0", "@vitejs/plugin-react": "^4.2.1", "eslint": "^8.56.0", "eslint-plugin-react": "^7.33.2", diff --git a/src/components/Scanner/Quagga.js b/src/components/Scanner/Quagga.js new file mode 100644 index 0000000..55af72e --- /dev/null +++ b/src/components/Scanner/Quagga.js @@ -0,0 +1,49 @@ +import Quagga from 'quagga'; // ES6 + +export function setOnRead(onRead) { + Quagga.onDetected(onRead); +} + +export async function startQuagga() { + try { + const camera = await getCamera(); + Quagga.init({ + inputStream: { + name: "Live", + type: "LiveStream", + target: document.querySelector('#scanner-source'), + constraints: { + deviceId: camera.deviceId, + } + }, + locator: { + patchSize: "medium", + halfSample: true + }, + numOfWorkers: 2, + frequency: 10, + locate: true, + decoder: { + readers: ["ean_reader"] + } + }, function (err) { + if (err) { + alert(`Error al iniciar tu camara ${camera.label} \n ${err}`); + console.log(err); + return + } + Quagga.start(); + }); + } catch (error) { + console.log(error); + alert(`Error al iniciar tu camara \n ${error}`); + } +} + +async function getCamera() { + const stream = await navigator.mediaDevices.getUserMedia({ video: true }); + const videoDevices = await navigator.mediaDevices.enumerateDevices(); + const filterDevices = videoDevices.filter(device => !!device.deviceId && device.kind === 'videoinput'); + stream.getTracks().forEach(track => track.stop()); + return filterDevices[filterDevices.length - 1]; +} \ No newline at end of file diff --git a/src/components/Scanner/Scanner.css b/src/components/Scanner/Scanner.css index e53276b..7119e30 100644 --- a/src/components/Scanner/Scanner.css +++ b/src/components/Scanner/Scanner.css @@ -2,13 +2,43 @@ display: flex; flex-direction: column; align-items: center; + justify-content: center; background-color: var(--theme-surface-color); margin-top: 20px; - padding: var(--size-large); + padding: var(--size-small); border-radius: var(--border-radius-normal); + height: 200px; } .Scanner__text { font-size: var(--size-pixel-norma); color: var(--theme-hint-color); } + + + +.Scanner__source { + width: var(--scanner-width); + height: var(--scanner-height); + position: relative; +} + + +.Scanner__source canvas, video { + float: left; + width: var(--scanner-width); + height: var(--scanner-height); + display: block; + position: absolute; + top:0; left:0; +} + +.Scanner__source canvas { + position:relative; + transform: scale(-1, 1); +} + +.Scanner__source video { + object-fit: cover; + border-radius: var(--border-radius-normal); +} diff --git a/src/components/Scanner/index.jsx b/src/components/Scanner/index.jsx index 97fc8df..a0c3c3e 100644 --- a/src/components/Scanner/index.jsx +++ b/src/components/Scanner/index.jsx @@ -1,11 +1,46 @@ +import { useEffect, useState } from 'react'; import Icon from '../../components/Icon' import './Scanner.css' +import { startQuagga, setOnRead } from './Quagga'; function Scanner() { + const [barDecoded, setBarDecoded] = useState('initialState') + + const onNewScanResult = (decodedText) => { + setBarDecoded(decodedText) + console.log(barDecoded) + }; + + setOnRead(function (result) { + if (result.codeResult?.code === barDecoded) return + onNewScanResult(result.codeResult.code) + }); + + const [isScannerActive, setIsScannerActive] = useState(false) + + const startScanner = () => { + setIsScannerActive(true) + } + + useEffect(() => { + if (!isScannerActive) return + startQuagga() + }, [isScannerActive]); + return (
- -

Toca para activar el escaner

+ {(!isScannerActive) ? +
+ +

Toca para activar el escaner

+
: + <> +
+
+

{barDecoded}

+
+ + }
) } diff --git a/src/main.css b/src/main.css index 064f621..e431459 100644 --- a/src/main.css +++ b/src/main.css @@ -52,6 +52,9 @@ --transition-normal: all 300ms ease-in-out; --transition-slow: all 600ms ease-in-out; --transition-slower: all 1000ms ease-in-out; + + --scanner-width: 100%; + --scanner-height: 100%; } body { diff --git a/vite.config.js b/vite.config.js index a136fe9..0f03cdf 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,3 +1,4 @@ +import basicSsl from '@vitejs/plugin-basic-ssl' import react from '@vitejs/plugin-react' import jotaiDebugLabel from 'jotai/babel/plugin-debug-label' import jotaiReactRefresh from 'jotai/babel/plugin-react-refresh' @@ -11,6 +12,7 @@ export default defineConfig({ plugins: [jotaiDebugLabel, jotaiReactRefresh], }, }), + basicSsl(), ], test: { environment: 'jsdom',