/* global React */ // Nuevo / Editar Usuario (HU.4.1) — pantalla interna, formulario único validado. // Mismo patrón que "Nueva institución". const { useState: useStateNU, useMemo: useMemoNU, useEffect: useEffectNU } = React; const ROLES_CATALOG = [ { id: 'superadmin', label: 'Súper Administrador', desc: 'Acceso total: gestiona usuarios, instituciones y configuración global.' }, { id: 'admin', label: 'Administrador', desc: 'Registra recomendaciones, asigna instituciones, revisa y aprueba avances.' }, { id: 'institucion', label: 'Enlace Institucional', desc: 'Carga avances y evidencias de los compromisos de su institución.' }, { id: 'cancilleria', label: 'Cancillería · MRE', desc: 'Solo lectura del tablero país e informes consolidados.' }, ]; const ROLE_PILL_CLS = { superadmin: 'role-super', admin: 'role-admin', institucion: 'role-inst', cancilleria: 'role-canc', }; // ---------------- Validación ---------------- function validateUser(form, items, editingId) { const e = {}; const otras = (items || []).filter((it) => !editingId || it.id !== editingId); if (!form.rol) e.rol = 'Selecciona un rol.'; const nombre = (form.nombre || '').trim(); if (!nombre) e.nombre = 'Ingresa el nombre.'; else if (nombre.length < 2) e.nombre = 'Mínimo 2 caracteres.'; const apellido = (form.apellido || '').trim(); if (!apellido) e.apellido = 'Ingresa el apellido.'; else if (apellido.length < 2) e.apellido = 'Mínimo 2 caracteres.'; if (form.rol === 'institucion' && !form.institucionId) { e.institucionId = 'Selecciona la institución del usuario.'; } else if (form.rol === 'institucion' && form.institucionId) { const inst = (window.cgrData ? window.cgrData.instituciones() : []).find(i => i.id === form.institucionId); if (inst && inst.estado === 'desactivado') { e.institucionId = 'Esa institución está desactivada. Elige una institución activa.'; } } const tel = (form.telefono || '').trim(); if (tel && !/^[+0-9()\s-]{6,20}$/.test(tel)) { e.telefono = 'Ingresa un teléfono válido.'; } const email = (form.email || '').trim(); if (!email) { e.email = 'Ingresa el correo institucional.'; } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(email)) { e.email = 'Ingresa un correo válido, ej. nombre@institucion.gob'; } else if (otras.some((it) => (it.email || '').trim().toLowerCase() === email.toLowerCase())) { e.email = 'Ya existe un usuario con este correo. Usa otro diferente.'; } return e; } function splitNombre(full) { const p = (full || '').trim().split(/\s+/); return { nombre: p[0] || '', apellido: p.slice(1).join(' ') }; } function NuevoUsuarioForm({ onCancel, onSave, editing, items }) { const I = window.Icons; const isEdit = !!editing; const initForm = () => { if (editing) { const { nombre, apellido } = splitNombre(editing.nombre); const inst = window.cgrData.instituciones().find(i => i.nombre === editing.institucion); return { rol: editing.rol || '', nombre, apellido, documento: editing.documento || '', telefono: editing.telefono || '', institucionId: inst ? inst.id : '', cargo: editing.cargo || '', email: editing.email || '', esContacto: window.cgrData ? window.cgrData.esContactoPrincipal(editing) : !!editing.esContacto, }; } return { rol: '', nombre: '', apellido: '', documento: '', telefono: '', institucionId: '', cargo: '', email: '', esContacto: false }; }; const [form, setForm] = useStateNU(initForm); const [touched, setTouched] = useStateNU({}); const [submitAttempted, setSubmitAttempted] = useStateNU(false); useEffectNU(() => { setForm(initForm()); setTouched({}); setSubmitAttempted(false); }, [editing]); const errors = useMemoNU( () => validateUser(form, items, editing && editing.id), [form, items, editing] ); const isValid = Object.keys(errors).length === 0; const update = (k, v) => setForm(f => ({ ...f, [k]: v })); const blur = (k) => setTouched(t => ({ ...t, [k]: true })); const showErr = (k) => (touched[k] || submitAttempted) && errors[k]; const requiereInst = form.rol === 'institucion'; const handleSubmit = () => { if (!isValid) { setSubmitAttempted(true); return; } const rolObj = ROLES_CATALOG.find(r => r.id === form.rol); const inst = window.cgrData.instituciones().find(i => i.id === form.institucionId); const nombreCompleto = `${form.nombre.trim()} ${form.apellido.trim()}`.trim(); const initials = ((form.nombre.trim()[0] || '') + (form.apellido.trim()[0] || '')).toUpperCase() || '··'; const institucionLabel = requiereInst ? (inst ? inst.nombre : '') : (form.cargo.trim() || (editing ? editing.institucion : '') || 'CGR'); onSave && onSave({ ...(editing || {}), nombre: nombreCompleto, initials, email: form.email.trim(), rol: form.rol, rolLabel: rolObj ? rolObj.label : '', institucion: institucionLabel, cargo: form.cargo.trim(), telefono: form.telefono.trim(), documento: form.documento.trim(), esContacto: requiereInst ? form.esContacto : false, }); }; return (
{isEdit ? 'Actualiza los datos, el rol o la institución de la cuenta. Los cambios quedan registrados.' : 'Completa los datos para crear una cuenta de acceso. El rol define a qué módulos y datos accede.'}