import { useDashboardStore } from "../store"; import { useI18n } from "../contexts/I18nContext"; export default function ProjectOverview() { const graph = useDashboardStore((s) => s.graph); const startTour = useDashboardStore((s) => s.startTour); const { t } = useI18n(); if (!graph) { return (

{t.common.loading}

); } const { project, nodes, edges, layers } = graph; const hasTour = graph.tour.length > 0; const typeCounts: Record = {}; for (const node of nodes) { typeCounts[node.type] = (typeCounts[node.type] ?? 0) + 1; } const complexityCounts: Record = { simple: 0, moderate: 0, complex: 0 }; for (const node of nodes) { if (node.complexity) { complexityCounts[node.complexity] = (complexityCounts[node.complexity] ?? 0) + 1; } } const nodeConnections = new Map(); for (const edge of edges) { nodeConnections.set(edge.source, (nodeConnections.get(edge.source) ?? 0) + 1); nodeConnections.set(edge.target, (nodeConnections.get(edge.target) ?? 0) + 1); } const topNodes = Array.from(nodeConnections.entries()) .sort((a, b) => b[1] - a[1]) .slice(0, 5) .map(([nodeId, count]) => { const node = nodes.find((n) => n.id === nodeId); return { id: nodeId, name: node?.name ?? nodeId, count }; }); const avgConnections = nodes.length > 0 ? (edges.length * 2 / nodes.length).toFixed(1) : "0"; const categoryBreakdown = [ { label: t.projectOverview.code, color: "var(--color-node-file)", count: (typeCounts["file"] ?? 0) + (typeCounts["function"] ?? 0) + (typeCounts["class"] ?? 0) + (typeCounts["module"] ?? 0) + (typeCounts["concept"] ?? 0) }, { label: t.projectOverview.config, color: "var(--color-node-config)", count: typeCounts["config"] ?? 0 }, { label: t.projectOverview.docs, color: "var(--color-node-document)", count: typeCounts["document"] ?? 0 }, { label: t.projectOverview.infra, color: "var(--color-node-service)", count: (typeCounts["service"] ?? 0) + (typeCounts["resource"] ?? 0) + (typeCounts["pipeline"] ?? 0) }, { label: t.projectOverview.data, color: "var(--color-node-table)", count: (typeCounts["table"] ?? 0) + (typeCounts["endpoint"] ?? 0) + (typeCounts["schema"] ?? 0) }, { label: t.projectOverview.domain, color: "var(--color-node-concept)", count: (typeCounts["domain"] ?? 0) + (typeCounts["flow"] ?? 0) + (typeCounts["step"] ?? 0) }, ]; const hasNonCodeNodes = categoryBreakdown.some((c) => c.label !== t.projectOverview.code && c.count > 0); return (
{/* Project name */}

{project.name}

{project.description}

{/* Stats grid */}
{nodes.length}
{t.projectOverview.nodes}
{edges.length}
{t.projectOverview.edges}
{layers.length}
{t.projectOverview.layers}
{Object.keys(typeCounts).length}
{t.projectOverview.types}
{/* File Types breakdown */} {hasNonCodeNodes && (

{t.projectOverview.fileTypes}

{categoryBreakdown.filter((c) => c.count > 0).map((cat) => (
{cat.label} {cat.count}
))}
)} {/* Languages */} {project.languages.length > 0 && (

{t.projectOverview.languages}

{project.languages.map((lang) => ( {lang} ))}
)} {/* Frameworks */} {project.frameworks.length > 0 && (

{t.projectOverview.frameworks}

{project.frameworks.map((fw) => ( {fw} ))}
)} {/* Node Type Breakdown */}

{t.projectOverview.nodeTypeDistribution}

{Object.entries(typeCounts) .sort((a, b) => b[1] - a[1]) .map(([type, count]) => { const percentage = ((count / nodes.length) * 100).toFixed(0); return (
{type} {count} ({percentage}%)
); })}
{/* Complexity Breakdown */} {Object.values(complexityCounts).some((c) => c > 0) && (

{t.projectOverview.complexityDistribution}

{complexityCounts.simple}
{t.projectOverview.simple}
{complexityCounts.moderate}
{t.projectOverview.moderate}
{complexityCounts.complex}
{t.projectOverview.complex}
)} {/* Top Connected Nodes */} {topNodes.length > 0 && (

{t.projectOverview.mostConnectedNodes}

{topNodes.map((node, idx) => (
{idx + 1}
{node.name} {node.count}
))}
)} {/* Average Connections */}
{t.projectOverview.avgConnectionsPerNode} {avgConnections}
{/* Analyzed at */}
{t.common.analyzed}: {new Date(project.analyzedAt).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' })}
{/* Start Tour button */} {hasTour && ( )}
); }