import { useEffect, useMemo, useState, type FormEvent } from 'react'; import { AlertTriangle, AtSign, Check, Copy, Edit3, KeyRound, Loader2, Mail, Plus, RefreshCw, Search, Trash2, User as UserIcon, UserCheck, UserPlus, UserX, X } from 'lucide-react'; import { createUser, deleteUser as deleteManagedUser, fetchUsers, updateUser } from '../dataService'; import type { ManagedUser } from '../types'; type StatusFilter = 'all' | 'active' | 'inactive'; type PasswordMode = 'auto' | 'manual'; type Notice = { tone: 'success' | 'warning' | 'error'; text: string; temporaryPassword?: string; }; const statusOptions: Array<{ key: StatusFilter; label: string }> = [ { key: 'all', label: 'Todos' }, { key: 'active', label: 'Ativos' }, { key: 'inactive', label: 'Inativos' } ]; const roleLabels: Record = { admin: 'Admin', supervisor: 'Supervisor', producao: 'Produção', operacao: 'Operação', vendedor: 'Vendedor', financeiro: 'Financeiro', user: 'Usuário' }; const inputWrapClassName = 'flex h-11 items-center gap-3 rounded-lg border border-dark-border bg-dark-input px-3 transition-colors focus-within:border-brand-primary focus-within:ring-1 focus-within:ring-brand-primary'; const inputClassName = 'min-w-0 flex-1 bg-transparent text-sm font-semibold text-dark-text outline-none placeholder:text-dark-muted'; const getInitials = (name: string) => { const parts = name.trim().split(/\s+/).filter(Boolean); if (!parts.length) return '?'; return parts.slice(0, 2).map((part) => part[0]).join('').toUpperCase(); }; const getUserRoleLabel = (user: ManagedUser) => { const role = String((user as ManagedUser & { role?: string }).role || 'user').toLowerCase(); return roleLabels[role] || role; }; const AdminUsers = () => { const [users, setUsers] = useState([]); const [searchTerm, setSearchTerm] = useState(''); const [statusFilter, setStatusFilter] = useState('all'); const [isLoading, setIsLoading] = useState(true); const [isModalOpen, setIsModalOpen] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); const [editingUser, setEditingUser] = useState(null); const [userToDelete, setUserToDelete] = useState(null); const [passwordMode, setPasswordMode] = useState('auto'); const [isActive, setIsActive] = useState(true); const [name, setName] = useState(''); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [notice, setNotice] = useState(null); const [copyLabel, setCopyLabel] = useState('Copiar'); const activeCount = useMemo(() => users.filter((user) => user.isActive).length, [users]); const inactiveCount = users.length - activeCount; const filteredUsers = useMemo(() => { const query = searchTerm.trim().toLowerCase(); return users.filter((user) => { const matchesStatus = statusFilter === 'all' || (statusFilter === 'active' && user.isActive) || (statusFilter === 'inactive' && !user.isActive); const matchesQuery = !query || user.name.toLowerCase().includes(query) || user.email.toLowerCase().includes(query); return matchesStatus && matchesQuery; }); }, [searchTerm, statusFilter, users]); const hasFilters = searchTerm.trim() !== '' || statusFilter !== 'all'; const loadUsers = async () => { setIsLoading(true); try { setUsers(await fetchUsers()); } finally { setIsLoading(false); } }; useEffect(() => { // User management needs an initial API load when the admin page opens. // eslint-disable-next-line react-hooks/set-state-in-effect void loadUsers(); }, []); const resetForm = () => { setName(''); setEmail(''); setPassword(''); setPasswordMode('auto'); setIsActive(true); setEditingUser(null); setNotice(null); setCopyLabel('Copiar'); }; const closeModal = () => { if (isSubmitting) return; setIsModalOpen(false); resetForm(); }; const clearFilters = () => { setSearchTerm(''); setStatusFilter('all'); }; const openCreateModal = () => { resetForm(); setIsModalOpen(true); }; const openEditModal = (user: ManagedUser) => { setEditingUser(user); setName(user.name); setEmail(user.email); setIsActive(user.isActive); setPassword(''); setPasswordMode('auto'); setNotice(null); setCopyLabel('Copiar'); setIsModalOpen(true); }; const handleCreateUser = async (event: FormEvent) => { event.preventDefault(); setIsSubmitting(true); setNotice(null); setCopyLabel('Copiar'); try { const result = await createUser({ name, email, password: passwordMode === 'manual' ? password : undefined }); setUsers((currentUsers) => [result.user, ...currentUsers]); if (result.temporaryPassword) { setNotice({ tone: 'success', text: 'Acesso criado. Copie a senha gerada antes de fechar.', temporaryPassword: result.temporaryPassword }); setName(''); setEmail(''); setPassword(''); setPasswordMode('auto'); } else { setNotice({ tone: 'success', text: 'Acesso criado com a senha definida.' }); window.setTimeout(() => { setIsModalOpen(false); resetForm(); }, 900); } } catch (error) { setNotice({ tone: 'error', text: error instanceof Error ? error.message : 'Não foi possível criar o acesso.' }); } finally { setIsSubmitting(false); } }; const handleUpdateUser = async (event: FormEvent) => { event.preventDefault(); if (!editingUser) return; setIsSubmitting(true); setNotice(null); try { const updatedUser = await updateUser(editingUser.id, { name, email, isActive, password: passwordMode === 'manual' ? password : undefined }); setUsers((currentUsers) => currentUsers.map((user) => user.id === updatedUser.id ? updatedUser : user)); setNotice({ tone: 'success', text: 'Usuário atualizado.' }); window.setTimeout(() => { setIsModalOpen(false); resetForm(); }, 700); } catch (error) { setNotice({ tone: 'error', text: error instanceof Error ? error.message : 'Não foi possível editar o usuário.' }); } finally { setIsSubmitting(false); } }; const handleDeleteUser = async () => { if (!userToDelete) return; setIsSubmitting(true); try { await deleteManagedUser(userToDelete.id); setUsers((currentUsers) => currentUsers.filter((user) => user.id !== userToDelete.id)); setUserToDelete(null); } catch (error) { setNotice({ tone: 'error', text: error instanceof Error ? error.message : 'Não foi possível excluir o usuário.' }); } finally { setIsSubmitting(false); } }; const copyTemporaryPassword = async () => { if (!notice?.temporaryPassword) return; try { await navigator.clipboard.writeText(notice.temporaryPassword); setCopyLabel('Copiado'); window.setTimeout(() => setCopyLabel('Copiar'), 1600); } catch { setCopyLabel('Falhou'); } }; const noticeClass = notice?.tone === 'error' ? 'border-red-500/30 bg-red-500/10 text-red-300' : notice?.tone === 'warning' ? 'border-amber-500/30 bg-amber-500/10 text-amber-200' : 'border-emerald-500/30 bg-emerald-500/10 text-emerald-300'; const statusCounts: Record = { all: users.length, active: activeCount, inactive: inactiveCount }; const stats = [ { label: 'Total', value: users.length, icon: UserIcon, tone: 'text-dark-text', detail: 'acessos cadastrados' }, { label: 'Ativos', value: activeCount, icon: UserCheck, tone: 'text-emerald-300', detail: 'podem entrar agora' }, { label: 'Inativos', value: inactiveCount, icon: UserX, tone: 'text-red-300', detail: 'bloqueados no login' }, { label: 'Exibindo', value: filteredUsers.length, icon: Search, tone: 'text-brand-primary', detail: hasFilters ? 'após filtros' : 'sem filtros' } ]; return (

Usuários

Gerencie acessos individuais, senhas iniciais e bloqueios de entrada no painel.

{stats.map((stat) => { const Icon = stat.icon; return (

{stat.label}

{stat.value}

{stat.detail}

); })}

Acessos cadastrados

Busque, filtre e edite os usuários do painel.

setSearchTerm(event.target.value)} className="min-w-0 flex-1 bg-transparent text-sm font-semibold text-dark-text outline-none placeholder:text-dark-muted" placeholder="Buscar nome ou e-mail" /> {searchTerm && ( )}
{statusOptions.map((option) => ( ))}
{isLoading ? (
{Array.from({ length: 5 }).map((_, index) => (
{Array.from({ length: 5 }).map((__, column) => (
))}
))}
) : users.length === 0 ? (

Nenhum usuário cadastrado

Crie o primeiro acesso individual para tirar o uso compartilhado do login administrativo.

) : filteredUsers.length === 0 ? (

Nenhum resultado

Não encontramos usuários com os filtros atuais.

) : (
{filteredUsers.map((user) => ( ))}
Usuário E-mail Perfil Status Ações
{getInitials(user.name)}

{user.name}

ID {user.id}

{user.email}
{getUserRoleLabel(user)} {user.isActive ? 'Ativo' : 'Inativo'}
)}
{isModalOpen && (
{editingUser ? : }

{editingUser ? 'Editar usuário' : 'Novo acesso'}

{editingUser ? 'Atualize identificação, status e senha.' : 'Crie uma credencial individual para o painel.'}

Identificação

Use um nome reconhecível e um e-mail individual.

{editingUser ? 'Senha' : 'Senha inicial'}

{editingUser ? 'Mantenha a senha atual ou defina uma nova.' : 'Gere uma senha temporária ou defina uma senha manual.'}

{passwordMode === 'manual' && (
setPassword(event.target.value)} className={inputClassName} placeholder="Mínimo de 6 caracteres" minLength={6} required />
)}
{editingUser && ( )} {notice && (
{notice.tone === 'error' ? : }

{notice.text}

{notice.temporaryPassword && (
{notice.temporaryPassword}
)}
)}
)} {userToDelete && (

Excluir usuário

Esta ação remove o acesso imediatamente.

{userToDelete.name}

{userToDelete.email}

{notice?.tone === 'error' && (
{notice.text}
)}
)}
); }; export default AdminUsers;