const { useState, useMemo } = React;
window.AdminDashboard = function({ globalUsers, logs, roles, reminders = [], setView, onLogout }) {
const [tab, setTab] = useState('logs');
const [searchName, setSearchName] = useState('');
const [searchDate, setSearchDate] = useState(window.getNICDate());
const [editingUser, setEditingUser] = useState(null);
const [editingLog, setEditingLog] = useState(null);
const [userToDelete, setUserToDelete] = useState(null);
const [submitError, setSubmitError] = useState('');
// Gestión de Roles y Permisos
const [newRoleName, setNewRoleName] = useState('');
const [selectedPermissions, setSelectedPermissions] = useState([]);
// --- GESTIÓN DE NOTIFICACIONES (NUEVO) ---
const [notifTitle, setNotifTitle] = useState('');
const [notifBody, setNotifBody] = useState('');
const [notifExpiry, setNotifExpiry] = useState('');
const [targetUsers, setTargetUsers] = useState([]);
// Acciones base configurables (Requerimiento: poder configurar qué se marca)
const availableActions = [
{ id: 'almuerzo', label: 'Almuerzo' },
{ id: 'break', label: 'Break / Merienda' },
{ id: 'visita_in', label: 'Visita Cliente' },
{ id: 'reunion', label: 'Reunión' },
{ id: 'capacitacion', label: 'Capacitación' },
{ id: 'gestiones', label: 'Gestiones de Campo' }
];
const filteredLogs = useMemo(() => {
return logs.filter(l => {
const matchName = l.userName.toLowerCase().includes(searchName.toLowerCase());
const matchDate = searchDate ? l.date === searchDate : true;
return matchName && matchDate;
}).sort((a,b) => b.timestamp - a.timestamp);
}, [logs, searchName, searchDate]);
const handleUserSubmit = async (e) => {
e.preventDefault();
setSubmitError('');
const f = new FormData(e.target);
const email = f.get('email').toLowerCase().trim();
// VALIDACIÓN: Verificar si el correo ya existe y mostrar estado (NUEVO)
if (!editingUser) {
const existing = globalUsers.find(u => u.email === email);
if (existing) {
setSubmitError(`ADVERTENCIA: El correo ya existe. Pertenece a "${existing.name}" y su estado actual es [${existing.status.toUpperCase()}]`);
return;
}
}
const data = {
name: f.get('name'),
email,
password: f.get('pass'),
role: f.get('role'),
status: f.get('status'),
hiringDate: f.get('date'),
vacationDaysUsed: parseInt(f.get('vused')) || 0,
vacationStart: f.get('vs') || '',
vacationEnd: f.get('ve') || '',
overrideCheckOut: editingUser ? (editingUser.overrideCheckOut || false) : false
};
try {
if(editingUser) {
await db.collection('artifacts').doc(appId).collection('public').doc('data').collection('users').doc(editingUser.id).update(data);
} else {
await db.collection('artifacts').doc(appId).collection('public').doc('data').collection('users').add(data);
}
setEditingUser(null);
e.target.reset();
} catch (err) { setSubmitError("Error al conectar con la base de datos."); }
};
const unlockUser = async (uId) => {
try {
await db.collection('artifacts').doc(appId).collection('public').doc('data').collection('users').doc(uId).update({ overrideCheckOut: true });
alert("Usuario desbloqueado. Podrá volver a marcar hoy.");
} catch (err) { alert("Error al desbloquear."); }
};
const deleteUser = async () => {
try {
await db.collection('artifacts').doc(appId).collection('public').doc('data').collection('users').doc(userToDelete.id).delete();
setUserToDelete(null);
} catch (err) { alert("Error al eliminar cuenta."); }
};
const updateLog = async (e) => {
e.preventDefault();
const f = new FormData(e.target);
const ntime = f.get('ntime');
try {
await db.collection('artifacts').doc(appId).collection('public').doc('data').collection('logs').doc(editingLog.id).update({
timestamp: new Date(ntime).getTime(),
type: f.get('ntype'),
client: f.get('nclient'),
edited: true,
date: ntime.split('T')[0]
});
setEditingLog(null);
} catch (err) { alert("Error al editar."); }
};
const togglePermission = (id) => {
setSelectedPermissions(prev => prev.includes(id) ? prev.filter(p => p !== id) : [...prev, id]);
};
const saveRole = async () => {
if (!newRoleName) return;
try {
const newRoleObj = { name: newRoleName.toLowerCase().trim(), permissions: selectedPermissions };
const updated = [...roles.filter(r => r.name !== newRoleObj.name), newRoleObj];
await db.collection('artifacts').doc(appId).collection('public').doc('data').collection('settings').doc('roles').set({ list: updated });
setNewRoleName('');
setSelectedPermissions([]);
} catch (err) { alert("Error al guardar rol."); }
};
// --- FUNCIÓN DE NOTIFICACIONES (NUEVO) ---
const sendNotification = async () => {
if (!notifTitle || targetUsers.length === 0) return alert("Completa el título y elige al menos un usuario destinatario.");
try {
await db.collection('artifacts').doc(appId).collection('public').doc('data').collection('reminders').add({
title: notifTitle,
message: notifBody,
expiresAt: notifExpiry ? new Date(notifExpiry).getTime() : null,
targetUsers: targetUsers,
completedBy: {},
createdAt: Date.now(),
createdBy: 'Admin'
});
setNotifTitle(''); setNotifBody(''); setNotifExpiry(''); setTargetUsers([]);
alert("Aviso enviado correctamente.");
} catch (e) { alert("Error al enviar la notificación."); }
};
return (
{tab === 'logs' && (
)}
{tab === 'users' && (
{editingUser ? "Editar Perfil" : "Nuevo Registro"}
{globalUsers.map(u => (
{u.name[0]}
{u.name}
{u.role} • {u.status} {u.overrideCheckOut && (DESBLOQUEADO)}
))}
)}
{tab === 'roles' && (
Configurar Rol y Permisos
setNewRoleName(e.target.value)} placeholder="Nombre del Rol" className="w-full p-4 bg-slate-50 border-2 border-slate-100 rounded-2xl outline-none font-bold uppercase" />
Habilitar botones para este rol:
{availableActions.map(action => (
))}
{roles.map(r => (
{r.name}
{r.permissions.map(p => {p})}
))}
)}
{/* --- NUEVO TAB: NOTIFICACIONES --- */}
{tab === 'notif' && (
Historial de Avisos
{reminders.sort((a,b)=>b.createdAt-a.createdAt).map(r => (
{r.title}
{r.message}
Enviado: {new Date(r.createdAt).toLocaleString('es-NI', {timeZone: 'America/Managua'})}
{r.expiresAt && Expira: {new Date(r.expiresAt).toLocaleString('es-NI', {timeZone: 'America/Managua'})}}
Confirmaciones de lectura:
{Object.entries(r.completedBy || {}).map(([uId, ts]) => (
{globalUsers.find(u=>u.id===uId)?.name || 'Usuario'} - {new Date(ts).toLocaleTimeString('es-NI', {timeZone: 'America/Managua', hour:'2-digit', minute:'2-digit', hour12:true})}
))}
{Object.keys(r.completedBy || {}).length === 0 &&
Nadie ha completado este aviso.}
))}
)}
{userToDelete && (
¿Eliminar Usuario?
Esta acción borrará permanentemente a {userToDelete.name} y todo su historial.
)}
{editingLog && (
)}
);
};