VersionsTab zeigt jetzt kontextabhaengige Workflow-Buttons: - Entwurf → "Zur Pruefung" (Submit for Review) - In Pruefung → "Genehmigen" / "Ablehnen" (Approve/Reject) - Genehmigt → "Publizieren" (Publish) Backend-Endpoints (legal_document_routes.py) existierten bereits, wurden aber vom Frontend nicht genutzt. Status-Badges erweitert: draft, review, approved, published, archived, rejected. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
108 lines
4.9 KiB
TypeScript
108 lines
4.9 KiB
TypeScript
'use client'
|
|
|
|
import type { Document, Version } from '../_types'
|
|
|
|
const STATUS_STYLES: Record<string, { label: string; color: string }> = {
|
|
draft: { label: 'Entwurf', color: 'bg-gray-100 text-gray-700' },
|
|
review: { label: 'Pruefung', color: 'bg-yellow-100 text-yellow-700' },
|
|
approved: { label: 'Genehmigt', color: 'bg-blue-100 text-blue-700' },
|
|
published: { label: 'Publiziert', color: 'bg-green-100 text-green-700' },
|
|
archived: { label: 'Archiviert', color: 'bg-gray-100 text-gray-400' },
|
|
rejected: { label: 'Abgelehnt', color: 'bg-red-100 text-red-700' },
|
|
}
|
|
|
|
export function VersionsTab({
|
|
loading, documents, versions, selectedDocument, setSelectedDocument,
|
|
onSubmitReview, onApprove, onReject, onPublish,
|
|
}: {
|
|
loading: boolean
|
|
documents: Document[]
|
|
versions: Version[]
|
|
selectedDocument: string
|
|
setSelectedDocument: (id: string) => void
|
|
onSubmitReview?: (versionId: string) => void
|
|
onApprove?: (versionId: string) => void
|
|
onReject?: (versionId: string, comment: string) => void
|
|
onPublish?: (versionId: string) => void
|
|
}) {
|
|
return (
|
|
<div className="p-6">
|
|
<div className="flex items-center justify-between mb-6">
|
|
<div className="flex items-center gap-4">
|
|
<h2 className="text-lg font-semibold text-slate-900">Versionen</h2>
|
|
<select
|
|
value={selectedDocument}
|
|
onChange={(e) => setSelectedDocument(e.target.value)}
|
|
className="px-3 py-2 border border-slate-300 rounded-lg text-sm"
|
|
>
|
|
<option value="">Dokument auswaehlen...</option>
|
|
{documents.map((doc) => (
|
|
<option key={doc.id} value={doc.id}>{doc.name}</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
{!selectedDocument ? (
|
|
<div className="text-center py-12 text-slate-500">Bitte waehlen Sie ein Dokument aus</div>
|
|
) : loading ? (
|
|
<div className="text-center py-12 text-slate-500">Lade Versionen...</div>
|
|
) : versions.length === 0 ? (
|
|
<div className="text-center py-12 text-slate-500">Keine Versionen vorhanden</div>
|
|
) : (
|
|
<div className="space-y-4">
|
|
{versions.map((version) => {
|
|
const style = STATUS_STYLES[version.status] || STATUS_STYLES.draft
|
|
return (
|
|
<div key={version.id} className="border border-slate-200 rounded-lg p-4 hover:border-purple-300 transition-colors">
|
|
<div className="flex items-start justify-between">
|
|
<div>
|
|
<div className="flex items-center gap-2 mb-1">
|
|
<span className="font-semibold text-slate-900">v{version.version}</span>
|
|
<span className="px-2 py-0.5 bg-slate-100 text-slate-600 rounded text-xs">
|
|
{version.language.toUpperCase()}
|
|
</span>
|
|
<span className={`px-2 py-0.5 rounded text-xs ${style.color}`}>{style.label}</span>
|
|
</div>
|
|
<h3 className="text-slate-700">{version.title}</h3>
|
|
<p className="text-sm text-slate-500 mt-1">
|
|
Erstellt: {new Date(version.created_at).toLocaleDateString('de-DE')}
|
|
{version.published_at && ` | Publiziert: ${new Date(version.published_at).toLocaleDateString('de-DE')}`}
|
|
</p>
|
|
</div>
|
|
<div className="flex gap-2 flex-wrap justify-end">
|
|
{version.status === 'draft' && onSubmitReview && (
|
|
<button onClick={() => onSubmitReview(version.id)}
|
|
className="px-3 py-1.5 text-sm text-white bg-yellow-500 hover:bg-yellow-600 rounded-lg">
|
|
Zur Pruefung
|
|
</button>
|
|
)}
|
|
{version.status === 'review' && onApprove && (
|
|
<button onClick={() => onApprove(version.id)}
|
|
className="px-3 py-1.5 text-sm text-white bg-blue-600 hover:bg-blue-700 rounded-lg">
|
|
Genehmigen
|
|
</button>
|
|
)}
|
|
{version.status === 'review' && onReject && (
|
|
<button onClick={() => { const c = prompt('Ablehnungsgrund:'); if (c) onReject(version.id, c) }}
|
|
className="px-3 py-1.5 text-sm text-white bg-red-500 hover:bg-red-600 rounded-lg">
|
|
Ablehnen
|
|
</button>
|
|
)}
|
|
{version.status === 'approved' && onPublish && (
|
|
<button onClick={() => onPublish(version.id)}
|
|
className="px-3 py-1.5 text-sm text-white bg-green-600 hover:bg-green-700 rounded-lg">
|
|
Publizieren
|
|
</button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|