// src/pages/agent-office/AgentOffice.jsx import { useState, useEffect, useCallback } from 'react'; import { useAgentManager } from './hooks/useAgentManager.js'; import { useOfficeCanvas } from './hooks/useOfficeCanvas.js'; import TopBar from './components/TopBar.jsx'; import SidePanel from './components/SidePanel.jsx'; import './AgentOffice.css'; export default function AgentOffice() { const { agents, pendingTasks, notifications, connected, refreshTrigger, clearNotifications } = useAgentManager(); const { canvasRef, updateAgentState, setAgentNotification, setTheme, setZoom, hitTest, getZoom, wasDragging } = useOfficeCanvas(); const [selectedAgent, setSelectedAgent] = useState(null); const [theme, setThemeState] = useState(localStorage.getItem('agent-office-theme') || 'modern'); const [zoom, setZoomState] = useState(2); // WebSocket 상태 → 캔버스 동기화 useEffect(() => { for (const [id, agentState] of Object.entries(agents)) { updateAgentState(id, agentState.state, agentState.detail); } }, [agents, updateAgentState]); // 알림 → 캔버스 동기화 useEffect(() => { for (const [id, count] of Object.entries(notifications)) { setAgentNotification(id, count); } }, [notifications, setAgentNotification]); // 캔버스 클릭 핸들러 const handleCanvasClick = useCallback((e) => { if (wasDragging()) return; // 드래그 후 발생하는 클릭 무시 const result = hitTest(e.clientX, e.clientY); if (result.type === 'agent') { setSelectedAgent(result.id); clearNotifications(result.id); setAgentNotification(result.id, 0); } else { setSelectedAgent(null); } }, [hitTest, clearNotifications, setAgentNotification, wasDragging]); // 테마 변경 const handleThemeChange = useCallback((name) => { setThemeState(name); setTheme(name); }, [setTheme]); // 줌 변경 const handleZoomChange = useCallback((level) => { setZoomState(level); setZoom(level); }, [setZoom]); // 선택된 에이전트의 pending task const pendingTask = selectedAgent ? pendingTasks.find(t => t.agent_id === selectedAgent) : null; return (