Web: eigene Felder nachträglich bearbeiten

Backend und API-Client konnten Felddefinitionen laengst aendern (PATCH), nur die
Oberflaeche bot bisher nur Anlegen und Loeschen. In der Felder-Verwaltung einer
Kategorie gibt es jetzt je Feld einen Bearbeiten-Knopf: er laedt Name, Typ,
Einheit, Auswahlmoeglichkeiten und Pflicht ins Formular; Speichern aktualisiert
das Feld (oder Abbrechen). Geerbte und eingebaute Felder bleiben unveraendert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-26 13:11:29 +02:00
parent dc66a6d7ff
commit 272609e70a

View File

@@ -287,6 +287,7 @@ function CategoryFields({ category, isAdmin, onClose }) {
const confirm = useConfirm();
const [fields, setFields] = useState([]);
const [form, setForm] = useState(EMPTY_FIELD);
const [editId, setEditId] = useState(null); // null = neues Feld, sonst bearbeiten
const [error, setError] = useState(null);
async function load() {
@@ -298,21 +299,45 @@ function CategoryFields({ category, isAdmin, onClose }) {
}
useEffect(() => { load(); }, [category.id]);
async function add(e) {
// Ein bestehendes Feld in das Formular laden (mehrfach getrennte Optionen
// wieder als Komma-Liste).
function startEdit(f) {
setEditId(f.id);
setForm({
label: f.label,
field_type: f.field_type,
unit: f.unit || "",
options: (f.options || []).join(", "),
required: f.required,
});
setError(null);
}
function cancelEdit() {
setEditId(null);
setForm(EMPTY_FIELD);
}
async function submit(e) {
e.preventDefault();
setError(null);
const body = {
label: form.label,
field_type: form.field_type,
unit: form.field_type === "number" ? (form.unit || null) : null,
options: form.field_type === "select"
? form.options.split(",").map((o) => o.trim()).filter(Boolean)
: null,
required: form.required,
};
try {
await api.createFieldDefinition({
category_id: category.id,
label: form.label,
field_type: form.field_type,
unit: form.field_type === "number" ? (form.unit || null) : null,
options: form.field_type === "select"
? form.options.split(",").map((o) => o.trim()).filter(Boolean)
: null,
required: form.required,
});
if (editId) {
await api.updateFieldDefinition(editId, body);
} else {
await api.createFieldDefinition({ category_id: category.id, ...body });
}
setForm(EMPTY_FIELD);
setEditId(null);
load();
} catch (err) {
setError(err.message);
@@ -351,7 +376,7 @@ function CategoryFields({ category, isAdmin, onClose }) {
) : (
<ul className="clean-list">
{fields.map((f) => (
<li key={f.id} className="cell-row">
<li key={f.id} className={`cell-row ${editId === f.id ? "row-active" : ""}`}>
<span className="strong">{f.label}</span>
<span className="badge nowrap">{fieldTypeLabel(f.field_type)}</span>
{f.field_type === "number" && f.unit && <span className="muted small">{f.unit}</span>}
@@ -360,10 +385,16 @@ function CategoryFields({ category, isAdmin, onClose }) {
<span className="badge nowrap" title="stammt aus einer Oberkategorie">geerbt</span>
) : (
isAdmin && (
<button className="btn-icon danger" style={{ marginLeft: "auto" }}
title="Feld löschen" onClick={() => remove(f)}>
<Icon name="trash" size={15} />
</button>
<span style={{ marginLeft: "auto", display: "flex", gap: 4 }}>
{!f.is_builtin && (
<button className="btn-icon" title="Feld bearbeiten" onClick={() => startEdit(f)}>
<Icon name="edit" size={15} />
</button>
)}
<button className="btn-icon danger" title="Feld löschen" onClick={() => remove(f)}>
<Icon name="trash" size={15} />
</button>
</span>
)
)}
</li>
@@ -372,7 +403,12 @@ function CategoryFields({ category, isAdmin, onClose }) {
)}
{isAdmin && (
<form onSubmit={add} className="stack" style={{ marginTop: "var(--sp-3)" }}>
<form onSubmit={submit} className="stack" style={{ marginTop: "var(--sp-3)" }}>
{editId && (
<div className="muted small" style={{ display: "flex", alignItems: "center", gap: 6 }}>
<Icon name="edit" size={14} />Feld bearbeiten
</div>
)}
<label>
Feldname
<input value={form.label} placeholder="z.B. Kapazität"
@@ -406,7 +442,15 @@ function CategoryFields({ category, isAdmin, onClose }) {
onChange={(e) => setForm({ ...form, required: e.target.checked })} />
<span>Pflichtfeld</span>
</label>
<button className="btn primary"><Icon name="plus" size={16} />Feld hinzufügen</button>
<div className="field-inline">
<button className="btn primary">
<Icon name={editId ? "check" : "plus"} size={16} />
{editId ? "Änderungen speichern" : "Feld hinzufügen"}
</button>
{editId && (
<button type="button" className="btn ghost" onClick={cancelEdit}>Abbrechen</button>
)}
</div>
</form>
)}
</div>