1021d61be3
Moved 43 component files into 9 feature domains: - features/git/ — commit-dialog, commit-panel, file-editor, git-mount-editor, git-toolbar, merge-dialog - features/project/ — repositories-settings-tab, repository-create-dialog - features/terminal/ — special-keys-panel, special-keys-strip, terminal-session-tabs, terminal - features/workspace/ — workspace-card, workspace-create-form, workspace-header, workspace-instance-chips - features/session/ — create-session-form, session-card, session-list - features/tool/ — instance-list, manifest-editor, start-tool-fab, start-tool-modal, tool-starter, tools-bottom-sheet - features/notification/ — event-toast-bridge, notification-center, notification-item - features/settings/ — settings-tab-layout - features/mobile/ — mobile-action-sheet, mobile-detail-view, mobile-edit-view, mobile-fab, mobile-list-view, mobile-nav, mobile-page-header, mobile-terminal-header, mobile-terminal-wrapper Updated all imports across pages and components. Root components/ now only contains generic UI pieces: app-shell, code-editor, data-states, icon, protected-route, syntax-highlighter. Quality gates: verified no remaining old imports.
109 lines
2.9 KiB
TypeScript
109 lines
2.9 KiB
TypeScript
/** Workspaces list page. */
|
|
|
|
import { useState } from "react";
|
|
import { Icon } from "../components/icon";
|
|
import { useWorkspaces } from "../hooks/use-workspaces";
|
|
import { useWorkspaceActions } from "../hooks/use-workspace-actions";
|
|
import { WorkspaceCard } from "../components/features/workspace/workspace-card";
|
|
import { WorkspaceCreateForm } from "../components/features/workspace/workspace-create-form";
|
|
import { ToolStarter } from "../components/features/tool/tool-starter";
|
|
import type { Workspace } from "../types/workspace";
|
|
|
|
export function WorkspacesPage() {
|
|
const [showCreate, setShowCreate] = useState(false);
|
|
const [startWorkspace, setStartWorkspace] = useState<Workspace | null>(null);
|
|
|
|
const { workspaces, loading, error, refresh } = useWorkspaces();
|
|
const actions = useWorkspaceActions();
|
|
const handleDelete = async (workspace: Workspace) => {
|
|
await actions.delete(workspace, refresh);
|
|
};
|
|
|
|
const handleSync = async (workspace: Workspace) => {
|
|
await actions.sync(
|
|
workspace.project_id,
|
|
workspace.repo_id,
|
|
workspace,
|
|
refresh,
|
|
);
|
|
};
|
|
|
|
return (
|
|
<div className="page workspaces-page">
|
|
<header className="page-header">
|
|
<h1>Workspaces</h1>
|
|
<div className="header-actions">
|
|
<button
|
|
className="btn btn-secondary"
|
|
onClick={refresh}
|
|
disabled={loading}
|
|
>
|
|
<Icon name="refresh" size="sm" />
|
|
</button>
|
|
<button
|
|
className="btn btn-primary"
|
|
onClick={() => setShowCreate(true)}
|
|
>
|
|
<Icon name="add" size="sm" /> New Workspace
|
|
</button>
|
|
</div>
|
|
</header>
|
|
|
|
{error && <div className="alert alert-error">{error}</div>}
|
|
|
|
{showCreate && (
|
|
<WorkspaceCreateForm
|
|
onSubmit={async () => {
|
|
setShowCreate(false);
|
|
await refresh();
|
|
}}
|
|
onCancel={() => setShowCreate(false)}
|
|
/>
|
|
)}
|
|
|
|
{loading && workspaces.length === 0 ? (
|
|
<div className="loading-state">Loading workspaces...</div>
|
|
) : workspaces.length === 0 ? (
|
|
<div className="empty-state">
|
|
<p>No workspaces yet.</p>
|
|
<button
|
|
className="btn btn-primary"
|
|
onClick={() => setShowCreate(true)}
|
|
>
|
|
<Icon name="add" size="sm" /> Create your first workspace
|
|
</button>
|
|
</div>
|
|
) : (
|
|
<div className="workspaces-grid">
|
|
{workspaces.map((ws) => (
|
|
<WorkspaceCard
|
|
key={ws.id}
|
|
workspace={ws}
|
|
loading={actions.loadingId === ws.id}
|
|
onStartTool={setStartWorkspace}
|
|
onSync={handleSync}
|
|
onDelete={handleDelete}
|
|
/>
|
|
))}
|
|
</div>
|
|
)}
|
|
|
|
{startWorkspace && (
|
|
<div className="modal-overlay" onClick={() => setStartWorkspace(null)}>
|
|
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
|
|
<h3>Start Tool</h3>
|
|
<ToolStarter
|
|
workspace={startWorkspace}
|
|
onStarted={() => {
|
|
setStartWorkspace(null);
|
|
void refresh();
|
|
}}
|
|
onCancel={() => setStartWorkspace(null)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|