- |
+ |
{it.uid} |
{isAdmin ? (
diff --git a/web/src/pages/Transfer.jsx b/web/src/pages/Transfer.jsx
index 9fb49ba..67f347d 100644
--- a/web/src/pages/Transfer.jsx
+++ b/web/src/pages/Transfer.jsx
@@ -3,10 +3,11 @@ import { api } from "../api";
import { useConfirm } from "../confirm";
import Icon from "../components/Icon";
import { asTree } from "../categoryTree";
+import { itemDeepLink } from "../qr";
// Baut die Etiketten-CSV mit wählbarem Trennzeichen (BOM für Excel-Umlaute).
// QR-Inhalt = Link aufs Stück.
-function buildLabelCsv(rows, origin, delim = ",") {
+function buildLabelCsv(rows, delim = ",") {
const head = ["QR-Inhalt", "UID", "Produkt", "Marke", "Kategorie", "Lagerort"];
const delimRe = delim === "\t" ? "\\t" : delim;
const needsQuote = new RegExp(`[${delimRe}"\\n\\r]`);
@@ -20,7 +21,7 @@ function buildLabelCsv(rows, origin, delim = ",") {
};
const lines = [head.map(esc).join(delim)];
for (const r of rows) {
- lines.push([`${origin}/i/${r.uid}`, r.uid, r.product, r.brand, r.category, r.location]
+ lines.push([itemDeepLink(r.uid), r.uid, r.product, r.brand, r.category, r.location]
.map(esc).join(delim));
}
return "" + lines.join("\r\n");
@@ -161,7 +162,7 @@ export default function Transfer() {
try {
const rows = await api.labelRows([...selCats]);
if (!rows.length) { setLabelInfo("Keine Einzelstücke in der Auswahl."); return; }
- const csv = buildLabelCsv(rows, window.location.origin, labelDelim);
+ const csv = buildLabelCsv(rows, labelDelim);
const blob = new Blob([csv], { type: "text/csv;charset=utf-8" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
diff --git a/web/src/qr.jsx b/web/src/qr.jsx
index c8859e1..1c82a38 100644
--- a/web/src/qr.jsx
+++ b/web/src/qr.jsx
@@ -1,6 +1,15 @@
import { useEffect, useState } from "react";
import QRCode from "qrcode";
+/**
+ * QR-Inhalt für ein Einzelstück. Bewusst das Custom-Scheme `vorrania://` statt
+ * einer https-URL: Die normale Kamera-App öffnet damit trotzdem die App, aber
+ * OHNE an eine feste Domain gebunden zu sein. Das ist für einen selbstgehosteten
+ * Dienst nötig (jede Instanz hat eine andere URL) und der QR verrät keinen Server.
+ * Die App öffnet die UID am gerade aktiven Server.
+ */
+export const itemDeepLink = (uid) => `vorrania://i/${uid}`;
+
/** Kleines QR-Bild für einen Wert (asynchron erzeugt). */
export function QrImg({ text, size = 60 }) {
const [url, setUrl] = useState(null);
|