import { asError } from '@/utils/errorTypes'; import React, { useState } from 'react'; import { useWorkflowInstance, useAdvanceWorkflowInstance, useCancelWorkflowInstance, } from '@/api/workflows'; import { Modal } from '@/components/ui/Modal'; import { Button } from '@/components/ui/Button'; import { Badge } from '@/components/ui/Badge'; import { Input } from '@/components/ui/Input'; import { Skeleton } from '@/components/ui/Skeleton'; import { useToast } from '@/components/ui/Toast'; import { CheckCircle2, XCircle, Ban, Clock, AlertCircle, } from 'lucide-react'; function statusBadgeVariant( status: string ): 'success' | 'warning' | 'danger' | 'info' | 'secondary' { switch (status) { case 'completed': return 'success'; case 'in_progress': return 'info'; case 'pending': return 'warning'; case 'rejected': return 'danger'; case 'cancelled': return 'secondary'; default: return 'secondary'; } } function statusLabel(status: string): string { const map: Record = { pending: 'Wartend', in_progress: 'In Bearbeitung', completed: 'Abgeschlossen', rejected: 'Abgelehnt', cancelled: 'Abgebrochen', }; return map[status] ?? status; } function stepTypeLabel(type: string): string { const map: Record = { action: 'Action', approval: 'Approval', notification: 'Notification', condition: 'Condition', }; return map[type] ?? type; } export interface WorkflowInstanceDetailProps { instanceId: string; onClose: () => void; } export function WorkflowInstanceDetail({ instanceId, onClose, }: WorkflowInstanceDetailProps) { const toast = useToast(); const { data: instance, isLoading, isError, refetch } = useWorkflowInstance(instanceId); const advanceMutation = useAdvanceWorkflowInstance(); const cancelMutation = useCancelWorkflowInstance(); const [comment, setComment] = useState(''); const [showCommentField, setShowCommentField] = useState< 'approve' | 'reject' | null >(null); const handleAdvance = async (decision: 'approve' | 'reject') => { if (!instance) return; try { await advanceMutation.mutateAsync({ instanceId: instance.id, data: { decision, comment: comment || null, }, }); toast.success( decision === 'approve' ? 'Schritt genehmigt' : 'Schritt abgelehnt' ); setComment(''); setShowCommentField(null); } catch (err: unknown) { const errObj = asError(err); toast.error(errObj.message || 'Fehler bei der Aktion'); } }; const handleCancel = async () => { if (!instance) return; try { await cancelMutation.mutateAsync(instance.id); toast.success('Instanz abgebrochen'); } catch (err: unknown) { const errObj = asError(err); toast.error(errObj.message || 'Fehler beim Abbrechen'); } }; const canAct = instance?.status === 'in_progress' || instance?.status === 'pending'; const canCancel = instance?.status === 'in_progress' || instance?.status === 'pending'; return ( {isLoading && (
)} {isError && (
Fehler beim Laden der Instanz
)} {!isLoading && !isError && instance && (
{/* Header info */}
{statusLabel(instance.status)} {instance.workflow_name && ( {instance.workflow_name} )} {!instance.workflow_name && ( Workflow {instance.workflow_id.slice(0, 8)} )} ID: {instance.id}
{/* Key info grid */}

Aktueller Schritt

{instance.current_step_index + 1}

Initiiert von

{instance.initiated_by || '—'}

Erstellt am

{instance.created_at ? new Date(instance.created_at).toLocaleString() : '—'}

Timeout

{instance.timeout_at ? new Date(instance.timeout_at).toLocaleString() : '—'}

{/* Context JSON */}

Kontext

              {JSON.stringify(instance.context ?? {}, null, 2)}
            
{/* Step history timeline */}

Schritt-Historie

{instance.history && instance.history.length > 0 ? (
{instance.history.map((entry, idx) => (
{entry.step_index + 1}
{idx < instance.history.length - 1 && (
)}
{stepTypeLabel(entry.step_type)} {entry.action}
{entry.actor_id && ( Aktor: {entry.actor_id} )} {entry.created_at && ( {new Date(entry.created_at).toLocaleString()} )}
{entry.details && (
                          {JSON.stringify(entry.details, null, 2)}
                        
)}
))}
) : (

Keine Historie vorhanden

)}
{/* Action buttons */} {canAct && (
{showCommentField && ( setComment(e.target.value)} placeholder="Kommentar hinzufuegen..." /> )}
{!showCommentField && ( <> )} {showCommentField === 'approve' && ( <> )} {showCommentField === 'reject' && ( <> )} {canCancel && !showCommentField && ( )}
)} {instance.status === 'completed' && (
Dieser Workflow ist abgeschlossen
)} {instance.status === 'rejected' && (
Dieser Workflow wurde abgelehnt
)} {instance.status === 'cancelled' && (
Dieser Workflow wurde abgebrochen
)}
)} ); }