Corrección gestión de notificaciones
This commit is contained in:
@@ -37,7 +37,7 @@ function notificaciones()
|
|||||||
$preferenciasRow = false;
|
$preferenciasRow = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si no existe registro, crear valores por defecto (incluyendo horario)
|
// Si no existe registro, crear valores por defecto
|
||||||
if (!$preferenciasRow) {
|
if (!$preferenciasRow) {
|
||||||
$preferencias = [
|
$preferencias = [
|
||||||
'nuevas_solicitudes' => 0,
|
'nuevas_solicitudes' => 0,
|
||||||
@@ -49,14 +49,14 @@ function notificaciones()
|
|||||||
'nuevos_archivos' => 0,
|
'nuevos_archivos' => 0,
|
||||||
'intentos_fallidos' => 0,
|
'intentos_fallidos' => 0,
|
||||||
'bloqueo_cuenta' => 0,
|
'bloqueo_cuenta' => 0,
|
||||||
'resumen_diario_hora' => '08:00:00',
|
'resumen_diario_hora' => '08:00',
|
||||||
'resumen_diario_dias' => 'L-V'
|
'resumen_diario_dias' => 'L-V'
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
$preferencias = $preferenciasRow;
|
$preferencias = $preferenciasRow;
|
||||||
// Agregar campos de horario si no existen en el registro
|
// Asegurar valores por defecto para campos de resumen si no existen
|
||||||
$preferencias['resumen_diario_hora'] = $preferenciasRow['resumen_diario_hora'] ?? '08:00:00';
|
$preferencias['resumen_diario_hora'] = $preferencias['resumen_diario_hora'] ?? '08:00';
|
||||||
$preferencias['resumen_diario_dias'] = $preferenciasRow['resumen_diario_dias'] ?? 'L-V';
|
$preferencias['resumen_diario_dias'] = $preferencias['resumen_diario_dias'] ?? 'L-V';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtener tipos de notificaciones disponibles
|
// Obtener tipos de notificaciones disponibles
|
||||||
@@ -152,6 +152,11 @@ function guardarPreferenciasAjax()
|
|||||||
sqlsrv_free_stmt($stmt_delete);
|
sqlsrv_free_stmt($stmt_delete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$response_data = [
|
||||||
|
'notificaciones' => $notificaciones,
|
||||||
|
'notificaciones_extra' => $notificaciones_extra
|
||||||
|
];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'notificaciones_extra':
|
case 'notificaciones_extra':
|
||||||
@@ -180,6 +185,10 @@ function guardarPreferenciasAjax()
|
|||||||
throw new Exception("Error al actualizar configuración de correo extra");
|
throw new Exception("Error al actualizar configuración de correo extra");
|
||||||
}
|
}
|
||||||
sqlsrv_free_stmt($stmt);
|
sqlsrv_free_stmt($stmt);
|
||||||
|
|
||||||
|
$response_data = [
|
||||||
|
'notificaciones_extra' => $notificaciones_extra
|
||||||
|
];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'tipo_notificacion':
|
case 'tipo_notificacion':
|
||||||
@@ -190,6 +199,17 @@ function guardarPreferenciasAjax()
|
|||||||
throw new Exception("Tipo de notificación no especificado");
|
throw new Exception("Tipo de notificación no especificado");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validar que el tipo de notificación es válido
|
||||||
|
$tipos_validos = [
|
||||||
|
'nuevas_solicitudes', 'registro_solicitud', 'cambio_estado',
|
||||||
|
'resumen_diario', 'alertas_tiempo', 'documentos_expediente',
|
||||||
|
'nuevos_archivos', 'intentos_fallidos', 'bloqueo_cuenta'
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!in_array($tipo_nombre, $tipos_validos)) {
|
||||||
|
throw new Exception("Tipo de notificación no válido");
|
||||||
|
}
|
||||||
|
|
||||||
// Verificar que las notificaciones generales estén activadas
|
// Verificar que las notificaciones generales estén activadas
|
||||||
$query_check = "SELECT notificaciones FROM usuarios_sistema WHERE id_usuario = ?";
|
$query_check = "SELECT notificaciones FROM usuarios_sistema WHERE id_usuario = ?";
|
||||||
$stmt_check = sqlsrv_prepare($conn, $query_check, [$id_usuario]);
|
$stmt_check = sqlsrv_prepare($conn, $query_check, [$id_usuario]);
|
||||||
@@ -216,7 +236,7 @@ function guardarPreferenciasAjax()
|
|||||||
|
|
||||||
if ($exists) {
|
if ($exists) {
|
||||||
// Actualizar el campo específico
|
// Actualizar el campo específico
|
||||||
$query = "UPDATE preferencias_notificaciones_usuario SET $tipo_nombre = ? WHERE id_usuario = ?";
|
$query = "UPDATE preferencias_notificaciones_usuario SET [$tipo_nombre] = ? WHERE id_usuario = ?";
|
||||||
$stmt = sqlsrv_prepare($conn, $query, [$valor, $id_usuario]);
|
$stmt = sqlsrv_prepare($conn, $query, [$valor, $id_usuario]);
|
||||||
} else {
|
} else {
|
||||||
// Crear registro con valores por defecto y el campo específico
|
// Crear registro con valores por defecto y el campo específico
|
||||||
@@ -229,13 +249,15 @@ function guardarPreferenciasAjax()
|
|||||||
'documentos_expediente' => 0,
|
'documentos_expediente' => 0,
|
||||||
'nuevos_archivos' => 0,
|
'nuevos_archivos' => 0,
|
||||||
'intentos_fallidos' => 0,
|
'intentos_fallidos' => 0,
|
||||||
'bloqueo_cuenta' => 0
|
'bloqueo_cuenta' => 0,
|
||||||
|
'resumen_diario_hora' => '08:00',
|
||||||
|
'resumen_diario_dias' => 'L-V'
|
||||||
];
|
];
|
||||||
|
|
||||||
// Establecer el valor específico
|
// Establecer el valor específico
|
||||||
$tipos_default[$tipo_nombre] = $valor;
|
$tipos_default[$tipo_nombre] = $valor;
|
||||||
|
|
||||||
$campos = implode(', ', array_keys($tipos_default));
|
$campos = '[' . implode('], [', array_keys($tipos_default)) . ']';
|
||||||
$placeholders = rtrim(str_repeat('?, ', count($tipos_default)), ', ');
|
$placeholders = rtrim(str_repeat('?, ', count($tipos_default)), ', ');
|
||||||
$query = "INSERT INTO preferencias_notificaciones_usuario (id_usuario, $campos) VALUES (?, $placeholders)";
|
$query = "INSERT INTO preferencias_notificaciones_usuario (id_usuario, $campos) VALUES (?, $placeholders)";
|
||||||
|
|
||||||
@@ -244,12 +266,16 @@ function guardarPreferenciasAjax()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!$stmt || !sqlsrv_execute($stmt)) {
|
if (!$stmt || !sqlsrv_execute($stmt)) {
|
||||||
throw new Exception("Error al actualizar preferencia específica");
|
throw new Exception("Error al actualizar preferencia específica: " . print_r(sqlsrv_errors(), true));
|
||||||
}
|
}
|
||||||
sqlsrv_free_stmt($stmt);
|
sqlsrv_free_stmt($stmt);
|
||||||
|
|
||||||
|
$response_data = [
|
||||||
|
$tipo_nombre => $valor
|
||||||
|
];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'resumen_diario_config':
|
case 'resumen_config':
|
||||||
$hora = $input['hora'] ?? '08:00';
|
$hora = $input['hora'] ?? '08:00';
|
||||||
$dias = $input['dias'] ?? 'L-V';
|
$dias = $input['dias'] ?? 'L-V';
|
||||||
|
|
||||||
@@ -259,23 +285,35 @@ function guardarPreferenciasAjax()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validar días
|
// Validar días
|
||||||
$dias_validos = ['L-V', 'TODOS', 'L-S'];
|
$dias_validos = ['L-V', 'TODOS'];
|
||||||
if (!in_array($dias, $dias_validos)) {
|
$es_personalizado = !in_array($dias, $dias_validos);
|
||||||
throw new Exception("Configuración de días inválida");
|
|
||||||
|
if ($es_personalizado) {
|
||||||
|
// Validar formato personalizado (ej: "L,M,X" o "L,V,S,D")
|
||||||
|
$dias_array = explode(',', $dias);
|
||||||
|
$dias_permitidos = ['L', 'M', 'X', 'J', 'V', 'S', 'D'];
|
||||||
|
|
||||||
|
foreach ($dias_array as $dia) {
|
||||||
|
$dia = trim($dia);
|
||||||
|
if (!in_array($dia, $dias_permitidos)) {
|
||||||
|
throw new Exception("Días seleccionados inválidos");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verificar que las notificaciones generales estén activadas
|
// Verificar que el resumen diario esté activado
|
||||||
$query_check = "SELECT notificaciones FROM usuarios_sistema WHERE id_usuario = ?";
|
$query_check = "SELECT resumen_diario FROM preferencias_notificaciones_usuario WHERE id_usuario = ?";
|
||||||
$stmt_check = sqlsrv_prepare($conn, $query_check, [$id_usuario]);
|
$stmt_check = sqlsrv_prepare($conn, $query_check, [$id_usuario]);
|
||||||
|
$resumen_activo = false;
|
||||||
|
|
||||||
if ($stmt_check && sqlsrv_execute($stmt_check)) {
|
if ($stmt_check && sqlsrv_execute($stmt_check)) {
|
||||||
$row = sqlsrv_fetch_array($stmt_check, SQLSRV_FETCH_ASSOC);
|
$row = sqlsrv_fetch_array($stmt_check, SQLSRV_FETCH_ASSOC);
|
||||||
|
$resumen_activo = $row && $row['resumen_diario'];
|
||||||
sqlsrv_free_stmt($stmt_check);
|
sqlsrv_free_stmt($stmt_check);
|
||||||
|
}
|
||||||
|
|
||||||
if (!$row || !$row['notificaciones']) {
|
if (!$resumen_activo) {
|
||||||
throw new Exception("Las notificaciones generales deben estar activadas primero");
|
throw new Exception("El resumen diario debe estar activado para configurar sus opciones");
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new Exception("Error al verificar configuración");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verificar si existe el registro
|
// Verificar si existe el registro
|
||||||
@@ -289,10 +327,8 @@ function guardarPreferenciasAjax()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($exists) {
|
if ($exists) {
|
||||||
// Actualizar configuración de resumen diario
|
// Actualizar configuración del resumen
|
||||||
$query = "UPDATE preferencias_notificaciones_usuario
|
$query = "UPDATE preferencias_notificaciones_usuario SET resumen_diario_hora = ?, resumen_diario_dias = ? WHERE id_usuario = ?";
|
||||||
SET resumen_diario_hora = ?, resumen_diario_dias = ?
|
|
||||||
WHERE id_usuario = ?";
|
|
||||||
$stmt = sqlsrv_prepare($conn, $query, [$hora, $dias, $id_usuario]);
|
$stmt = sqlsrv_prepare($conn, $query, [$hora, $dias, $id_usuario]);
|
||||||
} else {
|
} else {
|
||||||
// Crear registro con valores por defecto
|
// Crear registro con valores por defecto
|
||||||
@@ -300,7 +336,7 @@ function guardarPreferenciasAjax()
|
|||||||
'nuevas_solicitudes' => 0,
|
'nuevas_solicitudes' => 0,
|
||||||
'registro_solicitud' => 0,
|
'registro_solicitud' => 0,
|
||||||
'cambio_estado' => 0,
|
'cambio_estado' => 0,
|
||||||
'resumen_diario' => 0,
|
'resumen_diario' => 1, // Activado porque llegamos aquí desde su configuración
|
||||||
'alertas_tiempo' => 0,
|
'alertas_tiempo' => 0,
|
||||||
'documentos_expediente' => 0,
|
'documentos_expediente' => 0,
|
||||||
'nuevos_archivos' => 0,
|
'nuevos_archivos' => 0,
|
||||||
@@ -310,7 +346,7 @@ function guardarPreferenciasAjax()
|
|||||||
'resumen_diario_dias' => $dias
|
'resumen_diario_dias' => $dias
|
||||||
];
|
];
|
||||||
|
|
||||||
$campos = implode(', ', array_keys($tipos_default));
|
$campos = '[' . implode('], [', array_keys($tipos_default)) . ']';
|
||||||
$placeholders = rtrim(str_repeat('?, ', count($tipos_default)), ', ');
|
$placeholders = rtrim(str_repeat('?, ', count($tipos_default)), ', ');
|
||||||
$query = "INSERT INTO preferencias_notificaciones_usuario (id_usuario, $campos) VALUES (?, $placeholders)";
|
$query = "INSERT INTO preferencias_notificaciones_usuario (id_usuario, $campos) VALUES (?, $placeholders)";
|
||||||
|
|
||||||
@@ -319,9 +355,14 @@ function guardarPreferenciasAjax()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!$stmt || !sqlsrv_execute($stmt)) {
|
if (!$stmt || !sqlsrv_execute($stmt)) {
|
||||||
throw new Exception("Error al actualizar configuración de resumen diario");
|
throw new Exception("Error al actualizar configuración del resumen: " . print_r(sqlsrv_errors(), true));
|
||||||
}
|
}
|
||||||
sqlsrv_free_stmt($stmt);
|
sqlsrv_free_stmt($stmt);
|
||||||
|
|
||||||
|
$response_data = [
|
||||||
|
'resumen_hora' => $hora,
|
||||||
|
'resumen_dias' => $dias
|
||||||
|
];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -334,7 +375,8 @@ function guardarPreferenciasAjax()
|
|||||||
echo json_encode([
|
echo json_encode([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'message' => 'Preferencias guardadas automáticamente',
|
'message' => 'Preferencias guardadas automáticamente',
|
||||||
'tipo' => $tipo_cambio
|
'tipo' => $tipo_cambio,
|
||||||
|
'data' => $response_data ?? []
|
||||||
]);
|
]);
|
||||||
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
@@ -420,3 +462,70 @@ function obtenerPreferenciasNotificacion($id_usuario)
|
|||||||
'correo_extra' => $correo_extra
|
'correo_extra' => $correo_extra
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Función auxiliar para verificar si un usuario debe recibir un tipo específico de notificación
|
||||||
|
function debeRecibirNotificacion($id_usuario, $tipo_notificacion)
|
||||||
|
{
|
||||||
|
$preferencias = obtenerPreferenciasNotificacion($id_usuario);
|
||||||
|
|
||||||
|
if (!$preferencias || !$preferencias['config_general']['notificaciones']) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si no hay preferencias específicas, usar valores por defecto (false)
|
||||||
|
if (!$preferencias['preferencias']) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isset($preferencias['preferencias'][$tipo_notificacion]) &&
|
||||||
|
$preferencias['preferencias'][$tipo_notificacion];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Función auxiliar para obtener la configuración del resumen diario de un usuario
|
||||||
|
function obtenerConfigResumenDiario($id_usuario)
|
||||||
|
{
|
||||||
|
$conn = getConnection();
|
||||||
|
|
||||||
|
$query = "
|
||||||
|
SELECT pnu.resumen_diario, pnu.resumen_diario_hora, pnu.resumen_diario_dias
|
||||||
|
FROM preferencias_notificaciones_usuario pnu
|
||||||
|
INNER JOIN usuarios_sistema us ON pnu.id_usuario = us.id_usuario
|
||||||
|
WHERE pnu.id_usuario = ? AND us.notificaciones = 1 AND pnu.resumen_diario = 1
|
||||||
|
";
|
||||||
|
|
||||||
|
$stmt = sqlsrv_prepare($conn, $query, [$id_usuario]);
|
||||||
|
$config = null;
|
||||||
|
|
||||||
|
if ($stmt && sqlsrv_execute($stmt)) {
|
||||||
|
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||||
|
if ($row) {
|
||||||
|
$config = [
|
||||||
|
'hora' => $row['resumen_diario_hora'] ?? '08:00',
|
||||||
|
'dias' => $row['resumen_diario_dias'] ?? 'L-V'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
sqlsrv_free_stmt($stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlsrv_close($conn);
|
||||||
|
return $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Función auxiliar para verificar si hoy es día de envío de resumen según la configuración del usuario
|
||||||
|
function esDiaResumen($config_dias)
|
||||||
|
{
|
||||||
|
$hoy = date('N'); // 1=Lunes, 7=Domingo
|
||||||
|
$dia_letra = ['', 'L', 'M', 'X', 'J', 'V', 'S', 'D'][$hoy];
|
||||||
|
|
||||||
|
switch ($config_dias) {
|
||||||
|
case 'L-V':
|
||||||
|
return in_array($hoy, [1, 2, 3, 4, 5]); // Lunes a Viernes
|
||||||
|
case 'TODOS':
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
// Configuración personalizada
|
||||||
|
$dias_activos = explode(',', $config_dias);
|
||||||
|
return in_array($dia_letra, array_map('trim', $dias_activos));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
@@ -64,7 +64,7 @@ if (!isset($_SESSION['usuario_id']) || $_SESSION['tipo_usuario'] !== 'importador
|
|||||||
// Detecta si estamos en alguna parta de seguridad
|
// Detecta si estamos en alguna parta de seguridad
|
||||||
$esVistaSeguridad = str_contains($_SERVER['REQUEST_URI'], '/seguridad');
|
$esVistaSeguridad = str_contains($_SERVER['REQUEST_URI'], '/seguridad');
|
||||||
// Detecta si estamos en alguna parte de preferencias
|
// Detecta si estamos en alguna parte de preferencias
|
||||||
$esVistaPreferencias = str_contains($_SERVER['REQUEST_URI'], '/preferencias')
|
$esVistaPreferencias = str_contains($_SERVER['REQUEST_URI'], '/preferencias');
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<!-- INFORMACIÓN GENERAL -->
|
<!-- INFORMACIÓN GENERAL -->
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ include __DIR__ . '/../partials/sidebar_configuracion.php';
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: 'Segoe UI', sans-serif;
|
font-family: 'Segoe UI', sans-serif;
|
||||||
@@ -54,7 +55,6 @@ include __DIR__ . '/../partials/sidebar_configuracion.php';
|
|||||||
margin-left: 250px; /* Ancho del sidebar */
|
margin-left: 250px; /* Ancho del sidebar */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* En móviles, sin margen lateral */
|
/* En móviles, sin margen lateral */
|
||||||
@media (max-width: 767.98px) {
|
@media (max-width: 767.98px) {
|
||||||
.content {
|
.content {
|
||||||
@@ -74,81 +74,86 @@ include __DIR__ . '/../partials/sidebar_configuracion.php';
|
|||||||
.card {
|
.card {
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
}
|
}
|
||||||
.section-divider {
|
|
||||||
border-left: 4px solid #007bff;
|
|
||||||
padding-left: 15px;
|
|
||||||
margin: 20px 0;
|
|
||||||
}
|
|
||||||
.fade-transition {
|
.fade-transition {
|
||||||
transition: opacity 0.3s ease-in-out;
|
transition: all 0.3s ease-in-out;
|
||||||
}
|
}
|
||||||
.correo-extra-section {
|
.section-divider {
|
||||||
background-color: #f8f9fa;
|
border-bottom: 1px solid #e9ecef;
|
||||||
border-radius: 8px;
|
padding-bottom: 1.5rem;
|
||||||
padding: 15px;
|
margin-bottom: 1.5rem;
|
||||||
margin-top: 15px;
|
|
||||||
}
|
}
|
||||||
.success-message {
|
.section-divider:last-child {
|
||||||
background-color: #d4edda;
|
border-bottom: none;
|
||||||
color: #155724;
|
margin-bottom: 0;
|
||||||
padding: 10px;
|
padding-bottom: 0;
|
||||||
border-radius: 5px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
border: 1px solid #c3e6cb;
|
|
||||||
}
|
}
|
||||||
.error-message {
|
|
||||||
background-color: #f8d7da;
|
|
||||||
color: #721c24;
|
|
||||||
padding: 10px;
|
|
||||||
border-radius: 5px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
border: 1px solid #f5c6cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Estilos para indicadores de guardado */
|
|
||||||
.save-indicator {
|
.save-indicator {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 20px;
|
top: 20px;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
padding: 10px 15px;
|
background: #28a745;
|
||||||
border-radius: 8px;
|
color: white;
|
||||||
font-weight: 500;
|
padding: 10px 20px;
|
||||||
z-index: 9999;
|
border-radius: 25px;
|
||||||
transition: all 0.3s ease;
|
|
||||||
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||||||
|
z-index: 1050;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
|
.success-message {
|
||||||
.save-indicator.saving {
|
background: #d4edda;
|
||||||
background-color: #fff3cd;
|
color: #155724;
|
||||||
color: #856404;
|
padding: 12px 16px;
|
||||||
border: 1px solid #ffeaa7;
|
border-radius: 8px;
|
||||||
|
border: 1px solid #c3e6cb;
|
||||||
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
.error-message {
|
||||||
.save-indicator.saved {
|
background: #f8d7da;
|
||||||
background-color: #d1ecf1;
|
|
||||||
color: #0c5460;
|
|
||||||
border: 1px solid #bee5eb;
|
|
||||||
}
|
|
||||||
|
|
||||||
.save-indicator.error {
|
|
||||||
background-color: #f8d7da;
|
|
||||||
color: #721c24;
|
color: #721c24;
|
||||||
|
padding: 12px 16px;
|
||||||
|
border-radius: 8px;
|
||||||
border: 1px solid #f5c6cb;
|
border: 1px solid #f5c6cb;
|
||||||
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
.resumen-config {
|
||||||
.spinner-border-sm {
|
background: #f8f9fa;
|
||||||
width: 1rem;
|
border: 1px solid #dee2e6;
|
||||||
height: 1rem;
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
.time-input {
|
||||||
/* Estilo para switches deshabilitados temporalmente */
|
max-width: 120px;
|
||||||
.form-check-input:disabled {
|
|
||||||
opacity: 0.6;
|
|
||||||
}
|
}
|
||||||
|
.days-selector {
|
||||||
/* Animación sutil para switches */
|
display: flex;
|
||||||
.form-check-input {
|
flex-wrap: wrap;
|
||||||
transition: all 0.2s ease;
|
gap: 10px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.day-option {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 45px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.day-preset {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
.day-preset .btn {
|
||||||
|
margin-right: 10px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
.form-check-input:checked {
|
||||||
|
background-color: #0d6efd;
|
||||||
|
border-color: #0d6efd;
|
||||||
|
}
|
||||||
|
.btn-outline-primary.active {
|
||||||
|
background-color: #0d6efd;
|
||||||
|
border-color: #0d6efd;
|
||||||
|
color: white;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
@@ -187,62 +192,227 @@ include __DIR__ . '/../partials/sidebar_configuracion.php';
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Tipos de notificaciones -->
|
<!-- Tipos de notificaciones -->
|
||||||
<div id="tipos-notificaciones" class="fade-transition"
|
<div id="tipos-notificaciones" class="fade-transition" style="opacity:1;">
|
||||||
<?= !$notificaciones['notificaciones'] ? 'style="display:none; opacity:0;"' : 'style="opacity:1;"' ?>>
|
|
||||||
|
|
||||||
<div class="section-divider">
|
<div class="section-divider">
|
||||||
<h6 class="mb-3">📋 Tipos de Notificaciones</h6>
|
<h6 class="mb-3">📋 Tipos de Notificaciones</h6>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<?php foreach ($tipos as $clave => $descripcion): ?>
|
<div class="col-md-6 mb-3">
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input tipo-notificacion" type="checkbox"
|
||||||
|
name="nuevas_solicitudes" id="nuevas_solicitudes"
|
||||||
|
data-tipo="tipo_notificacion" data-nombre="nuevas_solicitudes"
|
||||||
|
<?= !empty($preferencias['nuevas_solicitudes']) ? 'checked' : '' ?>>
|
||||||
|
<label class="form-check-label" for="nuevas_solicitudes">
|
||||||
|
<strong>Nuevas Solicitudes</strong>
|
||||||
|
<div class="form-text">Creación de nuevas solicitudes de importación</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input tipo-notificacion" type="checkbox"
|
||||||
|
name="registro_solicitud" id="registro_solicitud"
|
||||||
|
data-tipo="tipo_notificacion" data-nombre="registro_solicitud"
|
||||||
|
<?= !empty($preferencias['registro_solicitud']) ? 'checked' : '' ?>>
|
||||||
|
<label class="form-check-label" for="registro_solicitud">
|
||||||
|
<strong>Registro Solicitud</strong>
|
||||||
|
<div class="form-text">Notificación inmediata al registrar una solicitud</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input tipo-notificacion" type="checkbox"
|
||||||
|
name="cambio_estado" id="cambio_estado"
|
||||||
|
data-tipo="tipo_notificacion" data-nombre="cambio_estado"
|
||||||
|
<?= !empty($preferencias['cambio_estado']) ? 'checked' : '' ?>>
|
||||||
|
<label class="form-check-label" for="cambio_estado">
|
||||||
|
<strong>Cambio Estado</strong>
|
||||||
|
<div class="form-text">Cambio de estado de solicitudes de importación</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input tipo-notificacion" type="checkbox"
|
||||||
|
name="resumen_diario" id="resumen_diario"
|
||||||
|
data-tipo="tipo_notificacion" data-nombre="resumen_diario"
|
||||||
|
<?= !empty($preferencias['resumen_diario']) ? 'checked' : '' ?>>
|
||||||
|
<label class="form-check-label" for="resumen_diario">
|
||||||
|
<strong>Resumen Diario</strong>
|
||||||
|
<div class="form-text">Resumen diario de solicitudes de importación</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input tipo-notificacion" type="checkbox"
|
||||||
|
name="alertas_tiempo" id="alertas_tiempo"
|
||||||
|
data-tipo="tipo_notificacion" data-nombre="alertas_tiempo"
|
||||||
|
<?= !empty($preferencias['alertas_tiempo']) ? 'checked' : '' ?>>
|
||||||
|
<label class="form-check-label" for="alertas_tiempo">
|
||||||
|
<strong>Alertas Tiempo</strong>
|
||||||
|
<div class="form-text">Alertas por tiempo excedido en estados críticos</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input tipo-notificacion" type="checkbox"
|
||||||
|
name="documentos_expediente" id="documentos_expediente"
|
||||||
|
data-tipo="tipo_notificacion" data-nombre="documentos_expediente"
|
||||||
|
<?= !empty($preferencias['documentos_expediente']) ? 'checked' : '' ?>>
|
||||||
|
<label class="form-check-label" for="documentos_expediente">
|
||||||
|
<strong>Documentos Expediente</strong>
|
||||||
|
<div class="form-text">Incorporación de documentos al expediente electrónico</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input tipo-notificacion" type="checkbox"
|
||||||
|
name="nuevos_archivos" id="nuevos_archivos"
|
||||||
|
data-tipo="tipo_notificacion" data-nombre="nuevos_archivos"
|
||||||
|
<?= !empty($preferencias['nuevos_archivos']) ? 'checked' : '' ?>>
|
||||||
|
<label class="form-check-label" for="nuevos_archivos">
|
||||||
|
<strong>Nuevos Archivos</strong>
|
||||||
|
<div class="form-text">Aviso al agregarse nuevos archivos o documentos</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input tipo-notificacion" type="checkbox"
|
||||||
|
name="intentos_fallidos" id="intentos_fallidos"
|
||||||
|
data-tipo="tipo_notificacion" data-nombre="intentos_fallidos"
|
||||||
|
<?= !empty($preferencias['intentos_fallidos']) ? 'checked' : '' ?>>
|
||||||
|
<label class="form-check-label" for="intentos_fallidos">
|
||||||
|
<strong>Intentos Fallidos</strong>
|
||||||
|
<div class="form-text">Intentos fallidos de acceso</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input tipo-notificacion" type="checkbox"
|
||||||
|
name="bloqueo_cuenta" id="bloqueo_cuenta"
|
||||||
|
data-tipo="tipo_notificacion" data-nombre="bloqueo_cuenta"
|
||||||
|
<?= !empty($preferencias['bloqueo_cuenta']) ? 'checked' : '' ?>>
|
||||||
|
<label class="form-check-label" for="bloqueo_cuenta">
|
||||||
|
<strong>Bloqueo Cuenta</strong>
|
||||||
|
<div class="form-text">Bloqueo de cuenta</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Configuración específica del resumen diario -->
|
||||||
|
<div id="resumen-diario-config" class="fade-transition" style="display: none; opacity: 0;">
|
||||||
|
<div class="resumen-config">
|
||||||
|
<h6 class="mb-3">
|
||||||
|
<i class="fas fa-clock me-2"></i>
|
||||||
|
⏰ Configuración del Resumen Diario
|
||||||
|
</h6>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
<div class="col-md-6 mb-3">
|
<div class="col-md-6 mb-3">
|
||||||
<div class="form-check form-switch">
|
<label for="resumen_hora" class="form-label fw-bold">Hora de envío</label>
|
||||||
<input class="form-check-input tipo-notificacion" type="checkbox"
|
<input type="time" class="form-control time-input" id="resumen_hora"
|
||||||
name="<?= $clave ?>" id="<?= $clave ?>"
|
name="resumen_hora" value="08:00">
|
||||||
data-tipo="tipo_notificacion" data-nombre="<?= $clave ?>"
|
<div class="form-text">Hora en que se enviará el resumen diario</div>
|
||||||
<?= ($preferencias[$clave] ?? 0) ? 'checked' : '' ?>>
|
</div>
|
||||||
<label class="form-check-label" for="<?= $clave ?>">
|
|
||||||
<strong><?= ucwords(str_replace('_', ' ', $clave)) ?></strong>
|
<div class="col-md-6 mb-3">
|
||||||
<div class="form-text"><?= htmlspecialchars($descripcion) ?></div>
|
<label class="form-label fw-bold">Días de envío</label>
|
||||||
</label>
|
|
||||||
|
<!-- Botones de preselección -->
|
||||||
|
<div class="day-preset">
|
||||||
|
<button type="button" class="btn btn-outline-primary btn-sm preset-btn active" data-preset="L-V">
|
||||||
|
Lunes a Viernes
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-outline-primary btn-sm preset-btn" data-preset="TODOS">
|
||||||
|
Todos los días
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-outline-primary btn-sm preset-btn" data-preset="PERSONALIZADO">
|
||||||
|
Personalizado
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Configuración específica para resumen diario -->
|
<!-- Selector individual de días -->
|
||||||
<?php if ($clave === 'resumen_diario'): ?>
|
<div class="days-selector" id="days-selector" style="display: none;">
|
||||||
<div id="resumen-diario-config" class="mt-3 ps-4 fade-transition"
|
<div class="day-option">
|
||||||
style="<?= ($preferencias['resumen_diario'] ?? 0) ? 'display:block; opacity:1;' : 'display:none; opacity:0;' ?>">
|
<div class="form-check">
|
||||||
<div class="card border-0 bg-light p-3">
|
<input class="form-check-input day-checkbox" type="checkbox"
|
||||||
<h6 class="mb-3 text-primary">⚙️ Configuración de Horario</h6>
|
value="L" id="day-L" name="dias[]">
|
||||||
<div class="row">
|
<label class="form-check-label" for="day-L">L</label>
|
||||||
<div class="col-md-6 mb-2">
|
|
||||||
<label for="resumen_hora" class="form-label small fw-bold">🕐 Hora de envío</label>
|
|
||||||
<input type="time" class="form-control form-control-sm"
|
|
||||||
id="resumen_hora" name="resumen_hora"
|
|
||||||
value="<?= date('H:i', strtotime($preferencias['resumen_diario_hora'] ?? '08:00:00')) ?>">
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6 mb-2">
|
|
||||||
<label for="resumen_dias" class="form-label small fw-bold">📅 Días de envío</label>
|
|
||||||
<select class="form-select form-select-sm" id="resumen_dias" name="resumen_dias">
|
|
||||||
<option value="L-V" <?= ($preferencias['resumen_diario_dias'] ?? 'L-V') === 'L-V' ? 'selected' : '' ?>>
|
|
||||||
Lunes a Viernes
|
|
||||||
</option>
|
|
||||||
<option value="L-S" <?= ($preferencias['resumen_diario_dias'] ?? 'L-V') === 'L-S' ? 'selected' : '' ?>>
|
|
||||||
Lunes a Sábado
|
|
||||||
</option>
|
|
||||||
<option value="TODOS" <?= ($preferencias['resumen_diario_dias'] ?? 'L-V') === 'TODOS' ? 'selected' : '' ?>>
|
|
||||||
Todos los días
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-text mt-2">
|
|
||||||
<i class="fas fa-info-circle text-info"></i>
|
|
||||||
Recibirás un resumen con las actividades del día anterior
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<div class="day-option">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input day-checkbox" type="checkbox"
|
||||||
|
value="M" id="day-M" name="dias[]">
|
||||||
|
<label class="form-check-label" for="day-M">M</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="day-option">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input day-checkbox" type="checkbox"
|
||||||
|
value="X" id="day-X" name="dias[]">
|
||||||
|
<label class="form-check-label" for="day-X">X</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="day-option">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input day-checkbox" type="checkbox"
|
||||||
|
value="J" id="day-J" name="dias[]">
|
||||||
|
<label class="form-check-label" for="day-J">J</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="day-option">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input day-checkbox" type="checkbox"
|
||||||
|
value="V" id="day-V" name="dias[]">
|
||||||
|
<label class="form-check-label" for="day-V">V</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="day-option">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input day-checkbox" type="checkbox"
|
||||||
|
value="S" id="day-S" name="dias[]">
|
||||||
|
<label class="form-check-label" for="day-S">S</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="day-option">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input day-checkbox" type="checkbox"
|
||||||
|
value="D" id="day-D" name="dias[]">
|
||||||
|
<label class="form-check-label" for="day-D">D</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input type="hidden" id="resumen_dias" name="resumen_dias" value="L-V">
|
||||||
|
<div class="form-text">Días en que se enviará el resumen diario</div>
|
||||||
</div>
|
</div>
|
||||||
<?php endforeach; ?>
|
</div>
|
||||||
|
|
||||||
|
<div class="alert alert-info d-flex align-items-center mt-3">
|
||||||
|
<i class="fas fa-info-circle me-2"></i>
|
||||||
|
<small>
|
||||||
|
El resumen diario se enviará automáticamente a la hora configurada,
|
||||||
|
únicamente en los días seleccionados y solo si hay actividad de solicitudes.
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -400,6 +570,18 @@ include __DIR__ . '/../partials/sidebar_configuracion.php';
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Función para debounce (evitar múltiples guardados rápidos)
|
||||||
|
function debounce(func, wait) {
|
||||||
|
return function executedFunction(...args) {
|
||||||
|
const later = () => {
|
||||||
|
clearTimeout(saveTimeout);
|
||||||
|
func(...args);
|
||||||
|
};
|
||||||
|
clearTimeout(saveTimeout);
|
||||||
|
saveTimeout = setTimeout(later, wait);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Event listener para switch general de notificaciones
|
// Event listener para switch general de notificaciones
|
||||||
document.getElementById('notificaciones').addEventListener('change', function() {
|
document.getElementById('notificaciones').addEventListener('change', function() {
|
||||||
const isChecked = this.checked;
|
const isChecked = this.checked;
|
||||||
@@ -429,6 +611,15 @@ include __DIR__ . '/../partials/sidebar_configuracion.php';
|
|||||||
document.querySelectorAll('.tipo-notificacion').forEach(checkbox => {
|
document.querySelectorAll('.tipo-notificacion').forEach(checkbox => {
|
||||||
checkbox.checked = false;
|
checkbox.checked = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Ocultar configuración de resumen diario
|
||||||
|
const resumenDiarioConfig = document.getElementById('resumen-diario-config');
|
||||||
|
if (resumenDiarioConfig) {
|
||||||
|
resumenDiarioConfig.style.opacity = '0';
|
||||||
|
setTimeout(() => {
|
||||||
|
resumenDiarioConfig.style.display = 'none';
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -483,10 +674,147 @@ include __DIR__ . '/../partials/sidebar_configuracion.php';
|
|||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.disabled = false;
|
this.disabled = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Si es el resumen diario, mostrar/ocultar configuración
|
||||||
|
if (tipoNombre === 'resumen_diario') {
|
||||||
|
toggleSection(this, 'resumen-diario-config');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Prevenir envío accidental del formulario (aunque ya no lo necesitamos)
|
// === FUNCIONALIDAD DE RESUMEN DIARIO ===
|
||||||
|
|
||||||
|
// Referencias específicas para resumen diario
|
||||||
|
const resumenDiario = document.getElementById('resumen_diario');
|
||||||
|
const resumenDiarioConfig = document.getElementById('resumen-diario-config');
|
||||||
|
const presetButtons = document.querySelectorAll('.preset-btn');
|
||||||
|
const daysSelector = document.getElementById('days-selector');
|
||||||
|
const dayCheckboxes = document.querySelectorAll('.day-checkbox');
|
||||||
|
const resumenDiasInput = document.getElementById('resumen_dias');
|
||||||
|
const resumenHoraInput = document.getElementById('resumen_hora');
|
||||||
|
|
||||||
|
// Función para actualizar el valor de días seleccionados
|
||||||
|
function updateResumenDias() {
|
||||||
|
const selectedDays = Array.from(dayCheckboxes)
|
||||||
|
.filter(cb => cb.checked)
|
||||||
|
.map(cb => cb.value);
|
||||||
|
|
||||||
|
if (selectedDays.length === 7) {
|
||||||
|
resumenDiasInput.value = 'TODOS';
|
||||||
|
} else if (selectedDays.length === 5 &&
|
||||||
|
['L', 'M', 'X', 'J', 'V'].every(day => selectedDays.includes(day))) {
|
||||||
|
resumenDiasInput.value = 'L-V';
|
||||||
|
} else {
|
||||||
|
resumenDiasInput.value = selectedDays.join(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Función para cargar preset de días
|
||||||
|
function loadDaysPreset(preset) {
|
||||||
|
// Desmarcar todos los checkboxes primero
|
||||||
|
dayCheckboxes.forEach(cb => cb.checked = false);
|
||||||
|
|
||||||
|
// Marcar según el preset
|
||||||
|
if (preset === 'L-V') {
|
||||||
|
['L', 'M', 'X', 'J', 'V'].forEach(day => {
|
||||||
|
const checkbox = document.getElementById(`day-${day}`);
|
||||||
|
if (checkbox) checkbox.checked = true;
|
||||||
|
});
|
||||||
|
} else if (preset === 'TODOS') {
|
||||||
|
dayCheckboxes.forEach(cb => cb.checked = true);
|
||||||
|
} else if (preset.includes(',')) {
|
||||||
|
// Preset personalizado
|
||||||
|
const days = preset.split(',');
|
||||||
|
days.forEach(day => {
|
||||||
|
const checkbox = document.getElementById(`day-${day.trim()}`);
|
||||||
|
if (checkbox) checkbox.checked = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateResumenDias();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Función para actualizar botones de preset según selección actual
|
||||||
|
function updatePresetButtons() {
|
||||||
|
const currentValue = resumenDiasInput.value;
|
||||||
|
presetButtons.forEach(btn => btn.classList.remove('active'));
|
||||||
|
|
||||||
|
const activeButton = document.querySelector(`[data-preset="${currentValue}"]`);
|
||||||
|
if (activeButton) {
|
||||||
|
activeButton.classList.add('active');
|
||||||
|
daysSelector.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
// Es personalizado
|
||||||
|
const customButton = document.querySelector('[data-preset="PERSONALIZADO"]');
|
||||||
|
if (customButton) {
|
||||||
|
customButton.classList.add('active');
|
||||||
|
daysSelector.style.display = 'flex';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Función debounced para guardar configuración de resumen
|
||||||
|
const saveResumenConfig = debounce(async function() {
|
||||||
|
const hora = resumenHoraInput.value;
|
||||||
|
const dias = resumenDiasInput.value;
|
||||||
|
|
||||||
|
await autoSave('resumen_config', {
|
||||||
|
hora: hora,
|
||||||
|
dias: dias
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
// Event listeners para botones de preset de días
|
||||||
|
if (presetButtons.length > 0) {
|
||||||
|
presetButtons.forEach(button => {
|
||||||
|
button.addEventListener('click', function() {
|
||||||
|
// Remover clase active de todos los botones
|
||||||
|
presetButtons.forEach(btn => btn.classList.remove('active'));
|
||||||
|
// Agregar clase active al botón clickeado
|
||||||
|
this.classList.add('active');
|
||||||
|
|
||||||
|
const preset = this.dataset.preset;
|
||||||
|
|
||||||
|
if (preset === 'PERSONALIZADO') {
|
||||||
|
daysSelector.style.display = 'flex';
|
||||||
|
} else {
|
||||||
|
daysSelector.style.display = 'none';
|
||||||
|
resumenDiasInput.value = preset;
|
||||||
|
loadDaysPreset(preset);
|
||||||
|
saveResumenConfig();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event listeners para checkboxes individuales de días
|
||||||
|
if (dayCheckboxes.length > 0) {
|
||||||
|
dayCheckboxes.forEach(checkbox => {
|
||||||
|
checkbox.addEventListener('change', function() {
|
||||||
|
updateResumenDias();
|
||||||
|
updatePresetButtons();
|
||||||
|
saveResumenConfig();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event listener para cambio de hora
|
||||||
|
if (resumenHoraInput) {
|
||||||
|
resumenHoraInput.addEventListener('change', function() {
|
||||||
|
saveResumenConfig();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inicialización del estado de los días al cargar la página
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
if (resumenDiasInput && resumenDiasInput.value) {
|
||||||
|
loadDaysPreset(resumenDiasInput.value);
|
||||||
|
updatePresetButtons();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// === FIN FUNCIONALIDAD DE RESUMEN DIARIO ===
|
||||||
|
// Prevenir envío accidental del formulario
|
||||||
document.addEventListener('keydown', function(e) {
|
document.addEventListener('keydown', function(e) {
|
||||||
if (e.key === 'Enter' && e.target.type !== 'submit') {
|
if (e.key === 'Enter' && e.target.type !== 'submit') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -501,80 +829,6 @@ include __DIR__ . '/../partials/sidebar_configuracion.php';
|
|||||||
return e.returnValue;
|
return e.returnValue;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Event listener específico para el switch de resumen diario
|
|
||||||
document.getElementById('resumen_diario').addEventListener('change', function() {
|
|
||||||
const isChecked = this.checked;
|
|
||||||
const configSection = document.getElementById('resumen-diario-config');
|
|
||||||
|
|
||||||
// Mostrar/ocultar configuración de horario con animación
|
|
||||||
if (isChecked) {
|
|
||||||
configSection.style.display = 'block';
|
|
||||||
setTimeout(() => {
|
|
||||||
configSection.style.opacity = '1';
|
|
||||||
}, 10);
|
|
||||||
} else {
|
|
||||||
configSection.style.opacity = '0';
|
|
||||||
setTimeout(() => {
|
|
||||||
configSection.style.display = 'none';
|
|
||||||
}, 300);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Event listeners para los controles de horario
|
|
||||||
document.getElementById('resumen_hora').addEventListener('change', function() {
|
|
||||||
const hora = this.value;
|
|
||||||
const dias = document.getElementById('resumen_dias').value;
|
|
||||||
|
|
||||||
// Validar que resumen_diario esté activado
|
|
||||||
const resumenDiarioCheckbox = document.getElementById('resumen_diario');
|
|
||||||
if (!resumenDiarioCheckbox.checked) {
|
|
||||||
showSaveIndicator('error', 'El resumen diario debe estar activado');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deshabilitar controles temporalmente
|
|
||||||
const horaInput = this;
|
|
||||||
const diasSelect = document.getElementById('resumen_dias');
|
|
||||||
horaInput.disabled = true;
|
|
||||||
diasSelect.disabled = true;
|
|
||||||
|
|
||||||
// Guardar configuración
|
|
||||||
autoSave('resumen_diario_config', {
|
|
||||||
hora: hora,
|
|
||||||
dias: dias
|
|
||||||
}).finally(() => {
|
|
||||||
horaInput.disabled = false;
|
|
||||||
diasSelect.disabled = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById('resumen_dias').addEventListener('change', function() {
|
|
||||||
const hora = document.getElementById('resumen_hora').value;
|
|
||||||
const dias = this.value;
|
|
||||||
|
|
||||||
// Validar que resumen_diario esté activado
|
|
||||||
const resumenDiarioCheckbox = document.getElementById('resumen_diario');
|
|
||||||
if (!resumenDiarioCheckbox.checked) {
|
|
||||||
showSaveIndicator('error', 'El resumen diario debe estar activado');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deshabilitar controles temporalmente
|
|
||||||
const horaInput = document.getElementById('resumen_hora');
|
|
||||||
const diasSelect = this;
|
|
||||||
horaInput.disabled = true;
|
|
||||||
diasSelect.disabled = true;
|
|
||||||
|
|
||||||
// Guardar configuración
|
|
||||||
autoSave('resumen_diario_config', {
|
|
||||||
hora: hora,
|
|
||||||
dias: dias
|
|
||||||
}).finally(() => {
|
|
||||||
horaInput.disabled = false;
|
|
||||||
diasSelect.disabled = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in New Issue
Block a user