refactor: Rename component pages to program pages and remove tools concept

The 'tools' concept was just a filtered view of programs and added unnecessary
complexity to the frontend. This commit:

- Removes ToolCard.tsx and Tools.tsx (pages/components never used in router)
- Renames ComponentDetail.tsx → ProgramDetail.tsx (exports ProgramDetailPage)
- Renames ComponentRedirect.tsx → ProgramRedirect.tsx (exports ProgramRedirect)
- Updates imports in routes.tsx to match new file names
- Fixes stale comment in hooks.ts

Frontend naming now aligns with the unified programs model.
This commit is contained in:
2026-04-27 21:10:31 -07:00
parent 2069e30353
commit 9fd2221e05
6 changed files with 7 additions and 97 deletions

View File

@@ -1,57 +0,0 @@
import { Link } from "react-router-dom"
import { Terminal } from "lucide-react"
import type { ProgramSummary } from "@/types"
import { runnerLabel } from "@/lib/labels"
interface ToolCardProps {
tool: ProgramSummary
}
export function ToolCard({ tool }: ToolCardProps) {
return (
<div className="bg-[var(--card)] border border-[var(--border)] rounded-lg p-5">
<div className="flex items-start justify-between mb-2">
<Link
to={`/component/${tool.id}`}
className="text-base font-semibold hover:text-[var(--primary)] transition-colors"
>
{tool.id}
</Link>
{tool.installed && (
<span className="text-xs px-2 py-0.5 rounded bg-green-900/30 text-green-400 border border-green-800">
installed
</span>
)}
</div>
{tool.description && (
<p className="text-sm text-[var(--muted)] mb-3">{tool.description}</p>
)}
<div className="flex items-center gap-3 text-xs text-[var(--muted)] mb-3">
{tool.runner && (
<span className="flex items-center gap-1">
<Terminal size={12} />
{runnerLabel(tool.runner)}
</span>
)}
{tool.version && (
<span className="font-mono">v{tool.version}</span>
)}
</div>
{tool.system_dependencies.length > 0 && (
<div className="flex flex-wrap gap-1">
{tool.system_dependencies.map((dep) => (
<span
key={dep}
className="text-xs px-2 py-0.5 rounded bg-amber-900/30 text-amber-400 border border-amber-800"
>
{dep}
</span>
))}
</div>
)}
</div>
)
}

View File

@@ -6,7 +6,7 @@ import { DetailHeader } from "@/components/detail/DetailHeader"
import { ConfigPanel } from "@/components/detail/ConfigPanel"
import { ProgramActions, ActionOutputPanel, type ActionOutput } from "@/components/ProgramActions"
export function ComponentDetailPage() {
export function ProgramDetailPage() {
useEventStream()
const { name } = useParams<{ name: string }>()
const { data: component, isLoading, error, refetch } = useProgram(name ?? "")

View File

@@ -1,7 +1,7 @@
import { useParams, Navigate } from "react-router-dom"
import { useComponent } from "@/services/api/hooks"
export function ComponentRedirect() {
export function ProgramRedirect() {
const { name } = useParams<{ name: string }>()
const { data: component, isLoading, error } = useComponent(name ?? "")

View File

@@ -1,33 +0,0 @@
import { Link } from "react-router-dom"
import { ArrowLeft } from "lucide-react"
import { usePrograms } from "@/services/api/hooks"
import { ToolCard } from "@/components/ToolCard"
export function ToolsPage() {
const { data: tools, isLoading } = usePrograms("tool")
return (
<div className="max-w-6xl mx-auto px-6 py-8">
<Link to="/" className="text-[var(--primary)] hover:underline flex items-center gap-1 mb-6">
<ArrowLeft size={16} /> Back
</Link>
<h1 className="text-3xl font-bold mb-2">Tools</h1>
<p className="text-sm text-[var(--muted)] mb-8">
CLI utilities installed to PATH via castle and run with uv.
</p>
{isLoading ? (
<p className="text-[var(--muted)]">Loading tools...</p>
) : tools?.length ? (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{tools.map((tool) => (
<ToolCard key={tool.id} tool={tool} />
))}
</div>
) : (
<p className="text-[var(--muted)]">No tools registered.</p>
)}
</div>
)
}

View File

@@ -2,8 +2,8 @@ import { createBrowserRouter } from "react-router-dom"
import { Dashboard } from "@/pages/Dashboard"
import { ServiceDetailPage } from "@/pages/ServiceDetail"
import { ScheduledDetailPage } from "@/pages/ScheduledDetail"
import { ComponentDetailPage } from "@/pages/ComponentDetail"
import { ComponentRedirect } from "@/pages/ComponentRedirect"
import { ProgramDetailPage } from "@/pages/ProgramDetail"
import { ProgramRedirect } from "@/pages/ProgramRedirect"
import { NodeDetailPage } from "@/pages/NodeDetail"
export const router = createBrowserRouter([
@@ -21,11 +21,11 @@ export const router = createBrowserRouter([
},
{
path: "/programs/:name",
element: <ComponentDetailPage />,
element: <ProgramDetailPage />,
},
{
path: "/component/:name",
element: <ComponentRedirect />,
element: <ProgramRedirect />,
},
{
path: "/node/:hostname",

View File

@@ -18,7 +18,7 @@ import type {
NodeDetail,
} from "@/types"
// Legacy compat hook — used by ConfigEditorPage and ComponentRedirect
// Legacy compat hook — used by ConfigEditorPage and ProgramRedirect
export function useComponent(name: string) {
return useQuery({
queryKey: ["components", name],