import { useState, useEffect } from 'react'; import { useQuery } from '@tanstack/react-query'; import { fetchRepositories } from '@/services/repositoryService'; import type { PaginatedRepositories } from '@/services/repositoryService'; import { useDebounce } from '@/hooks/useDebounce'; import { Input } from '@/components/ui/input'; import { Search } from 'lucide-react'; import { Skeleton } from "@/components/ui/skeleton"; import { columns } from "./RepositoryTableColumns"; import { DataTable } from "./DataTable"; import { Pagination, PaginationContent, PaginationItem, PaginationPrevious, PaginationNext } from "@/components/ui/pagination"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; function DataTableSkeleton() { return (
{Array.from({ length: 10 }).map((_, i) => ( ))}
); } export function RepositoryManager() { const [searchTerm, setSearchTerm] = useState(''); const [page, setPage] = useState(1); const debouncedSearchTerm = useDebounce(searchTerm, 500); const { data, isLoading, isError, error } = useQuery({ queryKey: ['repositories', page, debouncedSearchTerm], queryFn: () => fetchRepositories(page, debouncedSearchTerm), }); // 当搜索词变化时,重置到第一页 useEffect(() => { if (debouncedSearchTerm) { setPage(1); } }, [debouncedSearchTerm]); const repos = data?.data || []; const totalCount = data?.totalCount || 0; const limit = data?.limit || 30; const totalPages = Math.ceil(totalCount / limit); return (
setSearchTerm(e.target.value)} className="theme-input-surface pl-9 w-full sm:w-[300px] md:w-[250px] lg:w-[300px] focus-visible:ring-1 transition-all font-mono text-sm" />
{isLoading ? ( ) : isError ? (

System Error_

加载仓库列表失败: {error.message}

) : ( <> {totalPages > 1 && (
{page} 页 / 共 {totalPages}|{totalCount} 个仓库
{ e.preventDefault(); setPage(p => Math.max(1, p - 1)); }} className={`border border-border/50 hover:bg-accent hover:text-foreground hover:border-border/80 font-mono text-xs transition-colors ${page <= 1 ? "pointer-events-none opacity-30 bg-muted/40" : "bg-muted/70 text-muted-foreground"}`} /> { e.preventDefault(); setPage(p => Math.min(totalPages, p + 1)); }} className={`border border-border/50 hover:bg-accent hover:text-foreground hover:border-border/80 font-mono text-xs transition-colors ${page >= totalPages ? "pointer-events-none opacity-30 bg-muted/40" : "bg-muted/70 text-muted-foreground"}`} />
)} )}
); }