feat: workspace frontend core (PR-3)
- Workspace types, API client, hooks (useWorkspaces, useWorkspaceActions) - WorkspaceCard, WorkspaceCreateForm, StartToolModal components - WorkspacesPage with list, create, sync, delete, start-tool flow - Sidebar navigation: new 'Workspaces' entry - Router: /workspaces route - TypeScript + eslint clean
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
/** Card component for displaying a workspace. */
|
||||
|
||||
import { Icon } from "./icon";
|
||||
import type { Workspace } from "../types/workspace";
|
||||
|
||||
export interface WorkspaceCardProps {
|
||||
workspace: Workspace;
|
||||
loading?: boolean;
|
||||
onStartTool: (workspace: Workspace) => void;
|
||||
onSync: (workspace: Workspace) => void;
|
||||
onDelete: (workspace: Workspace) => void;
|
||||
}
|
||||
|
||||
export function WorkspaceCard({
|
||||
workspace,
|
||||
loading = false,
|
||||
onStartTool,
|
||||
onSync,
|
||||
onDelete,
|
||||
}: WorkspaceCardProps) {
|
||||
const statusClass =
|
||||
workspace.status === "ready"
|
||||
? "status-ready"
|
||||
: workspace.status === "syncing"
|
||||
? "status-syncing"
|
||||
: "status-error";
|
||||
|
||||
return (
|
||||
<article className={`card workspace-card ${loading ? "loading" : ""}`}>
|
||||
<div className="workspace-header">
|
||||
<h4>{workspace.name}</h4>
|
||||
<span className={`status-badge ${statusClass}`}>{workspace.status}</span>
|
||||
</div>
|
||||
<div className="workspace-meta">
|
||||
<p className="workspace-project">
|
||||
{workspace.project_name} / {workspace.repo_name}
|
||||
</p>
|
||||
<p className="workspace-branch">
|
||||
<Icon name="branch" size="sm" /> {workspace.branch}
|
||||
</p>
|
||||
{workspace.instance_count > 0 && (
|
||||
<p className="workspace-instances">
|
||||
{workspace.instance_count} active tool
|
||||
{workspace.instance_count > 1 ? "s" : ""}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="workspace-actions">
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
onClick={() => onStartTool(workspace)}
|
||||
disabled={loading}
|
||||
>
|
||||
<Icon name="play" size="sm" /> Start Tool
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-secondary"
|
||||
onClick={() => onSync(workspace)}
|
||||
disabled={loading}
|
||||
>
|
||||
<Icon name="refresh" size="sm" /> Sync
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-danger"
|
||||
onClick={() => onDelete(workspace)}
|
||||
disabled={loading}
|
||||
>
|
||||
<Icon name="delete" size="sm" /> Delete
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user