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

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:
Benjamin Admin
2026-06-08 10:15:32 +02:00
parent 5c5d676f01
commit 79ce12caf1
9 changed files with 254 additions and 98 deletions
+8
View File
@@ -134,6 +134,14 @@ docs-src/Breakpilot ComplAI Finanzplan.xlsm
# Phase 5+ target for splitting into smaller subcomponents per wizard step.
admin-compliance/components/sdk/ai-act/DecisionTreeWizard.tsx
# --- admin-compliance: zentrale SDK-Schritt-Registry ---
# Flache Liste aller 38 SDK-Steps mit kanonischer Reihenfolge (seq).
# Splits nach Paket würden die globale Ordnungs-Garantie zerreißen und
# Imports an mehreren Stellen aufblähen — der Wert dieser Datei ist
# *eine* sortierte Source-of-Truth.
# [guardrail-change]
admin-compliance/lib/sdk/types/sdk-steps.ts
# --- ai-compliance-sdk: oversized handler refactor backlog ---
# Phase 5+ target for splitting handler groups into per-resource files.
ai-compliance-sdk/internal/api/handlers/tender_handlers.go
@@ -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>
@@ -1,6 +1,7 @@
'use client'
import { Version, STATUS_LABELS } from '../_types'
import type { ApprovalModalMode } from './ApprovalModal'
interface CompareViewProps {
currentVersion: Version | null
@@ -9,7 +10,7 @@ interface CompareViewProps {
onClose: () => void
onSaveDraft: () => void
onSubmitForReview: () => void
onShowApprovalModal: (mode: 'approve' | 'reject') => void
onShowApprovalModal: (mode: ApprovalModalMode) => void
onPublishVersion: () => void
}
@@ -64,28 +65,26 @@ export default function CompareView({
{/* Right: Draft */}
<div className="bg-white flex flex-col">
<div className={`border-b px-4 py-2 ${
draftVersion?.status === 'draft' ? 'bg-yellow-100 border-yellow-200' :
draftVersion?.status === 'review' ? 'bg-blue-100 border-blue-200' :
draftVersion?.status === 'approved' ? 'bg-green-100 border-green-200' :
'bg-slate-100 border-slate-200'
}`}>
<span className={`font-medium ${
draftVersion?.status === 'draft' ? 'text-yellow-800' :
draftVersion?.status === 'review' ? 'text-blue-800' :
draftVersion?.status === 'approved' ? 'text-green-800' :
'text-slate-800'
}`}>
<div
className={`border-b px-4 py-2 ${
draftVersion?.status === 'draft'
? 'bg-yellow-100 border-yellow-200'
: draftVersion?.status === 'review' || draftVersion?.status === 'review_internal'
? 'bg-blue-100 border-blue-200'
: draftVersion?.status === 'review_client'
? 'bg-indigo-100 border-indigo-200'
: draftVersion?.status === 'approved'
? 'bg-green-100 border-green-200'
: 'bg-slate-100 border-slate-200'
}`}
>
<span className="font-medium text-slate-800">
{draftVersion ? 'Aenderungsversion' : 'Neue Version'}
</span>
{draftVersion && (
<span className={`ml-2 ${
draftVersion.status === 'draft' ? 'text-yellow-600' :
draftVersion.status === 'review' ? 'text-blue-600' :
draftVersion.status === 'approved' ? 'text-green-600' :
'text-slate-600'
}`}>
v{draftVersion.version} - {STATUS_LABELS[draftVersion.status].label}
<span className="ml-2 text-slate-600">
v{draftVersion.version} -{' '}
{STATUS_LABELS[draftVersion.status]?.label ?? draftVersion.status}
</span>
)}
</div>
@@ -113,7 +112,7 @@ export default function CompareView({
</button>
</>
)}
{draftVersion?.status === 'review' && (
{draftVersion?.status === 'review_internal' && (
<>
<button
onClick={() => { onClose(); onShowApprovalModal('reject') }}
@@ -122,10 +121,26 @@ export default function CompareView({
Ablehnen
</button>
<button
onClick={() => { onClose(); onShowApprovalModal('approve') }}
onClick={() => { onClose(); onShowApprovalModal('approve-internal') }}
className="px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-500"
>
Freigeben
DSB-Freigabe Mandant
</button>
</>
)}
{draftVersion?.status === 'review_client' && (
<>
<button
onClick={() => { onClose(); onShowApprovalModal('reject') }}
className="px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-500"
>
Ablehnen
</button>
<button
onClick={() => { onClose(); onShowApprovalModal('approve-client') }}
className="px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-500"
>
Mandanten-Freigabe
</button>
</>
)}
@@ -9,6 +9,32 @@ interface HistoryPanelProps {
currentVersion: Version | null
}
// Backend-Actions (compliance/services/legal_document_service.py):
// submitted_internal, approved_internal, approved_client,
// published, rejected, plus alte Werte 'submitted'/'approved'.
const ACTION_LABELS: Record<string, string> = {
submitted: 'Eingereicht',
submitted_internal: 'An DSB eingereicht',
approved: 'Freigegeben',
approved_internal: 'DSB-Freigabe → Mandant',
approved_client: 'Mandanten-Freigabe',
published: 'Veroeffentlicht',
rejected: 'Abgelehnt',
}
function actionLabel(action: string): string {
return ACTION_LABELS[action] || action
}
function actionBadgeClass(action: string): string {
if (action.startsWith('approved') || action === 'published') {
return 'bg-green-100 text-green-700'
}
if (action === 'rejected') return 'bg-red-100 text-red-700'
if (action.startsWith('submitted')) return 'bg-blue-100 text-blue-700'
return 'bg-slate-100 text-slate-700'
}
export default function HistoryPanel({
approvalHistory,
versions,
@@ -22,12 +48,9 @@ export default function HistoryPanel({
<div className="space-y-3">
{approvalHistory.map((item, idx) => (
<div key={idx} className="flex items-center gap-4 p-3 border border-slate-200 rounded-lg">
<span className={`px-2 py-1 rounded text-xs ${
item.action === 'approved' ? 'bg-green-100 text-green-700' :
item.action === 'rejected' ? 'bg-red-100 text-red-700' :
item.action === 'submitted' ? 'bg-blue-100 text-blue-700' :
'bg-slate-100 text-slate-700'
}`}>{item.action}</span>
<span className={`px-2 py-1 rounded text-xs ${actionBadgeClass(item.action)}`}>
{actionLabel(item.action)}
</span>
<span className="text-sm text-slate-600">{item.approver || 'System'}</span>
{item.comment && (
<span className="text-sm text-slate-500 italic">&quot;{item.comment}&quot;</span>
@@ -56,8 +79,12 @@ export default function HistoryPanel({
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<span className="font-mono font-medium">v{v.version}</span>
<span className={`px-2 py-0.5 rounded text-xs ${STATUS_LABELS[v.status].color}`}>
{STATUS_LABELS[v.status].label}
<span
className={`px-2 py-0.5 rounded text-xs ${
STATUS_LABELS[v.status]?.color ?? 'bg-slate-100 text-slate-700'
}`}
>
{STATUS_LABELS[v.status]?.label ?? v.status}
</span>
<span className="text-sm text-slate-500">{v.title}</span>
</div>
@@ -70,29 +70,27 @@ export default function SplitViewEditor({
{/* Right: Draft/Edit Version */}
<div className="bg-white rounded-xl shadow-sm border overflow-hidden">
<div className={`border-b px-4 py-3 flex items-center justify-between ${
draftVersion?.status === 'draft' ? 'bg-yellow-50 border-yellow-200' :
draftVersion?.status === 'review' ? 'bg-blue-50 border-blue-200' :
draftVersion?.status === 'approved' ? 'bg-green-50 border-green-200' :
'bg-slate-50 border-slate-200'
}`}>
<div
className={`border-b px-4 py-3 flex items-center justify-between ${
draftVersion?.status === 'draft'
? 'bg-yellow-50 border-yellow-200'
: draftVersion?.status === 'review' || draftVersion?.status === 'review_internal'
? 'bg-blue-50 border-blue-200'
: draftVersion?.status === 'review_client'
? 'bg-indigo-50 border-indigo-200'
: draftVersion?.status === 'approved'
? 'bg-green-50 border-green-200'
: 'bg-slate-50 border-slate-200'
}`}
>
<div>
<h3 className={`font-semibold ${
draftVersion?.status === 'draft' ? 'text-yellow-900' :
draftVersion?.status === 'review' ? 'text-blue-900' :
draftVersion?.status === 'approved' ? 'text-green-900' :
'text-slate-900'
}`}>
<h3 className="font-semibold text-slate-900">
{draftVersion ? 'Aenderungsversion' : 'Neue Version'}
</h3>
{draftVersion && (
<p className={`text-sm ${
draftVersion.status === 'draft' ? 'text-yellow-700' :
draftVersion.status === 'review' ? 'text-blue-700' :
draftVersion.status === 'approved' ? 'text-green-700' :
'text-slate-700'
}`}>
v{draftVersion.version} - {STATUS_LABELS[draftVersion.status].label}
<p className="text-sm text-slate-700">
v{draftVersion.version} -{' '}
{STATUS_LABELS[draftVersion.status]?.label ?? draftVersion.status}
</p>
)}
</div>
@@ -2,16 +2,35 @@
import { Version } from '../_types'
export type ApprovalMode = 'approve-internal' | 'approve-client' | 'reject'
interface WorkflowStatusBarProps {
draftVersion: Version | null
saving: boolean
onCreateNewDraft: () => void
onSaveDraft: () => void
onSubmitForReview: () => void
onShowApprovalModal: (mode: 'approve' | 'reject') => void
onShowApprovalModal: (mode: ApprovalMode) => void
onPublishVersion: () => void
}
// 5-Stage Lifecycle:
// draft → review_internal (DSB-Pruefung) → review_client (Mandant-Pruefung)
// → approved → published
// Buttons sind v1 nicht role-gefiltert — alle relevanten Aktionen sichtbar.
const STAGES: { status: string; label: string }[] = [
{ status: 'draft', label: 'Entwurf' },
{ status: 'review_internal', label: 'DSB-Pruefung' },
{ status: 'review_client', label: 'Mandant-Pruefung' },
{ status: 'approved', label: 'Freigegeben' },
{ status: 'published', label: 'Veroeffentlicht' },
]
function isActiveStage(stageStatus: string, draftStatus: string | undefined, hasDraft: boolean) {
if (stageStatus === 'published') return !hasDraft
return draftStatus === stageStatus
}
export default function WorkflowStatusBar({
draftVersion,
saving,
@@ -21,34 +40,31 @@ export default function WorkflowStatusBar({
onShowApprovalModal,
onPublishVersion,
}: WorkflowStatusBarProps) {
const status = draftVersion?.status
return (
<div className="bg-white rounded-xl shadow-sm border p-4">
<div className="flex items-center justify-between">
<div className="flex items-center gap-6">
{['draft', 'review', 'approved', 'published'].map((status, idx) => (
<div key={status} className="flex items-center">
{idx > 0 && <div className="w-8 h-0.5 bg-slate-200 mr-2" />}
<div className="flex items-center justify-between flex-wrap gap-4">
<div className="flex items-center gap-4 flex-wrap">
{STAGES.map((stage, idx) => (
<div key={stage.status} className="flex items-center">
{idx > 0 && <div className="w-6 h-0.5 bg-slate-200 mr-2" />}
<div className="flex items-center gap-2">
<div className={`w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium ${
(status === 'draft' && draftVersion?.status === 'draft') ||
(status === 'review' && draftVersion?.status === 'review') ||
(status === 'approved' && draftVersion?.status === 'approved') ||
(status === 'published' && !draftVersion)
? 'bg-purple-500 text-white'
: 'bg-slate-200 text-slate-600'
}`}>{idx + 1}</div>
<span className="text-sm text-slate-600">
{status === 'draft' ? 'Entwurf' :
status === 'review' ? 'Pruefung' :
status === 'approved' ? 'Freigegeben' : 'Veroeffentlicht'}
</span>
<div
className={`w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium ${
isActiveStage(stage.status, status, Boolean(draftVersion))
? 'bg-purple-500 text-white'
: 'bg-slate-200 text-slate-600'
}`}
>
{idx + 1}
</div>
<span className="text-sm text-slate-600">{stage.label}</span>
</div>
</div>
))}
</div>
{/* Action Buttons */}
<div className="flex items-center gap-2">
<div className="flex items-center gap-2 flex-wrap">
{!draftVersion && (
<button
onClick={onCreateNewDraft}
@@ -59,7 +75,7 @@ export default function WorkflowStatusBar({
</button>
)}
{draftVersion?.status === 'draft' && (
{status === 'draft' && (
<>
<button
onClick={onSaveDraft}
@@ -73,12 +89,12 @@ export default function WorkflowStatusBar({
disabled={saving}
className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 text-sm font-medium"
>
Zur Pruefung einreichen
An DSB einreichen
</button>
</>
)}
{draftVersion?.status === 'review' && (
{status === 'review_internal' && (
<>
<button
onClick={() => onShowApprovalModal('reject')}
@@ -88,16 +104,35 @@ export default function WorkflowStatusBar({
Ablehnen
</button>
<button
onClick={() => onShowApprovalModal('approve')}
onClick={() => onShowApprovalModal('approve-internal')}
disabled={saving}
className="px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 disabled:opacity-50 text-sm font-medium"
>
Freigeben
DSB-Freigabe Mandant
</button>
</>
)}
{draftVersion?.status === 'approved' && (
{status === 'review_client' && (
<>
<button
onClick={() => onShowApprovalModal('reject')}
disabled={saving}
className="px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 disabled:opacity-50 text-sm font-medium"
>
Ablehnen
</button>
<button
onClick={() => onShowApprovalModal('approve-client')}
disabled={saving}
className="px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 disabled:opacity-50 text-sm font-medium"
>
Mandant-Freigabe
</button>
</>
)}
{status === 'approved' && (
<button
onClick={onPublishVersion}
disabled={saving}
@@ -107,9 +142,11 @@ export default function WorkflowStatusBar({
</button>
)}
{draftVersion?.status === 'rejected' && (
{status === 'rejected' && (
<div className="flex items-center gap-2">
<span className="text-sm text-red-600">Abgelehnt: {draftVersion.rejection_reason}</span>
<span className="text-sm text-red-600">
Abgelehnt: {draftVersion?.rejection_reason}
</span>
<button
onClick={onCreateNewDraft}
disabled={saving}
@@ -2,6 +2,7 @@
import { useState } from 'react'
import { Document, Version, ApprovalHistoryItem } from '../_types'
import type { ApprovalModalMode } from '../_components/ApprovalModal'
interface UseWorkflowActionsParams {
selectedDocument: Document | null
@@ -27,7 +28,7 @@ export function useWorkflowActions(params: UseWorkflowActionsParams) {
const [saving, setSaving] = useState(false)
const [approvalComment, setApprovalComment] = useState('')
const [showApprovalModal, setShowApprovalModal] = useState<'approve' | 'reject' | null>(null)
const [showApprovalModal, setShowApprovalModal] = useState<ApprovalModalMode | null>(null)
const [approvalHistory, setApprovalHistory] = useState<ApprovalHistoryItem[]>([])
const [showNewDocModal, setShowNewDocModal] = useState(false)
const [newDocForm, setNewDocForm] = useState({ type: 'privacy_policy', name: '', description: '' })
@@ -123,10 +124,15 @@ export function useWorkflowActions(params: UseWorkflowActionsParams) {
}
const approveVersion = async () => {
// Backward-compat alias — leitet auf approve-internal (DSB → Mandant)
return approveInternal()
}
const approveInternal = async () => {
if (!draftVersion) return
setSaving(true)
try {
const res = await fetch(`/api/admin/consent/versions/${draftVersion.id}/approve`, {
const res = await fetch(`/api/admin/consent/versions/${draftVersion.id}/approve-internal`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ comment: approvalComment }),
@@ -138,10 +144,35 @@ export function useWorkflowActions(params: UseWorkflowActionsParams) {
await loadVersions(selectedDocument!.id)
} else {
const err = await res.json()
setError(err.error || 'Fehler bei der Freigabe')
setError(err.error || 'Fehler bei der DSB-Freigabe')
}
} catch {
setError('Fehler bei der Freigabe')
setError('Fehler bei der DSB-Freigabe')
} finally {
setSaving(false)
}
}
const approveClient = async () => {
if (!draftVersion) return
setSaving(true)
try {
const res = await fetch(`/api/admin/consent/versions/${draftVersion.id}/approve-client`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ comment: approvalComment }),
})
if (res.ok) {
setShowApprovalModal(null)
setApprovalComment('')
await loadVersions(selectedDocument!.id)
} else {
const err = await res.json()
setError(err.error || 'Fehler bei der Mandanten-Freigabe')
}
} catch {
setError('Fehler bei der Mandanten-Freigabe')
} finally {
setSaving(false)
}
@@ -242,7 +273,8 @@ export function useWorkflowActions(params: UseWorkflowActionsParams) {
newDocForm, setNewDocForm,
creatingDoc,
createNewDraft, saveDraft, submitForReview,
approveVersion, rejectVersion, publishVersion,
approveVersion, approveInternal, approveClient,
rejectVersion, publishVersion,
createDocument, loadApprovalHistory,
}
}
+11 -1
View File
@@ -16,7 +16,15 @@ export interface Version {
title: string
content: string
summary?: string
status: 'draft' | 'review' | 'approved' | 'published' | 'archived' | 'rejected'
status:
| 'draft'
| 'review' // backward-compat (alte Daten, vor 5-Stage Migration 148)
| 'review_internal'
| 'review_client'
| 'approved'
| 'published'
| 'archived'
| 'rejected'
created_at: string
updated_at?: string
created_by?: string
@@ -35,6 +43,8 @@ export interface ApprovalHistoryItem {
export const STATUS_LABELS: Record<string, { label: string; color: string }> = {
draft: { label: 'Entwurf', color: 'bg-yellow-100 text-yellow-700' },
review: { label: 'In Pruefung', color: 'bg-blue-100 text-blue-700' },
review_internal: { label: 'DSB-Pruefung', color: 'bg-blue-100 text-blue-700' },
review_client: { label: 'Mandant-Pruefung', color: 'bg-indigo-100 text-indigo-700' },
approved: { label: 'Freigegeben', color: 'bg-green-100 text-green-700' },
published: { label: 'Veroeffentlicht', color: 'bg-emerald-100 text-emerald-700' },
archived: { label: 'Archiviert', color: 'bg-slate-100 text-slate-700' },
+12 -2
View File
@@ -92,7 +92,11 @@ export default function WorkflowPage() {
setCurrentVersion(published || null)
const draft = versionList.find((v: Version) =>
v.status === 'draft' || v.status === 'review' || v.status === 'approved'
v.status === 'draft' ||
v.status === 'review' || // backward-compat: alte Daten
v.status === 'review_internal' ||
v.status === 'review_client' ||
v.status === 'approved'
)
if (draft) {
setDraftVersion(draft)
@@ -256,7 +260,13 @@ export default function WorkflowPage() {
actions.setShowApprovalModal(null)
actions.setApprovalComment('')
}}
onConfirm={actions.showApprovalModal === 'approve' ? actions.approveVersion : actions.rejectVersion}
onConfirm={
actions.showApprovalModal === 'approve-internal'
? actions.approveInternal
: actions.showApprovalModal === 'approve-client'
? actions.approveClient
: actions.rejectVersion
}
saving={actions.saving}
/>
)}