import { useRef } from "react";
import { useNavigate } from "react-router";
import type { FileSummary, BodyElement, ContractPhase } from "../../lib/api";
import { markdownToBody } from "../../lib/markdown";
interface FileListProps {
files: FileSummary[];
loading: boolean;
onSelect: (id: string) => void;
onDelete: (id: string) => void;
onCreate: () => void;
onUploadMarkdown?: (name: string, body: BodyElement[]) => void;
}
function formatDuration(seconds: number | null): string {
if (seconds === null) return "-";
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}:${secs.toString().padStart(2, "0")}`;
}
function formatDate(dateStr: string): string {
const date = new Date(dateStr);
return date.toLocaleDateString("en-US", {
month: "short",
day: "numeric",
year: "numeric",
hour: "2-digit",
minute: "2-digit",
});
}
const phaseColors: Record<ContractPhase, string> = {
research: "bg-purple-500/20 text-purple-400 border-purple-400/30",
specify: "bg-blue-500/20 text-blue-400 border-blue-400/30",
plan: "bg-cyan-500/20 text-cyan-400 border-cyan-400/30",
execute: "bg-green-500/20 text-green-400 border-green-400/30",
review: "bg-yellow-500/20 text-yellow-400 border-yellow-400/30",
};
export function FileList({
files,
loading,
onSelect,
onDelete,
onCreate,
onUploadMarkdown,
}: FileListProps) {
const navigate = useNavigate();
const fileInputRef = useRef<HTMLInputElement>(null);
const handleFileUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (!file || !onUploadMarkdown) return;
const reader = new FileReader();
reader.onload = (e) => {
const content = e.target?.result as string;
if (content) {
const body = markdownToBody(content);
// Use filename without extension as the name
const name = file.name.replace(/\.md$/i, '') || 'Imported Document';
onUploadMarkdown(name, body);
}
};
reader.readAsText(file);
// Reset input so the same file can be uploaded again
if (fileInputRef.current) {
fileInputRef.current.value = '';
}
};
if (loading) {
return (
<div className="panel h-full flex items-center justify-center">
<div className="font-mono text-[#9bc3ff] text-sm">Loading files...</div>
</div>
);
}
return (
<div className="panel h-full flex flex-col">
<div className="flex items-center justify-between p-4 pb-2 border-b border-dashed border-[rgba(117,170,252,0.35)]">
<div className="font-mono text-xs text-[#9bc3ff] tracking-wide uppercase">
FILES//
</div>
<div className="flex items-center gap-2">
{onUploadMarkdown && (
<>
<input
ref={fileInputRef}
type="file"
accept=".md,.markdown,text/markdown"
onChange={handleFileUpload}
className="hidden"
/>
<button
onClick={() => fileInputRef.current?.click()}
className="px-3 py-1 font-mono text-xs text-[#9bc3ff] border border-[rgba(117,170,252,0.25)] hover:border-[#3f6fb3] hover:bg-[rgba(117,170,252,0.05)] transition-colors uppercase"
>
Upload .md
</button>
</>
)}
<button
onClick={onCreate}
className="px-3 py-1 font-mono text-xs text-[#9bc3ff] border border-[rgba(117,170,252,0.25)] hover:border-[#3f6fb3] hover:bg-[rgba(117,170,252,0.05)] transition-colors uppercase"
>
+ New
</button>
</div>
</div>
<div className="flex-1 overflow-y-auto">
{files.length === 0 ? (
<div className="text-center text-[#9bc3ff] text-sm font-mono opacity-60 py-8">
No saved files yet. Start recording to create one.
</div>
) : (
<div className="divide-y divide-[rgba(117,170,252,0.15)]">
{files.map((file) => (
<div
key={file.id}
className="p-4 hover:bg-[rgba(117,170,252,0.05)] transition-colors"
>
<div className="flex items-start justify-between gap-4">
<button
onClick={() => onSelect(file.id)}
className="flex-1 text-left"
>
<h3 className="font-mono text-sm text-[#dbe7ff] mb-1">
{file.name}
</h3>
{file.description && (
<p className="font-mono text-xs text-[#9bc3ff] mb-2 line-clamp-2">
{file.description}
</p>
)}
<div className="flex items-center gap-4 font-mono text-[10px] text-[#75aafc]">
<span>{file.transcriptCount} segments</span>
<span>{formatDuration(file.duration)}</span>
<span>{formatDate(file.createdAt)}</span>
{file.contractId && file.contractName && (
<button
onClick={(e) => {
e.stopPropagation();
navigate(`/contracts/${file.contractId}`);
}}
className={`px-2 py-0.5 text-[9px] font-mono uppercase border rounded ${
file.contractPhase ? phaseColors[file.contractPhase] : "bg-[#21262d] text-[#8b949e] border-[#30363d]"
} hover:opacity-80 transition-opacity`}
title={`View contract: ${file.contractName}`}
>
{file.contractName}
{file.contractPhase && ` · ${file.contractPhase}`}
</button>
)}
</div>
</button>
<button
onClick={(e) => {
e.stopPropagation();
onDelete(file.id);
}}
className="px-2 py-1 font-mono text-[10px] text-red-400 hover:bg-red-400/10 border border-red-400/30 hover:border-red-400/50 transition-colors uppercase"
>
Delete
</button>
</div>
</div>
))}
</div>
)}
</div>
</div>
);
}