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
Kriterien-Fortschritt in der Gate-Liste, Modal-UX fuer Checklisten und optionales Erst-Kriterium beim Anlegen. Co-authored-by: Cursor <cursoragent@cursor.com>
82 lines
2.2 KiB
JavaScript
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>
|
|
)
|
|
}
|