Lagerort-QR + Zuordnen per Scan

Web: druckbare QR-Etiketten fuer Lagerorte (Locations-Seite) und Route /l/<id>
(zeigt den Ort im Browser). Geteilter QR-Helfer (web/src/qr.jsx).

iOS: neuer Ablauf "Ort zuordnen" - erst Einzelstueck-QR (…/i/<UID>) scannen, dann
Lagerort-QR (…/l/<ID>); das Stueck wird dem Ort zugewiesen, danach gleich das
naechste. Plus die zuvor gebaute "Nachschlagen"-Kachel.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-26 08:09:00 +02:00
parent 953e0aa483
commit 7f9895245c
8 changed files with 198 additions and 3 deletions

42
web/src/qr.jsx Normal file
View File

@@ -0,0 +1,42 @@
import { useEffect, useState } from "react";
import QRCode from "qrcode";
/** Kleines QR-Bild für einen Wert (asynchron erzeugt). */
export function QrImg({ text, size = 60 }) {
const [url, setUrl] = useState(null);
useEffect(() => {
let ok = true;
QRCode.toDataURL(text, { margin: 1, width: size * 2 })
.then((u) => { if (ok) setUrl(u); })
.catch(() => {});
return () => { ok = false; };
}, [text, size]);
return url
? <img src={url} width={size} height={size} alt="QR" style={{ display: "block" }} />
: <span style={{ display: "inline-block", width: size, height: size }} />;
}
const esc = (s) => (s || "").replace(/[<>&]/g, "");
/** Druckt QR-Etiketten in einem neuen Fenster. entries: [{ text, line1, line2 }]. */
export async function printQrLabels(title, entries) {
const labels = await Promise.all(entries.map(async (e) => {
const url = await QRCode.toDataURL(e.text, { margin: 1, width: 260 });
return `<div class="label"><img src="${url}"/><div class="l1">${esc(e.line1)}</div>`
+ `<div class="l2">${esc(e.line2)}</div></div>`;
}));
const w = window.open("", "_blank");
if (!w) return false;
w.document.write(
`<!doctype html><html><head><meta charset="utf-8"><title>${esc(title)}</title><style>
body{font-family:sans-serif;margin:8mm;display:flex;flex-wrap:wrap;gap:6mm}
.label{width:34mm;text-align:center;border:1px solid #ccc;border-radius:3mm;padding:3mm;page-break-inside:avoid}
.label img{width:28mm;height:28mm}
.l1{font-weight:700;font-size:10pt;margin-top:1mm}
.l2{font-size:8pt;color:#444}
</style></head><body>${labels.join("")}
<script>window.onload=function(){window.print()}</script></body></html>`,
);
w.document.close();
return true;
}