/* global React, IconLock, IconMail, IconUser, IconUsers, IconCheck, IconClose, IconPlus */ // Login screen + user management (admin only). const { useState: _aus } = React; function Avatar({ name, color, size = 34 }) { const initials = name.split(" ").map((s) => s[0]).slice(0, 2).join("").toUpperCase(); return (
{initials}
); } // ============ Login ============================================= function LoginScreen({ onLogin }) { const { USERS, CLOSERS } = window.REVOLVR_DATA; const [email, setEmail] = _aus(""); const [password, setPassword] = _aus(""); const [error, setError] = _aus(""); const [loading, setLoading] = _aus(false); const submit = (e) => { e && e.preventDefault(); setLoading(true); setError(""); const tryLogin = (userList) => { const u = userList.find((x) => x.email.toLowerCase() === email.trim().toLowerCase()); if (!u || u.password !== password) { setError("Correo o contraseña incorrectos."); setLoading(false); return; } if (!u.active) { setError("Tu usuario está desactivado. Contacta a un administrador."); setLoading(false); return; } setError(""); setLoading(false); onLogin(u); }; // Intentar desde Supabase primero, fallback a data.js if (window.SUPABASE) { window.SUPABASE.from("crm_users").select("*") .then(({ data, error }) => { if (!error && data && data.length > 0) { const mapped = data.map((u) => ({ id: u.id, name: u.name, email: u.email, password: u.password, role: u.role, closerId: u.closer_id, active: u.active, lastLogin: u.last_login || "" })); tryLogin(mapped); } else { tryLogin(USERS); } }); } else { tryLogin(USERS); } }; return (
REVOLVR
CRM · Gestión de llamadas
{error &&
{error}
}
); } // ============ Administración de usuarios (admin) ================ function UsersView({ users, onAddUser, onToggleActive, onDeleteUser, onResetPassword, currentUser }) { const { CLOSERS } = window.REVOLVR_DATA; const [modal, setModal] = _aus(false); const [resetModal, setResetModal] = _aus(null); // usuario a resetear return (

Usuarios y accesos

{users.length} usuarios · {users.filter((u) => u.active).length} activos
{users.map((u) => { const c = CLOSERS.find((x) => x.id === u.closerId); return ( ); })}
Usuario Correo Rol Pipeline Estado Acciones
{u.name}
Último acceso: {u.lastLogin}
{u.email} {u.role === "admin" ? "Administrador" : "Closer"} {c ? c.name : "— (todos)"} {u.id !== currentUser?.id && }
{modal && setModal(false)} onSave={(u) => { onAddUser(u); setModal(false); }}/>} {resetModal && setResetModal(null)} onSave={(id, pwd) => { onResetPassword(id, pwd); setResetModal(null); }}/>}
); } function NewUserModal({ onClose, onSave }) { const { CLOSERS } = window.REVOLVR_DATA; const [name, setName] = _aus(""); const [email, setEmail] = _aus(""); const [password, setPassword] = _aus(""); const [role, setRole] = _aus("closer"); const [closerId, setCloserId] = _aus("new"); const field = { width: "100%", padding: "8px 10px", border: "1px solid var(--border)", borderRadius: "var(--radius-s)", background: "var(--surface)", color: "var(--text)", fontFamily: "inherit", fontSize: 12.5, marginTop: 4, }; const lbl = { fontSize: 11, color: "var(--text-3)", fontWeight: 600, textTransform: "uppercase", letterSpacing: ".04em" }; const save = () => { if (!name.trim() || !email.trim()) return; onSave({ name: name.trim(), email: email.trim(), password, role, closerId }); }; return (
e.stopPropagation()}>

Nuevo usuario

Crea un acceso para un closer o administrador del equipo.

setName(e.target.value)} style={field} placeholder="Ej. Carla Núñez"/>
setEmail(e.target.value)} style={field} placeholder="carla@revolvr.io"/>
setPassword(e.target.value)} style={field}/>
{role === "closer" &&
}
); } function ResetPasswordModal({ user, onClose, onSave }) { const [pwd, setPwd] = _aus(""); const [confirm, setConfirm] = _aus(""); const [err, setErr] = _aus(""); const field = { width: "100%", padding: "8px 10px", border: "1px solid var(--border)", borderRadius: 7, fontFamily: "inherit", fontSize: 13, background: "var(--bg)", color: "var(--text-1)" }; const save = () => { if (pwd.length < 6) { setErr("La contraseña debe tener al menos 6 caracteres."); return; } if (pwd !== confirm) { setErr("Las contraseñas no coinciden."); return; } onSave(user.id, pwd); }; return (
e.stopPropagation()}>

Resetear contraseña

Cambiando contraseña de {user.name} ({user.email})
{err &&
{err}
}
); } Object.assign(window, { LoginScreen, UsersView, Avatar });