import { useState, useEffect } from 'react'; import { getDataValidationObject, type DataValidationObjectResponse } from '../services/api'; import { useAuthStore } from '../stores/authStore'; interface ObjectDetailModalProps { objectId: string | null; onClose: () => void; onObjectClick?: (objectId: string) => void; onBack?: () => void; canGoBack?: boolean; } interface ObjectReference { objectId: string; objectKey: string; label: string; } function isObjectReference(value: any): value is ObjectReference { return value && typeof value === 'object' && 'objectId' in value; } function formatValue(value: any): string { if (value === null || value === undefined) return '—'; if (typeof value === 'boolean') return value ? 'Ja' : 'Nee'; if (typeof value === 'object') { if (Array.isArray(value)) { if (value.length === 0) return '—'; return value.map(v => formatValue(v)).join(', '); } if (isObjectReference(value)) { return value.label || value.objectKey || value.objectId; } return JSON.stringify(value); } return String(value); } export default function ObjectDetailModal({ objectId, onClose, onObjectClick, onBack, canGoBack = false }: ObjectDetailModalProps) { const [objectData, setObjectData] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const { config } = useAuthStore(); useEffect(() => { if (!objectId) { setObjectData(null); return; } const loadObject = async () => { setLoading(true); setError(null); try { const data = await getDataValidationObject(objectId); setObjectData(data); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load object'); } finally { setLoading(false); } }; loadObject(); }, [objectId]); if (!objectId) return null; const handleReferenceClick = (ref: ObjectReference, e: React.MouseEvent) => { e.stopPropagation(); if (onObjectClick) { onObjectClick(ref.objectId); } }; const handleBack = () => { if (onBack) { onBack(); } }; const renderAttributeValue = (key: string, value: any) => { // Skip internal/system fields if (key.startsWith('_')) return null; // Handle reference fields if (isObjectReference(value)) { return ( ); } // Handle arrays of references if (Array.isArray(value) && value.length > 0 && isObjectReference(value[0])) { return (
{value.map((ref, idx) => ( ))}
); } // Regular values return {formatValue(value)}; }; return (
{/* Backdrop */}
{/* Modal */}
e.stopPropagation()} > {/* Header */}
{/* Back Button */} {canGoBack && onBack && ( )}
{loading ? (

Laden...

) : objectData ? (

{objectData.metadata.label}

{objectData.metadata.objectKey} {objectData.metadata.typeDisplayName}
) : (

Object Details

)}
{/* Jira Assets Link */} {objectData && config?.jiraHost && ( )}
{/* Content */}
{error ? (

{error}

) : objectData ? (
{/* Basic Info */}

Basis Informatie

ID
{objectData.metadata.objectKey}
Type
{objectData.metadata.typeDisplayName}
{/* Attributes */}

Attributen

{Object.entries(objectData.object as Record) .filter(([key]) => !key.startsWith('_')) .sort(([a], [b]) => a.localeCompare(b)) .map(([key, value]) => { const renderedValue = renderAttributeValue(key, value); if (renderedValue === null) return null; return ( ); })} {Object.entries(objectData.object as Record) .filter(([key]) => !key.startsWith('_')).length === 0 && ( )}
Attribuut Waarde
{key} {renderedValue}
Geen attributen beschikbaar
{/* Metadata */} {objectData.object && typeof objectData.object === 'object' && '_jiraUpdatedAt' in objectData.object && (

Metadata

{objectData.object._jiraUpdatedAt && (
Laatst bijgewerkt (Jira)
{new Date(objectData.object._jiraUpdatedAt).toLocaleString('nl-NL')}
{objectData.object._jiraCreatedAt && (
Aangemaakt (Jira)
{new Date(objectData.object._jiraCreatedAt).toLocaleString('nl-NL')}
)}
)}
)}
) : (

Laden van object details...

)}
{/* Footer */}
); }