Add pagination to agents screen
Implement pagination controls on the agents screen to manage a large number of agents. This includes state management for current page and items per page, logic to slice and display agents, and UI elements for navigation (previous, next, page numbers, ellipsis). The search functionality now resets to the first page.
This commit is contained in:
+91
-3
@@ -5,12 +5,23 @@ import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import {
|
||||
Pagination,
|
||||
PaginationContent,
|
||||
PaginationEllipsis,
|
||||
PaginationItem,
|
||||
PaginationLink,
|
||||
PaginationNext,
|
||||
PaginationPrevious,
|
||||
} from "@/components/ui/pagination";
|
||||
import { Plus, Search, Bot, ChevronRight } from "lucide-react";
|
||||
|
||||
export default function Agents() {
|
||||
const navigate = useNavigate();
|
||||
const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const itemsPerPage = 9;
|
||||
|
||||
const [agents] = useState([
|
||||
{
|
||||
@@ -43,6 +54,18 @@ export default function Agents() {
|
||||
agent.name.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
// Paginação
|
||||
const totalPages = Math.ceil(filteredAgents.length / itemsPerPage);
|
||||
const startIndex = (currentPage - 1) * itemsPerPage;
|
||||
const endIndex = startIndex + itemsPerPage;
|
||||
const paginatedAgents = filteredAgents.slice(startIndex, endIndex);
|
||||
|
||||
// Reset para primeira página quando buscar
|
||||
const handleSearch = (query: string) => {
|
||||
setSearchQuery(query);
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="animate-fade-in">
|
||||
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4 mb-6">
|
||||
@@ -64,13 +87,20 @@ export default function Agents() {
|
||||
<Input
|
||||
placeholder="Pesquisar agentes..."
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
onChange={(e) => handleSearch(e.target.value)}
|
||||
className="pl-10"
|
||||
/>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground mt-2">
|
||||
<div className="flex items-center justify-between mt-2">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{filteredAgents.length} {filteredAgents.length === 1 ? 'agente encontrado' : 'agentes encontrados'}
|
||||
</p>
|
||||
{totalPages > 1 && (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Página {currentPage} de {totalPages}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{filteredAgents.length === 0 ? (
|
||||
@@ -78,8 +108,9 @@ export default function Agents() {
|
||||
<p className="text-muted-foreground">Nenhum agente encontrado.</p>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{filteredAgents.map((agent) => (
|
||||
{paginatedAgents.map((agent) => (
|
||||
<Card
|
||||
key={agent.id}
|
||||
className="group relative overflow-hidden border-2 transition-all duration-300 hover:shadow-lg hover:scale-[1.02] bg-gradient-to-br from-card to-card/50 cursor-pointer"
|
||||
@@ -132,6 +163,63 @@ export default function Agents() {
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<div className="mt-8 flex justify-center">
|
||||
<Pagination>
|
||||
<PaginationContent>
|
||||
<PaginationItem>
|
||||
<PaginationPrevious
|
||||
onClick={() => setCurrentPage(prev => Math.max(1, prev - 1))}
|
||||
className={currentPage === 1 ? "pointer-events-none opacity-50" : "cursor-pointer"}
|
||||
/>
|
||||
</PaginationItem>
|
||||
|
||||
{[...Array(totalPages)].map((_, index) => {
|
||||
const pageNumber = index + 1;
|
||||
|
||||
// Mostrar primeira página, última página e páginas próximas à atual
|
||||
if (
|
||||
pageNumber === 1 ||
|
||||
pageNumber === totalPages ||
|
||||
(pageNumber >= currentPage - 1 && pageNumber <= currentPage + 1)
|
||||
) {
|
||||
return (
|
||||
<PaginationItem key={pageNumber}>
|
||||
<PaginationLink
|
||||
onClick={() => setCurrentPage(pageNumber)}
|
||||
isActive={currentPage === pageNumber}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
{pageNumber}
|
||||
</PaginationLink>
|
||||
</PaginationItem>
|
||||
);
|
||||
}
|
||||
|
||||
// Mostrar ellipsis
|
||||
if (pageNumber === currentPage - 2 || pageNumber === currentPage + 2) {
|
||||
return (
|
||||
<PaginationItem key={pageNumber}>
|
||||
<PaginationEllipsis />
|
||||
</PaginationItem>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
})}
|
||||
|
||||
<PaginationItem>
|
||||
<PaginationNext
|
||||
onClick={() => setCurrentPage(prev => Math.min(totalPages, prev + 1))}
|
||||
className={currentPage === totalPages ? "pointer-events-none opacity-50" : "cursor-pointer"}
|
||||
/>
|
||||
</PaginationItem>
|
||||
</PaginationContent>
|
||||
</Pagination>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
<CreateAgentDialog
|
||||
|
||||
Reference in New Issue
Block a user