"use client"; import { useEffect, useState } from "react"; import { Plus, Loader2, MapPin } from "lucide-react"; import { HelpTrigger } from "@/components/help/HelpTrigger"; import { useAgentsData } from "./useAgentsData"; import { getAgentColumns } from "./columns"; import { getExternalAccountColumns } from "./externalColumns"; import UptimeStatsCards from "./UptimeStatsCards"; import AgentsTableSection from "./AgentsTableSection"; import ExternalAccountsSection from "./ExternalAccountsSection"; import AgentsPageModals from "./AgentsPageModals"; import AgentLocationMap from "@/components/admin/AgentLocationMap"; import { SubnetConfigModal } from "@/components/admin/SubnetConfigModal"; import { resolveAgentLabel } from "@/lib/admin-api"; export default function AgentsPage() { useEffect(() => { document.title = "Agents | BackOne - Deep Package Inspection"; }, []); const { role, agents, uptimeMap, storageMap, isLoading, error, isCreateOpen, setIsCreateOpen, isDeleteOpen, setIsDeleteOpen, detailAgent, setDetailAgent, managedUsers, accountModalOpen, setAccountModalOpen, accountModalAgent, setAccountModalAgent, externalModalOpen, setExternalModalOpen, externalModalUser, setExternalModalUser, targetSiteUuid, setTargetSiteUuid, targetCreatedBy, setTargetCreatedBy, locations, isLocModalOpen, setIsLocModalOpen, locModalAgentUuid, setLocModalAgentUuid, locModalAgentLabel, setLocModalAgentLabel, locModalCurrentLoc, setLocModalCurrentLoc, viewAsLoading, selectedAgent, loadAgents, loadLocations, handleViewAs, openDelete, handleEditLocation, } = useAgentsData(); const [subnetModalOpen, setSubnetModalOpen] = useState(false); const [subnetModalAgent, setSubnetModalAgent] = useState<{ uuid: string; label: string } | null>(null); const handleEditSubnet = (agentUuid: string, agentLabel: string) => { setSubnetModalAgent({ uuid: agentUuid, label: agentLabel }); setSubnetModalOpen(true); }; const columns = getAgentColumns({ role, uptimeMap, storageMap, managedUsers, viewAsLoading, setDetailAgent, setAccountModalOpen, setAccountModalAgent, handleViewAs, openDelete, handleEditLocation, handleEditSubnet, locationUuids: new Set(locations.map((l: any) => l.agent_uuid)), }); const externalColumns = getExternalAccountColumns((user) => { setExternalModalUser(user); setExternalModalOpen(true); }); const totalAgents = agents.length; const onlineAgents = agents.filter(a => { const hum = a.last_seen_at?.human; return hum === 'Online' || hum === 'Flows Detected' || (hum && hum.startsWith('Last seen:')); }).length; const offlineAgents = totalAgents - onlineAgents; const uptimeValues = agents.map(a => uptimeMap[a.uuid || a.serial] ?? 100); const avgUptime = uptimeValues.length > 0 ? uptimeValues.reduce((s, v) => s + v, 0) / uptimeValues.length : 100; // External Accounts di halaman Agents = akun eksternal teknikal/operasional saja // AGENT_VIEWER = akun network agent (sudah ada di tabel agents) → BUKAN akun eksternal // COMPANY_* = akun customer/client → sudah ada di halaman User Accounts const EXCLUDED_ROLES = ['COMPANY_ADMIN', 'COMPANY_OPERATOR', 'COMPANY_VIEWER', 'AGENT_VIEWER']; const externalUsers = managedUsers.filter(u => !EXCLUDED_ROLES.includes(u.role || '')); // Grouping by site — semua sudah dipastikan hanya SUPER_ADMIN, EXECUTIVE, TENANT_ADMIN, SOC_ANALYST, ENGINEER const superadminUsers = externalUsers.filter(u => u.role === 'SUPER_ADMIN' || u.role === 'EXECUTIVE' || !u.site_uuid || u.site_uuid === 'default'); const siabUsers = externalUsers.filter(u => u.site_uuid === '6681452d_9cae_4ff4_8ae8_0d504774265e' && u.role !== 'SUPER_ADMIN' && u.role !== 'EXECUTIVE'); const nexusUsers = externalUsers.filter(u => u.site_uuid === '1959bb55_045b_47c7_bbdd_f33b7db197b9' && u.role !== 'SUPER_ADMIN' && u.role !== 'EXECUTIVE'); return (

Agents Inventory {isLoading && }

{/* Mobile Actions: Inline next to Title */}

Managed DPI probes, remote collectors, and probe infrastructure.

{/* Laptop/Tablet Actions: Floats on the right */}
{error && (
{error}
)} {/* Agent Location Map — tampil untuk SUPER_ADMIN, TENANT_ADMIN, dan COMPANY_ADMIN */} {(role === 'SUPER_ADMIN' || role === 'TENANT_ADMIN' || role === 'COMPANY_ADMIN') && (
Agent Network Map {locations.length > 0 ? `${locations.length} of ${agents.length} agent${agents.length !== 1 ? 's' : ''} positioned` : 'No positions configured yet'}
{agents.length > locations.length && ( {agents.length - locations.length} agent{agents.length - locations.length !== 1 ? 's' : ''} without location — click 📍 in the table )}
agents.some(a => (a.uuid || a.serial) === loc.agent_uuid)) .map(loc => { const agent = agents.find(a => (a.uuid || a.serial) === loc.agent_uuid); const agentLabel = agent ? (resolveAgentLabel(loc.agent_uuid, managedUsers) !== loc.agent_uuid ? resolveAgentLabel(loc.agent_uuid, managedUsers) : (agent.label || loc.label || loc.agent_uuid)) : (loc.label || loc.agent_uuid); const isOnline = !!(agent?.last_seen_at?.human === 'Online' || agent?.last_seen_at?.human === 'Flows Detected' || (agent?.last_seen_at?.human && agent.last_seen_at.human.startsWith('Last seen:'))); const uptime = uptimeMap[loc.agent_uuid]; return { agent_uuid: loc.agent_uuid, label: agentLabel, latitude: loc.latitude, longitude: loc.longitude, isOnline, uptimePercent: uptime, }; })} onEditLocation={handleEditLocation} canEdit={role === 'SUPER_ADMIN' || role === 'TENANT_ADMIN'} />
)} setIsCreateOpen(true)} /> {(role === 'SUPER_ADMIN' || role === 'TENANT_ADMIN') && ( )} setSubnetModalOpen(false)} />
); }