Spaces:
Sleeping
Sleeping
David Prince
fix: add all missing local module stubs (remote_mcp_registry, mcp_auth, mcp_transport, etc)
cce8120 | 'use client'; | |
| import React, { useState, useEffect } from 'react'; | |
| import FileExplorer from './explorer/FileExplorer'; | |
| import AIChatPanel from './chat/AIChatPanel'; | |
| import CodeEditor from './editor/CodeEditor'; | |
| import TerminalPanel from './terminal/TerminalPanel'; | |
| import AgentMonitor from './dashboards/AgentMonitor'; | |
| import { api } from '../services/api'; | |
| export default function WorkspaceLayout() { | |
| const [activeFile, setActiveFile] = useState(''); | |
| const [fileContent, setFileContent] = useState(''); | |
| const [sessionId, setSessionId] = useState(null); | |
| const [activeTab, setActiveTab] = useState('editor'); // 'editor' | 'preview' | 'monitor' | |
| const [showTerminal, setShowTerminal] = useState(true); | |
| useEffect(() => { | |
| api.createSession('.') | |
| .then((data) => setSessionId(data.session_id)) | |
| .catch((err) => console.error('Failed to initialize workspace session:', err)); | |
| }, []); | |
| const handleSelectFile = async (filepath) => { | |
| setActiveFile(filepath); | |
| try { | |
| const content = await api.getFileContent(filepath); | |
| setFileContent(content); | |
| } catch (err) { | |
| setFileContent(`// Error reading file: ${filepath}`); | |
| } | |
| }; | |
| const handleSaveFile = async () => { | |
| if (!activeFile) return; | |
| try { | |
| await api.saveFile(activeFile, fileContent); | |
| alert(`Successfully saved ${activeFile}`); | |
| } catch (err) { | |
| alert(`Failed to save ${activeFile}`); | |
| } | |
| }; | |
| return ( | |
| <div className="flex h-screen bg-slate-950 font-sans text-white overflow-hidden select-none"> | |
| {/* 1. File Explorer Sidebar */} | |
| <FileExplorer onSelectFile={handleSelectFile} activeFile={activeFile} /> | |
| {/* 2. Main Workstation Center Area */} | |
| <div className="flex-1 flex flex-col h-full border-r border-slate-800"> | |
| {/* Workspace Top Navigation Bar */} | |
| <div className="h-10 bg-slate-900 border-b border-slate-800 flex items-center justify-between px-4"> | |
| <div className="flex gap-1 text-xs"> | |
| <button | |
| onClick={() => setActiveTab('editor')} | |
| className={`px-3 py-1 rounded transition-colors ${ | |
| activeTab === 'editor' ? 'bg-slate-800 text-blue-400 font-semibold' : 'text-slate-400 hover:text-white' | |
| }`} | |
| > | |
| 💻 Editor {activeFile && `(${activeFile.split('/').pop()})`} | |
| </button> | |
| <button | |
| onClick={() => setActiveTab('preview')} | |
| className={`px-3 py-1 rounded transition-colors ${ | |
| activeTab === 'preview' ? 'bg-slate-800 text-blue-400 font-semibold' : 'text-slate-400 hover:text-white' | |
| }`} | |
| > | |
| 👁️ Device Preview | |
| </button> | |
| <button | |
| onClick={() => setActiveTab('monitor')} | |
| className={`px-3 py-1 rounded transition-colors ${ | |
| activeTab === 'monitor' ? 'bg-slate-800 text-blue-400 font-semibold' : 'text-slate-400 hover:text-white' | |
| }`} | |
| > | |
| 🚀 Build Center | |
| </button> | |
| </div> | |
| <div className="flex items-center gap-2"> | |
| <button | |
| onClick={() => setShowTerminal(!showTerminal)} | |
| className="text-xs px-2.5 py-1 bg-slate-800 hover:bg-slate-700 text-slate-300 rounded transition-colors" | |
| > | |
| {showTerminal ? 'Terminal ▼' : 'Terminal ▲'} | |
| </button> | |
| {activeFile && ( | |
| <button | |
| onClick={handleSaveFile} | |
| className="bg-blue-600 hover:bg-blue-500 text-white text-xs px-3 py-1 rounded font-medium transition-colors" | |
| > | |
| Save | |
| </button> | |
| )} | |
| </div> | |
| </div> | |
| {/* Viewport Content Panel */} | |
| <div className="flex-1 overflow-hidden p-2 bg-slate-950"> | |
| {activeTab === 'editor' && ( | |
| <CodeEditor | |
| filename={activeFile} | |
| value={fileContent} | |
| onChange={setFileContent} | |
| onSave={handleSaveFile} | |
| /> | |
| )} | |
| {activeTab === 'preview' && ( | |
| <div className="w-full h-full bg-white rounded-lg overflow-hidden border border-slate-800"> | |
| <iframe title="preview-viewport" src="http://localhost:8000/docs" className="w-full h-full border-none" /> | |
| </div> | |
| )} | |
| {activeTab === 'monitor' && <AgentMonitor />} | |
| </div> | |
| {/* Bottom Terminal Drawer */} | |
| {showTerminal && <TerminalPanel />} | |
| </div> | |
| {/* 3. AI Assistant Right Drawer */} | |
| <AIChatPanel sessionId={sessionId} /> | |
| </div> | |
| ); | |
| } | |