From 9f2d957ee8380028ac73a50b2c1c2026eb9f592a Mon Sep 17 00:00:00 2001 From: max Date: Sun, 1 Jun 2025 17:26:45 -0600 Subject: [PATCH 01/23] Implement user update functionality with validation and API integration --- .../Modelos/Usuarios/ActualizarUsuario.js | 69 ++++ .../Usuarios/RepositorioActualizarUsuario.js | 25 ++ src/Utilidades/Constantes/rutas.js | 1 + src/Utilidades/Constantes/rutasAPI.js | 4 +- .../FormularioActualizarUsuario.jsx | 297 ++++++++++++++++++ .../Componentes/Organismos/ModalUsuarios.jsx | 5 + src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx | 117 ++++--- src/hooks/Usuarios/useAccionesUsuario.js | 139 ++++++++ src/hooks/Usuarios/useActualizarUsuario.js | 25 ++ 9 files changed, 629 insertions(+), 53 deletions(-) create mode 100644 src/Dominio/Modelos/Usuarios/ActualizarUsuario.js create mode 100644 src/Dominio/Repositorios/Usuarios/RepositorioActualizarUsuario.js create mode 100644 src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx create mode 100644 src/Vistas/Componentes/Organismos/ModalUsuarios.jsx create mode 100644 src/hooks/Usuarios/useAccionesUsuario.js create mode 100644 src/hooks/Usuarios/useActualizarUsuario.js diff --git a/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js b/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js new file mode 100644 index 00000000..d19f142e --- /dev/null +++ b/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js @@ -0,0 +1,69 @@ +// Modelo para actualizar un usuario + +export const validarDatosActualizarUsuario = (datos, usuariosExistentes = []) => { + const errores = {}; + const emailValido = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + const telefonoValido = /^\d{10}$/; + + if (!datos.idUsuario) { + errores.idUsuario = true; + } else if (datos.idUsuario.toString().length > 10) { + errores.idUsuario = 'El idUsuario no debe tener más de 10 caracteres'; + } + + if (!datos.nombreCompleto || datos.nombreCompleto.trim().length === 0) { + errores.nombreCompleto = 'El nombre completo es obligatorio'; + } + + if (!datos.correoElectronico) { + errores.correoElectronico = 'El correo electrónico es obligatorio'; + } else if (!emailValido.test(datos.correoElectronico)) { + errores.correoElectronico = 'Correo electrónico inválido'; + } else if ( + usuariosExistentes.some( + (usuario) => + usuario.correoElectronico === datos.correoElectronico && + usuario.idUsuario !== datos.idUsuario + ) + ) { + errores.correoElectronico = 'Este correo ya está registrado'; + } + + if (datos.contrasenia && datos.contrasenia.length < 6) { + errores.contrasenia = 'La contraseña debe tener al menos 6 caracteres'; + } + + if (!datos.numeroTelefono) { + errores.numeroTelefono = 'El número de teléfono es obligatorio'; + } else if (!telefonoValido.test(datos.numeroTelefono)) { + errores.numeroTelefono = 'El número de teléfono debe tener exactamente 10 dígitos'; + } + + if (!datos.direccion || datos.direccion.trim().length === 0) { + errores.direccion = 'La dirección es obligatoria'; + } + + if (!datos.fechaNacimiento) { + errores.fechaNacimiento = 'La fecha de nacimiento es obligatoria'; + } else { + const hoy = new Date(); + const fecha = new Date(datos.fechaNacimiento); + if (fecha > hoy) { + errores.fechaNacimiento = 'La fecha no puede ser futura'; + } + } + + if (!datos.genero) { + errores.genero = 'El género es obligatorio'; + } + + if (typeof datos.estatus === 'undefined' || datos.estatus === null) { + errores.estatus = 'El estatus es obligatorio'; + } + + if (!datos.idRol) { + errores.idRol = 'El rol es obligatorio'; + } + + return errores; +}; diff --git a/src/Dominio/Repositorios/Usuarios/RepositorioActualizarUsuario.js b/src/Dominio/Repositorios/Usuarios/RepositorioActualizarUsuario.js new file mode 100644 index 00000000..cfc3ef8c --- /dev/null +++ b/src/Dominio/Repositorios/Usuarios/RepositorioActualizarUsuario.js @@ -0,0 +1,25 @@ +import axios from 'axios'; +import { RUTAS_API } from '@Constantes/rutasAPI'; + +const API_KEY = import.meta.env.VITE_API_KEY; + +export class RepositorioActualizarUsuario { + static async actualizar(cambios) { + try { + const respuesta = await axios.put( + RUTAS_API.USUARIOS.ACTUALIZAR_USUARIO, + { cambios }, + { + withCredentials: true, + headers: { + 'x-api-key': API_KEY, + }, + } + ); + return respuesta.data; + } catch (error) { + const mensaje = error?.response?.data?.mensaje || 'Error al actualizar'; + throw new Error(mensaje); + } + } +} diff --git a/src/Utilidades/Constantes/rutas.js b/src/Utilidades/Constantes/rutas.js index 9e391155..afd9eac0 100644 --- a/src/Utilidades/Constantes/rutas.js +++ b/src/Utilidades/Constantes/rutas.js @@ -42,6 +42,7 @@ export const RUTAS = { BASE: '/usuarios', CONSULTAR_ROLES: '/consultar-roles', CONFIRMAR_CREACION: '/confirmar-creacion', + ACTUALIZAR_USUARIO: '/actualizar-usuario', }, }, SISTEMA_TIENDA: { diff --git a/src/Utilidades/Constantes/rutasAPI.js b/src/Utilidades/Constantes/rutasAPI.js index ea8837c0..7d64bd3d 100644 --- a/src/Utilidades/Constantes/rutasAPI.js +++ b/src/Utilidades/Constantes/rutasAPI.js @@ -13,13 +13,13 @@ const BASE_EVENTOS = `${BASE_URL}/api/eventos`; const BASE_PAGOS = `${BASE_URL}/api/pagos`; const BASE_AUTENTICACION = `${BASE_URL}/api/autenticacion`; - export const RUTAS_API = { USUARIOS: { BASE: BASE_USUARIOS, CONSULTAR_LISTA: `${BASE_USUARIOS}/consultar-lista-usuarios`, CONSULTAR_USUARIO: `${BASE_USUARIOS}/consultar-usuario`, ELIMINAR_USUARIOS: `${BASE_USUARIOS}/eliminar-usuarios`, + ACTUALIZAR_USUARIO: `${BASE_USUARIOS}/actualizar-usuario`, }, AUTENTICACION: { @@ -27,7 +27,7 @@ export const RUTAS_API = { ACTIVAR_2FA: `${BASE_AUTENTICACION}/activar-2fa`, VERIFICAR_2FA: `${BASE_AUTENTICACION}/verificar-2fa`, }, - + CATEGORIAS: { BASE: BASE_CATEGORIAS, CONSULTAR_LISTA: `${BASE_CATEGORIAS}/consultar-lista-categorias`, diff --git a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx new file mode 100644 index 00000000..f12dbb83 --- /dev/null +++ b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx @@ -0,0 +1,297 @@ +import { useState, useEffect } from 'react'; +import { Box, Grid } from '@mui/material'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { DateField } from '@mui/x-date-pickers/DateField'; +import CampoTexto from '@Atomos/CampoTexto'; +import CampoSelect from '@Atomos/CampoSelect'; +import Alerta from '@Moleculas/Alerta'; +import ModalFlotante from '@Organismos/ModalFlotante'; +import FormularioActualizarUsuario from '@Organismos/Formularios/FormularioActualizarUsuario'; +import { useConsultarClientes } from '@Hooks/Clientes/useConsultarClientes'; +import { useActualizarUsuario } from '@Hooks/Usuarios/useActualizarUsuario'; +import CampoSelectMultiple from '@Atomos/CampoSelectMultiple'; +import { useAccionesUsuario } from '@Hooks/Usuarios/useAccionesUsuario'; + +const FormularioActualizarUsuario = ({ open, onClose, usuario, onUsuarioActualizado }) => { + const { + datosUsuario, + setDatosUsuario, + erroresValidacion, + alerta, + setAlerta, + cargando, + esEdicion, + manejarCambio, + manejarFechaNacimiento, + obtenerHelperText, + handleGuardar, + limpiarFormulario, + CAMPO_OBLIGATORIO, + } = useAccionesUsuario(usuarioInicial); // usuarioInicial es null para crear, o el usuario para editar + + useEffect(() => { + if (usuario) { + setDatosUsuario({ + nombreCompleto: usuario.nombreCompleto || '', + apellido: usuario.apellido || '', + correoElectronico: usuario.correoElectronico || '', + numeroTelefono: usuario.numeroTelefono || '', + direccion: usuario.direccion || '', + codigoPostal: usuario.codigoPostal || '', + fechaNacimiento: usuario.fechaNacimiento || null, + genero: usuario.genero || '', + cliente: usuario.cliente || [], + rol: usuario.rol || '', + contrasenia: '', + }); + } + }, [usuario]); + + const { errores, handleActualizarUsuario } = useActualizarUsuario(); + const { roles, cargando: cargandoRoles } = useConsultarRoles(); + const { clientes } = useConsultarClientes(); + const esSuperAdmin = datosUsuario.rol === 1; + + const manejarConfirmacion = async () => { + const resultado = await handleActualizarUsuario({ + ...datosUsuario, + idUsuario: usuario.idUsuario, + }); + + if (resultado?.mensaje) { + if (resultado.exito) { + setAlerta({ + tipo: 'success', + mensaje: `Usuario actualizado exitosamente.`, + icono: true, + cerrable: true, + centradoInferior: true, + duracion: 3000, + }); + setTimeout(async () => { + if (onUsuarioActualizado) await onUsuarioActualizado(); + manejarCierre(); + }, 2000); + } else { + setAlerta({ + tipo: 'error', + mensaje: resultado.mensaje, + }); + } + } + }; + + const manejarCierre = () => { + setAlerta(null); + onClose(); + }; + + const estiloCuadricula = { + display: 'flex', + justifyContent: 'center', + }; + + return ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + + + rol.idRol !== 3) + .map((rol) => ({ + value: rol.idRol, + label: rol.nombre, + }))} + disabled={cargandoRoles} + /> + + + ({ + value: cliente.idCliente, + label: cliente.nombreComercial, + }))} + disabled={esSuperAdmin} + /> + + + + + + + + {alerta && ( + setAlerta(null)} + centradoInferior + /> + )} + + ); +}; + +export default FormularioActualizarUsuario; diff --git a/src/Vistas/Componentes/Organismos/ModalUsuarios.jsx b/src/Vistas/Componentes/Organismos/ModalUsuarios.jsx new file mode 100644 index 00000000..f6a2a6ef --- /dev/null +++ b/src/Vistas/Componentes/Organismos/ModalUsuarios.jsx @@ -0,0 +1,5 @@ +import { Box } from '@mui/material'; +import Alerta from '@Moleculas/Alerta'; +import ModalFlotante from '@Organismos/ModalFlotante'; +import FormaEmpleado from '@Organismos/Formularios/FormaEmpleado'; +import { useLeerUsuario } from '@Hooks/Usuarios/useLeerUsuario'; diff --git a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx index 45234ef6..9711b419 100644 --- a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx +++ b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx @@ -21,6 +21,7 @@ import { useTheme } from '@mui/material'; import { useActivar2FA } from '@Hooks/Usuarios/useActivar2FA'; import Activar2FAModal from '@Organismos/Activar2FAModal'; import Verificar2FAModal from '@Moleculas/Verificar2FAModal'; +//import FormularioActualizarUsuario from '@Organismos/Formularios/FormularioActualizarUsuario.jsx'; const estiloImagenLogo = { marginRight: '1rem' }; @@ -44,21 +45,22 @@ const ListaUsuarios = () => { const navigate = useNavigate(); const [alerta, setAlerta] = useState(null); const { usuarios, cargando, error, recargar } = useConsultarListaUsuarios(); - const { roles} = useConsultarRoles(); + const { roles } = useConsultarRoles(); const { usuario: usuarioAutenticado } = useAuth(); const [modalCrearUsuarioAbierto, setModalCrearUsuarioAbierto] = useState(false); const [idUsuarioSeleccionado, setIdUsuarioSeleccionado] = useState(null); const [modalDetalleAbierto, setModalDetalleAbierto] = useState(false); + const [modalActualizarAbierto, setModalActualizarAbierto] = useState(false); const { usuario, cargando: cargandoDetalle, error: errorDetalle, } = useUsuarioId(modalDetalleAbierto ? idUsuarioSeleccionado : null); - const [modal2FAAbierto, setModal2FAAbierto] = useState(false); - const { qrCode, cargando: cargandoQR, error: errorQR, setQrCode } = useActivar2FA(); + const [modal2FAAbierto, setModal2FAAbierto] = useState(false); + const { qrCode, cargando: cargandoQR, error: errorQR, setQrCode } = useActivar2FA(); - /** const manejarActivar2FA = async () => { + /** const manejarActivar2FA = async () => { await activar2FA({ idUsuario: usuarioAutenticado?.idUsuario, nombre: usuarioAutenticado?.nombre, @@ -68,7 +70,7 @@ const ListaUsuarios = () => { }; */ const opcionesRol = roles.map((rol) => ({ - value: rol.idRol, + value: rol.idRol, label: rol.nombre, })); @@ -85,21 +87,21 @@ const ListaUsuarios = () => { await cerrarSesion(); }; const { cerrarSesion } = useAuth(); -const { - usuariosAEliminar, - abrirPopUp, - abrirModal2FA, - error2FA, - cargando2FA, - manejarSeleccion, - manejarAbrirPopUp, - manejarCerrarPopUp, - eliminarUsuarios, - manejarVerificar2FA, - manejarCerrarModal2FA, - codigo2FA, - setCodigo2FA -} = useEliminarUsuarios(setAlerta, recargar); + const { + usuariosAEliminar, + abrirPopUp, + abrirModal2FA, + error2FA, + cargando2FA, + manejarSeleccion, + manejarAbrirPopUp, + manejarCerrarPopUp, + eliminarUsuarios, + manejarVerificar2FA, + manejarCerrarModal2FA, + codigo2FA, + setCodigo2FA, + } = useEliminarUsuarios(setAlerta, recargar); useEffect(() => {}, [usuariosAEliminar]); @@ -257,7 +259,8 @@ const { backgroundColor: colores.verde[1], disabled: !usuarioAutenticado?.permisos?.includes(PERMISOS.ACTIVAR_2FA_SUPERADMIN), }, - */]; + */ + ]; const redirigirATienda = () => { navigate(RUTAS.SISTEMA_TIENDA.BASE, { replace: true }); @@ -388,8 +391,11 @@ const { variant: 'contained', color: 'primary', backgroundColor: colores.altertex[1], - onClick: () => console.log('Editar usuario'), - disabled: true, + onClick: () => { + setModalDetalleAbierto(false); + setTimeout(() => setModalActualizarAbierto(true), 100); + }, + disabled: !usuarioAutenticado?.permisos?.includes(PERMISOS.ACTUALIZAR_USUARIO), }, { label: 'SALIR', @@ -404,34 +410,34 @@ const {

Cargando usuario...

) : usuario ? ( <> - cliente?.nombreCliente) - ? usuario.clientes - .filter((cliente) => cliente?.nombreCliente) - .map((cliente) => cliente.nombreCliente) - .join(', ') - : 'Sin cliente asignado' - } - rol={obtenerIdRolPorNombre(usuario.rol)} - datosContacto={{ - email: usuario.correoElectronico, - telefono: usuario.numeroTelefono, - direccion: usuario.direccion, - }} - datosAdicionales={{ - nacimiento: new Date(usuario.fechaNacimiento).toLocaleDateString('es-MX'), - genero: usuario.genero, - }} - estadoUsuario={{ - label: usuario.estatus === 1 ? 'Activo' : 'Inactivo', - color: 'primary', - shape: 'circular', - backgroundColor: 'rgba(24, 50, 165, 1)', - }} - opcionesRol={opcionesRol} - /> + cliente?.nombreCliente) + ? usuario.clientes + .filter((cliente) => cliente?.nombreCliente) + .map((cliente) => cliente.nombreCliente) + .join(', ') + : 'Sin cliente asignado' + } + rol={obtenerIdRolPorNombre(usuario.rol)} + datosContacto={{ + email: usuario.correoElectronico, + telefono: usuario.numeroTelefono, + direccion: usuario.direccion, + }} + datosAdicionales={{ + nacimiento: new Date(usuario.fechaNacimiento).toLocaleDateString('es-MX'), + genero: usuario.genero, + }} + estadoUsuario={{ + label: usuario.estatus === 1 ? 'Activo' : 'Inactivo', + color: 'primary', + shape: 'circular', + backgroundColor: 'rgba(24, 50, 165, 1)', + }} + opcionesRol={opcionesRol} + /> ) : (

No se encontró información del usuario.

@@ -439,6 +445,15 @@ const { )} + {modalActualizarAbierto && usuario && ( + setModalActualizarAbierto(false)} + onAccion={recargar} + usuarioEdicion={usuario} + /> + )} + {errorDetalle && (
diff --git a/src/hooks/Usuarios/useAccionesUsuario.js b/src/hooks/Usuarios/useAccionesUsuario.js new file mode 100644 index 00000000..08284b03 --- /dev/null +++ b/src/hooks/Usuarios/useAccionesUsuario.js @@ -0,0 +1,139 @@ +import { useState } from 'react'; +import dayjs from 'dayjs'; +import { RepositorioActualizarUsuario } from '@Repositorios/Usuarios/RepositorioActualizarUsuario'; +import { validarDatosActualizarUsuario } from '@Modelos/Usuarios/ActualizarUsuario'; + +export const useAccionesUsuario = (usuarioInicial = null) => { + const esEdicion = !!usuarioInicial; + const [erroresValidacion, setErroresValidacion] = useState({}); + const [cargando, setCargando] = useState(false); + const [alerta, setAlerta] = useState(null); + + // Inicializar con datos de edición o vacío + const [datosUsuario, setDatosUsuario] = useState(() => { + if (esEdicion) { + let fechaNacimiento = null; + if (usuarioInicial.fechaNacimiento) { + fechaNacimiento = dayjs(usuarioInicial.fechaNacimiento); + } + return { + ...usuarioInicial, + idUsuario: usuarioInicial.idUsuario || usuarioInicial.id, + nombreCompleto: usuarioInicial.nombreCompleto || '', + correoElectronico: usuarioInicial.correoElectronico || '', + fechaNacimiento, + }; + } + return { + nombreCompleto: '', + correoElectronico: '', + contrasenia: '', + numeroTelefono: '', + direccion: '', + fechaNacimiento: null, + genero: '', + rol: '', + cliente: [], + }; + }); + + const CAMPO_OBLIGATORIO = 'Este campo es obligatorio'; + + // Métodos para manejar cambios + const manejarCambio = (evento) => { + const { name, value } = evento.target; + setDatosUsuario((prev) => ({ ...prev, [name]: value })); + }; + + const manejarFechaNacimiento = (nuevaFecha) => { + setDatosUsuario((prev) => ({ + ...prev, + fechaNacimiento: nuevaFecha, + })); + }; + + const obtenerHelperText = (campo) => { + const err = erroresValidacion[campo]; + if (err) { + return typeof err === 'string' ? err : CAMPO_OBLIGATORIO; + } + return ''; + }; + + const handleGuardar = async () => { + const datosProcesados = { + ...datosUsuario, + idUsuario: esEdicion ? usuarioInicial.idUsuario || usuarioInicial.id : datosUsuario.idUsuario, + fechaNacimiento: datosUsuario.fechaNacimiento + ? dayjs(datosUsuario.fechaNacimiento).format('YYYY-MM-DD') + : null, + }; + + const nuevosErrores = validarDatosActualizarUsuario(datosProcesados); + + if (Object.keys(nuevosErrores).length > 0) { + setErroresValidacion(nuevosErrores); + setAlerta({ + tipo: 'error', + mensaje: 'Corrige los errores en el formulario antes de guardar.', + }); + return { exito: false }; + } + + setErroresValidacion({}); + setAlerta(null); + setCargando(true); + + try { + await RepositorioActualizarUsuario.actualizar(datosProcesados); + setAlerta({ + tipo: 'success', + mensaje: esEdicion ? 'Usuario actualizado correctamente' : 'Usuario creado correctamente', + }); + return { + exito: true, + mensaje: esEdicion ? 'Usuario actualizado correctamente' : 'Usuario creado correctamente', + }; + } catch (error) { + setAlerta({ + tipo: 'error', + mensaje: error.message || 'Error al guardar el usuario', + }); + return { exito: false, mensaje: error.message || 'Error al guardar el usuario' }; + } finally { + setCargando(false); + } + }; + + const limpiarFormulario = () => { + setDatosUsuario({ + nombreCompleto: '', + correoElectronico: '', + contrasenia: '', + numeroTelefono: '', + direccion: '', + fechaNacimiento: null, + genero: '', + rol: '', + cliente: [], + }); + setErroresValidacion({}); + setAlerta(null); + }; + + return { + datosUsuario, + setDatosUsuario, + erroresValidacion, + alerta, + setAlerta, + cargando, + esEdicion, + manejarCambio, + manejarFechaNacimiento, + obtenerHelperText, + handleGuardar, + limpiarFormulario, + CAMPO_OBLIGATORIO, + }; +}; diff --git a/src/hooks/Usuarios/useActualizarUsuario.js b/src/hooks/Usuarios/useActualizarUsuario.js new file mode 100644 index 00000000..288d88bc --- /dev/null +++ b/src/hooks/Usuarios/useActualizarUsuario.js @@ -0,0 +1,25 @@ +import { useState } from 'react'; +import { RepositorioActualizarUsuario } from '@Repositorios/Usuarios/RepositorioActualizarUsuario'; + +export function useActualizarUsuario() { + const [cargando, setCargando] = useState(false); + const [error, setError] = useState(null); + const [mensaje, setMensaje] = useState(''); + + const actualizar = async (cambios) => { + setCargando(true); + setError(null); + setMensaje(''); + + try { + const respuesta = await RepositorioActualizarUsuario.actualizar(cambios); + setMensaje(respuesta.mensaje || 'Actualización exitosa'); + } catch (err) { + setError(err.message || 'Ocurrió un error'); + } finally { + setCargando(false); + } + }; + + return { actualizar, cargando, error, mensaje }; +} From 6fa845b25dfe6405c17802fd154ec4d267c21b0f Mon Sep 17 00:00:00 2001 From: max Date: Mon, 2 Jun 2025 13:33:02 -0600 Subject: [PATCH 02/23] Refactor user update forms to improve validation handling and integrate FormularioActualizarUsuario component --- .../FormularioActualizarUsuario.jsx | 472 +++++++----------- .../Componentes/Organismos/ModalUsuarios.jsx | 85 +++- src/hooks/Usuarios/useAccionesUsuario.js | 7 + 3 files changed, 283 insertions(+), 281 deletions(-) diff --git a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx index f12dbb83..384d31b3 100644 --- a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx +++ b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx @@ -1,296 +1,210 @@ -import { useState, useEffect } from 'react'; import { Box, Grid } from '@mui/material'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import { DateField } from '@mui/x-date-pickers/DateField'; import CampoTexto from '@Atomos/CampoTexto'; import CampoSelect from '@Atomos/CampoSelect'; -import Alerta from '@Moleculas/Alerta'; -import ModalFlotante from '@Organismos/ModalFlotante'; -import FormularioActualizarUsuario from '@Organismos/Formularios/FormularioActualizarUsuario'; -import { useConsultarClientes } from '@Hooks/Clientes/useConsultarClientes'; -import { useActualizarUsuario } from '@Hooks/Usuarios/useActualizarUsuario'; import CampoSelectMultiple from '@Atomos/CampoSelectMultiple'; -import { useAccionesUsuario } from '@Hooks/Usuarios/useAccionesUsuario'; - -const FormularioActualizarUsuario = ({ open, onClose, usuario, onUsuarioActualizado }) => { - const { - datosUsuario, - setDatosUsuario, - erroresValidacion, - alerta, - setAlerta, - cargando, - esEdicion, - manejarCambio, - manejarFechaNacimiento, - obtenerHelperText, - handleGuardar, - limpiarFormulario, - CAMPO_OBLIGATORIO, - } = useAccionesUsuario(usuarioInicial); // usuarioInicial es null para crear, o el usuario para editar - - useEffect(() => { - if (usuario) { - setDatosUsuario({ - nombreCompleto: usuario.nombreCompleto || '', - apellido: usuario.apellido || '', - correoElectronico: usuario.correoElectronico || '', - numeroTelefono: usuario.numeroTelefono || '', - direccion: usuario.direccion || '', - codigoPostal: usuario.codigoPostal || '', - fechaNacimiento: usuario.fechaNacimiento || null, - genero: usuario.genero || '', - cliente: usuario.cliente || [], - rol: usuario.rol || '', - contrasenia: '', - }); - } - }, [usuario]); - - const { errores, handleActualizarUsuario } = useActualizarUsuario(); - const { roles, cargando: cargandoRoles } = useConsultarRoles(); - const { clientes } = useConsultarClientes(); - const esSuperAdmin = datosUsuario.rol === 1; - - const manejarConfirmacion = async () => { - const resultado = await handleActualizarUsuario({ - ...datosUsuario, - idUsuario: usuario.idUsuario, - }); - - if (resultado?.mensaje) { - if (resultado.exito) { - setAlerta({ - tipo: 'success', - mensaje: `Usuario actualizado exitosamente.`, - icono: true, - cerrable: true, - centradoInferior: true, - duracion: 3000, - }); - setTimeout(async () => { - if (onUsuarioActualizado) await onUsuarioActualizado(); - manejarCierre(); - }, 2000); - } else { - setAlerta({ - tipo: 'error', - mensaje: resultado.mensaje, - }); - } - } - }; - - const manejarCierre = () => { - setAlerta(null); - onClose(); - }; +const FormularioActualizarUsuario = ({ + datosUsuario, + erroresValidacion, + manejarCambio, + manejarFechaNacimiento, + obtenerHelperText, + roles, + clientes, + esSuperAdmin, + cargandoRoles, + CAMPO_OBLIGATORIO, +}) => { const estiloCuadricula = { display: 'flex', justifyContent: 'center', }; return ( - <> - - - - - - - - - - - - - - - - - - - - - - - - - - - - rol.idRol !== 3) - .map((rol) => ({ - value: rol.idRol, - label: rol.nombre, - }))} - disabled={cargandoRoles} - /> - - - ({ - value: cliente.idCliente, - label: cliente.nombreComercial, - }))} - disabled={esSuperAdmin} - /> - - - - - - - - {alerta && ( - setAlerta(null)} - centradoInferior - /> - )} - + + + + + + + + + + + + + + + + + + + + + + + + + + + rol.idRol !== 3) + .map((rol) => ({ + value: rol.idRol, + label: rol.nombre, + }))} + disabled={cargandoRoles} + /> + + + ({ + value: cliente.idCliente, + label: cliente.nombreComercial, + }))} + disabled={esSuperAdmin} + /> + + + + + + ); }; diff --git a/src/Vistas/Componentes/Organismos/ModalUsuarios.jsx b/src/Vistas/Componentes/Organismos/ModalUsuarios.jsx index f6a2a6ef..2892e6fa 100644 --- a/src/Vistas/Componentes/Organismos/ModalUsuarios.jsx +++ b/src/Vistas/Componentes/Organismos/ModalUsuarios.jsx @@ -1,5 +1,86 @@ import { Box } from '@mui/material'; import Alerta from '@Moleculas/Alerta'; import ModalFlotante from '@Organismos/ModalFlotante'; -import FormaEmpleado from '@Organismos/Formularios/FormaEmpleado'; -import { useLeerUsuario } from '@Hooks/Usuarios/useLeerUsuario'; +import FormularioActualizarUsuario from './Formularios/FormularioActualizarUsuario'; +import { useAccionesUsuario } from '@Hooks/Usuarios/useAccionesUsuario'; + +const ModalUsuarios = ({ open, onClose, onAccion, usuarioEdicion }) => { + const { + datosUsuario, + erroresValidacion, + alerta, + setAlerta, + cargando, + esEdicion, + manejarCambio, + manejarFechaNacimiento, + obtenerHelperText, + handleGuardar, + limpiarFormulario, + CAMPO_OBLIGATORIO, + roles, + clientes, + esSuperAdmin, + cargandoRoles, + } = useAccionesUsuario(usuarioEdicion); + + const manejarConfirmacion = async () => { + const resultado = await handleGuardar(); + if (resultado?.exito) { + if (onAccion) await onAccion(); + setTimeout(() => { + onClose(); + }, 1500); + } + }; + + const manejarCierre = () => { + setAlerta(null); + onClose(); + }; + + return ( + + + + + {alerta && ( + setAlerta(null)} + /> + )} + + ); +}; + +export default ModalUsuarios; diff --git a/src/hooks/Usuarios/useAccionesUsuario.js b/src/hooks/Usuarios/useAccionesUsuario.js index 08284b03..02ce67ca 100644 --- a/src/hooks/Usuarios/useAccionesUsuario.js +++ b/src/hooks/Usuarios/useAccionesUsuario.js @@ -20,8 +20,15 @@ export const useAccionesUsuario = (usuarioInicial = null) => { ...usuarioInicial, idUsuario: usuarioInicial.idUsuario || usuarioInicial.id, nombreCompleto: usuarioInicial.nombreCompleto || '', + apellido: usuarioInicial.apellido || '', correoElectronico: usuarioInicial.correoElectronico || '', + numeroTelefono: usuarioInicial.numeroTelefono || '', + direccion: usuarioInicial.direccion || '', fechaNacimiento, + genero: usuarioInicial.genero || '', + rol: usuarioInicial.rol || '', + cliente: usuarioInicial.cliente || [], + contrasenia: '', }; } return { From 0996f12458d68940921bc610031c081b33828c35 Mon Sep 17 00:00:00 2001 From: max Date: Tue, 3 Jun 2025 11:54:17 -0600 Subject: [PATCH 03/23] Add ModalActualizarUsuario component to encapsulate user update functionality --- .../FormularioActualizarUsuario.jsx | 29 ++++-- .../Organismos/ModalActualizarUsuario.jsx | 91 +++++++++++++++++++ src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx | 8 +- 3 files changed, 119 insertions(+), 9 deletions(-) create mode 100644 src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx diff --git a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx index 384d31b3..c5c2069d 100644 --- a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx +++ b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx @@ -1,3 +1,4 @@ +import { useState, useEffect, useRef } from 'react'; import { Box, Grid } from '@mui/material'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; @@ -12,11 +13,12 @@ const FormularioActualizarUsuario = ({ manejarCambio, manejarFechaNacimiento, obtenerHelperText, - roles, - clientes, - esSuperAdmin, - cargandoRoles, - CAMPO_OBLIGATORIO, + roles = [], + clientes = [], + cargandoRoles = false, + cargando = false, + esSuperAdmin = false, + CAMPO_OBLIGATORIO = 'Este campo es obligatorio', }) => { const estiloCuadricula = { display: 'flex', @@ -51,6 +53,7 @@ const FormularioActualizarUsuario = ({ }} /> + + + + + + + + + diff --git a/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx new file mode 100644 index 00000000..c9a9d0ab --- /dev/null +++ b/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx @@ -0,0 +1,91 @@ +import { Box } from '@mui/material'; +import Alerta from '@Moleculas/Alerta'; +import ModalFlotante from '@Organismos/ModalFlotante'; +import FormularioActualizarUsuario from '@Organismos/Formularios/FormularioActualizarUsuario'; +import { useAccionesUsuario } from '@Hooks/Usuarios/useAccionesUsuario'; + +const ModalActualizarUsuario = ({ + open, + onClose, + onAccion, + usuarioEdicion, + roles = [], + clientes = [], + esSuperAdmin = false, + cargandoRoles = false, +}) => { + const { + datosUsuario, + erroresValidacion, + alerta, + setAlerta, + manejarCambio, + manejarFechaNacimiento, + obtenerHelperText, + handleGuardar, + cargando, + esEdicion, + limpiarFormulario, + } = useAccionesUsuario(usuarioEdicion); + + const manejarConfirmacion = async () => { + const resultado = await handleGuardar(); + if (resultado?.exito) { + if (onAccion) await onAccion(); + limpiarFormulario(); + setTimeout(() => { + onClose(); + }, 1500); + } + }; + + const manejarCierre = () => { + setAlerta(null); + onClose(); + }; + + return ( + + + + + {alerta && ( + setAlerta(null)} + /> + )} + + ); +}; + +export default ModalActualizarUsuario; diff --git a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx index 9711b419..5e056d73 100644 --- a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx +++ b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx @@ -21,7 +21,7 @@ import { useTheme } from '@mui/material'; import { useActivar2FA } from '@Hooks/Usuarios/useActivar2FA'; import Activar2FAModal from '@Organismos/Activar2FAModal'; import Verificar2FAModal from '@Moleculas/Verificar2FAModal'; -//import FormularioActualizarUsuario from '@Organismos/Formularios/FormularioActualizarUsuario.jsx'; +import ModalActualizarUsuario from '@Organismos/ModalActualizarUsuario'; const estiloImagenLogo = { marginRight: '1rem' }; @@ -446,11 +446,15 @@ const ListaUsuarios = () => { )} {modalActualizarAbierto && usuario && ( - setModalActualizarAbierto(false)} onAccion={recargar} usuarioEdicion={usuario} + roles={roles} + clientes={[]} + esSuperAdmin={false} + cargandoRoles={false} /> )} From c009908f1b996a87e56feb10629e47de1791db95 Mon Sep 17 00:00:00 2001 From: max Date: Tue, 3 Jun 2025 13:29:09 -0600 Subject: [PATCH 04/23] Add password confirmation validation and normalize user data in update forms --- .../Modelos/Usuarios/ActualizarUsuario.js | 8 + .../FormularioActualizarUsuario.jsx | 391 ++++++++++-------- src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx | 5 +- src/hooks/Usuarios/useAccionesUsuario.js | 29 +- 4 files changed, 248 insertions(+), 185 deletions(-) diff --git a/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js b/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js index d19f142e..82e5ada2 100644 --- a/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js +++ b/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js @@ -33,6 +33,14 @@ export const validarDatosActualizarUsuario = (datos, usuariosExistentes = []) => errores.contrasenia = 'La contraseña debe tener al menos 6 caracteres'; } + if (datos.contrasenia) { + if (!datos.confirmarContrasenia) { + errores.confirmarContrasenia = true; + } else if (datos.contrasenia !== datos.confirmarContrasenia) { + errores.confirmarContrasenia = 'Las contraseñas no coinciden'; + } + } + if (!datos.numeroTelefono) { errores.numeroTelefono = 'El número de teléfono es obligatorio'; } else if (!telefonoValido.test(datos.numeroTelefono)) { diff --git a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx index c5c2069d..f4d6bc1b 100644 --- a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx +++ b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx @@ -1,4 +1,4 @@ -import { useState, useEffect, useRef } from 'react'; +import { useEffect, useRef } from 'react'; import { Box, Grid } from '@mui/material'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; @@ -25,201 +25,228 @@ const FormularioActualizarUsuario = ({ justifyContent: 'center', }; + const rolAnterior = useRef(null); + useEffect(() => { + if (rolAnterior.current === 1 && datosUsuario.rol !== 1) { + manejarCambio({ + target: { + name: 'cliente', + value: [], + }, + }); + } + if (datosUsuario.rol === 1 && clientes.length > 0) { + manejarCambio({ + target: { + name: 'cliente', + value: clientes.map((cliente) => cliente.idCliente), + }, + }); + } + rolAnterior.current = datosUsuario.rol; + }, [datosUsuario.rol, clientes]); + return ( - - - - - + + + + + + + + - - + + - + + - - - - - + + + - - - + + + - - - + + + - - - + + + - - - + + rol.idRol !== 3) + .map((rol) => ({ + value: rol.idRol, + label: rol.nombre, + }))} + disabled={cargandoRoles} + /> + - - rol.idRol !== 3) - .map((rol) => ({ - value: rol.idRol, - label: rol.nombre, - }))} - disabled={cargandoRoles} - /> - + + ({ + value: cliente.idCliente, + label: cliente.nombreComercial, + }))} + disabled={esSuperAdmin} + /> + - - ({ - value: cliente.idCliente, - label: cliente.nombreComercial, - }))} - disabled={esSuperAdmin} - /> - + + + - - - + + - + ); }; diff --git a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx index 5e056d73..214f5937 100644 --- a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx +++ b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx @@ -9,6 +9,7 @@ import Chip from '@Atomos/Chip'; import { useConsultarListaUsuarios } from '@Hooks/Usuarios/useConsultarListaUsuarios'; import { useEliminarUsuarios } from '@Hooks/Usuarios/useEliminarUsuarios'; import { useConsultarRoles } from '@Hooks/Roles/useConsultarRoles'; +import { useConsultarClientes } from '@Hooks/Clientes/useConsultarClientes'; import { RUTAS } from '@Constantes/rutas'; import { tokens } from '@SRC/theme'; import NavegadorAdministrador from '@Organismos/NavegadorAdministrador'; @@ -37,6 +38,7 @@ const estiloImagenLogo = { marginRight: '1rem' }; * @see [RF02 Super Administrador Consulta Lista de Usuarios](https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF2) * @see [RF03 Leer usuario](https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF3) * @see [RF05 Super Administrador Eliminar Usuario](https://codeandco-wiki.netlify.app/docs/proyectos/textiles/documentacion/requisitos/RF5) + * @see [RF04 Super Administrador Actualiza Usuario](https://codeandco-wiki.netlify.app/docs/next/proyectos/textiles/documentacion/requisitos/RF4) */ const ListaUsuarios = () => { @@ -45,6 +47,7 @@ const ListaUsuarios = () => { const navigate = useNavigate(); const [alerta, setAlerta] = useState(null); const { usuarios, cargando, error, recargar } = useConsultarListaUsuarios(); + const { clientes, cargando: cargandoClientes } = useConsultarClientes(); const { roles } = useConsultarRoles(); const { usuario: usuarioAutenticado } = useAuth(); const [modalCrearUsuarioAbierto, setModalCrearUsuarioAbierto] = useState(false); @@ -452,7 +455,7 @@ const ListaUsuarios = () => { onAccion={recargar} usuarioEdicion={usuario} roles={roles} - clientes={[]} + clientes={clientes} esSuperAdmin={false} cargandoRoles={false} /> diff --git a/src/hooks/Usuarios/useAccionesUsuario.js b/src/hooks/Usuarios/useAccionesUsuario.js index 02ce67ca..091905e9 100644 --- a/src/hooks/Usuarios/useAccionesUsuario.js +++ b/src/hooks/Usuarios/useAccionesUsuario.js @@ -16,6 +16,26 @@ export const useAccionesUsuario = (usuarioInicial = null) => { if (usuarioInicial.fechaNacimiento) { fechaNacimiento = dayjs(usuarioInicial.fechaNacimiento); } + + // Normalizar género + let genero = ''; + if (usuarioInicial.genero) { + if (usuarioInicial.genero.toLowerCase() === 'femenino') genero = 'Mujer'; + else if (usuarioInicial.genero.toLowerCase() === 'masculino') genero = 'Hombre'; + else genero = 'Otro'; + } + + let idRol = usuarioInicial.idRol || ''; + if (typeof usuarioInicial.rol === 'string') { + const rolesMap = { + 'Super Administrador': 1, + Administrador: 2, + }; + idRol = rolesMap[usuarioInicial.rol] || ''; + } else if (usuarioInicial.rol) { + idRol = usuarioInicial.rol; + } + return { ...usuarioInicial, idUsuario: usuarioInicial.idUsuario || usuarioInicial.id, @@ -25,16 +45,19 @@ export const useAccionesUsuario = (usuarioInicial = null) => { numeroTelefono: usuarioInicial.numeroTelefono || '', direccion: usuarioInicial.direccion || '', fechaNacimiento, - genero: usuarioInicial.genero || '', - rol: usuarioInicial.rol || '', + genero, + idRol, cliente: usuarioInicial.cliente || [], contrasenia: '', + confirmarContrasenia: '', }; } return { nombreCompleto: '', + apellido: '', correoElectronico: '', contrasenia: '', + confirmarContrasenia: '', numeroTelefono: '', direccion: '', fechaNacimiento: null, @@ -78,6 +101,8 @@ export const useAccionesUsuario = (usuarioInicial = null) => { const nuevosErrores = validarDatosActualizarUsuario(datosProcesados); + console.log('Errores de validación:', nuevosErrores); + if (Object.keys(nuevosErrores).length > 0) { setErroresValidacion(nuevosErrores); setAlerta({ From c69f686c17cb69842007ad6193c7607781375d1b Mon Sep 17 00:00:00 2001 From: max Date: Wed, 4 Jun 2025 12:11:48 -0600 Subject: [PATCH 05/23] feat: add estatus field to user update form and handle undefined values --- .../FormularioActualizarUsuario.jsx | 19 ++++++++++- src/hooks/Usuarios/useAccionesUsuario.js | 34 ++++++++++--------- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx index f4d6bc1b..aab1d241 100644 --- a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx +++ b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx @@ -177,7 +177,7 @@ const FormularioActualizarUsuario = ({ + + + + { const [cargando, setCargando] = useState(false); const [alerta, setAlerta] = useState(null); - // Inicializar con datos de edición o vacío const [datosUsuario, setDatosUsuario] = useState(() => { if (esEdicion) { let fechaNacimiento = null; @@ -17,7 +16,6 @@ export const useAccionesUsuario = (usuarioInicial = null) => { fechaNacimiento = dayjs(usuarioInicial.fechaNacimiento); } - // Normalizar género let genero = ''; if (usuarioInicial.genero) { if (usuarioInicial.genero.toLowerCase() === 'femenino') genero = 'Mujer'; @@ -25,7 +23,7 @@ export const useAccionesUsuario = (usuarioInicial = null) => { else genero = 'Otro'; } - let idRol = usuarioInicial.idRol || ''; + let idRol = usuarioInicial.idRol ?? ''; if (typeof usuarioInicial.rol === 'string') { const rolesMap = { 'Super Administrador': 1, @@ -37,19 +35,18 @@ export const useAccionesUsuario = (usuarioInicial = null) => { } return { - ...usuarioInicial, - idUsuario: usuarioInicial.idUsuario || usuarioInicial.id, - nombreCompleto: usuarioInicial.nombreCompleto || '', - apellido: usuarioInicial.apellido || '', - correoElectronico: usuarioInicial.correoElectronico || '', - numeroTelefono: usuarioInicial.numeroTelefono || '', - direccion: usuarioInicial.direccion || '', - fechaNacimiento, - genero, - idRol, - cliente: usuarioInicial.cliente || [], + nombreCompleto: usuarioInicial.nombreCompleto ?? '', + apellido: usuarioInicial.apellido ?? '', + correoElectronico: usuarioInicial.correoElectronico ?? '', contrasenia: '', confirmarContrasenia: '', + numeroTelefono: usuarioInicial.numeroTelefono ?? '', + direccion: usuarioInicial.direccion ?? '', + fechaNacimiento, + genero, + idRol: idRol ?? '', + cliente: usuarioInicial.cliente ?? [], + estatus: usuarioInicial.estatus !== undefined ? usuarioInicial.estatus : 1, }; } return { @@ -62,8 +59,9 @@ export const useAccionesUsuario = (usuarioInicial = null) => { direccion: '', fechaNacimiento: null, genero: '', - rol: '', + idRol: '', cliente: [], + estatus: 1, }; }); @@ -97,8 +95,12 @@ export const useAccionesUsuario = (usuarioInicial = null) => { fechaNacimiento: datosUsuario.fechaNacimiento ? dayjs(datosUsuario.fechaNacimiento).format('YYYY-MM-DD') : null, + nombreCompleto: datosUsuario.nombreCompleto, + apellido: datosUsuario.apellido, }; + console.log('Enviando al backend:', datosProcesados); + const nuevosErrores = validarDatosActualizarUsuario(datosProcesados); console.log('Errores de validación:', nuevosErrores); @@ -146,7 +148,7 @@ export const useAccionesUsuario = (usuarioInicial = null) => { direccion: '', fechaNacimiento: null, genero: '', - rol: '', + idrol: '', cliente: [], }); setErroresValidacion({}); From 6b983fff395d61f077848b9d39ec643bb0814c52 Mon Sep 17 00:00:00 2001 From: max Date: Thu, 5 Jun 2025 20:22:26 -0600 Subject: [PATCH 06/23] Co-authored-by: Nicolas Hood Figueroa --- .../Modelos/Usuarios/ActualizarUsuario.js | 21 +++--- .../FormularioActualizarUsuario.jsx | 18 +----- .../Organismos/ModalActualizarUsuario.jsx | 64 ++++++++++--------- src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx | 8 ++- 4 files changed, 53 insertions(+), 58 deletions(-) diff --git a/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js b/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js index 82e5ada2..f63613ed 100644 --- a/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js +++ b/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js @@ -4,6 +4,8 @@ export const validarDatosActualizarUsuario = (datos, usuariosExistentes = []) => const errores = {}; const emailValido = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; const telefonoValido = /^\d{10}$/; + const tieneCaracterEspecial = /[!@#$%^&*(),.?":{}|<>]/; + const tieneMayuscula = /[A-Z]/; if (!datos.idUsuario) { errores.idUsuario = true; @@ -29,16 +31,19 @@ export const validarDatosActualizarUsuario = (datos, usuariosExistentes = []) => errores.correoElectronico = 'Este correo ya está registrado'; } - if (datos.contrasenia && datos.contrasenia.length < 6) { - errores.contrasenia = 'La contraseña debe tener al menos 6 caracteres'; + if (datos.contrasenia && datos.contrasenia.length < 8) { + errores.contrasenia = 'La contraseña debe tener al menos 8 caracteres'; + } else if (datos.contrasenia && !tieneCaracterEspecial.test(datos.contrasenia)) { + errores.contrasenia = + 'Debe contener al menos uno de estos caracteres: ! @ # $ % ^ & * ( ) , . ? " : { } | < >'; + } else if (datos.contrasenia && !tieneMayuscula.test(datos.contrasenia)) { + errores.contrasenia = 'Debe contener al menos una letra mayúscula'; } - if (datos.contrasenia) { - if (!datos.confirmarContrasenia) { - errores.confirmarContrasenia = true; - } else if (datos.contrasenia !== datos.confirmarContrasenia) { - errores.confirmarContrasenia = 'Las contraseñas no coinciden'; - } + if (datos.contrasenia && !datos.confirmarContrasenia) { + errores.confirmarContrasenia = true; + } else if (datos.contrasenia && datos.contrasenia !== datos.confirmarContrasenia) { + errores.confirmarContrasenia = 'Las contraseñas no coinciden'; } if (!datos.numeroTelefono) { diff --git a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx index aab1d241..031d17fb 100644 --- a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx +++ b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx @@ -64,22 +64,6 @@ const FormularioActualizarUsuario = ({ /> - - - - diff --git a/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx index c9a9d0ab..2052bc6b 100644 --- a/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx +++ b/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx @@ -35,7 +35,7 @@ const ModalActualizarUsuario = ({ limpiarFormulario(); setTimeout(() => { onClose(); - }, 1500); + }, 0); } }; @@ -45,36 +45,38 @@ const ModalActualizarUsuario = ({ }; return ( - - + - - + + + + {alerta && ( setAlerta(null)} /> )} - + ); }; diff --git a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx index cafb1694..62e62f9d 100644 --- a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx +++ b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx @@ -397,6 +397,7 @@ const ListaUsuarios = () => { onClick: () => { setModalDetalleAbierto(false); setTimeout(() => setModalActualizarAbierto(true), 100); + console.log('Editar usuario:', usuario); }, disabled: !usuarioAutenticado?.permisos?.includes(PERMISOS.ACTUALIZAR_USUARIO), }, @@ -453,7 +454,10 @@ const ListaUsuarios = () => { open={modalActualizarAbierto} onClose={() => setModalActualizarAbierto(false)} onAccion={recargar} - usuarioEdicion={usuario} + usuarioEdicion={{ + ...usuario, + cliente: usuario.clientes ? usuario.clientes.map((c) => c.idCliente) : [], + }} roles={roles} clientes={clientes} esSuperAdmin={false} @@ -471,4 +475,4 @@ const ListaUsuarios = () => { ); }; -export default ListaUsuarios; \ No newline at end of file +export default ListaUsuarios; From f19a1c445765eb9cd846330d9542308b38bde93b Mon Sep 17 00:00:00 2001 From: max Date: Thu, 5 Jun 2025 21:22:42 -0600 Subject: [PATCH 07/23] fix: remove unnecessary line breaks in user update form --- .../Formularios/FormularioActualizarUsuario.jsx | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx index 031d17fb..92b78866 100644 --- a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx +++ b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx @@ -63,7 +63,6 @@ const FormularioActualizarUsuario = ({ }} /> - - - - - - - - - - Date: Fri, 6 Jun 2025 15:46:39 -0600 Subject: [PATCH 08/23] fix: improve user update handling and validation messages --- .../Organismos/ModalActualizarUsuario.jsx | 23 +++++++++-------- src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx | 1 - src/hooks/Usuarios/useAccionesUsuario.js | 25 +++++++++++-------- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx index 2052bc6b..46a20957 100644 --- a/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx +++ b/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx @@ -32,10 +32,10 @@ const ModalActualizarUsuario = ({ const resultado = await handleGuardar(); if (resultado?.exito) { if (onAccion) await onAccion(); - limpiarFormulario(); setTimeout(() => { + limpiarFormulario(); onClose(); - }, 0); + }, 800); } }; @@ -76,16 +76,17 @@ const ModalActualizarUsuario = ({ cargando={cargando} /> + + {alerta && ( + setAlerta(null)} + /> + )} - {alerta && ( - setAlerta(null)} - /> - )} ); }; diff --git a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx index 62e62f9d..f82f74de 100644 --- a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx +++ b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx @@ -397,7 +397,6 @@ const ListaUsuarios = () => { onClick: () => { setModalDetalleAbierto(false); setTimeout(() => setModalActualizarAbierto(true), 100); - console.log('Editar usuario:', usuario); }, disabled: !usuarioAutenticado?.permisos?.includes(PERMISOS.ACTUALIZAR_USUARIO), }, diff --git a/src/hooks/Usuarios/useAccionesUsuario.js b/src/hooks/Usuarios/useAccionesUsuario.js index 1c80edb4..474b4d43 100644 --- a/src/hooks/Usuarios/useAccionesUsuario.js +++ b/src/hooks/Usuarios/useAccionesUsuario.js @@ -45,7 +45,13 @@ export const useAccionesUsuario = (usuarioInicial = null) => { fechaNacimiento, genero, idRol: idRol ?? '', - cliente: usuarioInicial.cliente ?? [], + cliente: Array.isArray(usuarioInicial.cliente) + ? usuarioInicial.cliente + : usuarioInicial.idCliente + ? [usuarioInicial.idCliente] + : typeof usuarioInicial.cliente === 'number' + ? [usuarioInicial.cliente] + : [], estatus: usuarioInicial.estatus !== undefined ? usuarioInicial.estatus : 1, }; } @@ -99,12 +105,8 @@ export const useAccionesUsuario = (usuarioInicial = null) => { apellido: datosUsuario.apellido, }; - console.log('Enviando al backend:', datosProcesados); - const nuevosErrores = validarDatosActualizarUsuario(datosProcesados); - console.log('Errores de validación:', nuevosErrores); - if (Object.keys(nuevosErrores).length > 0) { setErroresValidacion(nuevosErrores); setAlerta({ @@ -119,21 +121,24 @@ export const useAccionesUsuario = (usuarioInicial = null) => { setCargando(true); try { - await RepositorioActualizarUsuario.actualizar(datosProcesados); + const respuesta = await RepositorioActualizarUsuario.actualizar(datosProcesados); setAlerta({ tipo: 'success', - mensaje: esEdicion ? 'Usuario actualizado correctamente' : 'Usuario creado correctamente', + mensaje: respuesta?.mensaje || 'Usuario actualizado correctamente', }); return { exito: true, - mensaje: esEdicion ? 'Usuario actualizado correctamente' : 'Usuario creado correctamente', + mensaje: respuesta?.mensaje || (esEdicion ? 'Usuario actualizado correctamente' : ''), }; } catch (error) { setAlerta({ tipo: 'error', - mensaje: error.message || 'Error al guardar el usuario', + mensaje: error?.message || 'Error al guardar el usuario', }); - return { exito: false, mensaje: error.message || 'Error al guardar el usuario' }; + return { + exito: false, + mensaje: error?.message || 'Error al guardar el usuario', + }; } finally { setCargando(false); } From 73bff7646abd69f1e09cc9a280fa0ae29db6056f Mon Sep 17 00:00:00 2001 From: max Date: Fri, 6 Jun 2025 16:51:41 -0600 Subject: [PATCH 09/23] excluir cambiar usuario a superadmin --- .../Organismos/Formularios/FormularioActualizarUsuario.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx index 92b78866..efd7a018 100644 --- a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx +++ b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx @@ -162,7 +162,7 @@ const FormularioActualizarUsuario = ({ error={!!erroresValidacion.idRol} helperText={erroresValidacion.idRol && CAMPO_OBLIGATORIO} options={roles - .filter((rol) => rol.idRol !== 3) + .filter((rol) => rol.idRol !== 1) .map((rol) => ({ value: rol.idRol, label: rol.nombre, From 4d12542e2dd0352cc3a448e448bbaece6d36b9b2 Mon Sep 17 00:00:00 2001 From: max Date: Fri, 6 Jun 2025 17:03:44 -0600 Subject: [PATCH 10/23] fix: update role filtering to exclude additional role ID --- .../Organismos/Formularios/FormularioActualizarUsuario.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx index efd7a018..deda4657 100644 --- a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx +++ b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx @@ -162,7 +162,7 @@ const FormularioActualizarUsuario = ({ error={!!erroresValidacion.idRol} helperText={erroresValidacion.idRol && CAMPO_OBLIGATORIO} options={roles - .filter((rol) => rol.idRol !== 1) + .filter((rol) => rol.idRol !== 1 && rol.idRol !== 3) .map((rol) => ({ value: rol.idRol, label: rol.nombre, From fa75642c867b3416c13b95bd8cd611aab4ad628f Mon Sep 17 00:00:00 2001 From: max Date: Fri, 6 Jun 2025 17:30:58 -0600 Subject: [PATCH 11/23] fix: adjust confirmation delay and update success alert message in user modal --- .../Organismos/ModalActualizarUsuario.jsx | 21 +++++++++---------- src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx | 10 ++++++++- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx index 46a20957..3fbc788e 100644 --- a/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx +++ b/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx @@ -35,7 +35,7 @@ const ModalActualizarUsuario = ({ setTimeout(() => { limpiarFormulario(); onClose(); - }, 800); + }, 1000); } }; @@ -76,17 +76,16 @@ const ModalActualizarUsuario = ({ cargando={cargando} /> - - {alerta && ( - setAlerta(null)} - /> - )} + {alerta && ( + setAlerta(null)} + /> + )} ); }; diff --git a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx index f82f74de..d9196e2a 100644 --- a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx +++ b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx @@ -452,7 +452,15 @@ const ListaUsuarios = () => { setModalActualizarAbierto(false)} - onAccion={recargar} + onAccion={(exito) => { + recargar(); + if (exito) { + setAlerta({ + tipo: 'success', + mensaje: 'Usuario actualizado exitosamente', + }); + } + }} usuarioEdicion={{ ...usuario, cliente: usuario.clientes ? usuario.clientes.map((c) => c.idCliente) : [], From 8471589c2ca6f2bee2c1ed62123cb1e63aebcc21 Mon Sep 17 00:00:00 2001 From: max Date: Fri, 6 Jun 2025 17:48:05 -0600 Subject: [PATCH 12/23] fix: enhance user update confirmation with customizable alert message and properties --- .../Organismos/ModalActualizarUsuario.jsx | 11 +---------- src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx | 12 ++++++++---- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx index 3fbc788e..425b7955 100644 --- a/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx +++ b/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx @@ -31,7 +31,7 @@ const ModalActualizarUsuario = ({ const manejarConfirmacion = async () => { const resultado = await handleGuardar(); if (resultado?.exito) { - if (onAccion) await onAccion(); + if (onAccion) await onAccion(true, resultado?.mensaje || 'Usuario actualizado exitosamente'); setTimeout(() => { limpiarFormulario(); onClose(); @@ -77,15 +77,6 @@ const ModalActualizarUsuario = ({ /> - {alerta && ( - setAlerta(null)} - /> - )} ); }; diff --git a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx index d9196e2a..ce08423b 100644 --- a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx +++ b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx @@ -320,10 +320,11 @@ const ListaUsuarios = () => { setAlerta(null)} - centradoInferior /> )} {modalCrearUsuarioAbierto && ( @@ -452,12 +453,15 @@ const ListaUsuarios = () => { setModalActualizarAbierto(false)} - onAccion={(exito) => { + onAccion={(exito, mensaje) => { recargar(); if (exito) { setAlerta({ tipo: 'success', - mensaje: 'Usuario actualizado exitosamente', + mensaje: mensaje || 'Usuario actualizado exitosamente', + icono: true, + cerrable: true, + centradoInferior: true, }); } }} From bf13f34ceeb3081de41698718ef736457df5fde0 Mon Sep 17 00:00:00 2001 From: max Date: Fri, 6 Jun 2025 18:01:34 -0600 Subject: [PATCH 13/23] fix: update password fields labels for clarity in user update form --- .../Organismos/Formularios/FormularioActualizarUsuario.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx index deda4657..cedb411c 100644 --- a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx +++ b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx @@ -205,7 +205,7 @@ const FormularioActualizarUsuario = ({ Date: Fri, 6 Jun 2025 18:34:46 -0600 Subject: [PATCH 14/23] errores de lint --- hooks/Productos/ProductoFormProvider.jsx | 15 +++ .../FormularioActualizarUsuario.jsx | 9 ++ .../Organismos/ModalActualizarUsuario.jsx | 10 ++ .../Componentes/Organismos/ModalUsuarios.jsx | 7 ++ .../Paginas/Categorias/ListaCategorias.jsx | 7 ++ .../Vistas/Paginas/Usuarios/ListaUsuarios.jsx | 34 +++++ .../Modelos/Usuarios/ActualizarUsuario.js | 8 +- .../FormularioActualizarUsuario.jsx | 7 +- .../Organismos/ModalActualizarUsuario.jsx | 1 - .../Componentes/Organismos/ModalUsuarios.jsx | 2 - .../Paginas/Categorias/ListaCategorias.jsx | 116 ++++++++++-------- src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx | 4 +- src/hooks/Productos/ProductoFormProvider.jsx | 4 +- 13 files changed, 155 insertions(+), 69 deletions(-) create mode 100644 hooks/Productos/ProductoFormProvider.jsx create mode 100644 hooks/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx create mode 100644 hooks/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx create mode 100644 hooks/Vistas/Componentes/Organismos/ModalUsuarios.jsx create mode 100644 hooks/Vistas/Paginas/Categorias/ListaCategorias.jsx create mode 100644 hooks/Vistas/Paginas/Usuarios/ListaUsuarios.jsx diff --git a/hooks/Productos/ProductoFormProvider.jsx b/hooks/Productos/ProductoFormProvider.jsx new file mode 100644 index 00000000..6b448851 --- /dev/null +++ b/hooks/Productos/ProductoFormProvider.jsx @@ -0,0 +1,15 @@ +import React, { useCallback } from 'react'; + +const ProductoFormProvider = () => { + const callbackFunction = useCallback(() => { + alert('Callback executed!'); + }, []); + + return ( +
+ +
+ ); +}; + +export default ProductoFormProvider; diff --git a/hooks/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx b/hooks/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx new file mode 100644 index 00000000..5b71ab9d --- /dev/null +++ b/hooks/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx @@ -0,0 +1,9 @@ +import React, { useEffect } from 'react'; + +const FormularioActualizarUsuario = () => { + useEffect(() => {}, []); + + return
{/* Your component JSX here */}
; +}; + +export default FormularioActualizarUsuario; diff --git a/hooks/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx b/hooks/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx new file mode 100644 index 00000000..ecde420c --- /dev/null +++ b/hooks/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx @@ -0,0 +1,10 @@ +const ModalActualizarUsuario = () => { + // Your component logic here + return ( +
+ {/* Your component JSX here */} +
+ ); +}; + +export default ModalActualizarUsuario; \ No newline at end of file diff --git a/hooks/Vistas/Componentes/Organismos/ModalUsuarios.jsx b/hooks/Vistas/Componentes/Organismos/ModalUsuarios.jsx new file mode 100644 index 00000000..86639a75 --- /dev/null +++ b/hooks/Vistas/Componentes/Organismos/ModalUsuarios.jsx @@ -0,0 +1,7 @@ +import React from 'react'; + +const ModalUsuarios = () => { + return
{/* Contenido del modal aquí */}
; +}; + +export default ModalUsuarios; diff --git a/hooks/Vistas/Paginas/Categorias/ListaCategorias.jsx b/hooks/Vistas/Paginas/Categorias/ListaCategorias.jsx new file mode 100644 index 00000000..87847af4 --- /dev/null +++ b/hooks/Vistas/Paginas/Categorias/ListaCategorias.jsx @@ -0,0 +1,7 @@ +import React from 'react'; + +const ListaCategorias = () => { + return
{/* Tu contenido aquí */}
; +}; + +export default ListaCategorias; diff --git a/hooks/Vistas/Paginas/Usuarios/ListaUsuarios.jsx b/hooks/Vistas/Paginas/Usuarios/ListaUsuarios.jsx new file mode 100644 index 00000000..e0890b30 --- /dev/null +++ b/hooks/Vistas/Paginas/Usuarios/ListaUsuarios.jsx @@ -0,0 +1,34 @@ +import React, { useState, useEffect } from 'react'; + +const ListaUsuarios = () => { + const [usuarios, setUsuarios] = useState([]); + const [loading, setLoading] = useState(false); + + useEffect(() => { + const fetchUsuarios = async () => { + setLoading(true); + const response = await fetch('/api/usuarios'); + const data = await response.json(); + setUsuarios(data); + setLoading(false); + }; + + fetchUsuarios(); + }, []); + + return ( +
+ {loading ? ( +

Cargando...

+ ) : ( +
    + {usuarios.map((usuario) => ( +
  • {usuario.nombre}
  • + ))} +
+ )} +
+ ); +}; + +export default ListaUsuarios; diff --git a/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js b/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js index f63613ed..1c83f13f 100644 --- a/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js +++ b/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js @@ -24,8 +24,8 @@ export const validarDatosActualizarUsuario = (datos, usuariosExistentes = []) => } else if ( usuariosExistentes.some( (usuario) => - usuario.correoElectronico === datos.correoElectronico && - usuario.idUsuario !== datos.idUsuario + usuario.correoElectronico === datos.correoElectronico + && usuario.idUsuario !== datos.idUsuario ) ) { errores.correoElectronico = 'Este correo ya está registrado'; @@ -34,8 +34,8 @@ export const validarDatosActualizarUsuario = (datos, usuariosExistentes = []) => if (datos.contrasenia && datos.contrasenia.length < 8) { errores.contrasenia = 'La contraseña debe tener al menos 8 caracteres'; } else if (datos.contrasenia && !tieneCaracterEspecial.test(datos.contrasenia)) { - errores.contrasenia = - 'Debe contener al menos uno de estos caracteres: ! @ # $ % ^ & * ( ) , . ? " : { } | < >'; + errores.contrasenia + = 'Debe contener al menos uno de estos caracteres: ! @ # $ % ^ & * ( ) , . ? " : { } | < >'; } else if (datos.contrasenia && !tieneMayuscula.test(datos.contrasenia)) { errores.contrasenia = 'Debe contener al menos una letra mayúscula'; } diff --git a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx index cedb411c..d577b6f3 100644 --- a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx +++ b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx @@ -12,12 +12,9 @@ const FormularioActualizarUsuario = ({ erroresValidacion, manejarCambio, manejarFechaNacimiento, - obtenerHelperText, roles = [], clientes = [], cargandoRoles = false, - cargando = false, - esSuperAdmin = false, CAMPO_OBLIGATORIO = 'Este campo es obligatorio', }) => { const estiloCuadricula = { @@ -44,7 +41,7 @@ const FormularioActualizarUsuario = ({ }); } rolAnterior.current = datosUsuario.rol; - }, [datosUsuario.rol, clientes]); + }, [datosUsuario.rol, clientes, manejarCambio]); return ( @@ -205,7 +202,7 @@ const FormularioActualizarUsuario = ({ { erroresValidacion, alerta, setAlerta, - cargando, esEdicion, manejarCambio, manejarFechaNacimiento, obtenerHelperText, handleGuardar, - limpiarFormulario, CAMPO_OBLIGATORIO, roles, clientes, diff --git a/src/Vistas/Paginas/Categorias/ListaCategorias.jsx b/src/Vistas/Paginas/Categorias/ListaCategorias.jsx index 8c88d74a..0a602c5c 100644 --- a/src/Vistas/Paginas/Categorias/ListaCategorias.jsx +++ b/src/Vistas/Paginas/Categorias/ListaCategorias.jsx @@ -31,29 +31,36 @@ const ListaCategorias = () => { const [cargandoDetalle, setCargandoDetalle] = useState(false); const [modalEditarAbierto, setModalEditarAbierto] = useState(false); const [categoriaEditable, setCategoriaEditable] = useState(null); - + const actualizar = useActualizarCategoria(); const theme = useTheme(); const colores = tokens(theme.palette.mode); - const columns = useMemo(() => [ - { field: 'nombreCategoria', headerName: 'Nombre', flex: 1 }, - { field: 'descripcion', headerName: 'Descripción', flex: 2 }, - { - field: 'cantidadProductos', - headerName: 'Número de productos asociados', - type: 'number', - flex: 1, - }, - ], []); - - const rows = useMemo(() => categorias.map((cat) => ({ - id: cat.idCategoria, - nombreCategoria: cat.nombreCategoria, - descripcion: cat.descripcion, - cantidadProductos: cat.cantidadProductos, - idCliente: cat.idCliente, - })), [categorias]); + const columns = useMemo( + () => [ + { field: 'nombreCategoria', headerName: 'Nombre', flex: 1 }, + { field: 'descripcion', headerName: 'Descripción', flex: 2 }, + { + field: 'cantidadProductos', + headerName: 'Número de productos asociados', + type: 'number', + flex: 1, + }, + ], + [] + ); + + const rows = useMemo( + () => + categorias.map((cat) => ({ + id: cat.idCategoria, + nombreCategoria: cat.nombreCategoria, + descripcion: cat.descripcion, + cantidadProductos: cat.cantidadProductos, + idCliente: cat.idCliente, + })), + [categorias] + ); useEffect(() => { const cargarProductos = async () => { @@ -75,7 +82,7 @@ const ListaCategorias = () => { const handleAbrirModalCrear = useCallback(() => setModalCrearAbierto(true), []); const handleCerrarModalCrear = useCallback(() => setModalCrearAbierto(false), []); - + const handleCategoriaCreadaExitosamente = useCallback(() => { handleCerrarModalCrear(); // Recarga la lista de categorías @@ -167,7 +174,7 @@ const ListaCategorias = () => { setModalEditarAbierto(false); setCategoriaEditable(null); actualizar.limpiarEstado(); - setAlerta(null); + setAlerta(null); recargar(); }, 2000); } else if (actualizar.error) { @@ -209,36 +216,39 @@ const ListaCategorias = () => { setModalEditarAbierto(true); }, [productos, categoriaDetalle]); - const botones = useMemo(() => [ - { - label: 'Añadir', - variant: 'contained', - color: 'error', - size: 'large', - backgroundColor: colores.altertex[1], - onClick: handleAbrirModalCrear, - }, - { - label: 'Eliminar', - onClick: () => { - if (seleccionados.size === 0 || seleccionados.ids?.size === 0) { - setAlerta({ - tipo: 'error', - mensaje: 'Selecciona al menos una categoría para eliminar.', - icono: true, - cerrable: true, - centradoInferior: true, - }); - } else { - setIdsCategoria(Array.from(seleccionados.ids)); - setOpenModalEliminar(true); - } + const botones = useMemo( + () => [ + { + label: 'Añadir', + variant: 'contained', + color: 'error', + size: 'large', + backgroundColor: colores.altertex[1], + onClick: handleAbrirModalCrear, }, - color: 'error', - size: 'large', - backgroundColor: colores.altertex[1], - }, - ], [colores.altertex, handleAbrirModalCrear, seleccionados]); + { + label: 'Eliminar', + onClick: () => { + if (seleccionados.size === 0 || seleccionados.ids?.size === 0) { + setAlerta({ + tipo: 'error', + mensaje: 'Selecciona al menos una categoría para eliminar.', + icono: true, + cerrable: true, + centradoInferior: true, + }); + } else { + setIdsCategoria(Array.from(seleccionados.ids)); + setOpenModalEliminar(true); + } + }, + color: 'error', + size: 'large', + backgroundColor: colores.altertex[1], + }, + ], + [colores.altertex, handleAbrirModalCrear, seleccionados] + ); const botonesModalDetalle = useMemo(() => { if (errorDetalle) { @@ -269,7 +279,7 @@ const ListaCategorias = () => { onClick: () => setModalDetalleAbierto(false), }, ]; - }, [errorDetalle, colores.primario, colores.altertex, abrirModalEditar]); + }, [errorDetalle, colores.altertex, abrirModalEditar]); return ( <> @@ -308,7 +318,7 @@ const ListaCategorias = () => { setAlerta={setAlerta} refrescarPagina={recargar} /> - + {modalDetalleAbierto && !cargandoDetalle && ( { ); }; // <- Esta llave de cierre estaba faltando -export default ListaCategorias; \ No newline at end of file +export default ListaCategorias; diff --git a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx index ce08423b..455d77a3 100644 --- a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx +++ b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx @@ -47,7 +47,7 @@ const ListaUsuarios = () => { const navigate = useNavigate(); const [alerta, setAlerta] = useState(null); const { usuarios, cargando, error, recargar } = useConsultarListaUsuarios(); - const { clientes, cargando: cargandoClientes } = useConsultarClientes(); + const { clientes } = useConsultarClientes(); const { roles } = useConsultarRoles(); const { usuario: usuarioAutenticado } = useAuth(); const [modalCrearUsuarioAbierto, setModalCrearUsuarioAbierto] = useState(false); @@ -467,7 +467,7 @@ const ListaUsuarios = () => { }} usuarioEdicion={{ ...usuario, - cliente: usuario.clientes ? usuario.clientes.map((c) => c.idCliente) : [], + cliente: usuario.clientes ? usuario.clientes.map((cliente) => cliente.idCliente) : [], }} roles={roles} clientes={clientes} diff --git a/src/hooks/Productos/ProductoFormProvider.jsx b/src/hooks/Productos/ProductoFormProvider.jsx index 6526b713..6797f8f1 100644 --- a/src/hooks/Productos/ProductoFormProvider.jsx +++ b/src/hooks/Productos/ProductoFormProvider.jsx @@ -121,8 +121,8 @@ export const ProductoFormProvider = ({ children, alCerrarFormularioProducto }) = [campo]: valor, }, }; - }, []); - }); + }); + }, []); const manejarEliminarVariante = useCallback((idVariante) => { setVariantes((prev) => { From 5f3ff700b37d98dfe2410f45574dc767f777e2d6 Mon Sep 17 00:00:00 2001 From: max Date: Fri, 6 Jun 2025 19:23:14 -0600 Subject: [PATCH 15/23] fix: improve email validation and enhance date of birth checks in user update model --- .../Modelos/Usuarios/ActualizarUsuario.js | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js b/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js index 1c83f13f..c672338c 100644 --- a/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js +++ b/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js @@ -24,8 +24,8 @@ export const validarDatosActualizarUsuario = (datos, usuariosExistentes = []) => } else if ( usuariosExistentes.some( (usuario) => - usuario.correoElectronico === datos.correoElectronico - && usuario.idUsuario !== datos.idUsuario + usuario.correoElectronico === datos.correoElectronico && + usuario.idUsuario !== datos.idUsuario ) ) { errores.correoElectronico = 'Este correo ya está registrado'; @@ -34,8 +34,8 @@ export const validarDatosActualizarUsuario = (datos, usuariosExistentes = []) => if (datos.contrasenia && datos.contrasenia.length < 8) { errores.contrasenia = 'La contraseña debe tener al menos 8 caracteres'; } else if (datos.contrasenia && !tieneCaracterEspecial.test(datos.contrasenia)) { - errores.contrasenia - = 'Debe contener al menos uno de estos caracteres: ! @ # $ % ^ & * ( ) , . ? " : { } | < >'; + errores.contrasenia = + 'Debe contener al menos uno de estos caracteres: ! @ # $ % ^ & * ( ) , . ? " : { } | < >'; } else if (datos.contrasenia && !tieneMayuscula.test(datos.contrasenia)) { errores.contrasenia = 'Debe contener al menos una letra mayúscula'; } @@ -56,13 +56,28 @@ export const validarDatosActualizarUsuario = (datos, usuariosExistentes = []) => errores.direccion = 'La dirección es obligatoria'; } - if (!datos.fechaNacimiento) { + /*if (!datos.fechaNacimiento) { errores.fechaNacimiento = 'La fecha de nacimiento es obligatoria'; } else { const hoy = new Date(); const fecha = new Date(datos.fechaNacimiento); + + if (fecha > hoy) { + errores.fechaNacimiento = 'La fecha no puede ser futura'; + } + }*/ + + if (!datos.fechaNacimiento) { + errores.fechaNacimiento = true; + } else { + const hoy = new Date(); + const limiteInferiorFecha = new Date('1900-01-01'); + const fecha = new Date(datos.fechaNacimiento); + if (fecha > hoy) { errores.fechaNacimiento = 'La fecha no puede ser futura'; + } else if (fecha < limiteInferiorFecha) { + errores.fechaNacimiento = 'Ingresa una fecha válida'; } } From 6c62a8f14e6bf093bc64ada11732ef46e1921dd9 Mon Sep 17 00:00:00 2001 From: max Date: Fri, 6 Jun 2025 19:28:58 -0600 Subject: [PATCH 16/23] fix: enhance gender handling in user data initialization for better inclusivity --- src/hooks/Usuarios/useAccionesUsuario.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/hooks/Usuarios/useAccionesUsuario.js b/src/hooks/Usuarios/useAccionesUsuario.js index 474b4d43..ccb61581 100644 --- a/src/hooks/Usuarios/useAccionesUsuario.js +++ b/src/hooks/Usuarios/useAccionesUsuario.js @@ -18,8 +18,10 @@ export const useAccionesUsuario = (usuarioInicial = null) => { let genero = ''; if (usuarioInicial.genero) { - if (usuarioInicial.genero.toLowerCase() === 'femenino') genero = 'Mujer'; - else if (usuarioInicial.genero.toLowerCase() === 'masculino') genero = 'Hombre'; + const generoLower = usuarioInicial.genero.toLowerCase(); + if (['hombre', 'masculino'].includes(generoLower)) genero = 'Hombre'; + else if (['mujer', 'femenino'].includes(generoLower)) genero = 'Mujer'; + else if (['otro', 'no binario', 'nb'].includes(generoLower)) genero = 'Otro'; else genero = 'Otro'; } From c6a6245b86daa8044625cfc53c4278877b39f475 Mon Sep 17 00:00:00 2001 From: max Date: Fri, 6 Jun 2025 19:49:12 -0600 Subject: [PATCH 17/23] fix: improve validation and sanitization in user update form fields --- .../Modelos/Usuarios/ActualizarUsuario.js | 10 ++++++++-- .../Formularios/FormularioActualizarUsuario.jsx | 16 +++++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js b/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js index c672338c..76975f07 100644 --- a/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js +++ b/src/Dominio/Modelos/Usuarios/ActualizarUsuario.js @@ -2,7 +2,7 @@ export const validarDatosActualizarUsuario = (datos, usuariosExistentes = []) => { const errores = {}; - const emailValido = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + const emailValido = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; const telefonoValido = /^\d{10}$/; const tieneCaracterEspecial = /[!@#$%^&*(),.?":{}|<>]/; const tieneMayuscula = /[A-Z]/; @@ -31,7 +31,9 @@ export const validarDatosActualizarUsuario = (datos, usuariosExistentes = []) => errores.correoElectronico = 'Este correo ya está registrado'; } - if (datos.contrasenia && datos.contrasenia.length < 8) { + if (datos.contrasenia && /\s/.test(datos.contrasenia)) { + errores.contrasenia = 'La contraseña no debe contener espacios en blanco'; + } else if (datos.contrasenia && datos.contrasenia.length < 8) { errores.contrasenia = 'La contraseña debe tener al menos 8 caracteres'; } else if (datos.contrasenia && !tieneCaracterEspecial.test(datos.contrasenia)) { errores.contrasenia = @@ -54,6 +56,10 @@ export const validarDatosActualizarUsuario = (datos, usuariosExistentes = []) => if (!datos.direccion || datos.direccion.trim().length === 0) { errores.direccion = 'La dirección es obligatoria'; + } else if (datos.direccion.trim().length < 3) { + errores.direccion = 'La dirección debe tener al menos 3 caracteres'; + } else if (datos.direccion.length > 100) { + errores.direccion = 'La dirección no debe exceder 100 caracteres'; } /*if (!datos.fechaNacimiento) { diff --git a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx index d577b6f3..6148a6db 100644 --- a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx +++ b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx @@ -50,7 +50,10 @@ const FormularioActualizarUsuario = ({ label='Nombre' name='nombreCompleto' value={datosUsuario.nombreCompleto} - onChange={manejarCambio} + onChange={(letra) => { + const soloLetras = letra.target.value.replace(/[^a-zA-ZáéíóúÁÉÍÓÚñÑ\s]/g, ''); + manejarCambio({ target: { name: 'nombreCompleto', value: soloLetras } }); + }} required size='medium' error={!!erroresValidacion.nombreCompleto} @@ -119,7 +122,10 @@ const FormularioActualizarUsuario = ({ label='Número de Teléfono' name='numeroTelefono' value={datosUsuario.numeroTelefono} - onChange={manejarCambio} + onChange={(num) => { + const soloNumeros = num.target.value.replace(/\D/g, ''); + manejarCambio({ target: { name: 'numeroTelefono', value: soloNumeros } }); + }} required size='medium' error={!!erroresValidacion.numeroTelefono} @@ -142,7 +148,11 @@ const FormularioActualizarUsuario = ({ required size='medium' error={!!erroresValidacion.direccion} - helperText={erroresValidacion.direccion && CAMPO_OBLIGATORIO} + helperText={ + erroresValidacion.direccion === true + ? CAMPO_OBLIGATORIO + : erroresValidacion.direccion || '' + } inputProps={{ maxLength: 100, }} From 00e66f17a336aa4b5c8c8cf76e95d72cb33821dc Mon Sep 17 00:00:00 2001 From: NicoH00d Date: Fri, 6 Jun 2025 20:57:24 -0600 Subject: [PATCH 18/23] fix: corregir despliegue de super Admin --- .../Organismos/Formularios/FormularioActualizarUsuario.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx index 6148a6db..b6a3c5d7 100644 --- a/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx +++ b/src/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx @@ -169,7 +169,7 @@ const FormularioActualizarUsuario = ({ error={!!erroresValidacion.idRol} helperText={erroresValidacion.idRol && CAMPO_OBLIGATORIO} options={roles - .filter((rol) => rol.idRol !== 1 && rol.idRol !== 3) + .filter((rol) => rol.idRol !== 3) .map((rol) => ({ value: rol.idRol, label: rol.nombre, From 576fd9e5d61f5906432427b436d6c65fae44262f Mon Sep 17 00:00:00 2001 From: NicoH00d Date: Fri, 6 Jun 2025 22:22:56 -0600 Subject: [PATCH 19/23] fix: Despliegue de rol de usuario y eliminacion de carpeta --- hooks/Productos/ProductoFormProvider.jsx | 15 -------- .../FormularioActualizarUsuario.jsx | 9 ----- .../Organismos/ModalActualizarUsuario.jsx | 10 ------ .../Componentes/Organismos/ModalUsuarios.jsx | 7 ---- .../Paginas/Categorias/ListaCategorias.jsx | 7 ---- .../Vistas/Paginas/Usuarios/ListaUsuarios.jsx | 34 ------------------- src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx | 7 +--- 7 files changed, 1 insertion(+), 88 deletions(-) delete mode 100644 hooks/Productos/ProductoFormProvider.jsx delete mode 100644 hooks/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx delete mode 100644 hooks/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx delete mode 100644 hooks/Vistas/Componentes/Organismos/ModalUsuarios.jsx delete mode 100644 hooks/Vistas/Paginas/Categorias/ListaCategorias.jsx delete mode 100644 hooks/Vistas/Paginas/Usuarios/ListaUsuarios.jsx diff --git a/hooks/Productos/ProductoFormProvider.jsx b/hooks/Productos/ProductoFormProvider.jsx deleted file mode 100644 index 6b448851..00000000 --- a/hooks/Productos/ProductoFormProvider.jsx +++ /dev/null @@ -1,15 +0,0 @@ -import React, { useCallback } from 'react'; - -const ProductoFormProvider = () => { - const callbackFunction = useCallback(() => { - alert('Callback executed!'); - }, []); - - return ( -
- -
- ); -}; - -export default ProductoFormProvider; diff --git a/hooks/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx b/hooks/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx deleted file mode 100644 index 5b71ab9d..00000000 --- a/hooks/Vistas/Componentes/Organismos/Formularios/FormularioActualizarUsuario.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import React, { useEffect } from 'react'; - -const FormularioActualizarUsuario = () => { - useEffect(() => {}, []); - - return
{/* Your component JSX here */}
; -}; - -export default FormularioActualizarUsuario; diff --git a/hooks/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx b/hooks/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx deleted file mode 100644 index ecde420c..00000000 --- a/hooks/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx +++ /dev/null @@ -1,10 +0,0 @@ -const ModalActualizarUsuario = () => { - // Your component logic here - return ( -
- {/* Your component JSX here */} -
- ); -}; - -export default ModalActualizarUsuario; \ No newline at end of file diff --git a/hooks/Vistas/Componentes/Organismos/ModalUsuarios.jsx b/hooks/Vistas/Componentes/Organismos/ModalUsuarios.jsx deleted file mode 100644 index 86639a75..00000000 --- a/hooks/Vistas/Componentes/Organismos/ModalUsuarios.jsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react'; - -const ModalUsuarios = () => { - return
{/* Contenido del modal aquí */}
; -}; - -export default ModalUsuarios; diff --git a/hooks/Vistas/Paginas/Categorias/ListaCategorias.jsx b/hooks/Vistas/Paginas/Categorias/ListaCategorias.jsx deleted file mode 100644 index 87847af4..00000000 --- a/hooks/Vistas/Paginas/Categorias/ListaCategorias.jsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react'; - -const ListaCategorias = () => { - return
{/* Tu contenido aquí */}
; -}; - -export default ListaCategorias; diff --git a/hooks/Vistas/Paginas/Usuarios/ListaUsuarios.jsx b/hooks/Vistas/Paginas/Usuarios/ListaUsuarios.jsx deleted file mode 100644 index e0890b30..00000000 --- a/hooks/Vistas/Paginas/Usuarios/ListaUsuarios.jsx +++ /dev/null @@ -1,34 +0,0 @@ -import React, { useState, useEffect } from 'react'; - -const ListaUsuarios = () => { - const [usuarios, setUsuarios] = useState([]); - const [loading, setLoading] = useState(false); - - useEffect(() => { - const fetchUsuarios = async () => { - setLoading(true); - const response = await fetch('/api/usuarios'); - const data = await response.json(); - setUsuarios(data); - setLoading(false); - }; - - fetchUsuarios(); - }, []); - - return ( -
- {loading ? ( -

Cargando...

- ) : ( -
    - {usuarios.map((usuario) => ( -
  • {usuario.nombre}
  • - ))} -
- )} -
- ); -}; - -export default ListaUsuarios; diff --git a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx index 455d77a3..0fb25b74 100644 --- a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx +++ b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx @@ -77,11 +77,6 @@ const ListaUsuarios = () => { label: rol.nombre, })); - const obtenerIdRolPorNombre = (nombreRol) => { - const rolEncontrado = roles.find((rol) => rol.nombre === nombreRol); - return rolEncontrado ? rolEncontrado.idRol : ''; - }; - const redirigirAInicio = () => { navigate(RUTAS.SISTEMA_ADMINISTRATIVO.BASE, { replace: true }); }; @@ -424,7 +419,7 @@ const ListaUsuarios = () => { .join(', ') : 'Sin cliente asignado' } - rol={obtenerIdRolPorNombre(usuario.rol)} + rol={(usuario.rol)} datosContacto={{ email: usuario.correoElectronico, telefono: usuario.numeroTelefono, From 5e2104d94276de260fbd172386cb67f281af0eb3 Mon Sep 17 00:00:00 2001 From: NicoH00d Date: Fri, 6 Jun 2025 23:05:41 -0600 Subject: [PATCH 20/23] fix despliegue de roles --- src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx index 0fb25b74..e26f6a66 100644 --- a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx +++ b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx @@ -62,6 +62,8 @@ const ListaUsuarios = () => { const [modal2FAAbierto, setModal2FAAbierto] = useState(false); const { qrCode, cargando: cargandoQR, error: errorQR, setQrCode } = useActivar2FA(); + const rolesPorId = Object.fromEntries(roles.map((fila) => [fila.idRol, fila.nombre])); + /** const manejarActivar2FA = async () => { await activar2FA({ @@ -196,7 +198,7 @@ const ListaUsuarios = () => { id, idUsuario: id, nombre: usuario.nombre, - rol: usuario.rol || 'Sin rol', + rol: rolesPorId[usuario.rol] || 'Sin rol', cliente: usuario.cliente ? [usuario.cliente] : [], estatus: usuario.estatus, correo: usuario.correo, From 011ffdc9da4f5890e37bbe4276fbb248d557790d Mon Sep 17 00:00:00 2001 From: NicoH00d Date: Thu, 12 Jun 2025 21:56:54 -0600 Subject: [PATCH 21/23] fix: posicion de alerta al eliminar --- src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx index e26f6a66..69c04b46 100644 --- a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx +++ b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx @@ -313,17 +313,6 @@ const ListaUsuarios = () => { } informacionBotones={botones} > - {alerta && ( - setAlerta(null)} - /> - )} {modalCrearUsuarioAbierto && ( {
)} + {alerta && ( + setAlerta(null)} + /> + )} ); }; From e5de6c6973e5c55c0e2a1e2f42fbb8626bf0a29b Mon Sep 17 00:00:00 2001 From: NicoH00d Date: Thu, 12 Jun 2025 22:47:42 -0600 Subject: [PATCH 22/23] Mensaje de correo duplicado --- .../Organismos/ModalActualizarUsuario.jsx | 12 ++++++++++++ src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx | 11 +---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx b/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx index f1992c0f..2f0cfd86 100644 --- a/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx +++ b/src/Vistas/Componentes/Organismos/ModalActualizarUsuario.jsx @@ -18,6 +18,7 @@ const ModalActualizarUsuario = ({ datosUsuario, erroresValidacion, setAlerta, + alerta, manejarCambio, manejarFechaNacimiento, obtenerHelperText, @@ -75,7 +76,18 @@ const ModalActualizarUsuario = ({ cargando={cargando} /> + + {alerta && ( + setAlerta(null)} + centradoInferior + /> + )} ); }; diff --git a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx index 69c04b46..2b2d4e79 100644 --- a/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx +++ b/src/Vistas/Paginas/Usuarios/ListaUsuarios.jsx @@ -439,17 +439,8 @@ const ListaUsuarios = () => { setModalActualizarAbierto(false)} - onAccion={(exito, mensaje) => { + onAccion={() => { recargar(); - if (exito) { - setAlerta({ - tipo: 'success', - mensaje: mensaje || 'Usuario actualizado exitosamente', - icono: true, - cerrable: true, - centradoInferior: true, - }); - } }} usuarioEdicion={{ ...usuario, From 31a5afed300430667fea317800c7c82add674271 Mon Sep 17 00:00:00 2001 From: NicoH00d Date: Thu, 12 Jun 2025 23:06:10 -0600 Subject: [PATCH 23/23] Manejo de la alerta --- src/hooks/Usuarios/useAccionesUsuario.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/hooks/Usuarios/useAccionesUsuario.js b/src/hooks/Usuarios/useAccionesUsuario.js index ccb61581..ed400e03 100644 --- a/src/hooks/Usuarios/useAccionesUsuario.js +++ b/src/hooks/Usuarios/useAccionesUsuario.js @@ -111,10 +111,6 @@ export const useAccionesUsuario = (usuarioInicial = null) => { if (Object.keys(nuevosErrores).length > 0) { setErroresValidacion(nuevosErrores); - setAlerta({ - tipo: 'error', - mensaje: 'Corrige los errores en el formulario antes de guardar.', - }); return { exito: false }; }