Kairo-Jinkendo/frontend/src/components/GateCriterionForm.jsx
Lars bd64340ca1
All checks were successful
Deploy Development / deploy (push) Successful in 47s
Test Suite / pytest-backend (push) Successful in 2m13s
Test Suite / lint-backend (push) Successful in 2s
Test Suite / compose-smoke (push) Has been skipped
Test Suite / k6 /api/health Baseline (push) Successful in 18s
Test Suite / playwright-smoke (push) Successful in 12s
AP1.4c: Gate-Checkliste statt Freitext-DoD.
Kriterien-Fortschritt in der Gate-Liste, Modal-UX fuer Checklisten und optionales Erst-Kriterium beim Anlegen.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-11 07:53:38 +02:00

82 lines
2.2 KiB
JavaScript

import { CRITERION_KIND_LABELS, CRITERION_KINDS } from '../constants/status.js'
export function GateCriterionForm({
initial = {},
onSubmit,
onCancel,
busy = false,
submitLabel = 'Speichern',
mode = 'create',
itemReached = false,
}) {
async function handleSubmit(e) {
e.preventDefault()
const form = e.target
const payload = {
title: form.title.value.trim(),
description: form.description.value.trim(),
criterion_kind: form.criterion_kind.value,
}
if (mode === 'edit' && itemReached) {
payload.change_reason = form.change_reason.value.trim()
}
await onSubmit(payload)
}
return (
<form className="form workspace-form gate-criterion-form" onSubmit={handleSubmit}>
<label>
Titel
<input
name="title"
defaultValue={initial.title || ''}
maxLength={500}
required
autoFocus
placeholder="z. B. Akzeptanzkriterium dokumentiert"
/>
</label>
<label>
Beschreibung (optional)
<textarea
name="description"
rows={3}
defaultValue={initial.description || ''}
placeholder="Prüfhinweis oder Kontext"
/>
</label>
<label>
Art
<select name="criterion_kind" defaultValue={initial.criterion_kind || 'manual'}>
{CRITERION_KINDS.map((k) => (
<option key={k} value={k}>
{CRITERION_KIND_LABELS[k]}
</option>
))}
</select>
</label>
{mode === 'edit' && itemReached && (
<label>
Begründung (Gate bereits erreicht)
<input
name="change_reason"
maxLength={500}
required
placeholder="Warum wird das Kriterium geändert?"
/>
</label>
)}
<div className="form-actions">
<button type="submit" className="btn btn-primary" disabled={busy}>
{busy ? 'Speichern …' : submitLabel}
</button>
{onCancel && (
<button type="button" className="btn btn-secondary" onClick={onCancel} disabled={busy}>
Abbrechen
</button>
)}
</div>
</form>
)
}