import React, { useState, useEffect } from "react"; import { useAuth } from "../contexts/AuthContext"; import { getPendingUsers, getAllUsers, createAdminUser, approveUser as apiApproveUser, rejectUser as apiRejectUser, updateUserRole, getCompanies, } from "../services/apiService"; import { UserApprovalStatus, UserRole } from "../types"; import { CheckCircle, XCircle, Clock, Search, Users, Briefcase, UserPlus, RefreshCw, } from "lucide-react"; import { Button } from "../components/Button"; import { Input } from "../components/Input"; import { formatPhone, formatCPFCNPJ, formatCEP } from "../utils/masks"; // INTERFACES interface UserApprovalProps { onNavigate?: (page: string) => void; } interface UserDetailsModalProps { selectedUser: any | null; onClose: () => void; onApprove: (userId: string) => void; isProcessing: string | null; viewMode: "pending" | "all"; handleRoleChange: (userId: string, newRole: string) => void; setSelectedUser: React.Dispatch>; } interface CreateUserModalProps { isOpen: boolean; onClose: () => void; onSubmit: (e: React.FormEvent) => void; isCreating: boolean; formData: any; setFormData: React.Dispatch>; } // COMPONENT DEFINITIONS const UserDetailsModal: React.FC = ({ selectedUser, onClose, onApprove, isProcessing, viewMode, handleRoleChange, setSelectedUser }) => { if (!selectedUser) return null; return (

Detalhes do Cadastro

{selectedUser.name || "-"}

{selectedUser.email || "-"}

{selectedUser.phone || "-"}

{selectedUser.created_at ? new Date(selectedUser.created_at).toLocaleDateString("pt-BR") : "-"}

{selectedUser.role === "EVENT_OWNER" && (

{selectedUser.company_name || "-"}

)}
{selectedUser.role === "EVENT_OWNER" ? ( Cliente (Empresa) ) : ( )}
{selectedUser.approvalStatus === UserApprovalStatus.PENDING && ( )}
); }; const CreateUserModal: React.FC = ({ isOpen, onClose, onSubmit, isCreating, formData, setFormData }) => { // Fetch companies const [companies, setCompanies] = useState([]); useEffect(() => { if (formData.role === "EVENT_OWNER") { getCompanies().then(res => { if(res.data) setCompanies(res.data); }); } }, [formData.role]); if (!isOpen) return null; return (

Novo Usuário

setFormData({...formData, nome: e.target.value})} /> setFormData({...formData, email: e.target.value})} /> setFormData({...formData, telefone: formatPhone(e.target.value)})} />
setFormData({...formData, senha: e.target.value})} />
{formData.role === "EVENT_OWNER" && (

Dados Cadastrais

setFormData({...formData, cpfCnpj: formatCPFCNPJ(e.target.value)})} placeholder="000.000.000-00" maxLength={18} /> setFormData({...formData, cep: formatCEP(e.target.value)})} placeholder="00000-000" onBlur={(e) => { const cep = e.target.value.replace(/\D/g, ''); if (cep.length === 8) { fetch(`https://viacep.com.br/ws/${cep}/json/`) .then(res => res.json()) .then(data => { if (!data.erro) { setFormData(prev => ({ ...prev, endereco: data.logradouro, bairro: data.bairro, cidade: data.localidade, estado: data.uf })); } }); } }} />
setFormData({...formData, endereco: e.target.value})} /> setFormData({...formData, numero: e.target.value})} />
setFormData({...formData, complemento: e.target.value})} /> setFormData({...formData, bairro: e.target.value})} />
setFormData({...formData, cidade: e.target.value})} /> setFormData({...formData, estado: e.target.value})} maxLength={2} />
)} {/* Show Address for Professionals too if not EVENT_OWNER (since we handled it above inside the block, wait - logic change needed) */} {/* Actually, let's make the Address block generic for PHOTOGRAPHER and BUSINESS_OWNER too */} {(formData.role === "PHOTOGRAPHER" || formData.role === "BUSINESS_OWNER") && (

Dados Profissionais

setFormData({...formData, cpfCnpj: formatCPFCNPJ(e.target.value)})} placeholder="000.000.000-00" maxLength={18} /> setFormData({...formData, cep: formatCEP(e.target.value)})} placeholder="00000-000" onBlur={(e) => { const cep = e.target.value.replace(/\D/g, ''); if (cep.length === 8) { fetch(`https://viacep.com.br/ws/${cep}/json/`) .then(res => res.json()) .then(data => { if (!data.erro) { setFormData(prev => ({ ...prev, endereco: data.logradouro, bairro: data.bairro, cidade: data.localidade, estado: data.uf })); } }); } }} />
setFormData({...formData, endereco: e.target.value})} /> setFormData({...formData, numero: e.target.value})} />
setFormData({...formData, complemento: e.target.value})} /> setFormData({...formData, bairro: e.target.value})} />
setFormData({...formData, cidade: e.target.value})} /> setFormData({...formData, estado: e.target.value})} maxLength={2} />
)} {formData.role === "PHOTOGRAPHER" && (
)}
); }; export const UserApproval: React.FC = ({ onNavigate }) => { const { token } = useAuth(); const [users, setUsers] = useState([]); const [isLoading, setIsLoading] = useState(true); const [searchTerm, setSearchTerm] = useState(""); const [viewMode, setViewMode] = useState<"pending" | "all">("pending"); const [activeTab, setActiveTab] = useState<"cliente" | "profissional">( "cliente" ); const [isProcessing, setIsProcessing] = useState(null); const [selectedUser, setSelectedUser] = useState(null); // Create User State const [showCreateModal, setShowCreateModal] = useState(false); const [isCreating, setIsCreating] = useState(false); const [createFormData, setCreateFormData] = useState({ nome: "", email: "", senha: "", role: "PHOTOGRAPHER", telefone: "", professional_type: "", // For photographer subtype empresa_id: "", cpfCnpj: "", cep: "", endereco: "", numero: "", complemento: "", bairro: "", cidade: "", estado: "", regiao: "", }); const fetchUsers = async () => { if (!token) { setIsLoading(false); return; } setIsLoading(true); try { let result; if (viewMode === "pending") { result = await getPendingUsers(token); } else { result = await getAllUsers(token); } if (result.data) { const mappedUsers = result.data.map((u: any) => ({ ...u, approvalStatus: u.ativo ? UserApprovalStatus.APPROVED : UserApprovalStatus.PENDING, // Ensure role is mapped if needed, backend sends "role" })); setUsers(mappedUsers); } } catch (error) { console.error("Erro ao buscar usuários:", error); } finally { setIsLoading(false); } }; useEffect(() => { fetchUsers(); }, [token, viewMode]); const handleApprove = async (userId: string) => { if (!token) return; setIsProcessing(userId); try { await apiApproveUser(userId, token); await fetchUsers(); } catch (error) { console.error("Erro ao aprovar usuário:", error); alert("Erro ao aprovar usuário"); } finally { setIsProcessing(null); } }; const handleRoleChange = async (userId: string, newRole: string) => { if (!token) return; try { // Optimistic update setUsers(prev => prev.map(u => u.id === userId ? {...u, role: newRole} : u)); await updateUserRole(userId, newRole, token); } catch (error) { console.error("Erro ao atualizar role:", error); alert("Erro ao atualizar função do usuário"); fetchUsers(); } }; const handleCreateUser = async (e: React.FormEvent) => { e.preventDefault(); if(!token) return; setIsCreating(true); try { // Prepare payload const payload = { nome: createFormData.nome, email: createFormData.email, senha: createFormData.senha, role: createFormData.role, telefone: createFormData.telefone, professional_type: createFormData.role === "PHOTOGRAPHER" ? createFormData.professional_type : undefined, empresa_id: createFormData.role === "EVENT_OWNER" ? createFormData.empresa_id : undefined, cpf_cnpj: createFormData.cpfCnpj, cep: createFormData.cep, endereco: createFormData.endereco, numero: createFormData.numero, complemento: createFormData.complemento, bairro: createFormData.bairro, cidade: createFormData.cidade, estado: createFormData.estado, regiao: createFormData.regiao || undefined }; const result = await createAdminUser(payload, token); if (result.error) { alert(`Erro: ${result.error}`); } else { alert("Usuário criado com sucesso!"); setShowCreateModal(false); setCreateFormData({ nome: "", email: "", senha: "", role: "PHOTOGRAPHER", telefone: "", professional_type: "", empresa_id: "", cpfCnpj: "", cep: "", endereco: "", numero: "", complemento: "", bairro: "", cidade: "", estado: "", regiao: "" }); fetchUsers(); } } catch (err) { alert("Erro ao criar usuário."); } finally { setIsCreating(false); } }; // Separar usuários Clientes (EVENT_OWNER) e Profissionais const clientUsers = users.filter( (user) => user.role === "EVENT_OWNER" ); const professionalUsers = users.filter( (user) => user.role !== "EVENT_OWNER" ); // Filtrar usuários baseado na aba ativa const currentUsers = activeTab === "cliente" ? clientUsers : professionalUsers; const filteredUsers = currentUsers.filter((user) => { const matchesSearch = (user.name || "").toLowerCase().includes(searchTerm.toLowerCase()) || (user.email || "").toLowerCase().includes(searchTerm.toLowerCase()); // In "pending" mode, theoretically all are pending, but let's filter just in case logic changes // Actually getPendingUsers returns only pending. getAllUsers returns all. // So we don't need extra status filtering here unless we add a specific status filter dropdown. return matchesSearch; }); const getStatusBadge = (status: UserApprovalStatus) => { // If we are in "All" mode, approved users are common if (status === UserApprovalStatus.APPROVED) { return ( Ativo ); } const s = status || UserApprovalStatus.PENDING; switch (s) { case UserApprovalStatus.PENDING: return ( Pendente ); case UserApprovalStatus.REJECTED: return ( Rejeitado ); default: return null; } }; return (
{/* Header */}

{viewMode === "pending" ? "Aprovação de Cadastros" : "Gerenciamento de Usuários"}

{viewMode === "pending" ? "Gerencie os cadastros pendentes de aprovação" : "Visualize e gerencie todos os usuários do sistema"}

{/* Tabs */}
{/* Filters */}
{/* Search */}
setSearchTerm(e.target.value)} className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-brand-gold focus:border-transparent" />
{/* Table */}
{isLoading ? (
Carregando usuários...
) : ( {activeTab === "cliente" && ( )} {/* Role Column */} {filteredUsers.length === 0 ? ( ) : ( filteredUsers.map((user, index) => ( setSelectedUser(user)} > {activeTab === "cliente" && ( )} {/* Role Editor */} )) )}
Nome Empresa Email Telefone Função Data de Cadastro Status Ações
{activeTab === "cliente" ? ( ) : ( )}

{activeTab === "cliente" ? "Nenhum cadastro de cliente encontrado" : "Nenhum cadastro profissional encontrado"}

{user.name || user.email}
{user.company_name || "-"}
{user.email}
{user.phone || "-"}
e.stopPropagation()}> {activeTab === "cliente" ? ( Cliente ) : ( )}
{user.created_at ? new Date(user.created_at).toLocaleDateString( "pt-BR" ) : "-"}
{getStatusBadge( user.approvalStatus || UserApprovalStatus.PENDING )} e.stopPropagation()}>
{user.approvalStatus !== UserApprovalStatus.APPROVED && ( )} {user.approvalStatus === UserApprovalStatus.APPROVED && ( -- )}
) }
setSelectedUser(null)} onApprove={handleApprove} isProcessing={isProcessing} viewMode={viewMode} handleRoleChange={handleRoleChange} setSelectedUser={setSelectedUser} /> setShowCreateModal(false)} onSubmit={handleCreateUser} isCreating={isCreating} formData={createFormData} setFormData={setCreateFormData} />
); };