feat(workflow): 5-Stage Lifecycle UI im Compliance Workflow-Editor
CI / detect-changes (push) Successful in 8s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / build-sha-integrity (push) Failing after 4s
CI / validate-canonical-controls (push) Successful in 10s
CI / loc-budget (push) Successful in 14s
CI / sbom-scan (push) Has been skipped
CI / test-python-backend (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Successful in 2m42s
CI / test-go (push) Has been skipped
CI / test-python-document-crawler (push) Has been skipped
CI / detect-changes (push) Successful in 8s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / build-sha-integrity (push) Failing after 4s
CI / validate-canonical-controls (push) Successful in 10s
CI / loc-budget (push) Successful in 14s
CI / sbom-scan (push) Has been skipped
CI / test-python-backend (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Successful in 2m42s
CI / test-go (push) Has been skipped
CI / test-python-document-crawler (push) Has been skipped
Erweitert Phase 1 (Backend 5-Stage Lifecycle, Migration 148) jetzt auch im Frontend: Status-Pills, Buttons und Modal-Texte differenzieren nun zwischen DSB- und Mandanten-Pruefung. - WorkflowStatusBar zeigt 5 Schritte: draft -> review_internal -> review_client -> approved -> published, mit status-spezifischen Action-Buttons (Save/Submit, DSB-Freigabe, Mandant-Freigabe, Publish). - ApprovalModal differenziert Mode 'approve-internal' / 'approve-client' / 'reject' mit eigenen Titles und Button-Labels. - useWorkflowActions ruft neue Endpoints /approve-internal und /approve-client (Backend Phase 1); approveVersion bleibt als Backward-Compat-Alias. - page.tsx leitet Modal-Confirm an passende Action weiter und akzeptiert review_internal/review_client im draftVersion-Filter. - _types.ts: Status-Union + STATUS_LABELS um beide Review-Stufen erweitert; alter 'review'-Wert bleibt fuer Bestandsdaten erhalten. - CompareView, SplitViewEditor, HistoryPanel: Status-Rendering und neue Action-Labels (submitted_internal, approved_internal, approved_client). LOC-Exception fuer admin-compliance/lib/sdk/types/sdk-steps.ts (525): zentrale SDK-Step-Registry mit kanonischer Reihenfolge — splits wuerden die globale seq-Garantie zerreissen. [guardrail-change] Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
'use client'
|
||||
|
||||
export type ApprovalModalMode = 'approve-internal' | 'approve-client' | 'reject'
|
||||
|
||||
interface ApprovalModalProps {
|
||||
mode: 'approve' | 'reject'
|
||||
mode: ApprovalModalMode
|
||||
approvalComment: string
|
||||
onCommentChange: (comment: string) => void
|
||||
onCancel: () => void
|
||||
@@ -9,6 +11,26 @@ interface ApprovalModalProps {
|
||||
saving: boolean
|
||||
}
|
||||
|
||||
const TITLES: Record<ApprovalModalMode, string> = {
|
||||
'approve-internal': 'DSB-Freigabe → an Mandant weiterleiten',
|
||||
'approve-client': 'Mandanten-Freigabe erteilen',
|
||||
reject: 'Version ablehnen',
|
||||
}
|
||||
|
||||
const BUTTON_LABELS: Record<ApprovalModalMode, string> = {
|
||||
'approve-internal': 'DSB-Freigabe erteilen',
|
||||
'approve-client': 'Mandanten-Freigabe erteilen',
|
||||
reject: 'Ablehnen',
|
||||
}
|
||||
|
||||
const PLACEHOLDERS: Record<ApprovalModalMode, string> = {
|
||||
'approve-internal':
|
||||
'Kommentar (optional) — Hinweise für den Mandanten...',
|
||||
'approve-client':
|
||||
'Kommentar (optional) — z.B. Freigabe durch Geschäftsführung...',
|
||||
reject: 'Ablehnungsgrund...',
|
||||
}
|
||||
|
||||
export default function ApprovalModal({
|
||||
mode,
|
||||
approvalComment,
|
||||
@@ -17,18 +39,17 @@ export default function ApprovalModal({
|
||||
onConfirm,
|
||||
saving,
|
||||
}: ApprovalModalProps) {
|
||||
const isReject = mode === 'reject'
|
||||
return (
|
||||
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
|
||||
<div className="bg-white rounded-xl shadow-xl p-6 w-full max-w-md">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">
|
||||
{mode === 'approve' ? 'Version freigeben' : 'Version ablehnen'}
|
||||
</h3>
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">{TITLES[mode]}</h3>
|
||||
<textarea
|
||||
value={approvalComment}
|
||||
onChange={(e) => onCommentChange(e.target.value)}
|
||||
placeholder={mode === 'approve' ? 'Kommentar (optional)...' : 'Ablehnungsgrund...'}
|
||||
placeholder={PLACEHOLDERS[mode]}
|
||||
className="w-full px-3 py-2 border border-slate-300 rounded-lg min-h-[100px] mb-4"
|
||||
required={mode === 'reject'}
|
||||
required={isReject}
|
||||
/>
|
||||
<div className="flex justify-end gap-3">
|
||||
<button
|
||||
@@ -39,14 +60,12 @@ export default function ApprovalModal({
|
||||
</button>
|
||||
<button
|
||||
onClick={onConfirm}
|
||||
disabled={saving || (mode === 'reject' && !approvalComment)}
|
||||
disabled={saving || (isReject && !approvalComment)}
|
||||
className={`px-4 py-2 text-white rounded-lg disabled:opacity-50 ${
|
||||
mode === 'approve'
|
||||
? 'bg-green-600 hover:bg-green-700'
|
||||
: 'bg-red-600 hover:bg-red-700'
|
||||
isReject ? 'bg-red-600 hover:bg-red-700' : 'bg-green-600 hover:bg-green-700'
|
||||
}`}
|
||||
>
|
||||
{saving ? 'Wird verarbeitet...' : mode === 'approve' ? 'Freigeben' : 'Ablehnen'}
|
||||
{saving ? 'Wird verarbeitet...' : BUTTON_LABELS[mode]}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user