Admin-Portal: Bearbeiten für Bereich/Kategorie/Objekttyp/Standort/Benutzer,
Vorlagen-Versionierung und Objekt-Duplizieren im Frontend nachgerüstet Backend: PATCH-Endpoints für Bereich/Kategorie/Standort/Objekttyp ergänzt (analog zu Material), die bislang fehlten und Bearbeiten grundsätzlich unmöglich machten. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L85hmKbvX7Cqkq47KnQhFt
This commit is contained in:
@@ -24,6 +24,40 @@ export function VorlageSection({ vorlagen, objekttypen, materialien, onGeaendert
|
||||
const [objekttypId, setObjekttypId] = useState<number | "">("");
|
||||
const [zeilen, setZeilen] = useState<PositionZeile[]>([LEERE_ZEILE]);
|
||||
const [wirdAngelegt, setWirdAngelegt] = useState(false);
|
||||
const [ausgeklapptId, setAusgeklapptId] = useState<number | null>(null);
|
||||
const [neueVersionZeilen, setNeueVersionZeilen] = useState<PositionZeile[]>([]);
|
||||
const [wirdVersioniert, setWirdVersioniert] = useState(false);
|
||||
|
||||
function versionBearbeiten(v: Beladungsvorlage) {
|
||||
setAusgeklapptId(ausgeklapptId === v.id ? null : v.id);
|
||||
setNeueVersionZeilen(
|
||||
v.positionen.map((p) => ({
|
||||
materialId: p.material_id,
|
||||
fach: p.fach ?? "",
|
||||
sollmenge: p.sollmenge,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
function neueVersionZeileAendern(index: number, zeile: Partial<PositionZeile>) {
|
||||
setNeueVersionZeilen((bisherige) => bisherige.map((z, i) => (i === index ? { ...z, ...zeile } : z)));
|
||||
}
|
||||
|
||||
async function neueVersionSpeichern(vorlageId: number) {
|
||||
const positionen = neueVersionZeilen
|
||||
.filter((z) => z.materialId !== "")
|
||||
.map((z) => ({ material_id: z.materialId, fach: z.fach || null, sollmenge: z.sollmenge }));
|
||||
setWirdVersioniert(true);
|
||||
try {
|
||||
await apiRequest(`/vorlagen/${vorlageId}/neue-version`, { method: "POST", body: { positionen } });
|
||||
setAusgeklapptId(null);
|
||||
await onGeaendert();
|
||||
} catch {
|
||||
onFehler("Neue Version konnte nicht angelegt werden.");
|
||||
} finally {
|
||||
setWirdVersioniert(false);
|
||||
}
|
||||
}
|
||||
|
||||
function zeileAendern(index: number, zeile: Partial<PositionZeile>) {
|
||||
setZeilen((bisherige) => bisherige.map((z, i) => (i === index ? { ...z, ...zeile } : z)));
|
||||
@@ -124,9 +158,68 @@ export function VorlageSection({ vorlagen, objekttypen, materialien, onGeaendert
|
||||
{vorlagen.length > 0 && (
|
||||
<ul className="card-list" style={{ marginTop: "1.25rem" }}>
|
||||
{vorlagen.map((v) => (
|
||||
<li key={v.id} className="row-between" style={{ padding: "0.4rem 0" }}>
|
||||
<span>{v.name}</span>
|
||||
<span className="badge badge-neutral">v{v.version}</span>
|
||||
<li key={v.id} style={{ padding: "0.4rem 0" }}>
|
||||
<div className="row-between">
|
||||
<span>
|
||||
{v.name} <span className="badge badge-neutral">v{v.version}</span>
|
||||
</span>
|
||||
<button className="btn btn-secondary" onClick={() => versionBearbeiten(v)}>
|
||||
{ausgeklapptId === v.id ? "Schließen" : "Positionen / neue Version"}
|
||||
</button>
|
||||
</div>
|
||||
{ausgeklapptId === v.id && (
|
||||
<div className="stack" style={{ marginTop: "0.6rem" }}>
|
||||
<p className="text-muted" style={{ marginBottom: 0 }}>
|
||||
Änderungen erzeugen eine neue Version – die aktuelle v{v.version} bleibt unverändert
|
||||
erhalten.
|
||||
</p>
|
||||
{neueVersionZeilen.map((zeile, i) => (
|
||||
<div className="row" key={i}>
|
||||
<select
|
||||
className="input"
|
||||
value={zeile.materialId}
|
||||
onChange={(e) =>
|
||||
neueVersionZeileAendern(i, { materialId: Number(e.target.value) || "" })
|
||||
}
|
||||
>
|
||||
<option value="">Material…</option>
|
||||
{materialien.map((m) => (
|
||||
<option key={m.id} value={m.id}>
|
||||
{m.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<input
|
||||
className="input"
|
||||
style={{ width: "8rem" }}
|
||||
value={zeile.fach}
|
||||
onChange={(e) => neueVersionZeileAendern(i, { fach: e.target.value })}
|
||||
placeholder="Fach"
|
||||
/>
|
||||
<input
|
||||
className="input"
|
||||
style={{ width: "5rem" }}
|
||||
type="number"
|
||||
value={zeile.sollmenge}
|
||||
onChange={(e) => neueVersionZeileAendern(i, { sollmenge: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
<button
|
||||
className="btn btn-secondary"
|
||||
onClick={() => setNeueVersionZeilen((z) => [...z, LEERE_ZEILE])}
|
||||
>
|
||||
+ Position
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
onClick={() => neueVersionSpeichern(v.id)}
|
||||
disabled={wirdVersioniert}
|
||||
>
|
||||
Neue Version speichern
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user