import { useMemo } from 'react'; import { IconButton, Tooltip } from '@mui/material'; import RefreshIcon from '@mui/icons-material/Refresh'; import WarningIcon from '@mui/icons-material/Warning'; import InfoIcon from '@mui/icons-material/Info'; import BarChartIcon from '@mui/icons-material/BarChart'; import { calculateGraphMetrics } from '../../utils/graphAnalysis'; import type { Actor, Relation } from '../../types'; interface GraphMetricsProps { nodes: Actor[]; edges: Relation[]; onActorClick?: (actorId: string) => void; } /** * GraphMetrics - Display graph analysis and statistics * * Shows when no node or edge is selected in the right panel. * Provides insights into graph structure, connectivity, and key actors. */ const GraphMetrics = ({ nodes, edges, onActorClick }: GraphMetricsProps) => { // Calculate all metrics (memoized for performance) const metrics = useMemo(() => { return calculateGraphMetrics(nodes, edges); }, [nodes, edges]); const handleRefresh = () => { // Metrics are automatically recalculated via useMemo // This is just for visual feedback console.log('Metrics refreshed'); }; const formatNumber = (num: number, decimals: number = 2): string => { return num.toFixed(decimals); }; const formatPercentage = (num: number): string => { return `${(num * 100).toFixed(1)}%`; }; return (
{/* Header */}

Graph Analysis

{/* Scrollable Content */}
{/* Overview Section */}

Overview

{/* Most Connected Actors Section */} {metrics.mostConnectedActors.length > 0 && (

Most Connected Actors

{metrics.mostConnectedActors.map((actor, index) => (
onActorClick?.(actor.actorId)} >
{index + 1}. {actor.actorLabel}
{actor.degree} {actor.degree === 1 ? 'connection' : 'connections'}
))}
)} {/* Graph Structure Section */}

Graph Structure

0 ? ( ) : undefined } tooltip="Actors with no connections to other actors" highlight={metrics.isolatedActorCount > 0 ? 'warning' : undefined} /> 1 ? ( ) : undefined } tooltip="Number of separate, disconnected subgraphs" highlight={metrics.connectedComponentCount > 1 ? 'info' : undefined} />
{/* Actors by Type Section */} {metrics.actorsByType.size > 0 && (

Actors by Type

{Array.from(metrics.actorsByType.entries()) .sort((a, b) => b[1] - a[1]) .map(([type, count]) => (
{type} {count}
))}
)} {/* Relations by Type Section */} {metrics.relationsByType.size > 0 && (

Relations by Type

{Array.from(metrics.relationsByType.entries()) .sort((a, b) => b[1] - a[1]) .map(([type, count]) => (
{type} {count}
))}
)} {/* Empty graph state */} {metrics.actorCount === 0 && (

No Data

Add actors to see graph metrics

)}
); }; /** * MetricRow - Single metric display with label and value */ interface MetricRowProps { label: string; value: string; icon?: React.ReactNode; tooltip?: string; highlight?: 'warning' | 'info'; } const MetricRow = ({ label, value, icon, tooltip, highlight }: MetricRowProps) => { const content = (
{icon && {icon}} {label}
{value}
); if (tooltip) { return ( {content} ); } return content; }; export default GraphMetrics;