"use client"; import type React from "react"; import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Input } from "@/components/ui/input"; import { ArrowLeft, Search, Filter } from "lucide-react"; import { useRouter } from "next/navigation"; import { ThreadDisplayInfo, threadToDisplayInfo } from "@/components/v2/types"; import { useThreads } from "@/hooks/useThreads"; import { GraphState } from "@open-swe/shared/open-swe/types"; import { ThreadCard } from "@/components/v2/thread-card"; import { ThemeToggle } from "@/components/theme-toggle"; type FilterStatus = "all" | "running" | "completed" | "failed" | "pending"; export default function AllThreadsPage() { const router = useRouter(); const { threads } = useThreads( process.env.NEXT_PUBLIC_MANAGER_ASSISTANT_ID, ); const [searchQuery, setSearchQuery] = useState(""); const [statusFilter, setStatusFilter] = useState("all"); // Convert Thread objects to ThreadDisplayInfo for UI const displayThreads: ThreadDisplayInfo[] = threads?.map(threadToDisplayInfo) ?? []; // Filter and search threads const filteredThreads = displayThreads.filter((thread) => { const matchesSearch = thread.title.toLowerCase().includes(searchQuery.toLowerCase()) || thread.repository.toLowerCase().includes(searchQuery.toLowerCase()); const matchesStatus = statusFilter === "all" || thread.status === statusFilter; return matchesSearch && matchesStatus; }); // Group threads by status const groupedThreads = { running: filteredThreads.filter((t) => t.status === "running"), completed: filteredThreads.filter((t) => t.status === "completed"), failed: filteredThreads.filter((t) => t.status === "failed"), pending: filteredThreads.filter((t) => t.status === "pending"), }; const statusCounts = { all: displayThreads.length, running: displayThreads.filter((t) => t.status === "running").length, completed: displayThreads.filter((t) => t.status === "completed").length, failed: displayThreads.filter((t) => t.status === "failed").length, pending: displayThreads.filter((t) => t.status === "pending").length, }; return (
{/* Header */}
All Threads
{filteredThreads.length} threads
{/* Search and Filters */}
setSearchQuery(e.target.value)} className="border-border bg-background text-foreground placeholder:text-muted-foreground pl-10 dark:bg-gray-900" />
Filter: {( [ "all", "running", "completed", "failed", "pending", ] as FilterStatus[] ).map((status) => ( ))}
{/* Content */}
{statusFilter === "all" ? ( // Show grouped view when "all" is selected
{Object.entries(groupedThreads).map(([status, threads]) => { if (threads.length === 0) return null; return (

{status} Threads

{threads.length}
{threads.map((thread) => ( ))}
); })}
) : ( // Show flat list when specific status is selected
{filteredThreads.map((thread) => ( ))}
)} {filteredThreads.length === 0 && (
No threads found
{searchQuery ? "Try adjusting your search query" : "No threads match the selected filter"}
)}
); }