'use client'; import { useParams } from 'next/navigation'; import Link from 'next/link'; import { Server, ArrowLeft, Cpu, Users, Activity, ExternalLink } from 'lucide-react'; import { useNodeProfile } from '@/hooks/useNodes'; import { useNodeDashboard } from '@/hooks/useNodeDashboard'; import { NodeSummaryCard, InfraCard, AIServicesCard, AgentsCard, MatrixCard, ModulesCard, NodeStandardComplianceCard } from '@/components/node-dashboard'; import { NodeGuardianCard } from '@/components/nodes/NodeGuardianCard'; import { AgentChatWidget } from '@/components/chat/AgentChatWidget'; function getNodeLabel(nodeId: string): string { if (nodeId.includes('node-1')) return 'НОДА1'; if (nodeId.includes('node-2')) return 'НОДА2'; return 'НОДА'; } export default function NodeCabinetPage() { const params = useParams(); const nodeId = params.nodeId as string; const nodeLabel = getNodeLabel(nodeId); const dashboardEnabled = nodeId === 'node-1-hetzner-gex44'; // Basic node profile from node_cache const { node: nodeProfile, isLoading: profileLoading, error: profileError } = useNodeProfile(nodeId); // Full dashboard (if available - currently only for NODE1) const { dashboard, isLoading: dashboardLoading, error: dashboardError, refresh, lastUpdated } = useNodeDashboard({ refreshInterval: 30000, enabled: dashboardEnabled }); const isLoading = profileLoading || (dashboardEnabled && dashboardLoading); const shouldShowError = (!!profileError && !nodeProfile) || (!nodeProfile && !dashboard); const isProduction = nodeProfile?.environment === 'production'; if (isLoading && !nodeProfile && !dashboard) { return (

Loading node cabinet...

); } if (shouldShowError) { return (

Failed to load node

{profileError?.message || 'Node not found'}

Back to Nodes
); } // If we have full dashboard (NODE1), show it if (dashboard) { return (
{/* Header */}

{nodeLabel}

{dashboard.node.name}

{lastUpdated && (

Updated: {lastUpdated.toLocaleTimeString()}

)}
{dashboardError && (
Детальний моніторинг тимчасово недоступний. Показано останній кешований профіль ноди.
)} {/* Main Grid */}
{/* Node Guardian & Steward Agents */} {/* MicroDAO Presence */} {nodeProfile?.microdaos && nodeProfile.microdaos.length > 0 && (

MicroDAO Presence

    {nodeProfile.microdaos.map((dao) => (
  • {dao.name} {dao.rooms_count} rooms
  • ))}
)}
{/* Link to agents */}
Агенти цієї ноди
{/* Floating Chat Widget */} ); } // Basic profile view (for NODE2 and others) return (
{/* Header */}

{nodeLabel}

{nodeProfile?.name}

{/* Node Card */}

{nodeProfile?.name}

{nodeProfile?.status}

{nodeProfile?.hostname}

{/* Info Grid */}

Environment

{nodeProfile?.environment}

Node ID

{nodeProfile?.node_id}

Agents

{nodeProfile?.agents_total} total {nodeProfile?.agents_online} online
{nodeProfile?.last_heartbeat && (

Last Heartbeat

{new Date(nodeProfile.last_heartbeat).toLocaleString()}

)}
{/* Roles */} {nodeProfile?.roles && nodeProfile.roles.length > 0 && (

Roles

{nodeProfile.roles.map((role) => ( {role} ))}
)}
{/* Node Guardian & Steward Agents */}
{/* MicroDAO Presence */} {nodeProfile?.microdaos && nodeProfile.microdaos.length > 0 && (

MicroDAO Presence

    {nodeProfile.microdaos.map((dao) => (
  • {dao.name} {dao.rooms_count} rooms
  • ))}
)} {/* Notice for non-NODE1 */}

⚠️ Детальний моніторинг доступний тільки для НОДА1 (Production). Для цієї ноди показано базову інформацію з node_cache.

{/* Link to agents */} Агенти цієї ноди
{/* Floating Chat Widget */}
); }