const { useState, useEffect, useMemo } = React; const ALL_DAYS = [ { code: 'lun', label: 'Lunes' }, { code: 'mar', label: 'Martes' }, { code: 'mie', label: 'Miércoles' }, { code: 'jue', label: 'Jueves' }, { code: 'vie', label: 'Viernes' }, { code: 'sab', label: 'Sábado' }, { code: 'dom', label: 'Domingo' } ]; window.AdminPersonal = function({ globalUsers = [], roles = [], logs = [], handleUserSubmit, editingUser, setEditingUser, deleteUser, toggleLock, confirmAction, isReadOnly = false }) { const [showModal, setShowModal] = useState(false); const [searchTerm, setSearchTerm] = useState(''); const [filterRole, setFilterRole] = useState('ALL'); const [isSubmittingUser, setIsSubmittingUser] = useState(false); // BLOQUEO ANTI DOBLE CLIC // Horarios e Identidad const [selectedScheduleDays, setSelectedScheduleDays] = useState(['lun', 'mar', 'mie', 'jue', 'vie']); const [scheduleCustom, setScheduleCustom] = useState({}); const [baseStart, setBaseStart] = useState('08:00'); const [baseEnd, setBaseEnd] = useState('17:00'); // INSS e Impuestos const [hasInss, setHasInss] = useState(false); const [inssNumber, setInssNumber] = useState(''); const [appliesInss, setAppliesInss] = useState(true); const [appliesIr, setAppliesIr] = useState(true); const [gpsTracking, setGpsTracking] = useState(false); const [avatarBase64, setAvatarBase64] = useState(''); const [avatarPreview, setAvatarPreview] = useState(''); const isUserLockedToday = (user) => { const todayLogs = (logs || []).filter(l => Number(l.userId) === Number(user.id) && l.date === window.getNICDate()); const hasSalida = todayLogs.some(l => l.type === 'salida'); return Boolean(user.manualLock) || (hasSalida && !user.overrideCheckOut); }; useEffect(() => { if (editingUser) { setSelectedScheduleDays(editingUser.scheduleDays || ['lun', 'mar', 'mie', 'jue', 'vie']); setScheduleCustom(editingUser.scheduleCustom || {}); setBaseStart(editingUser.scheduleStart || '08:00'); setBaseEnd(editingUser.scheduleEnd || '17:00'); setHasInss(Boolean(editingUser.hasInss)); setInssNumber(editingUser.inssNumber || ''); setAppliesInss(editingUser.appliesInss !== undefined ? Boolean(editingUser.appliesInss) : true); setAppliesIr(editingUser.appliesIr !== undefined ? Boolean(editingUser.appliesIr) : true); setGpsTracking(Boolean(editingUser.gpsTrackingEnabled)); setAvatarPreview(editingUser.avatarUrl || ''); setAvatarBase64(''); setIsSubmittingUser(false); setShowModal(true); } else { setSelectedScheduleDays(['lun', 'mar', 'mie', 'jue', 'vie']); setScheduleCustom({}); setBaseStart('08:00'); setBaseEnd('17:00'); setHasInss(false); setInssNumber(''); setAppliesInss(true); setAppliesIr(true); setGpsTracking(false); setAvatarPreview(''); setAvatarBase64(''); setIsSubmittingUser(false); } }, [editingUser]); const openNewUserModal = () => { if (isReadOnly) return alert("Modo supervisión: no tienes permisos para crear empleados."); setEditingUser(null); setSelectedScheduleDays(['lun', 'mar', 'mie', 'jue', 'vie']); setScheduleCustom({}); setBaseStart('08:00'); setBaseEnd('17:00'); setHasInss(false); setInssNumber(''); setAppliesInss(true); setAppliesIr(true); setGpsTracking(false); setAvatarPreview(''); setAvatarBase64(''); setIsSubmittingUser(false); setShowModal(true); }; const closeModal = () => { if (isSubmittingUser) return; // Evitar cerrar mientras se procesa setEditingUser(null); setShowModal(false); }; const handleAvatarFile = (e) => { const file = e.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = (ev) => { setAvatarBase64(ev.target.result); setAvatarPreview(ev.target.result); }; reader.readAsDataURL(file); }; const handleToggleDay = (dayCode) => { setSelectedScheduleDays(prev => prev.includes(dayCode) ? prev.filter(d => d !== dayCode) : [...prev, dayCode] ); }; const handleToggleCustomDay = (dayCode) => { setScheduleCustom(prev => { const copy = { ...prev }; if (copy[dayCode]) { delete copy[dayCode]; } else { copy[dayCode] = { start: '08:00', end: '12:00', isHalfDay: true }; } return copy; }); }; const handleCustomDayChange = (dayCode, field, val) => { setScheduleCustom(prev => ({ ...prev, [dayCode]: { ...prev[dayCode], [field]: val } })); }; const dbRolesList = useMemo(() => { const roleSet = new Map(); roleSet.set('propietario', 'PROPIETARIO / ADMIN'); roleSet.set('empleado', 'EMPLEADO'); (roles || []).forEach(r => { const rawName = (typeof r === 'object' ? r.name : r) || ''; const key = rawName.toLowerCase().trim(); if (key) { if (key.includes('propietario') || key.includes('admin') || key.includes('dueño')) { roleSet.set('propietario', 'PROPIETARIO / ADMIN'); } else if (key === 'empleado') { roleSet.set('empleado', 'EMPLEADO'); } else { roleSet.set(key, rawName.toUpperCase()); } } }); return Array.from(roleSet.entries()).map(([key, label]) => ({ key, label })); }, [roles]); const filteredUsers = useMemo(() => { return (globalUsers || []).filter(u => { const matchText = (u.name || '').toLowerCase().includes(searchTerm.toLowerCase()) || (u.email || '').toLowerCase().includes(searchTerm.toLowerCase()) || (u.alias || '').toLowerCase().includes(searchTerm.toLowerCase()); const userRoleKey = (u.role || u.role_name || '').toLowerCase().trim(); const matchRole = filterRole === 'ALL' || userRoleKey === filterRole.toLowerCase().trim(); return matchText && matchRole; }); }, [globalUsers, searchTerm, filterRole]); const ownersAndAdmins = filteredUsers.filter(u => { const r = (u.role || u.role_name || '').toLowerCase().trim(); return r === 'propietario' || r === 'admin' || r === 'dueño' || r === 'owner'; }); const regularEmployees = filteredUsers.filter(u => { const r = (u.role || u.role_name || '').toLowerCase().trim(); return r !== 'propietario' && r !== 'admin' && r !== 'dueño' && r !== 'owner'; }); // Control seguro de envío con bloqueo de doble clic const onFormSubmit = async (e) => { e.preventDefault(); if (isSubmittingUser) return; setIsSubmittingUser(true); try { await handleUserSubmit(e); closeModal(); } catch (err) { console.error("Error al procesar usuario:", err); } finally { setIsSubmittingUser(false); } }; const renderUserRowCard = (u, isOwner = false) => { const isLocked = isUserLockedToday(u); const activeDaysStr = (u.scheduleDays || []).join(', ').toUpperCase(); const hasCustom = u.scheduleCustom && Object.keys(u.scheduleCustom).length > 0; return (
{u.email}
Gestión de colaboradores, salarios, turnos y emisión de contratos
Configuración de rol de acceso, permisos y datos laborales