f721d87423
- Skills: categorized list with search, detail view with markdown - Cron: job list grouped by status, manual trigger button - Soul: full SOUL.md editor with save/revert - Pulse: quick link cards to Skills, Cron, Soul - All routes proxied server-side (no CORS)
66 lines
2.3 KiB
TypeScript
66 lines
2.3 KiB
TypeScript
"use client";
|
|
|
|
import { use } from "react";
|
|
import { ArrowLeft, FileText, Folder } from "lucide-react";
|
|
import Link from "next/link";
|
|
import { useSkill } from "@/lib/hooks";
|
|
|
|
export default function SkillDetailPage({ params }: { params: Promise<{ name: string }> }) {
|
|
const { name } = use(params);
|
|
const { data, isLoading } = useSkill(name);
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
<div className="flex items-center gap-3">
|
|
<Link href="/skills" className="p-1.5 -ml-1.5 rounded-lg active:bg-white/[0.06]">
|
|
<ArrowLeft size={20} className="text-zinc-400" />
|
|
</Link>
|
|
<h1 className="text-base font-semibold text-zinc-200">{name}</h1>
|
|
</div>
|
|
|
|
{isLoading ? (
|
|
<div className="glass p-4 animate-pulse space-y-2">
|
|
<div className="h-4 bg-white/[0.06] rounded w-full" />
|
|
<div className="h-4 bg-white/[0.06] rounded w-3/4" />
|
|
<div className="h-4 bg-white/[0.06] rounded w-1/2" />
|
|
</div>
|
|
) : data ? (
|
|
<>
|
|
{/* Linked files */}
|
|
{data.linked_files && Object.keys(data.linked_files).length > 0 && (
|
|
<div className="glass p-3">
|
|
<div className="text-xs font-medium text-zinc-400 mb-2 flex items-center gap-1.5">
|
|
<Folder size={12} /> Linked Files
|
|
</div>
|
|
<div className="space-y-1">
|
|
{Object.entries(data.linked_files).map(([dir, files]) =>
|
|
(files as string[]).map((f) => (
|
|
<div
|
|
key={`${dir}/${f}`}
|
|
className="flex items-center gap-2 text-xs text-zinc-500 py-0.5"
|
|
>
|
|
<FileText size={11} />
|
|
<span className="font-mono">{dir}/{f}</span>
|
|
</div>
|
|
))
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Skill content */}
|
|
<div className="glass p-4">
|
|
<pre className="text-sm text-zinc-300 whitespace-pre-wrap leading-relaxed font-sans overflow-x-auto">
|
|
{data.content}
|
|
</pre>
|
|
</div>
|
|
</>
|
|
) : (
|
|
<div className="glass p-6 text-center text-sm text-zinc-500">
|
|
Skill not found
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|