Atajos de catálogos personalizables
This commit is contained in:
@@ -106,9 +106,9 @@ function aprobar_usuario()
|
|||||||
$email_encrypt = encrypt($email);
|
$email_encrypt = encrypt($email);
|
||||||
|
|
||||||
// Insertar en usuarios_sistema y obtener ID en la misma consulta
|
// Insertar en usuarios_sistema y obtener ID en la misma consulta
|
||||||
$sqlInsert = "INSERT INTO usuarios_sistema (nombre, email, password_hash, tipo_usuario, activo, creado_en, dos_factores, creado_por)
|
$sqlInsert = "INSERT INTO usuarios_sistema (nombre, email, password_hash, tipo_usuario, activo, creado_en, dos_factores, creado_por, preferencias_catalogos)
|
||||||
OUTPUT INSERTED.id_usuario
|
OUTPUT INSERTED.id_usuario
|
||||||
VALUES (?, ?, ?, ?, 1, GETDATE(), 0, ?)";
|
VALUES (?, ?, ?, ?, 1, GETDATE(), 0, ?, 1)";
|
||||||
|
|
||||||
$stmtInsert = sqlsrv_query($conn, $sqlInsert, [
|
$stmtInsert = sqlsrv_query($conn, $sqlInsert, [
|
||||||
$nombre_encrypt, $email_encrypt, $password_hash, $tipo, $_SESSION['usuario_id']
|
$nombre_encrypt, $email_encrypt, $password_hash, $tipo, $_SESSION['usuario_id']
|
||||||
@@ -140,6 +140,17 @@ function aprobar_usuario()
|
|||||||
throw new Exception("Error al insertar información general: " . print_r(sqlsrv_errors(), true));
|
throw new Exception("Error al insertar información general: " . print_r(sqlsrv_errors(), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Insertar en preferencias de catalogos
|
||||||
|
$sqlPref = "INSERT INTO preferencias_catalogos_usuario
|
||||||
|
(id_usuario, locaciones, vinculacion, transportistas, transportes, choferes, proveedores,
|
||||||
|
productos_frecuentes, solicitudes_importacion, expediente_electronico, configuracion, cerrar_sesion)
|
||||||
|
VALUES (?, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)";
|
||||||
|
$stmtPref = sqlsrv_query($conn, $sqlPref, [$id_usuario]);
|
||||||
|
|
||||||
|
if (!$stmtPref) {
|
||||||
|
throw new Exception("Error al insertar preferencias de catalogos: " . print_r(sqlsrv_errors(), true));
|
||||||
|
}
|
||||||
|
|
||||||
// Actualizar solicitud
|
// Actualizar solicitud
|
||||||
$sqlUpdate = "UPDATE solicitudes_importadores
|
$sqlUpdate = "UPDATE solicitudes_importadores
|
||||||
SET request_status = 'approved', approval_date = GETDATE(), approved_by = ?
|
SET request_status = 'approved', approval_date = GETDATE(), approved_by = ?
|
||||||
@@ -283,6 +294,7 @@ function guardar_usuario()
|
|||||||
|
|
||||||
// 4. Insertar usuario
|
// 4. Insertar usuario
|
||||||
$sqlInsert = "INSERT INTO usuarios_sistema (nombre, email, password_hash, tipo_usuario, activo, creado_en, dos_factores, creado_por)
|
$sqlInsert = "INSERT INTO usuarios_sistema (nombre, email, password_hash, tipo_usuario, activo, creado_en, dos_factores, creado_por)
|
||||||
|
OUTPUT INSERTED.id_usuario
|
||||||
VALUES (?, ?, ?, ?, 1, GETDATE(), 0, ?)";
|
VALUES (?, ?, ?, ?, 1, GETDATE(), 0, ?)";
|
||||||
$params = [$nombre_encrypted, $email_encrypted, $password_hash, $tipo, $_SESSION['usuario_id']];
|
$params = [$nombre_encrypted, $email_encrypted, $password_hash, $tipo, $_SESSION['usuario_id']];
|
||||||
$stmtInsert = sqlsrv_query($conn, $sqlInsert, $params);
|
$stmtInsert = sqlsrv_query($conn, $sqlInsert, $params);
|
||||||
@@ -293,12 +305,31 @@ function guardar_usuario()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 5. Obtener ID del nuevo usuario (para posibles tablas relacionadas)
|
// 5. Obtener ID del nuevo usuario (para posibles tablas relacionadas)
|
||||||
$sqlGetId = "SELECT SCOPE_IDENTITY() AS id_usuario";
|
$idUsuarioRow = sqlsrv_fetch_array($stmtInsert, SQLSRV_FETCH_ASSOC);
|
||||||
$stmtGetId = sqlsrv_query($conn, $sqlGetId);
|
|
||||||
$idUsuarioRow = sqlsrv_fetch_array($stmtGetId, SQLSRV_FETCH_ASSOC);
|
|
||||||
$id_usuario = $idUsuarioRow['id_usuario'] ?? null;
|
$id_usuario = $idUsuarioRow['id_usuario'] ?? null;
|
||||||
|
|
||||||
// 6. Enviar correo de bienvenida
|
// 6. Insertar en informacion_general
|
||||||
|
$sqlInfo = "INSERT INTO informacion_general
|
||||||
|
(id_usuario, nombre, correo)
|
||||||
|
VALUES (?, ?, ?)";
|
||||||
|
$stmtInfo = sqlsrv_query($conn, $sqlInfo, [$id_usuario, $nombre, $email]);
|
||||||
|
|
||||||
|
if (!$stmtInfo) {
|
||||||
|
throw new Exception("Error al insertar información general: " . print_r(sqlsrv_errors(), true));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. Insertar en preferencias de catalogos
|
||||||
|
$sqlPref = "INSERT INTO preferencias_catalogos_usuario
|
||||||
|
(id_usuario, locaciones, vinculacion, transportistas, transportes, choferes, proveedores,
|
||||||
|
productos_frecuentes, solicitudes_importacion, expediente_electronico, configuracion, cerrar_sesion)
|
||||||
|
VALUES (?, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)";
|
||||||
|
$stmtPref = sqlsrv_query($conn, $sqlPref, [$id_usuario]);
|
||||||
|
|
||||||
|
if (!$stmtPref) {
|
||||||
|
throw new Exception("Error al insertar preferencias de catalogos: " . print_r(sqlsrv_errors(), true));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8. Enviar correo de bienvenida
|
||||||
$mail = new PHPMailer(true);
|
$mail = new PHPMailer(true);
|
||||||
try {
|
try {
|
||||||
$mail->isSMTP();
|
$mail->isSMTP();
|
||||||
|
|||||||
@@ -3,15 +3,166 @@ require_once __DIR__ . '/../helpers/session.php';
|
|||||||
require_once __DIR__ . '/../../config/database.php';
|
require_once __DIR__ . '/../../config/database.php';
|
||||||
require_once __DIR__ . '/../helpers/crypto.php';
|
require_once __DIR__ . '/../helpers/crypto.php';
|
||||||
|
|
||||||
|
// Función para obtener catálogos visibles del usuario
|
||||||
|
function obtenerCatalogosVisibles($idUsuario) {
|
||||||
|
$conn = getConnection();
|
||||||
|
|
||||||
|
// Obtener configuración general y tipo de usuario
|
||||||
|
$query = "SELECT preferencias_catalogos, tipo_usuario FROM usuarios_sistema WHERE id_usuario = ?";
|
||||||
|
$stmt = sqlsrv_prepare($conn, $query, [$idUsuario]);
|
||||||
|
if (!$stmt || !sqlsrv_execute($stmt)) {
|
||||||
|
sqlsrv_close($conn);
|
||||||
|
return ['catalogos_activos' => false, 'catalogos' => []];
|
||||||
|
}
|
||||||
|
|
||||||
|
$usuario = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||||
|
if (!$usuario) {
|
||||||
|
sqlsrv_close($conn);
|
||||||
|
return ['catalogos_activos' => false, 'catalogos' => []];
|
||||||
|
}
|
||||||
|
|
||||||
|
$catalogos_general = $usuario['preferencias_catalogos'] ?? 0;
|
||||||
|
$tipoUsuario = $usuario['tipo_usuario'] ?? 'importador';
|
||||||
|
sqlsrv_free_stmt($stmt);
|
||||||
|
|
||||||
|
// Si los catálogos están desactivados, solo mostrar obligatorios
|
||||||
|
if (!$catalogos_general) {
|
||||||
|
// Obtener solo catálogos obligatorios
|
||||||
|
$query = "SELECT nombre, descripcion, color, ruta, accion
|
||||||
|
FROM tipos_catalogos
|
||||||
|
WHERE tipo_usuario = ? AND nombre IN ('Configuración', 'Cerrar sesión')
|
||||||
|
ORDER BY id";
|
||||||
|
$stmt = sqlsrv_prepare($conn, $query, [$tipoUsuario]);
|
||||||
|
|
||||||
|
if (!$stmt || !sqlsrv_execute($stmt)) {
|
||||||
|
sqlsrv_close($conn);
|
||||||
|
return ['catalogos_activos' => false, 'catalogos' => []];
|
||||||
|
}
|
||||||
|
|
||||||
|
$catalogos = [];
|
||||||
|
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||||
|
$catalogos[] = [
|
||||||
|
'nombre' => $row['nombre'],
|
||||||
|
'descripcion' => $row['descripcion'],
|
||||||
|
'color' => $row['color'],
|
||||||
|
'ruta' => $row['ruta'],
|
||||||
|
'accion' => $row['accion'],
|
||||||
|
'visible' => true,
|
||||||
|
'obligatorio' => true
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlsrv_free_stmt($stmt);
|
||||||
|
sqlsrv_close($conn);
|
||||||
|
|
||||||
|
return ['catalogos_activos' => false, 'catalogos' => $catalogos];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtener todos los catálogos para este tipo de usuario
|
||||||
|
$query = "SELECT nombre, descripcion, color, ruta, accion
|
||||||
|
FROM tipos_catalogos
|
||||||
|
WHERE tipo_usuario = ?
|
||||||
|
ORDER BY id";
|
||||||
|
$stmt = sqlsrv_prepare($conn, $query, [$tipoUsuario]);
|
||||||
|
|
||||||
|
if (!$stmt || !sqlsrv_execute($stmt)) {
|
||||||
|
sqlsrv_close($conn);
|
||||||
|
return ['catalogos_activos' => false, 'catalogos' => []];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crear array de catálogos disponibles
|
||||||
|
$catalogos_disponibles = [];
|
||||||
|
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||||
|
$catalogos_disponibles[] = [
|
||||||
|
'nombre' => $row['nombre'],
|
||||||
|
'descripcion' => $row['descripcion'],
|
||||||
|
'color' => $row['color'],
|
||||||
|
'ruta' => $row['ruta'],
|
||||||
|
'accion' => $row['accion'],
|
||||||
|
'campo_bd' => strtolower(str_replace([' ', 'ó', 'ú', 'á', 'é', 'í'], ['_', 'o', 'u', 'a', 'e', 'i'], $row['nombre']))
|
||||||
|
];
|
||||||
|
}
|
||||||
|
sqlsrv_free_stmt($stmt);
|
||||||
|
|
||||||
|
// Obtener preferencias específicas del usuario
|
||||||
|
$preferencias = [];
|
||||||
|
switch ($tipoUsuario) {
|
||||||
|
case 'importador':
|
||||||
|
$query = "SELECT * FROM preferencias_catalogos_usuario WHERE id_usuario = ?";
|
||||||
|
$stmt = sqlsrv_prepare($conn, $query, [$idUsuario]);
|
||||||
|
if ($stmt && sqlsrv_execute($stmt)) {
|
||||||
|
$preferenciasRow = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||||
|
if ($preferenciasRow) {
|
||||||
|
$preferencias = $preferenciasRow;
|
||||||
|
}
|
||||||
|
sqlsrv_free_stmt($stmt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// Aquí agregarías otros casos cuando implementes otros tipos de usuario
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determinar qué catálogos mostrar
|
||||||
|
$catalogos_visibles = [];
|
||||||
|
foreach ($catalogos_disponibles as $catalogo) {
|
||||||
|
$campo = $catalogo['campo_bd'];
|
||||||
|
$esObligatorio = in_array($catalogo['nombre'], ['Configuración', 'Cerrar sesión']);
|
||||||
|
|
||||||
|
if ($esObligatorio) {
|
||||||
|
// Catálogos obligatorios siempre visibles
|
||||||
|
$catalogo['visible'] = true;
|
||||||
|
$catalogo['obligatorio'] = true;
|
||||||
|
} else {
|
||||||
|
// Verificar si está activado en preferencias
|
||||||
|
$catalogo['visible'] = isset($preferencias[$campo]) && $preferencias[$campo] == 1;
|
||||||
|
$catalogo['obligatorio'] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($catalogo['visible']) {
|
||||||
|
$catalogos_visibles[] = $catalogo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlsrv_close($conn);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'catalogos_activos' => true,
|
||||||
|
'catalogos' => $catalogos_visibles,
|
||||||
|
'tipo_usuario' => $tipoUsuario
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Función para obtener icono según el nombre del catálogo
|
||||||
|
function obtenerIconoCatalogo($nombre) {
|
||||||
|
$iconos = [
|
||||||
|
'Locaciones' => '📍',
|
||||||
|
'Vinculación' => '🔗',
|
||||||
|
'Transportistas' => '🚚',
|
||||||
|
'Transportes' => '🚛',
|
||||||
|
'Choferes' => '👨✈️',
|
||||||
|
'Proveedores' => '🏭',
|
||||||
|
'Productos frecuentes' => '⭐',
|
||||||
|
'Solicitudes importación' => '📄',
|
||||||
|
'Expediente electrónico' => '📁',
|
||||||
|
'Configuración' => '⚙️',
|
||||||
|
'Cerrar sesión' => '🚪'
|
||||||
|
];
|
||||||
|
|
||||||
|
return $iconos[$nombre] ?? '📁';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Función para el dashboard del importador
|
||||||
function dashboard()
|
function dashboard()
|
||||||
{
|
{
|
||||||
if (!isset($_SESSION['usuario_id']) || $_SESSION['tipo_usuario'] !== 'importador') {
|
$idUsuario = $_SESSION['usuario_id'] ?? null;
|
||||||
header('Location: /IMPORTADORES/login');
|
|
||||||
|
if (!$idUsuario) {
|
||||||
|
header("Location: /IMPORTADORES/login");
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$nombreImportador = $_SESSION['usuario_nombre'];
|
// Obtener catálogos visibles
|
||||||
|
$catalogosData = obtenerCatalogosVisibles($idUsuario);
|
||||||
|
|
||||||
include __DIR__ . '/../../views/importadores/dashboard_importador.php';
|
include __DIR__ . '/../../views/importadores/dashboard_importador.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -540,4 +540,297 @@ function esDiaResumen($config_dias)
|
|||||||
return in_array($dia_letra, array_map('trim', $dias_activos));
|
return in_array($dia_letra, array_map('trim', $dias_activos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
|
||||||
|
function catalogos()
|
||||||
|
{
|
||||||
|
$conn = getConnection();
|
||||||
|
$idUsuario = $_SESSION['usuario_id'] ?? null;
|
||||||
|
|
||||||
|
if (!$idUsuario) {
|
||||||
|
header("Location: /IMPORTADORES/login");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtener configuración general de catalogos y tipo de usuario
|
||||||
|
$query = "SELECT preferencias_catalogos, tipo_usuario FROM usuarios_sistema WHERE id_usuario = ?";
|
||||||
|
$stmt = sqlsrv_prepare($conn, $query, [$idUsuario]);
|
||||||
|
if (!$stmt || !sqlsrv_execute($stmt)) {
|
||||||
|
die("Error al obtener configuración: " . print_r(sqlsrv_errors(), true));
|
||||||
|
}
|
||||||
|
$usuario = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||||
|
if (!$usuario) {
|
||||||
|
die("Usuario no encontrado");
|
||||||
|
}
|
||||||
|
|
||||||
|
$catalogos = $usuario['preferencias_catalogos'] ?? 0;
|
||||||
|
$tipoUsuario = $usuario['tipo_usuario'] ?? 'importador';
|
||||||
|
sqlsrv_free_stmt($stmt);
|
||||||
|
|
||||||
|
// Obtener preferencias específicas según el tipo de usuario
|
||||||
|
switch ($tipoUsuario) {
|
||||||
|
case 'importador':
|
||||||
|
$query = "SELECT * FROM preferencias_catalogos_usuario WHERE id_usuario = ?";
|
||||||
|
$stmt = sqlsrv_prepare($conn, $query, [$idUsuario]);
|
||||||
|
if ($stmt && sqlsrv_execute($stmt)) {
|
||||||
|
$preferenciasRow = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||||
|
sqlsrv_free_stmt($stmt);
|
||||||
|
} else {
|
||||||
|
$preferenciasRow = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si no existe registro, crear valores por defecto para importador
|
||||||
|
if (!$preferenciasRow) {
|
||||||
|
$preferencias = [
|
||||||
|
'locaciones' => 0,
|
||||||
|
'vinculacion' => 0,
|
||||||
|
'transportistas' => 0,
|
||||||
|
'transportes' => 0,
|
||||||
|
'choferes' => 0,
|
||||||
|
'proveedores' => 0,
|
||||||
|
'productos_frecuentes' => 0,
|
||||||
|
'solicitudes_importacion' => 0,
|
||||||
|
'expediente_electronico' => 0,
|
||||||
|
'configuracion' => 0,
|
||||||
|
'cerrar_sesion' => 0
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$preferencias = $preferenciasRow;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// case 'agente_aduanal':
|
||||||
|
// $query = "SELECT * FROM preferencias_catalogos_agente WHERE id_usuario = ?";
|
||||||
|
// $stmt = sqlsrv_prepare($conn, $query, [$idUsuario]);
|
||||||
|
// if ($stmt && sqlsrv_execute($stmt)) {
|
||||||
|
// $preferenciasRow = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||||
|
// sqlsrv_free_stmt($stmt);
|
||||||
|
// } else {
|
||||||
|
// $preferenciasRow = false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Si no existe registro, crear valores por defecto para agente aduanal
|
||||||
|
// if (!$preferenciasRow) {
|
||||||
|
// $preferencias = [
|
||||||
|
// Aquí se definirán los campos específicos para agente aduanal
|
||||||
|
// cuando se creen las tablas correspondientes
|
||||||
|
// 'configuracion' => 0,
|
||||||
|
// 'cerrar_sesion' => 0
|
||||||
|
// ];
|
||||||
|
// } else {
|
||||||
|
// $preferencias = $preferenciasRow;
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case 'admin_agencia':
|
||||||
|
// $query = "SELECT * FROM preferencias_catalogos_agencia WHERE id_usuario = ?";
|
||||||
|
// $stmt = sqlsrv_prepare($conn, $query, [$idUsuario]);
|
||||||
|
// if ($stmt && sqlsrv_execute($stmt)) {
|
||||||
|
// $preferenciasRow = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||||
|
// sqlsrv_free_stmt($stmt);
|
||||||
|
// } else {
|
||||||
|
// $preferenciasRow = false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Si no existe registro, crear valores por defecto para admin agencia
|
||||||
|
// if (!$preferenciasRow) {
|
||||||
|
// $preferencias = [
|
||||||
|
// Aquí se definirán los campos específicos para admin agencia
|
||||||
|
// cuando se creen las tablas correspondientes
|
||||||
|
// 'configuracion' => 0,
|
||||||
|
// 'cerrar_sesion' => 0
|
||||||
|
// ];
|
||||||
|
// } else {
|
||||||
|
// $preferencias = $preferenciasRow;
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case 'super_admin':
|
||||||
|
// $query = "SELECT * FROM preferencias_catalogos_admin WHERE id_usuario = ?";
|
||||||
|
// $stmt = sqlsrv_prepare($conn, $query, [$idUsuario]);
|
||||||
|
// if ($stmt && sqlsrv_execute($stmt)) {
|
||||||
|
// $preferenciasRow = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||||
|
// sqlsrv_free_stmt($stmt);
|
||||||
|
// } else {
|
||||||
|
// $preferenciasRow = false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Si no existe registro, crear valores por defecto para super admin
|
||||||
|
// if (!$preferenciasRow) {
|
||||||
|
// $preferencias = [
|
||||||
|
// Aquí se definirán los campos específicos para super admin
|
||||||
|
// cuando se creen las tablas correspondientes
|
||||||
|
// 'configuracion' => 0,
|
||||||
|
// 'cerrar_sesion' => 0
|
||||||
|
// ];
|
||||||
|
// } else {
|
||||||
|
// $preferencias = $preferenciasRow;
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Tipo de usuario no reconocido, usar valores por defecto mínimos
|
||||||
|
$preferencias = [
|
||||||
|
'configuracion' => 0,
|
||||||
|
'cerrar_sesion' => 0
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtener tipos de catalogos disponibles según el tipo de usuario
|
||||||
|
$query = "SELECT nombre, descripcion, color FROM tipos_catalogos WHERE tipo_usuario = ? ORDER BY id";
|
||||||
|
$stmt = sqlsrv_prepare($conn, $query, [$tipoUsuario]);
|
||||||
|
if (!$stmt || !sqlsrv_execute($stmt)) {
|
||||||
|
die("Error al obtener tipos: " . print_r(sqlsrv_errors(), true));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crear array asociativo para la vista
|
||||||
|
$tipos = [];
|
||||||
|
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||||
|
$tipos[$row['nombre']] = [
|
||||||
|
'descripcion' => $row['descripcion'],
|
||||||
|
'color' => $row['color']
|
||||||
|
];
|
||||||
|
}
|
||||||
|
sqlsrv_free_stmt($stmt);
|
||||||
|
sqlsrv_close($conn);
|
||||||
|
|
||||||
|
include __DIR__ . '/../../views/preferencias/catalogos.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
function guardarCatalogosAjax()
|
||||||
|
{
|
||||||
|
// Verificar que sea una petición AJAX
|
||||||
|
if (!isset($_SERVER['HTTP_X_REQUESTED_WITH']) ||
|
||||||
|
$_SERVER['HTTP_X_REQUESTED_WITH'] !== 'XMLHttpRequest') {
|
||||||
|
http_response_code(400);
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Petición no válida']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtener datos JSON del cuerpo de la petición
|
||||||
|
$input = json_decode(file_get_contents('php://input'), true);
|
||||||
|
|
||||||
|
if (!$input || !isset($input['tipo'])) {
|
||||||
|
http_response_code(400);
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Datos no válidos']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$conn = getConnection();
|
||||||
|
$idUsuario = $_SESSION['usuario_id'] ?? null;
|
||||||
|
|
||||||
|
if (!$idUsuario) {
|
||||||
|
http_response_code(401);
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Usuario no autenticado']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtener tipo de usuario
|
||||||
|
$query = "SELECT tipo_usuario FROM usuarios_sistema WHERE id_usuario = ?";
|
||||||
|
$stmt = sqlsrv_prepare($conn, $query, [$idUsuario]);
|
||||||
|
if (!$stmt || !sqlsrv_execute($stmt)) {
|
||||||
|
http_response_code(500);
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Error al obtener información del usuario']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
$usuario = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||||
|
$tipoUsuario = $usuario['tipo_usuario'] ?? 'importador';
|
||||||
|
sqlsrv_free_stmt($stmt);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$tipo = $input['tipo'];
|
||||||
|
|
||||||
|
switch ($tipo) {
|
||||||
|
case 'catalogos_general':
|
||||||
|
// Actualizar preferencias generales de catálogos
|
||||||
|
$valor = isset($input['valor']) && $input['valor'] ? 1 : 0;
|
||||||
|
|
||||||
|
$query = "UPDATE usuarios_sistema SET preferencias_catalogos = ? WHERE id_usuario = ?";
|
||||||
|
$stmt = sqlsrv_prepare($conn, $query, [$valor, $idUsuario]);
|
||||||
|
|
||||||
|
if (!$stmt || !sqlsrv_execute($stmt)) {
|
||||||
|
throw new Exception('Error al actualizar preferencias generales');
|
||||||
|
}
|
||||||
|
sqlsrv_free_stmt($stmt);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'tipo_catalogo':
|
||||||
|
// Actualizar preferencia específica de catálogo
|
||||||
|
if (!isset($input['nombre']) || !isset($input['valor'])) {
|
||||||
|
throw new Exception('Datos incompletos para tipo de catálogo');
|
||||||
|
}
|
||||||
|
|
||||||
|
$nombre = $input['nombre'];
|
||||||
|
$valor = $input['valor'] ? 1 : 0;
|
||||||
|
|
||||||
|
// Determinar la tabla según el tipo de usuario
|
||||||
|
$tabla = '';
|
||||||
|
switch ($tipoUsuario) {
|
||||||
|
case 'importador':
|
||||||
|
$tabla = 'preferencias_catalogos_usuario';
|
||||||
|
break;
|
||||||
|
case 'agente_aduanal':
|
||||||
|
$tabla = 'preferencias_catalogos_agente';
|
||||||
|
break;
|
||||||
|
case 'admin_agencia':
|
||||||
|
$tabla = 'preferencias_catalogos_agencia';
|
||||||
|
break;
|
||||||
|
case 'super_admin':
|
||||||
|
$tabla = 'preferencias_catalogos_admin';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception('Tipo de usuario no válido');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verificar si existe un registro para este usuario
|
||||||
|
$query = "SELECT id_preferencia FROM $tabla WHERE id_usuario = ?";
|
||||||
|
$stmt = sqlsrv_prepare($conn, $query, [$idUsuario]);
|
||||||
|
if (!$stmt || !sqlsrv_execute($stmt)) {
|
||||||
|
throw new Exception('Error al verificar preferencias existentes');
|
||||||
|
}
|
||||||
|
|
||||||
|
$existe = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||||
|
sqlsrv_free_stmt($stmt);
|
||||||
|
|
||||||
|
if ($existe) {
|
||||||
|
// Actualizar registro existente
|
||||||
|
$query = "UPDATE $tabla SET [$nombre] = ? WHERE id_usuario = ?";
|
||||||
|
$stmt = sqlsrv_prepare($conn, $query, [$valor, $idUsuario]);
|
||||||
|
} else {
|
||||||
|
// Crear nuevo registro
|
||||||
|
$query = "INSERT INTO $tabla (id_usuario, [$nombre]) VALUES (?, ?)";
|
||||||
|
$stmt = sqlsrv_prepare($conn, $query, [$idUsuario, $valor]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$stmt || !sqlsrv_execute($stmt)) {
|
||||||
|
throw new Exception('Error al actualizar preferencia de catálogo');
|
||||||
|
}
|
||||||
|
sqlsrv_free_stmt($stmt);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Exception('Tipo de operación no válido');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirmar transacción
|
||||||
|
sqlsrv_commit($conn);
|
||||||
|
|
||||||
|
// Respuesta exitosa
|
||||||
|
echo json_encode([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Preferencias actualizadas correctamente'
|
||||||
|
]);
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// Revertir transacción en caso de error
|
||||||
|
sqlsrv_rollback($conn);
|
||||||
|
|
||||||
|
http_response_code(500);
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'message' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
} finally {
|
||||||
|
sqlsrv_close($conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
61
catalogos.txt
Normal file
61
catalogos.txt
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
CREATE TABLE preferencias_catalogos_usuario (
|
||||||
|
id_preferencia INT IDENTITY(1,1) NOT NULL,
|
||||||
|
id_usuario INT NOT NULL,
|
||||||
|
locaciones BIT DEFAULT 0,
|
||||||
|
vinculacion BIT DEFAULT 0,
|
||||||
|
transportistas BIT DEFAULT 0,
|
||||||
|
transportes BIT DEFAULT 0,
|
||||||
|
choferes BIT DEFAULT 0,
|
||||||
|
proveedores BIT DEFAULT 0,
|
||||||
|
productos_frecuentes BIT DEFAULT 0,
|
||||||
|
solicitudes_importacion BIT DEFAULT 0,
|
||||||
|
expediente_electronico BIT DEFAULT 0,
|
||||||
|
configuracion BIT DEFAULT 0,
|
||||||
|
cerrar_sesion BIT DEFAULT 0,
|
||||||
|
FOREIGN KEY (id_usuario) REFERENCES usuarios_sistema(id_usuario)
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE usuarios_sistema
|
||||||
|
ADD [preferencias_catalogos] BIT DEFAULT 1;
|
||||||
|
|
||||||
|
CREATE TABLE tipos_catalogos (
|
||||||
|
id INT PRIMARY KEY IDENTITY,
|
||||||
|
tipo_usuario VARCHAR(20) NOT NULL,
|
||||||
|
nombre VARCHAR(255) NOT NULL,
|
||||||
|
descripcion VARCHAR(500) NULL,
|
||||||
|
color VARCHAR(20) NOT NULL,
|
||||||
|
ruta VARCHAR(100) NOT NULL,
|
||||||
|
accion VARCAHR(50) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO tipos_catalogos (tipo_usuario, nombre, descripcion, color, ruta, accion) VALUES
|
||||||
|
('importador', 'Locaciones', 'Visualiza las locaciones registradas.', 'lime', '/IMPORTADORES/importadores/lista', 'Ver locaciones'),
|
||||||
|
('importador', 'Vinculación', 'Visualiza o establece nuevas vinculaciones con agencias aduanales.', 'teal', '/IMPORTADORES/viculaciones/vinculacionesUsuario', 'Ver vinculaciones'),
|
||||||
|
('importador', 'Transportistas', 'Agrega o consulta los choferes que colaboran contigo.', 'success', '/IMPORTADORES/transportistas/lista', 'Ver transportistas'),
|
||||||
|
('importador', 'Transportes', 'Gestiona y carga tus unidades de transporte.', 'info', '/IMPORTADORES/transportes/lista', 'Ver transportes'),
|
||||||
|
('importador', 'Choferes', 'Gestiona y carga a tus choferes.', 'cyan', '/IMPORTADORES/choferes/lista', 'Ver choferes'),
|
||||||
|
('importador', 'Proveedores', 'Agrega tus proveedores.', 'primary', '/IMPORTADORES/proveedores/crear', 'Nuevo proveedor'),
|
||||||
|
('importador', 'Productos frecuentes', 'Agrega productos frecuentes de tu interez.', 'violet', '/IMPORTADORES/productos_frecuentes/alta', 'Nuevo producto'),
|
||||||
|
('importador', 'Solicitudes importación', 'Inicia nuevas solicitudes de pedimentos.', 'indigo', '/IMPORTADORES/solicitud_importacion/crear', 'Nueva solicitud'),
|
||||||
|
('importador', 'Expediente electrónico', 'Revisa el expediente electrónico para tus solicitudes.', 'orange', '/IMPORTADORES/expediente/index', 'Ver expediente'),
|
||||||
|
('importador', 'Configuración', 'Administra los datos de tu empresa y preferencias.', 'warning', '/IMPORTADORES/configuracion', 'Ir a configuración'),
|
||||||
|
('importador', 'Cerrar sesión', 'Salir del sistema de forma segura.', 'danger', '/IMPORTADORES/sistemas/logout', 'Cerrar sesión');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE usuarios_sistema
|
||||||
|
SET preferencias_catalogos = 1
|
||||||
|
WHERE preferencias_catalogos IS NULL OR preferencias_catalogos = 0;
|
||||||
|
|
||||||
|
-- 2. Insertar en preferencias_catalogos_usuario solo para los que aún no tienen registro
|
||||||
|
INSERT INTO preferencias_catalogos_usuario (
|
||||||
|
id_usuario, locaciones, vinculacion, transportistas, transportes, choferes, proveedores,
|
||||||
|
productos_frecuentes, solicitudes_importacion, expediente_electronico, configuracion, cerrar_sesion
|
||||||
|
)
|
||||||
|
SELECT u.id_usuario, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
||||||
|
FROM usuarios_sistema u
|
||||||
|
WHERE u.tipo_usuario = 'importador'
|
||||||
|
AND NOT EXISTS (
|
||||||
|
SELECT 1 FROM preferencias_catalogos_usuario p
|
||||||
|
WHERE p.id_usuario = u.id_usuario
|
||||||
|
);
|
||||||
@@ -25,6 +25,15 @@
|
|||||||
.btn-teal { background-color: #20c997; color: white; }
|
.btn-teal { background-color: #20c997; color: white; }
|
||||||
.btn-teal:hover { background-color: #4dd4ac; color: black; }
|
.btn-teal:hover { background-color: #4dd4ac; color: black; }
|
||||||
.text-teal { color: #20c997; }
|
.text-teal { color: #20c997; }
|
||||||
|
.btn-lime { background-color: #84cc16; color: white; }
|
||||||
|
.text-lime { color: #84cc16; }
|
||||||
|
.btn-lime:hover { background-color: #65a30d; color: white; }
|
||||||
|
.btn-cyan { background-color: #06b6d4; color: white; }
|
||||||
|
.text-cyan { color: #06b6d4; }
|
||||||
|
.btn-cyan:hover { background-color: #0891b2; color: white; }
|
||||||
|
.btn-violet { background-color: #8b5cf6; color: white; }
|
||||||
|
.text-violet { color: #8b5cf6; }
|
||||||
|
.btn-violet:hover { background-color: #7c3aed; color: white; }
|
||||||
/* A partir de dispositivos medianos (>=768px), deja espacio lateral */
|
/* A partir de dispositivos medianos (>=768px), deja espacio lateral */
|
||||||
@media (min-width: 768px) { .content { margin-left: 250px; /* Ancho del sidebar */ } }
|
@media (min-width: 768px) { .content { margin-left: 250px; /* Ancho del sidebar */ } }
|
||||||
/* En móviles, sin margen lateral */
|
/* En móviles, sin margen lateral */
|
||||||
@@ -42,92 +51,73 @@
|
|||||||
<div class="content">
|
<div class="content">
|
||||||
<h4 class="mb-4">📦 Panel del Importador</h4>
|
<h4 class="mb-4">📦 Panel del Importador</h4>
|
||||||
|
|
||||||
<div class="row g-4">
|
<?php if ($catalogosData['catalogos_activos']): ?>
|
||||||
<div class="col-md-4">
|
<div class="row g-4">
|
||||||
<div class="card shadow-sm p-3">
|
<?php foreach ($catalogosData['catalogos'] as $catalogo): ?>
|
||||||
<h5 class="text-primary">Transportes</h5>
|
<div class="col-md-4">
|
||||||
<p>Gestiona y carga tus unidades de transporte.</p>
|
<div class="card shadow-sm p-3 <?= $catalogo['obligatorio'] ? 'border-warning' : '' ?>">
|
||||||
<a href="/IMPORTADORES/transportes/lista"
|
<h5 class="text-<?= $catalogo['color'] ?>">
|
||||||
class="btn btn-primary btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/transportes/lista' ? 'active' : '' ?>">
|
<?= obtenerIconoCatalogo($catalogo['nombre']) ?> <?= $catalogo['nombre'] ?>
|
||||||
Ver transportes
|
</h5>
|
||||||
</a>
|
<p class="text-muted small"><?= $catalogo['descripcion'] ?></p>
|
||||||
</div>
|
<a href="<?= $catalogo['ruta'] ?>"
|
||||||
|
class="btn btn-<?= $catalogo['color'] ?> btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === $catalogo['ruta'] ? 'active' : '' ?>">
|
||||||
|
<?= $catalogo['accion'] ?>
|
||||||
|
</a>
|
||||||
|
<?php if ($catalogo['obligatorio']): ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-4">
|
<?php if (count($catalogosData['catalogos']) === 2): // Solo obligatorios ?>
|
||||||
<div class="card shadow-sm p-3">
|
<div class="row mt-4">
|
||||||
<h5 class="text-success">Transportistas</h5>
|
<div class="col-12">
|
||||||
<p>Agrega o consulta los choferes que colaboran contigo.</p>
|
<div class="alert alert-info">
|
||||||
<a href="/IMPORTADORES/transportistas/lista"
|
<h6>💡 Consejo</h6>
|
||||||
class="btn btn-success btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/transportistas/lista' ? 'active' : '' ?>">
|
<p class="mb-2">Parece que no tienes catálogos activados. Puedes activar los que necesites desde tus preferencias.</p>
|
||||||
Ver transportistas
|
<a href="/IMPORTADORES/preferencias/catalogos" class="btn btn-primary btn-sm">
|
||||||
</a>
|
Configurar Catálogos
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="col-md-4">
|
<?php else: ?>
|
||||||
<div class="card shadow-sm p-3">
|
<!-- Si los catálogos están completamente desactivados -->
|
||||||
<h5 class="text-info">Solicitudes de Importación</h5>
|
<div class="row g-4">
|
||||||
<p>Inicia nuevas solicitudes de pedimentos.</p>
|
<div class="col-12">
|
||||||
<a href="/IMPORTADORES/solicitud_importacion/crear"
|
<div class="alert alert-warning">
|
||||||
class="btn btn-info btn-sm mt-2 <?= str_contains($_SERVER['REQUEST_URI'], '/solicitud_importacion/crear') ? 'active' : '' ?>">
|
<h5>🔒 Catálogos Desactivados</h5>
|
||||||
Nueva solicitud
|
<p>Los catálogos están desactivados en tus preferencias. Solo tienes acceso a las funciones básicas del sistema.</p>
|
||||||
</a>
|
<a href="/IMPORTADORES/preferencias/catalogos" class="btn btn-primary btn-sm">
|
||||||
|
Activar Catálogos
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Mostrar solo catálogos obligatorios -->
|
||||||
|
<?php foreach ($catalogosData['catalogos'] as $catalogo): ?>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card shadow-sm p-3 border-warning">
|
||||||
|
<h5 class="text-<?= $catalogo['color'] ?>">
|
||||||
|
<?= obtenerIconoCatalogo($catalogo['nombre']) ?> <?= $catalogo['nombre'] ?>
|
||||||
|
</h5>
|
||||||
|
<p class="text-muted small"><?= $catalogo['descripcion'] ?></p>
|
||||||
|
<a href="<?= $catalogo['ruta'] ?>"
|
||||||
|
class="btn btn-<?= $catalogo['color'] ?> btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === $catalogo['ruta'] ? 'active' : '' ?>">
|
||||||
|
<?= $catalogo['accion'] ?>
|
||||||
|
</a>
|
||||||
|
<small class="text-warning mt-1">
|
||||||
|
<i class="fas fa-lock"></i> Función básica
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
</div>
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="card shadow-sm p-3">
|
|
||||||
<h5 class="text-indigo">Proveedores</h5>
|
|
||||||
<p>Agrega tus proveedores.</p>
|
|
||||||
<a href="/IMPORTADORES/proveedores/crear"
|
|
||||||
class="btn btn-indigo btn-sm mt-2 <?= str_contains($_SERVER['REQUEST_URI'], '/proveedores/crear') ? 'active' : '' ?>">
|
|
||||||
Nuevo proveedor
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="card shadow-sm p-3">
|
|
||||||
<h5 class="text-warning">Configuración</h5>
|
|
||||||
<p>Administra los datos de tu empresa y preferencias.</p>
|
|
||||||
<a href="/IMPORTADORES/configuracion"
|
|
||||||
class="btn btn-warning btn-sm mt-2 <?= str_contains($_SERVER['REQUEST_URI'], '/configuracion') ? 'active' : '' ?>">
|
|
||||||
Configurar
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="card shadow-sm p-3">
|
|
||||||
<h5 class="text-orange">Locaciones</h5>
|
|
||||||
<p>Visualiza las locaciones registradas.</p>
|
|
||||||
<a href="/IMPORTADORES/importadores/lista"
|
|
||||||
class="btn btn-orange btn-sm mt-2 <?= str_contains($_SERVER['REQUEST_URI'], '/importadores/lista') ? 'active' : '' ?>">
|
|
||||||
Ver locaciones
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="card shadow-sm p-3">
|
|
||||||
<h5 class="text-teal">Vinculaciones</h5>
|
|
||||||
<p>Visualiza o establece nuevas vinculaciones con agencias aduanales.</p>
|
|
||||||
<a href="/IMPORTADORES/vinculaciones/vinculacionesUsuario"
|
|
||||||
class="btn btn-teal btn-sm mt-2 <?= str_contains($_SERVER['REQUEST_URI'], '/importadores/vinculaciones') ? 'active' : '' ?>">
|
|
||||||
Ver vinculaciones
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="card shadow-sm p-3">
|
|
||||||
<h5 class="text-danger">Cerrar sesión</h5>
|
|
||||||
<p>Salir del sistema de forma segura.</p>
|
|
||||||
<a href="/IMPORTADORES/sistemas/logout" class="btn btn-danger btn-sm mt-2">Logout</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ function obtenerUrlPermiso($permiso) {
|
|||||||
role="button" aria-expanded="true" aria-controls="submenuPreferencias"
|
role="button" aria-expanded="true" aria-controls="submenuPreferencias"
|
||||||
onclick="<? $enDashboardPreferencias ? '' : 'event.preventDefault(); window.location.href = \'/IMPORTADORES/preferencias/index\';' ?>">
|
onclick="<? $enDashboardPreferencias ? '' : 'event.preventDefault(); window.location.href = \'/IMPORTADORES/preferencias/index\';' ?>">
|
||||||
✅ Preferencias
|
✅ Preferencias
|
||||||
<span class="badge bg-secondary">1</span>
|
<span class="badge bg-secondary">2</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse show" id="submenuPreferencias">
|
<div class="collapse show" id="submenuPreferencias">
|
||||||
<nav class="nav flex-column ms-3">
|
<nav class="nav flex-column ms-3">
|
||||||
@@ -241,13 +241,17 @@ function obtenerUrlPermiso($permiso) {
|
|||||||
class="nav-link px-3 py-1 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/preferencias/notificaciones' ? 'active' : '' ?>">
|
class="nav-link px-3 py-1 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/preferencias/notificaciones' ? 'active' : '' ?>">
|
||||||
• Gestión de Notificaciones
|
• Gestión de Notificaciones
|
||||||
</a>
|
</a>
|
||||||
|
<a href="/IMPORTADORES/preferencias/catalogos"
|
||||||
|
class="nav-link px-3 py-1 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/preferencias/catalogos' ? 'active' : '' ?>">
|
||||||
|
• Visualización de Catálogos
|
||||||
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
<?php elseif ($esConfiguracion || $esVistaAutomatizaciones || $esVistaSeguridad || $esVistaBitacoras || $esVistaReset): ?>
|
<?php elseif ($esConfiguracion || $esVistaAutomatizaciones || $esVistaSeguridad || $esVistaBitacoras || $esVistaReset): ?>
|
||||||
<a href="/IMPORTADORES/preferencias/index"
|
<a href="/IMPORTADORES/preferencias/index"
|
||||||
class="nav-link px-3 py-2 d-flex justify-content-between align-items-center">
|
class="nav-link px-3 py-2 d-flex justify-content-between align-items-center">
|
||||||
✅ Preferencias
|
✅ Preferencias
|
||||||
<span class="badge bg-secondary">1</span>
|
<span class="badge bg-secondary">2</span>
|
||||||
</a>
|
</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@@ -377,7 +381,7 @@ function obtenerUrlPermiso($permiso) {
|
|||||||
role="button" aria-expanded="true" aria-controls="submenuPreferencias"
|
role="button" aria-expanded="true" aria-controls="submenuPreferencias"
|
||||||
onclick="<? $enDashboardPreferencias ? '' : 'event.preventDefault(); window.location.href = \'/IMPORTADORES/preferencias/index\';' ?>">
|
onclick="<? $enDashboardPreferencias ? '' : 'event.preventDefault(); window.location.href = \'/IMPORTADORES/preferencias/index\';' ?>">
|
||||||
✅ Preferencias
|
✅ Preferencias
|
||||||
<span class="badge bg-secondary">1</span>
|
<span class="badge bg-secondary">2</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse show" id="submenuPreferencias">
|
<div class="collapse show" id="submenuPreferencias">
|
||||||
<nav class="nav flex-column ms-3">
|
<nav class="nav flex-column ms-3">
|
||||||
@@ -385,13 +389,17 @@ function obtenerUrlPermiso($permiso) {
|
|||||||
class="nav-link px-3 py-1 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/preferencias/notificaciones' ? 'active' : '' ?>">
|
class="nav-link px-3 py-1 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/preferencias/notificaciones' ? 'active' : '' ?>">
|
||||||
• Gestión de Notificaciones
|
• Gestión de Notificaciones
|
||||||
</a>
|
</a>
|
||||||
|
<a href="/IMPORTADORES/preferencias/catalogos"
|
||||||
|
class="nav-link px-3 py-1 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/preferencias/catalogos' ? 'active' : '' ?>">
|
||||||
|
• Visualización de Catálogos
|
||||||
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
<?php elseif ($esConfiguracion || $esVistaAutomatizaciones || $esVistaSeguridad || $esVistaBitacoras || $esVistaReset): ?>
|
<?php elseif ($esConfiguracion || $esVistaAutomatizaciones || $esVistaSeguridad || $esVistaBitacoras || $esVistaReset): ?>
|
||||||
<a href="/IMPORTADORES/preferencias/index"
|
<a href="/IMPORTADORES/preferencias/index"
|
||||||
class="nav-link px-3 py-2 d-flex justify-content-between align-items-center">
|
class="nav-link px-3 py-2 d-flex justify-content-between align-items-center">
|
||||||
✅ Preferencias
|
✅ Preferencias
|
||||||
<span class="badge bg-secondary">1</span>
|
<span class="badge bg-secondary">2</span>
|
||||||
</a>
|
</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|||||||
@@ -70,7 +70,7 @@
|
|||||||
<a class="nav-link px-3 py-2 d-flex justify-content-between align-items-center
|
<a class="nav-link px-3 py-2 d-flex justify-content-between align-items-center
|
||||||
<?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/transportistas') ? 'active' : '' ?>"
|
<?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/transportistas') ? 'active' : '' ?>"
|
||||||
data-bs-toggle="collapse" href="#submenuTransportistas" role="button" aria-expanded="false">
|
data-bs-toggle="collapse" href="#submenuTransportistas" role="button" aria-expanded="false">
|
||||||
👨✈️ Transportistas
|
🚚 Transportistas
|
||||||
<span class="badge bg-secondary">3</span>
|
<span class="badge bg-secondary">3</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse <?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/transportistas') ? 'show' : '' ?>" id="submenuTransportistas">
|
<div class="collapse <?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/transportistas') ? 'show' : '' ?>" id="submenuTransportistas">
|
||||||
@@ -94,7 +94,7 @@
|
|||||||
<a class="nav-link px-3 py-2 d-flex justify-content-between align-items-center
|
<a class="nav-link px-3 py-2 d-flex justify-content-between align-items-center
|
||||||
<?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/transportes') ? 'active' : '' ?>"
|
<?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/transportes') ? 'active' : '' ?>"
|
||||||
data-bs-toggle="collapse" href="#submenuTransportes" role="button" aria-expanded="false">
|
data-bs-toggle="collapse" href="#submenuTransportes" role="button" aria-expanded="false">
|
||||||
🚚 Transportes
|
🚛 Transportes
|
||||||
<span class="badge bg-secondary">3</span>
|
<span class="badge bg-secondary">3</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse <?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/transportes') ? 'show' : '' ?>" id="submenuTransportes">
|
<div class="collapse <?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/transportes') ? 'show' : '' ?>" id="submenuTransportes">
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
<a class="nav-link px-3 py-2 d-flex justify-content-between align-items-center
|
<a class="nav-link px-3 py-2 d-flex justify-content-between align-items-center
|
||||||
<?= str_contains($_SERVER['REQUEST_URI'], '/choferes') ? 'active' : '' ?>"
|
<?= str_contains($_SERVER['REQUEST_URI'], '/choferes') ? 'active' : '' ?>"
|
||||||
data-bs-toggle="collapse" href="#submenuChoferes" role="button" aria-expanded="false">
|
data-bs-toggle="collapse" href="#submenuChoferes" role="button" aria-expanded="false">
|
||||||
🚛 Choferes
|
👨✈️ Choferes
|
||||||
<span class="badge bg-secondary">2</span>
|
<span class="badge bg-secondary">2</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse <?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/choferes') ? 'show' : '' ?>" id="submenuChoferes">
|
<div class="collapse <?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/choferes') ? 'show' : '' ?>" id="submenuChoferes">
|
||||||
@@ -261,12 +261,12 @@
|
|||||||
</a>
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- TRANSPORTISTAS -->
|
<!-- TRANSPORTISTAS -->
|
||||||
<a class="nav-link px-3 py-2 d-flex justify-content-between align-items-center
|
<a class="nav-link px-3 py-2 d-flex justify-content-between align-items-center
|
||||||
<?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/transportistas') ? 'active' : '' ?>"
|
<?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/transportistas') ? 'active' : '' ?>"
|
||||||
data-bs-toggle="collapse" href="#submenuTransportistas" role="button" aria-expanded="false">
|
data-bs-toggle="collapse" href="#submenuTransportistas" role="button" aria-expanded="false">
|
||||||
👨✈️ Transportistas
|
🚚 Transportistas
|
||||||
<span class="badge bg-secondary">3</span>
|
<span class="badge bg-secondary">3</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse <?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/transportistas') ? 'show' : '' ?>" id="submenuTransportistas">
|
<div class="collapse <?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/transportistas') ? 'show' : '' ?>" id="submenuTransportistas">
|
||||||
@@ -290,7 +290,7 @@
|
|||||||
<a class="nav-link px-3 py-2 d-flex justify-content-between align-items-center
|
<a class="nav-link px-3 py-2 d-flex justify-content-between align-items-center
|
||||||
<?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/transportes') ? 'active' : '' ?>"
|
<?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/transportes') ? 'active' : '' ?>"
|
||||||
data-bs-toggle="collapse" href="#submenuTransportes" role="button" aria-expanded="false">
|
data-bs-toggle="collapse" href="#submenuTransportes" role="button" aria-expanded="false">
|
||||||
🚚 Transportes
|
🚛 Transportes
|
||||||
<span class="badge bg-secondary">3</span>
|
<span class="badge bg-secondary">3</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse <?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/transportes') ? 'show' : '' ?>" id="submenuTransportes">
|
<div class="collapse <?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/transportes') ? 'show' : '' ?>" id="submenuTransportes">
|
||||||
@@ -314,7 +314,7 @@
|
|||||||
<a class="nav-link px-3 py-2 d-flex justify-content-between align-items-center
|
<a class="nav-link px-3 py-2 d-flex justify-content-between align-items-center
|
||||||
<?= str_contains($_SERVER['REQUEST_URI'], '/choferes') ? 'active' : '' ?>"
|
<?= str_contains($_SERVER['REQUEST_URI'], '/choferes') ? 'active' : '' ?>"
|
||||||
data-bs-toggle="collapse" href="#submenuChoferes" role="button" aria-expanded="false">
|
data-bs-toggle="collapse" href="#submenuChoferes" role="button" aria-expanded="false">
|
||||||
🚛 Choferes
|
👨✈️ Choferes
|
||||||
<span class="badge bg-secondary">2</span>
|
<span class="badge bg-secondary">2</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse <?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/choferes') ? 'show' : '' ?>" id="submenuChoferes">
|
<div class="collapse <?= str_contains($_SERVER['REQUEST_URI'], '/IMPORTADORES/choferes') ? 'show' : '' ?>" id="submenuChoferes">
|
||||||
|
|||||||
348
views/preferencias/catalogos.php
Normal file
348
views/preferencias/catalogos.php
Normal file
@@ -0,0 +1,348 @@
|
|||||||
|
<?php include __DIR__ . '/../partials/sidebar_configuracion.php'; ?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="es">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>📊 Visualización de Catálogos</title>
|
||||||
|
<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">
|
||||||
|
<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>
|
||||||
|
body { font-family: 'Segoe UI', sans-serif; background-color: #f4f6f9; }
|
||||||
|
.sidebar { width: 220px; height: 100vh; background-color: #343a40; position: fixed; top: 0; left: 0; padding-top: 56px; z-index: 1040; }
|
||||||
|
.sidebar .nav-link { font-weight: bold; color: white; transition: all 0.3s ease; }
|
||||||
|
.sidebar .nav-link:hover,
|
||||||
|
.sidebar .nav-link.active { background-color: #495057; color: #fff; }
|
||||||
|
.content { margin-top: 56px; padding: 40px 20px; position: relative; z-index: 1; background-color: #f4f6f9; transition: margin-left 0.3s ease; }
|
||||||
|
.navbar { position: fixed; top: 0; width: 100%; z-index: 1050; }
|
||||||
|
.btn-indigo { background-color: #6610f2; color: white; }
|
||||||
|
.btn-indigo:hover { background-color: #520dc2; color: white; }
|
||||||
|
.text-indigo { color: #520dc2; }
|
||||||
|
.btn-orange { background-color: orangeRed; color: white; }
|
||||||
|
.btn-orange:hover { background-color: #ff3600; color: white; }
|
||||||
|
.text-orange { color: orangeRed; }
|
||||||
|
.btn-teal { background-color: #20c997; color: white; }
|
||||||
|
.btn-teal:hover { background-color: #4dd4ac; color: black; }
|
||||||
|
.text-teal { color: #20c997; }
|
||||||
|
.btn-lime { background-color: #84cc16; color: white; }
|
||||||
|
.text-lime { color: #84cc16; }
|
||||||
|
.btn-lime:hover { background-color: #65a30d; color: white; }
|
||||||
|
.btn-cyan { background-color: #06b6d4; color: white; }
|
||||||
|
.text-cyan { color: #06b6d4; }
|
||||||
|
.btn-cyan:hover { background-color: #0891b2; color: white; }
|
||||||
|
.btn-violet { background-color: #8b5cf6; color: white; }
|
||||||
|
.text-violet { color: #8b5cf6; }
|
||||||
|
.btn-violet:hover { background-color: #7c3aed; color: white; }
|
||||||
|
/* A partir de dispositivos medianos (>=768px), deja espacio lateral */
|
||||||
|
@media (min-width: 768px) { .content { margin-left: 250px; } }
|
||||||
|
/* En móviles, sin margen lateral */
|
||||||
|
@media (max-width: 767.98px) {
|
||||||
|
.content { margin-left: 0; }
|
||||||
|
.sidebar .nav-link { font-weight: normal; color: #343a40; background-color: transparent; }
|
||||||
|
.sidebar .nav-link:hover,
|
||||||
|
.sidebar .nav-link.active { background-color: #e9ecef; color: #212529; }
|
||||||
|
}
|
||||||
|
.card { border-radius: 12px; }
|
||||||
|
.fade-transition { transition: all 0.3s ease-in-out; }
|
||||||
|
.section-divider { border-bottom: 1px solid #e9ecef; padding-bottom: 1.5rem; margin-bottom: 1.5rem; }
|
||||||
|
.section-divider:last-child { border-bottom: none; margin-bottom: 0; padding-bottom: 0; }
|
||||||
|
/* Indicador de guardado */
|
||||||
|
.save-indicator { position: fixed; top: 20px; right: 20px; padding: 12px 20px; border-radius: 8px; font-weight: 500; font-size: 14px; z-index: 9999;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); transition: all 0.3s ease; display: flex; align-items: center; }
|
||||||
|
.save-indicator.saving { background-color: #ffc107; color: #856404; border: 1px solid #ffeaa7; }
|
||||||
|
.save-indicator.saved { background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
|
||||||
|
.save-indicator.error { background-color: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
|
||||||
|
/* Transiciones suaves para los switches */
|
||||||
|
.form-check-input:disabled { opacity: 0.6; cursor: not-allowed; }
|
||||||
|
.fade-transition { transition: opacity 0.3s ease; }
|
||||||
|
/* Mejorar la apariencia de los switches de catálogos */
|
||||||
|
.tipo-catalogo { margin-right: 10px; }
|
||||||
|
.form-check-label { cursor: pointer; }
|
||||||
|
.form-check-label .form-text { margin-top: 4px; font-size: 0.875rem; }
|
||||||
|
/* Animación para el spinner */
|
||||||
|
@keyframes spinner-border { to { transform: rotate(360deg); } }
|
||||||
|
.spinner-border { display: inline-block; width: 1rem; height: 1rem; vertical-align: text-bottom; border: 0.125em solid currentColor; border-right-color: transparent;
|
||||||
|
border-radius: 50%; animation: spinner-border 0.75s linear infinite; }
|
||||||
|
.spinner-border-sm { width: 0.875rem; height: 0.875rem; border-width: 0.125em; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<h4 class="mb-4">📊 Visualización de Catálogos</h4>
|
||||||
|
|
||||||
|
<!-- Mensajes de éxito o error iniciales -->
|
||||||
|
<?php if (isset($_GET['success'])): ?>
|
||||||
|
<div class="success-message">
|
||||||
|
✅ Las preferencias de catálogos se han guardado correctamente.
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if (isset($_GET['error'])): ?>
|
||||||
|
<div class="error-message">
|
||||||
|
❌ Error: <?= htmlspecialchars($_GET['error']) ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<div class="card shadow-sm p-4 mb-4 bg-white">
|
||||||
|
<!-- Switch general de notificaciones -->
|
||||||
|
<div class="section-divider">
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" id="preferencias-catalogos"
|
||||||
|
data-tipo="catalogos_general"
|
||||||
|
<?= !empty($catalogos) ? 'checked' : '' ?>>
|
||||||
|
<label class="form-check-label fw-bold" for="preferencias-catalogos">
|
||||||
|
Catálogos
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Tipos de catalogos -->
|
||||||
|
<div id="tipos-catalogos" class="fade-transition" style="opacity:1;">
|
||||||
|
<div class="section-divider">
|
||||||
|
<h6 class="mb-3">📋 Preferencias de Catálogos</h6>
|
||||||
|
<div class="row">
|
||||||
|
<?php if (!empty($tipos)): ?>
|
||||||
|
<?php foreach ($tipos as $nombre => $info): ?>
|
||||||
|
<?php
|
||||||
|
// Convertir el nombre a formato de campo (minúsculas y guiones bajos)
|
||||||
|
$nombreCampo = strtolower(str_replace([' ', 'ó', 'ú', 'á', 'é', 'í'], ['_', 'o', 'u', 'a', 'e', 'i'], $nombre));
|
||||||
|
$nombreCampo = str_replace(['ñ'], ['n'], $nombreCampo);
|
||||||
|
|
||||||
|
// Crear ID único para cada checkbox
|
||||||
|
$idCampo = 'catalogo_' . $nombreCampo;
|
||||||
|
|
||||||
|
// Verificar si el campo existe en preferencias
|
||||||
|
$checked = isset($preferencias[$nombreCampo]) && !empty($preferencias[$nombreCampo]);
|
||||||
|
?>
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input tipo-catalogo" type="checkbox"
|
||||||
|
name="<?= $nombreCampo ?>" id="<?= $idCampo ?>"
|
||||||
|
data-tipo="tipo-catalogo" data-nombre="<?= $nombreCampo ?>"
|
||||||
|
<?= $checked ? 'checked' : '' ?>>
|
||||||
|
<label class="form-check-label" for="<?= $idCampo ?>">
|
||||||
|
<strong><?= htmlspecialchars($nombre) ?></strong>
|
||||||
|
<div class="form-text text-<?= htmlspecialchars($info['color']) ?>">
|
||||||
|
<?= htmlspecialchars($info['descripcion']) ?>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="alert alert-info">
|
||||||
|
No hay catálogos disponibles para tu tipo de usuario.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Indicador de guardado -->
|
||||||
|
<div id="save-indicator" class="save-indicator" style="display: none;">
|
||||||
|
<span class="indicator-text">Guardando...</span>
|
||||||
|
<div class="spinner-border spinner-border-sm ms-2" style="display: none;"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Estado global para controlar las peticiones
|
||||||
|
let isAutoSaving = false;
|
||||||
|
let saveTimeout = null;
|
||||||
|
|
||||||
|
// Referencias a elementos
|
||||||
|
const saveIndicator = document.getElementById('save-indicator');
|
||||||
|
const indicatorText = saveIndicator.querySelector('.indicator-text');
|
||||||
|
const spinner = saveIndicator.querySelector('.spinner-border');
|
||||||
|
|
||||||
|
// Función para mostrar indicador de guardado
|
||||||
|
function showSaveIndicator(type, message) {
|
||||||
|
// Limpiar clases anteriores
|
||||||
|
saveIndicator.className = 'save-indicator';
|
||||||
|
|
||||||
|
// Agregar clase según el tipo
|
||||||
|
saveIndicator.classList.add(type);
|
||||||
|
indicatorText.textContent = message;
|
||||||
|
|
||||||
|
// Mostrar/ocultar spinner
|
||||||
|
if (type === 'saving') {
|
||||||
|
spinner.style.display = 'inline-block';
|
||||||
|
} else {
|
||||||
|
spinner.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
saveIndicator.style.display = 'block';
|
||||||
|
|
||||||
|
// Auto-ocultar después de unos segundos (excepto cuando está guardando)
|
||||||
|
if (type !== 'saving') {
|
||||||
|
setTimeout(() => {
|
||||||
|
saveIndicator.style.display = 'none';
|
||||||
|
}, type === 'error' ? 5000 : 3000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Función para realizar guardado automático
|
||||||
|
async function autoSave(tipo, data) {
|
||||||
|
if (isAutoSaving) return;
|
||||||
|
|
||||||
|
isAutoSaving = true;
|
||||||
|
showSaveIndicator('saving', 'Guardando cambios...');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('/IMPORTADORES/preferencias/guardarCatalogosAjax', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-Requested-With': 'XMLHttpRequest'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
tipo: tipo,
|
||||||
|
...data
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
showSaveIndicator('saved', '✓ Cambios guardados');
|
||||||
|
} else {
|
||||||
|
throw new Error(result.message || 'Error desconocido');
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error al guardar:', error);
|
||||||
|
showSaveIndicator('error', '✗ Error: ' + error.message);
|
||||||
|
|
||||||
|
// En caso de error, podríamos revertir el estado del switch
|
||||||
|
// pero por ahora solo mostramos el error
|
||||||
|
} finally {
|
||||||
|
isAutoSaving = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Función para mostrar/ocultar secciones con animación
|
||||||
|
function toggleSection(checkbox, targetId) {
|
||||||
|
const target = document.getElementById(targetId);
|
||||||
|
const isChecked = checkbox.checked;
|
||||||
|
|
||||||
|
if (isChecked) {
|
||||||
|
target.style.display = 'block';
|
||||||
|
setTimeout(() => {
|
||||||
|
target.style.opacity = '1';
|
||||||
|
}, 10);
|
||||||
|
} else {
|
||||||
|
target.style.opacity = '0';
|
||||||
|
setTimeout(() => {
|
||||||
|
target.style.display = 'none';
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// === FUNCIONALIDAD DE CATÁLOGOS ===
|
||||||
|
|
||||||
|
// Event listener para switch general de catálogos
|
||||||
|
document.getElementById('preferencias-catalogos').addEventListener('change', function() {
|
||||||
|
const isChecked = this.checked;
|
||||||
|
|
||||||
|
// Deshabilitar temporalmente otros switches para evitar conflictos
|
||||||
|
const allSwitches = document.querySelectorAll('.form-check-input');
|
||||||
|
allSwitches.forEach(sw => sw.disabled = true);
|
||||||
|
|
||||||
|
// Guardar cambio
|
||||||
|
autoSave('catalogos_general', {
|
||||||
|
valor: isChecked
|
||||||
|
}).finally(() => {
|
||||||
|
// Rehabilitar switches
|
||||||
|
allSwitches.forEach(sw => sw.disabled = false);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mostrar/ocultar sección de tipos
|
||||||
|
toggleSection(this, 'tipos-catalogos');
|
||||||
|
|
||||||
|
// Si se desactivan los catálogos, también desactivar todos los tipos
|
||||||
|
if (!isChecked) {
|
||||||
|
// Desmarcar todos los tipos de catálogo
|
||||||
|
document.querySelectorAll('.tipo-catalogo').forEach(checkbox => {
|
||||||
|
checkbox.checked = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Event listeners para tipos específicos de catálogo
|
||||||
|
document.querySelectorAll('.tipo-catalogo').forEach(checkbox => {
|
||||||
|
checkbox.addEventListener('change', function() {
|
||||||
|
const isChecked = this.checked;
|
||||||
|
const tipoNombre = this.dataset.nombre;
|
||||||
|
|
||||||
|
// Verificar que los catálogos generales estén activados
|
||||||
|
const catalogosGenerales = document.getElementById('preferencias-catalogos').checked;
|
||||||
|
if (!catalogosGenerales) {
|
||||||
|
showSaveIndicator('error', 'Primero debes activar las preferencias de catálogos');
|
||||||
|
this.checked = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deshabilitar switch temporalmente
|
||||||
|
this.disabled = true;
|
||||||
|
|
||||||
|
// Guardar cambio
|
||||||
|
autoSave('tipo_catalogo', {
|
||||||
|
nombre: tipoNombre,
|
||||||
|
valor: isChecked
|
||||||
|
}).finally(() => {
|
||||||
|
this.disabled = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// === FIN FUNCIONALIDAD DE CATÁLOGOS ===
|
||||||
|
|
||||||
|
// Prevenir envío accidental del formulario
|
||||||
|
document.addEventListener('keydown', function(e) {
|
||||||
|
if (e.key === 'Enter' && e.target.type !== 'submit') {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mensaje de confirmación antes de salir si hay guardado en progreso
|
||||||
|
window.addEventListener('beforeunload', function(e) {
|
||||||
|
if (isAutoSaving) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.returnValue = 'Hay cambios pendientes de guardar. ¿Estás seguro de que quieres salir?';
|
||||||
|
return e.returnValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Inicialización al cargar la página
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Verificar estado inicial del switch general
|
||||||
|
const catalogosGenerales = document.getElementById('preferencias-catalogos');
|
||||||
|
if (catalogosGenerales && !catalogosGenerales.checked) {
|
||||||
|
const tiposCatalogos = document.getElementById('tipos-catalogos');
|
||||||
|
if (tiposCatalogos) {
|
||||||
|
tiposCatalogos.style.opacity = '0';
|
||||||
|
tiposCatalogos.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -45,6 +45,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card shadow-sm p-3">
|
||||||
|
<h5 class="text-success">Catalogos</h5>
|
||||||
|
<p>Personaliza la visualización de tus catalogos.</p>
|
||||||
|
<a href="/IMPORTADORES/preferencias/catalogos"
|
||||||
|
class="btn btn-success btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/preferencias/catalogos' ? 'active' : '' ?>">
|
||||||
|
Personalizar Catálogos
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -38,6 +38,7 @@
|
|||||||
<!-- 📄 CONTENIDO -->
|
<!-- 📄 CONTENIDO -->
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<h4 class="mb-4">🔗 Mis vinculaciones</h4>
|
<h4 class="mb-4">🔗 Mis vinculaciones</h4>
|
||||||
|
<a href="/IMPORTADORES/vinculaciones/nuevaVinculacion" class="btn btn-success mb-3">➕ Nueva Vinculación</a>
|
||||||
<!-- TABLA DE VINCULACIÓN USUARIO -->
|
<!-- TABLA DE VINCULACIÓN USUARIO -->
|
||||||
<div class="card p-3 shadow-sm">
|
<div class="card p-3 shadow-sm">
|
||||||
<h5 class="mb-3">🏪 Agencia Vinculadas</h5>
|
<h5 class="mb-3">🏪 Agencia Vinculadas</h5>
|
||||||
|
|||||||
Reference in New Issue
Block a user