Spaces:
Paused
Paused
| import React, { useState, useEffect } from 'react'; | |
| import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels'; | |
| import ChatPanel from './components/ChatPanel'; | |
| import AgentPanel from './components/AgentPanel'; | |
| import CodeEditor from './components/CodeEditor'; | |
| import TerminalTabs from './components/TerminalTabs'; | |
| import FileTree from './components/FileTree'; | |
| import ModelSelector from './components/ModelSelector'; | |
| import TopBar from './components/TopBar'; | |
| import StatusBar from './components/StatusBar'; | |
| import GitPanel from './components/GitPanel'; | |
| import BackgroundTasks from './components/BackgroundTasks'; | |
| import { FaComments, FaRobot, FaTerminal, FaCodeBranch, FaTasks } from 'react-icons/fa'; | |
| const App: React.FC = () => { | |
| const [activeBottom, setActiveBottom] = useState('chat'); | |
| const [projectPath] = useState('/app/sandbox'); | |
| const [activeFile, setActiveFile] = useState<string | null>(null); | |
| const [selectedModel, setSelectedModel] = useState('groq-llama-3.3-70b-versatile'); | |
| const [sidebarVisible, setSidebarVisible] = useState(true); | |
| useEffect(() => { | |
| const handleKeyDown = (e: KeyboardEvent) => { | |
| const mod = e.ctrlKey || e.metaKey; | |
| if (mod && e.key === 'b') { e.preventDefault(); setSidebarVisible(prev => !prev); } | |
| else if (mod && e.key === '1') { e.preventDefault(); setActiveBottom('chat'); } | |
| else if (mod && e.key === '2') { e.preventDefault(); setActiveBottom('agent'); } | |
| else if (mod && e.key === '3') { e.preventDefault(); setActiveBottom('terminal'); } | |
| else if (mod && e.key === '4') { e.preventDefault(); setActiveBottom('git'); } | |
| else if (mod && e.key === '5') { e.preventDefault(); setActiveBottom('tasks'); } | |
| }; | |
| window.addEventListener('keydown', handleKeyDown); | |
| return () => window.removeEventListener('keydown', handleKeyDown); | |
| }, []); | |
| return ( | |
| <div style={{ display: 'flex', flexDirection: 'column', height: '100vh', background: 'var(--bg-primary)' }}> | |
| <TopBar /> | |
| <div style={{ display: 'flex', flex: 1, overflow: 'hidden' }}> | |
| {sidebarVisible && ( | |
| <div style={{ width: 280, background: 'var(--bg-secondary)', borderRight: '1px solid var(--border)', display: 'flex', flexDirection: 'column' }}> | |
| <div style={{ padding: '8px 12px', borderBottom: '1px solid var(--border)', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}> | |
| <span style={{ fontWeight: 600, fontSize: 13 }}>EXPLORER</span> | |
| <span onClick={() => setSidebarVisible(false)} style={{ cursor: 'pointer', color: 'var(--text-secondary)' }}>×</span> | |
| </div> | |
| <ModelSelector selectedModel={selectedModel} onModelChange={setSelectedModel} /> | |
| <FileTree projectPath={projectPath} onFileSelect={setActiveFile} /> | |
| </div> | |
| )} | |
| {!sidebarVisible && ( | |
| <div style={{ width: 40, background: 'var(--bg-secondary)', borderRight: '1px solid var(--border)', display: 'flex', alignItems: 'flex-start', paddingTop: 10, justifyContent: 'center' }}> | |
| <span onClick={() => setSidebarVisible(true)} style={{ cursor: 'pointer', color: 'var(--text-secondary)' }}>☰</span> | |
| </div> | |
| )} | |
| <PanelGroup direction="vertical" style={{ flex: 1 }}> | |
| <Panel defaultSize={65} minSize={20}> | |
| <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}> | |
| <div style={{ display: 'flex', background: 'var(--bg-tertiary)', borderBottom: '1px solid var(--border)', padding: '0 8px', overflowX: 'auto' }}> | |
| {activeFile ? ( | |
| <div style={{ padding: '8px 12px', borderBottom: '2px solid var(--accent)', color: 'var(--accent)', fontSize: 13 }}>📄 {activeFile}</div> | |
| ) : ( | |
| <div style={{ padding: '8px 12px', color: 'var(--text-secondary)', fontSize: 13 }}>No file selected</div> | |
| )} | |
| </div> | |
| <CodeEditor filePath={activeFile} projectPath={projectPath} /> | |
| </div> | |
| </Panel> | |
| <PanelResizeHandle style={{ height: 4, background: 'var(--border)' }} /> | |
| <Panel defaultSize={35} minSize={15}> | |
| <div style={{ height: '100%', display: 'flex', flexDirection: 'column', background: 'var(--bg-primary)' }}> | |
| <div style={{ display: 'flex', background: 'var(--bg-tertiary)', borderBottom: '1px solid var(--border)', padding: '0 8px' }}> | |
| <button onClick={() => setActiveBottom('chat')} style={{ padding: '8px 16px', background: activeBottom === 'chat' ? 'var(--bg-primary)' : 'transparent', borderBottom: activeBottom === 'chat' ? '2px solid var(--accent)' : 'none', color: activeBottom === 'chat' ? 'var(--accent)' : 'var(--text-secondary)' }}><FaComments /> Chat (Ctrl+1)</button> | |
| <button onClick={() => setActiveBottom('agent')} style={{ padding: '8px 16px', background: activeBottom === 'agent' ? 'var(--bg-primary)' : 'transparent', borderBottom: activeBottom === 'agent' ? '2px solid var(--accent)' : 'none', color: activeBottom === 'agent' ? 'var(--accent)' : 'var(--text-secondary)' }}><FaRobot /> Agent (Ctrl+2)</button> | |
| <button onClick={() => setActiveBottom('terminal')} style={{ padding: '8px 16px', background: activeBottom === 'terminal' ? 'var(--bg-primary)' : 'transparent', borderBottom: activeBottom === 'terminal' ? '2px solid var(--accent)' : 'none', color: activeBottom === 'terminal' ? 'var(--accent)' : 'var(--text-secondary)' }}><FaTerminal /> Terminal (Ctrl+3)</button> | |
| <button onClick={() => setActiveBottom('git')} style={{ padding: '8px 16px', background: activeBottom === 'git' ? 'var(--bg-primary)' : 'transparent', borderBottom: activeBottom === 'git' ? '2px solid var(--accent)' : 'none', color: activeBottom === 'git' ? 'var(--accent)' : 'var(--text-secondary)' }}><FaCodeBranch /> Git (Ctrl+4)</button> | |
| <button onClick={() => setActiveBottom('tasks')} style={{ padding: '8px 16px', background: activeBottom === 'tasks' ? 'var(--bg-primary)' : 'transparent', borderBottom: activeBottom === 'tasks' ? '2px solid var(--accent)' : 'none', color: activeBottom === 'tasks' ? 'var(--accent)' : 'var(--text-secondary)' }}><FaTasks /> Tasks (Ctrl+5)</button> | |
| </div> | |
| <div style={{ flex: 1, overflow: 'hidden' }}> | |
| {activeBottom === 'chat' && <ChatPanel projectPath={projectPath} model={selectedModel} />} | |
| {activeBottom === 'agent' && <AgentPanel projectPath={projectPath} />} | |
| {activeBottom === 'terminal' && <TerminalTabs />} | |
| {activeBottom === 'git' && <GitPanel projectPath={projectPath} />} | |
| {activeBottom === 'tasks' && <BackgroundTasks />} | |
| </div> | |
| </div> | |
| </Panel> | |
| </PanelGroup> | |
| </div> | |
| <StatusBar model={selectedModel} /> | |
| </div> | |
| ); | |
| }; | |
| export default App; |