Added connection between scanner and product displaying

This commit is contained in:
Samuel Ortion 2022-09-08 21:49:35 +02:00
parent e42553ddc1
commit f7b3629dd0
7 changed files with 338 additions and 27 deletions

142
www/package-lock.json generated
View File

@ -7,6 +7,9 @@
"": {
"name": "off-client",
"version": "0.0.0",
"dependencies": {
"axios": "^0.27.2"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^1.0.2",
"html5-qrcode": "^2.2.1",
@ -70,6 +73,31 @@
}
}
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/axios": {
"version": "0.27.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
"dependencies": {
"follow-redirects": "^1.14.9",
"form-data": "^4.0.0"
}
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@ -96,6 +124,14 @@
"node": ">=0.10.0"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/esbuild": {
"version": "0.15.7",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz",
@ -458,6 +494,38 @@
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true
},
"node_modules/follow-redirects": {
"version": "1.15.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
@ -529,6 +597,25 @@
"node": ">=12"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@ -749,6 +836,28 @@
"svelte-hmr": "^0.14.12"
}
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"axios": {
"version": "0.27.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
"requires": {
"follow-redirects": "^1.14.9",
"form-data": "^4.0.0"
}
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@ -764,6 +873,11 @@
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
"dev": true
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
"esbuild": {
"version": "0.15.7",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz",
@ -939,6 +1053,21 @@
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true
},
"follow-redirects": {
"version": "1.15.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA=="
},
"form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
},
"fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
@ -991,6 +1120,19 @@
"sourcemap-codec": "^1.4.8"
}
},
"mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
},
"mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"requires": {
"mime-db": "1.52.0"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",

View File

@ -16,5 +16,8 @@
"html5-qrcode": "^2.2.1",
"svelte": "^3.49.0",
"vite": "^3.1.0"
},
"dependencies": {
"axios": "^0.27.2"
}
}

97
www/public/off-logo.svg Normal file
View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="200"
height="200"
viewBox="0 0 200 200"
version="1.1"
id="svg2229"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
sodipodi:docname="off-logo.svg"
inkscape:export-filename="off-logo.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview2231"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="1"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1.7117941"
inkscape:cx="77.40417"
inkscape:cy="109.24211"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs2226" />
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1">
<g
id="g2113"
transform="translate(-125.215,-69.1)">
<g
id="g2105">
<path
class="f"
d="m 176.13,171.7 c 0,-27.11 21.97,-49.08 49.08,-49.08 27.11,0 49.08,21.97 49.08,49.08 z"
id="path2095"
style="fill:#ff8c14" />
<path
class="e"
d="m 261.85,171.7 c 0,20.24 -16.4,36.64 -36.64,36.64 -20.24,0 -36.64,-16.4 -36.64,-36.64 z"
id="path2097"
style="fill:#ffffff" />
<circle
class="h"
cx="241.83"
cy="140"
r="2.7"
id="circle2099"
style="fill:#8c3c00" />
<circle
class="h"
cx="254.98"
cy="152.07001"
r="2.7"
id="circle2101"
style="fill:#8c3c00" />
<circle
class="h"
cx="240.11"
cy="155.02"
r="2.7"
id="circle2103"
style="fill:#8c3c00" />
</g>
<path
d="m 201.41,214.6 -8.72,20.82 11.48,4.81 8.8,-21 c 3.92,1.01 8.02,1.55 12.25,1.55 27.06,0 49.08,-22.02 49.08,-49.08 h -12.44 c 0,20.2 -16.44,36.64 -36.64,36.64 -20.2,0 -36.64,-16.44 -36.64,-36.64 h -12.44 c 0,18.43 10.22,34.51 25.28,42.9 z"
id="path2107" />
<path
class="c"
d="m 245.51,97.97 c -9.65,0 -18.04,5.38 -22.35,13.3 3.32,3.09 5.83,7.05 7.13,11.52 11.23,-2.52 19.66,-12.45 19.86,-24.39 -1.5,-0.28 -3.05,-0.43 -4.63,-0.43 z"
id="path2109"
style="fill:#00641e" />
<path
class="d"
d="m 205.84,104.44 c -1.91,0 -3.77,0.22 -5.56,0.62 3.07,10.61 12.85,18.37 24.45,18.37 1.91,0 3.77,-0.22 5.56,-0.62 -3.07,-10.61 -12.85,-18.37 -24.45,-18.37 z"
id="path2111"
style="fill:#00961e" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -1,8 +1,29 @@
<script>
import offLogo from './assets/off-logo.svg';
import OFF from './lib/OFF.svelte';
import Scanner from './lib/Scanner.svelte';
import BarcodeIcon from './assets/barcode.svg';
import OFF from './components/OFF.svelte';
import Scanner from './components/Scanner.svelte';
import Card from './components/Card.svelte';
import { onMount } from 'svelte';
let showScanner = false;
let showCard = false;
let barcode = '';
function startScanner() {
showScanner = true;
}
function stopScanner() {
showScanner = false;
}
function scannerResult(result) {
barcode = result;
showCard = true;
}
</script>
<main class="dark">
@ -13,16 +34,26 @@
</div>
<h1>OpenFoodFacts Client</h1>
<div class="card">
<Scanner />
<div id="card" />
<div class="reader">
{#if showScanner}
<Scanner onClose={stopScanner} onResult={scannerResult} />
{/if}
</div>
<div class="product">
{#if showCard}
<Card barcode={barcode} />
{/if}
</div>
<nav class="menu bottom nav-bar">
<ul>
<li>
<a class="nav-item" href="/scan" title="Scan barcode">
<button class="nav-item" title="Scan barcode" on:click={ () => showScanner = true }>
<img class="icon" src={BarcodeIcon} alt="Barcode icon" />
</a>
</button>
</li>
</ul>
</nav>

View File

@ -0,0 +1,39 @@
<script>
import { onMount } from 'svelte';
import axios from 'axios';
let info = {};
let name;
let img;
const options = {
country: 'world',
};
const API_URL = `https://${options.country}.openfoodfacts.org`;
function getProductCard(barcode) {
axios
.get(`${API_URL}/api/v0/product/${barcode}.json`)
.then((response) => {
info = response.data.product;
img = info.image_front_url;
name = info.product_name;
console.log(info);
})
.catch((error) => {
console.error(error);
});
}
onMount(async () => {
console.debug(`Card mounted, got ${barcode} product code`);
getProductCard(barcode);
});
export let barcode;
</script>
<div class="card">
<h3>{ name }</h3>
<img src={img} alt={name}>
</div>

View File

@ -1,25 +1,18 @@
<reader id="reader"/>
{#if scanning}
<button on:click={stop}>stop</button>
{:else}
<button on:click={start}>start</button>
{/if}
<script>
import { Html5Qrcode } from 'html5-qrcode';
import { onMount } from 'svelte';
let codebar;
let scanning = false;
let html5Qrcode;
onMount(init);
function init() {
html5Qrcode = new Html5Qrcode('reader');
}
onMount(start);
function start() {
html5Qrcode = new Html5Qrcode('reader');
html5Qrcode.start(
{ facingMode: 'environment' },
{
@ -35,26 +28,32 @@
async function stop() {
await html5Qrcode.stop();
scanning = false;
onClose();
}
function onScanSuccess(decodedText, decodedResult) {
alert(`Code matched = ${decodedText}`);
codebar = decodedText;
// alert(`Code matched = ${decodedText}`);
console.log(decodedResult);
onResult(codebar);
stop();
}
function onScanFailure(error) {
console.warn(`Code scan error = ${error}`);
}
export let onClose, onResult;
</script>
<reader id="reader"/>
{#if scanning}
<button title="Stop barcode scanning" on:click={stop}>stop</button>
{:else}
<button title="Start barcode scanning" on:click={start}>start</button>
{/if}
<style>
main {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 20px;
}
reader {
width: 100%;
min-height: 500px;