"use client"; import React, { useEffect, useState, useCallback } from "react"; import Link from "next/link"; import { Button } from "@/components/ui/button"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Input } from "@/components/ui/input"; // <--- 1. Importação Adicionada import { Plus, Eye, Filter, Loader2, Search } from "lucide-react"; // <--- 1. Ícone Search Adicionado import { AlertDialog, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog"; import { api, login } from "services/api.mjs"; import { usersService } from "services/usersApi.mjs"; import Sidebar from "@/components/Sidebar"; interface FlatUser { id: string; user_id: string; full_name?: string; email: string; phone?: string | null; role: string; } interface UserInfoResponse { user: any; profile: any; roles: string[]; permissions: Record; } export default function UsersPage() { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [detailsDialogOpen, setDetailsDialogOpen] = useState(false); const [userDetails, setUserDetails] = useState( null ); // --- Estados de Filtro --- const [searchTerm, setSearchTerm] = useState(""); // <--- 2. Estado da busca const [selectedRole, setSelectedRole] = useState("all"); // --- Lógica de Paginação INÍCIO --- const [itemsPerPage, setItemsPerPage] = useState(10); const [currentPage, setCurrentPage] = useState(1); const handleItemsPerPageChange = (value: string) => { setItemsPerPage(Number(value)); setCurrentPage(1); }; // --- Lógica de Paginação FIM --- const fetchUsers = useCallback(async () => { setLoading(true); setError(null); try { const rolesData: any[] = await usersService.list_roles(); const rolesArray = Array.isArray(rolesData) ? rolesData : []; const profilesData: any[] = await api.get( `/rest/v1/profiles?select=id,full_name,email,phone` ); const profilesById = new Map(); if (Array.isArray(profilesData)) { for (const p of profilesData) { if (p?.id) profilesById.set(p.id, p); } } const mapped: FlatUser[] = rolesArray.map((roleItem) => { const uid = roleItem.user_id; const profile = profilesById.get(uid); return { id: uid, user_id: uid, full_name: profile?.full_name ?? "—", email: profile?.email ?? "—", phone: profile?.phone ?? "—", role: roleItem.role ?? "—", }; }); setUsers(mapped); setCurrentPage(1); } catch (err: any) { console.error("Erro ao buscar usuários:", err); setError("Não foi possível carregar os usuários. Veja console."); setUsers([]); } finally { setLoading(false); } }, []); useEffect(() => { const init = async () => { try { await login(); } catch (e) { console.warn("login falhou no init:", e); } await fetchUsers(); }; init(); }, [fetchUsers]); const openDetailsDialog = async (flatUser: FlatUser) => { setDetailsDialogOpen(true); setUserDetails(null); try { const data = await usersService.full_data(flatUser.user_id); setUserDetails(data); } catch (err: any) { console.error("Erro ao carregar detalhes:", err); setUserDetails({ user: { id: flatUser.user_id, email: flatUser.email }, profile: { full_name: flatUser.full_name, phone: flatUser.phone }, roles: [flatUser.role], permissions: {}, }); } }; // --- 3. Lógica de Filtragem Atualizada --- const filteredUsers = users.filter((u) => { // Filtro por Papel (Role) const roleMatch = selectedRole === "all" || u.role === selectedRole; // Filtro da Barra de Pesquisa (Nome, Email ou Telefone) const searchLower = searchTerm.toLowerCase(); const nameMatch = u.full_name?.toLowerCase().includes(searchLower); const emailMatch = u.email?.toLowerCase().includes(searchLower); const phoneMatch = u.phone?.includes(searchLower); const searchMatch = !searchTerm || nameMatch || emailMatch || phoneMatch; return roleMatch && searchMatch; }); const indexOfLastItem = currentPage * itemsPerPage; const indexOfFirstItem = indexOfLastItem - itemsPerPage; const currentItems = filteredUsers.slice(indexOfFirstItem, indexOfLastItem); const paginate = (pageNumber: number) => setCurrentPage(pageNumber); const totalPages = Math.ceil(filteredUsers.length / itemsPerPage); const goToPrevPage = () => { setCurrentPage((prev) => Math.max(1, prev - 1)); }; const goToNextPage = () => { setCurrentPage((prev) => Math.min(totalPages, prev + 1)); }; const getVisiblePageNumbers = (totalPages: number, currentPage: number) => { const pages: number[] = []; const maxVisiblePages = 5; const halfRange = Math.floor(maxVisiblePages / 2); let startPage = Math.max(1, currentPage - halfRange); let endPage = Math.min(totalPages, currentPage + halfRange); if (endPage - startPage + 1 < maxVisiblePages) { if (endPage === totalPages) { startPage = Math.max(1, totalPages - maxVisiblePages + 1); } if (startPage === 1) { endPage = Math.min(totalPages, maxVisiblePages); } } for (let i = startPage; i <= endPage; i++) { pages.push(i); } return pages; }; const visiblePageNumbers = getVisiblePageNumbers(totalPages, currentPage); return (
{/* Header */}

Usuários

Gerencie usuários.

{/* --- 4. Filtro (Barra de Pesquisa + Selects) --- */}
{/* Barra de Pesquisa */}
{ setSearchTerm(e.target.value); setCurrentPage(1); // Reseta a paginação ao pesquisar }} className="pl-10 w-full bg-gray-50 border-gray-200 focus:bg-white transition-colors" />
{/* Select de Filtro por Papel */}
{/* Select de Itens por Página */}
{/* Fim do Filtro */} {/* Tabela/Lista */}
{loading ? (
Carregando usuários...
) : error ? (
{error}
) : filteredUsers.length === 0 ? (
Nenhum usuário encontrado com os filtros aplicados.
) : ( <> {/* Tabela para Telas Médias e Grandes */} {currentItems.map((u) => ( ))}
Nome E-mail Telefone Cargo Ações
{u.full_name} {u.email} {u.phone} {u.role}
{/* Layout em Cards/Lista para Telas Pequenas */}
{currentItems.map((u) => (
{u.full_name || "—"}
{u.email}
{u.role || "—"}
))}
{/* Paginação */} {totalPages > 1 && (
{/* Botão Anterior */} {/* Números das Páginas */} {visiblePageNumbers.map((number) => ( ))} {/* Botão Próximo */}
)} )}
{/* Modal de Detalhes */} {userDetails?.profile?.full_name || "Detalhes do Usuário"} {!userDetails ? (
Buscando dados completos...
) : (
ID: {userDetails.user.id}
E-mail: {userDetails.user.email}
Nome completo:{" "} {userDetails.profile.full_name}
Telefone: {userDetails.profile.phone}
Roles:{" "} {userDetails.roles?.join(", ")}
Permissões:
    {Object.entries( userDetails.permissions || {} ).map(([k, v]) => (
  • {k}: {v ? "Sim" : "Não"}
  • ))}
)}
Fechar
); }