harryagasi
feat: implement dual-backend analysis workspace UX
30cd0c9
Raw
History Blame Contribute Delete
2.97 kB
import { Plus, Trash2 } from "lucide-react";
import type { Analysis } from "@/services/orchestrationApi";
import { EmptyState, LoadingState } from "./AnalysisStates";
import { cx, formatDateTime } from "./utils";
interface AnalysisSidebarProps {
analyses: Analysis[];
activeId?: string;
loading: boolean;
onNew: () => void;
onSelect: (analysis: Analysis) => void;
onDelete: (analysis: Analysis) => void;
}
export function AnalysisSidebar({ analyses, activeId, loading, onNew, onSelect, onDelete }: AnalysisSidebarProps) {
return (
<aside className="flex h-full w-full flex-col border-r border-slate-200 bg-white lg:w-72">
<div className="border-b border-slate-200 p-4">
<button
type="button"
aria-label="Create new analysis"
onClick={onNew}
className="flex w-full items-center justify-center gap-2 rounded-md bg-emerald-600 px-3 py-2 text-sm font-medium text-white hover:bg-emerald-700"
>
<Plus className="h-4 w-4" />
New Analysis
</button>
</div>
<div className="min-h-0 flex-1 overflow-y-auto p-3">
{loading ? (
<LoadingState label="Loading analyses" />
) : analyses.length === 0 ? (
<EmptyState title="No analyses yet" description="Create one after your knowledge sources are ready." />
) : (
<div className="space-y-2">
{analyses.map((analysis) => (
<button
key={analysis.id}
type="button"
onClick={() => onSelect(analysis)}
className={cx(
"group flex w-full flex-col rounded-lg border p-3 text-left transition",
activeId === analysis.id ? "border-emerald-200 bg-emerald-50" : "border-slate-200 bg-white hover:bg-slate-50"
)}
>
<span className="flex items-start justify-between gap-2">
<span className="min-w-0 flex-1 truncate text-sm font-medium text-slate-900">{analysis.analysis_title}</span>
<span
role="button"
tabIndex={0}
aria-label="Delete analysis"
onClick={(event) => {
event.stopPropagation();
onDelete(analysis);
}}
className="rounded p-1 text-slate-400 opacity-0 hover:bg-red-50 hover:text-red-600 group-hover:opacity-100"
>
<Trash2 className="h-3.5 w-3.5" />
</span>
</span>
<span className="mt-1 line-clamp-2 text-xs leading-5 text-slate-500">{analysis.objective}</span>
<span className="mt-2 text-[11px] text-slate-400">{formatDateTime(analysis.updated_at || analysis.created_at)}</span>
</button>
))}
</div>
)}
</div>
</aside>
);
}