/** Workspace detail page — primary work surface. */ import { useState } from "react"; import { useParams } from "react-router-dom"; import { Icon } from "../components/icon"; import { useWorkspaces } from "../hooks/use-workspaces"; import { useWorkspaceFiles } from "../hooks/use-workspace-files"; import { useWorkspaceGit } from "../hooks/use-workspace-git"; import { useWorkspaceInstances } from "../hooks/use-workspace-instances"; import { useMobileViewport } from "../hooks/use-mobile-viewport"; import { ToolStarter } from "../components/tool-starter"; import type { FileEntry } from "../api/workspace-files"; import type { Workspace } from "../types/workspace"; type Tab = "files" | "git" | "tools" | "settings"; export function WorkspaceDetailPage() { const { workspaceId } = useParams<{ workspaceId: string }>(); const [activeTab, setActiveTab] = useState("files"); const isMobile = useMobileViewport(); const { workspaces, loading: wsLoading } = useWorkspaces(); const workspace = workspaces.find((w) => w.id === workspaceId); if (wsLoading) { return
Loading workspace...
; } if (!workspace) { return (

Workspace not found

The workspace you are looking for does not exist.

); } return (
{activeTab === "files" && } {activeTab === "git" && } {activeTab === "tools" && } {activeTab === "settings" && }
{isMobile && }
); } function WorkspaceHeader({ workspace, }: { workspace: { name: string; repo_name: string; project_name: string; branch: string; }; }) { return (
{workspace.project_name} / {workspace.repo_name} / {workspace.name}
{workspace.branch}
); } function TabBar({ active, onChange, }: { active: Tab; onChange: (t: Tab) => void; }) { const tabs: { id: Tab; label: string; icon: string }[] = [ { id: "files", label: "Files", icon: "folder" }, { id: "git", label: "Git", icon: "branch" }, { id: "tools", label: "Tools", icon: "terminal" }, { id: "settings", label: "Settings", icon: "settings" }, ]; return ( ); } function MobileTabBar({ active, onChange, }: { active: Tab; onChange: (t: Tab) => void; }) { const tabs: { id: Tab; label: string; icon: string }[] = [ { id: "files", label: "Files", icon: "folder" }, { id: "git", label: "Git", icon: "branch" }, { id: "tools", label: "Tools", icon: "terminal" }, { id: "settings", label: "Settings", icon: "settings" }, ]; return ( ); } /* ─── Files Tab ─── */ function FilesTab({ workspaceId }: { workspaceId: string }) { const { entries, content, loadFile, saveFile, loading, error } = useWorkspaceFiles(workspaceId); const { status, commit, push, pull, fetch } = useWorkspaceGit(workspaceId); const [selectedPath, setSelectedPath] = useState(null); const [editContent, setEditContent] = useState(null); const [isEditing, setIsEditing] = useState(false); const [commitMessage, setCommitMessage] = useState(""); const handleSelect = (entry: FileEntry) => { if (entry.type === "directory") return; setSelectedPath(entry.path); setIsEditing(false); setEditContent(null); loadFile(entry.path); }; const handleEdit = () => { if (content !== null) { setEditContent(content); setIsEditing(true); } }; const handleSave = async () => { if (selectedPath && editContent !== null) { await saveFile(selectedPath, editContent, commitMessage || undefined); setIsEditing(false); setCommitMessage(""); } }; return (
{status && (
{status.modified.length > 0 && ( M {status.modified.length} )} {status.added.length > 0 && ( A {status.added.length} )} {status.deleted.length > 0 && ( D {status.deleted.length} )} {status.untracked.length > 0 && ( ? {status.untracked.length} )}
setCommitMessage(e.target.value)} placeholder="Commit message" />
)}
{loading &&

Loading...

} {error &&

{error}

} {entries.map((entry) => ( ))}
{selectedPath ? ( <>
{selectedPath} {!isEditing && }
{isEditing ? ( <>