'use client' import { useState, useEffect } from 'react' import { useSDK } from '@/lib/sdk' interface ReviewerInfo { role_key: string role_label?: string person_name?: string | null person_email?: string | null is_primary?: boolean } interface ReviewRecord { id: string status: string reviewer_role_key: string reviewer_name: string | null email_sent: boolean } const STATUS_COLORS: Record = { pending: 'bg-gray-100 text-gray-700', in_review: 'bg-blue-100 text-blue-700', approved: 'bg-green-100 text-green-700', rejected: 'bg-red-100 text-red-700', } const STATUS_LABELS: Record = { pending: 'Ausstehend', in_review: 'In Pruefung', approved: 'Freigegeben', rejected: 'Abgelehnt', } export default function ReviewAssignmentPanel({ documentType, documentTitle, documentContent, }: { documentType: string documentTitle: string documentContent: string }) { const { projectId } = useSDK() const [reviewers, setReviewers] = useState([]) const [existingReviews, setExistingReviews] = useState([]) const [sending, setSending] = useState(false) const [result, setResult] = useState(null) // Load reviewers for this document type useEffect(() => { if (!documentType) return const qs = new URLSearchParams() if (projectId) qs.set('project_id', projectId) qs.set('document_type', documentType) // Load mapping + existing reviews Promise.all([ fetch(`/api/sdk/v1/compliance/org-roles/mapping`).then(r => r.ok ? r.json() : []), fetch(`/api/sdk/v1/compliance/org-roles${projectId ? `?project_id=${projectId}` : ''}`).then(r => r.ok ? r.json() : []), fetch(`/api/sdk/v1/compliance/document-reviews/for-document?${qs}`).then(r => r.ok ? r.json() : []), ]).then(([mappings, roles, reviews]) => { // Filter mappings for this document type const relevant = (mappings as Array<{ document_type: string; role_key: string; is_primary: boolean }>) .filter(m => m.document_type === documentType) // Enrich with role info const enriched: ReviewerInfo[] = relevant.map(m => { const role = (roles as Array<{ role_key: string; role_label: string; person_name: string | null; person_email: string | null }>) .find(r => r.role_key === m.role_key) return { ...m, role_label: role?.role_label, person_name: role?.person_name, person_email: role?.person_email } }) setReviewers(enriched) setExistingReviews(reviews) }).catch(() => {}) }, [documentType, projectId]) const handleSendForReview = async () => { setSending(true) setResult(null) try { const res = await fetch('/api/sdk/v1/compliance/document-reviews', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ document_type: documentType, document_title: documentTitle, document_content: documentContent, project_id: projectId, review_link: window.location.href, }), }) if (!res.ok) throw new Error('Fehler beim Erstellen') const reviews = await res.json() // Send email for each review let sentCount = 0 for (const review of reviews) { if (review.reviewer_email) { const sendRes = await fetch(`/api/sdk/v1/compliance/document-reviews/${review.id}/send`, { method: 'POST' }) if (sendRes.ok) sentCount++ } } setResult(`${reviews.length} Review(s) erstellt, ${sentCount} E-Mail(s) gesendet`) // Refresh const qs = new URLSearchParams({ document_type: documentType }) if (projectId) qs.set('project_id', projectId) const updated = await fetch(`/api/sdk/v1/compliance/document-reviews/for-document?${qs}`).then(r => r.json()) setExistingReviews(updated) } catch (e) { setResult(e instanceof Error ? e.message : 'Fehler') } finally { setSending(false) } } if (reviewers.length === 0 && existingReviews.length === 0) return null return (

Pruefung & Freigabe

{/* Assigned reviewers */} {reviewers.length > 0 && (
{reviewers.map(r => (
{r.role_label || r.role_key}: {r.person_name ? ( {r.person_name} ({r.person_email || 'keine E-Mail'}) ) : ( Nicht zugewiesen )}
))}
)} {/* Existing reviews */} {existingReviews.length > 0 && (
{existingReviews.map(r => (
{STATUS_LABELS[r.status] || r.status} {r.reviewer_name || r.reviewer_role_key} {r.email_sent && E-Mail gesendet}
))}
)} {/* Send for review */} {result && (

{result}

)}
) }