Der Lagerort-QR (/l/<code>) zeigt jetzt, was am Ort (inkl. Unterorte) liegt - Artikel mit Bestand, jeweils verlinkt - statt nur den Namen. "Hier einlagern" springt ins Einlagern mit vorbelegtem Lagerort (?location=). In der Lagerorte- Verwaltung fuehrt ein neues Lupensymbol zur Inhaltsansicht. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
83 lines
2.8 KiB
React
83 lines
2.8 KiB
React
import { useEffect, useState } from "react";
|
||
import { Link, useParams } from "react-router-dom";
|
||
import { api } from "../api";
|
||
import Icon from "../components/Icon";
|
||
import { ProduktThumb } from "../components/ProduktBild";
|
||
import { fmt } from "../units";
|
||
|
||
/**
|
||
* Ziel eines gescannten Lagerort-QR (/l/<code>) – zeigt, was an diesem Ort (und
|
||
* allen Unterorten) liegt, mit Bestand je Artikel. Von hier direkt einlagern.
|
||
*/
|
||
export default function LocationResolve() {
|
||
const { id } = useParams();
|
||
const [data, setData] = useState(null); // { location_name, products: [...] }
|
||
const [error, setError] = useState(null);
|
||
const [loading, setLoading] = useState(true);
|
||
|
||
useEffect(() => {
|
||
setLoading(true);
|
||
setError(null);
|
||
api.locationContents(id)
|
||
.then(setData)
|
||
.catch((e) => setError(e.message))
|
||
.finally(() => setLoading(false));
|
||
}, [id]);
|
||
|
||
const produkte = data?.products || [];
|
||
|
||
return (
|
||
<div>
|
||
<div className="page-head">
|
||
<div>
|
||
<h1><Icon name="location" size={20} /> {data?.location_name || `Lagerort ${id}`}</h1>
|
||
<div className="sub">
|
||
{loading
|
||
? "Wird geladen…"
|
||
: `${produkte.length} Artikel hier (inkl. Unterorte)`}
|
||
</div>
|
||
</div>
|
||
<Link className="btn primary" to={`/checkin?location=${encodeURIComponent(id)}`}>
|
||
<Icon name="checkin" size={16} />Hier einlagern
|
||
</Link>
|
||
</div>
|
||
|
||
{error && <div className="alert error"><Icon name="alert" size={16} />{error}</div>}
|
||
|
||
<div className="card">
|
||
<div className="table-wrap">
|
||
<table className="table">
|
||
<thead>
|
||
<tr>
|
||
<th className="thumb-cell"></th>
|
||
<th>Artikel</th>
|
||
<th className="num">Bestand</th>
|
||
<th></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{produkte.map((p) => (
|
||
<tr key={p.product_id}>
|
||
<td className="thumb-cell"><ProduktThumb productId={p.product_id} alt={p.name} /></td>
|
||
<td>
|
||
<span className="strong">{p.name}</span>
|
||
{p.brand && <div className="muted small">{p.brand}</div>}
|
||
</td>
|
||
<td className="num">{fmt(p.stock)} {p.unit_label}</td>
|
||
<td className="num"><Link to={`/products/${p.product_id}`}>Details</Link></td>
|
||
</tr>
|
||
))}
|
||
{!loading && produkte.length === 0 && (
|
||
<tr><td colSpan={4} className="empty">Hier liegt gerade nichts.</td></tr>
|
||
)}
|
||
{loading && (
|
||
<tr><td colSpan={4} className="empty">Wird geladen…</td></tr>
|
||
)}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|