Error en Eliminacion masiva

Angelicahg

Angelicahg

Gamma
Verificado
Verificación en dos pasos activada
Verificado por Whatsapp
Verificado por Binance
Hola, estoy haciendo una web como de prueba, aprendiendo. Y estoy bastante avanzada, pero estoy estancada en una opcion de Eliminar Usuarios masivamente.

Tengo una lista de usuarios que, selecciono todos y el boton de eliminar seleccionados no sirve (Si sirve, eliminar uno por uno) pero eliminar masivamente no.
1745830157056.webp
1745830174508.webp


Aquí mis codigos:

usuarios.js
JavaScript:
document.addEventListener('DOMContentLoaded', () => {
  // Obtener el token CSRF desde el meta tag
  const csrf_token = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
 
  const createPopup = document.getElementById("create-user-popup");
  const editPopup = document.getElementById("edit-user-popup");
  const overlay = document.getElementById("popup-overlay");

  // Abrir popup de crear usuario
  document.getElementById("create-user-btn")?.addEventListener("click", () => {
    createPopup.style.display = "flex";
    overlay.style.display = "block";
  });

  // Cerrar popups al hacer clic en el overlay
  overlay?.addEventListener('click', (e) => {
    if (e.target === overlay) {
      closeAllPopups();
    }
  });

  // Botón de cerrar popup tipo "–"
  document.querySelectorAll(".close-popup")?.forEach(btn => {
    btn.addEventListener("click", () => {
      closeAllPopups();
    });
  });

  function closeAllPopups() {
    createPopup.style.display = "none";
    editPopup.style.display = "none";
    overlay.style.display = "none";
  }

  // Mostrar/ocultar contraseña (crear)
  document.getElementById("mostrar-password")?.addEventListener("click", () => {
    const input = document.getElementById("password");
    const icon = document.querySelector("#mostrar-password i");
    input.type = input.type === "password" ? "text" : "password";
    icon.classList.toggle("fa-eye");
    icon.classList.toggle("fa-eye-slash");
  });

  // Generar contraseña (crear)
  document.getElementById("generar-password")?.addEventListener("click", () => {
    const input = document.getElementById("password");
    const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%&";
    input.value = Array.from({ length: 10 }, () => chars[Math.floor(Math.random() * chars.length)]).join('');
  });

  // Abrir popup de editar usuario
  document.querySelectorAll('.editar-usuario-btn').forEach(btn => {
    btn.addEventListener("click", async (e) => {
      const id = e.currentTarget.dataset.id;
      try {
        const res = await fetch(`controllers/obtener_usuario.php?id=${id}`);
        const usuario = await res.json();

        document.getElementById("edit_usuario_id").value = usuario.id;
        document.getElementById("edit_username").value = usuario.username;
        document.getElementById("edit_password").value = "";
        document.getElementById("edit_rol").value = usuario.role;

        editPopup.style.display = "flex";
        overlay.style.display = "block";
      } catch (error) {
        mostrarSnackbar("❌ Error al cargar usuario", "error");
        console.error(error);
      }
    });
  });

  // Form crear usuario
  document.getElementById("form-crear-usuario")?.addEventListener("submit", async (e) => {
    e.preventDefault();
    const form = e.target;
    const formData = new FormData(form);

    try {
      const response = await fetch('controllers/crear_usuario.php', {
        method: "POST",
        body: formData,
      });

      const result = await response.json();

      if (result.success) {
        mostrarSnackbar(result.message || "✅ Usuario creado correctamente");
        closeAllPopups();
        form.reset();
        location.reload();
      } else {
        mostrarSnackbar(result.message || "⚠️ Algo salió mal", "error");
      }
    } catch (err) {
      mostrarSnackbar("❌ Error en el servidor", "error");
      console.error(err);
    }
  });

  // Form editar usuario
  document.getElementById("form-editar-usuario")?.addEventListener("submit", async (e) => {
    e.preventDefault();
    const form = e.target;
    const formData = new FormData(form);

    try {
      const response = await fetch('controllers/editar_usuario.php', {
        method: "POST",
        body: formData,
      });

      const result = await response.json();

      if (result.success) {
        mostrarSnackbar(result.message || "✅ Usuario actualizado");
        closeAllPopups();
        form.reset();
        location.reload();
      } else {
        mostrarSnackbar(result.message || "⚠️ Algo salió mal", "error");
      }
    } catch (err) {
      mostrarSnackbar("❌ Error en el servidor", "error");
      console.error(err);
    }
  });

  // Cambiar rol
  document.querySelectorAll('.select-rol').forEach(select => {
    select.addEventListener('change', async (e) => {
      const userId = e.target.dataset.id;
      const nuevoRol = e.target.value;

      try {
        const response = await fetch('controllers/cambiar_rol.php', {
          method: 'POST',
          body: new URLSearchParams({ id: userId, rol: nuevoRol })
        });

        const result = await response.json();
        if (result.success) {
          mostrarSnackbar("✅ Rol actualizado");
        } else {
          mostrarSnackbar("⚠️ No se pudo actualizar el rol", "error");
        }
      } catch (err) {
        mostrarSnackbar("❌ Error al actualizar", "error");
      }
    });
  });
 
  // Selección múltiple
  const checkboxes = document.querySelectorAll('.checkbox-usuario');
  const barraAcciones = document.querySelector('.acciones-masivas');

  function actualizarAcciones() {
    const seleccionados = [...checkboxes].filter(c => c.checked);
    const cantidad = seleccionados.length;

    barraAcciones.style.display = cantidad > 1 ? 'flex' : 'none';

    document.querySelectorAll('.tarjeta-usuario').forEach(tarjeta => {
      const cb = tarjeta.querySelector('.checkbox-usuario');
      const acciones = tarjeta.querySelector('.acciones-usuario');

      if (cb.checked) {
        tarjeta.classList.add('seleccionado');
        acciones.style.display = cantidad === 1 ? 'flex' : 'none';
      } else {
        tarjeta.classList.remove('seleccionado');
        acciones.style.display = 'none';
      }
    });
  }

  checkboxes.forEach(cb => {
    cb.addEventListener('change', actualizarAcciones);
  });
 
  // Eliminar usuarios
  document.querySelectorAll('.eliminar-usuario-btn').forEach(btn => {
    btn.addEventListener('click', async (e) => {
      e.preventDefault();  // Prevenir la acción por defecto

      const id = btn.dataset.id;
      console.log("ID del usuario a eliminar:", id); // Verifica si el ID es correcto

      if (confirm("¿Eliminar este usuario?")) {
        try {
          // Enviar la solicitud AJAX
          const res = await fetch('controllers/eliminar_usuario.php?id=' + id + '&token=' + csrf_token, {
            method: "GET",
          });

          const result = await res.json();  // Obtener respuesta JSON
          console.log(result);  // Verifica la respuesta de eliminación

          if (result.success) {
            mostrarSnackbar(result.message, 'success');  // Mostrar mensaje de éxito
            btn.closest('.tarjeta-usuario').remove();  // Eliminar el usuario de la interfaz
          } else {
            mostrarSnackbar(result.message, 'error');  // Mostrar mensaje de error
          }
        } catch (err) {
          mostrarSnackbar("❌ Error al eliminar", 'error');  // Mostrar mensaje de error si ocurre un fallo
          console.error(err);
        }
      }
    });
  });
 
  //Eliminar masivo
  document.addEventListener('DOMContentLoaded', () => {
    const checkboxes = document.querySelectorAll('.checkbox-usuario');
    const barraAcciones = document.querySelector('.acciones-masivas');
    const btnEliminarSeleccionados = document.getElementById('btnEliminarSeleccionados');
    const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');

    // Función para actualizar la visibilidad de las acciones masivas
    function actualizarAcciones() {
        const seleccionados = [...checkboxes].filter(c => c.checked);
        const cantidad = seleccionados.length;

        // Mostrar u ocultar la barra de acciones masivas
        barraAcciones.style.display = cantidad > 0 ? 'flex' : 'none';
    }

    // Evento de selección de checkboxes
    checkboxes.forEach(checkbox => {
        checkbox.addEventListener('change', actualizarAcciones);
    });

    // Función para eliminar los usuarios seleccionados
    btnEliminarSeleccionados.addEventListener('click', () => {
        const seleccionados = [...checkboxes].filter(c => c.checked);
        const idsSeleccionados = seleccionados.map(c => c.dataset.id);

        if (idsSeleccionados.length === 0) {
            alert('Selecciona al menos un usuario para eliminar.');
            return;
        }

        // Realizar la solicitud AJAX para eliminar usuarios
        fetch('<?= BASE_URL ?>wp-content/novu-admin/controllers/eliminar-masivo.php', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                usuarios: idsSeleccionados,
                csrf_token: csrfToken,
            }),
        })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                alert(data.success);
                location.reload(); // Recargar la página para actualizar la lista
            } else {
                alert(data.error);
            }
        })
        .catch(error => {
            console.error('Error:', error);
            alert('Hubo un error al eliminar los usuarios.');
        });
    });
});

});

eliminar_masivo.php


PHP:
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);

require_once __DIR__ . '/../../config/config.php';
require_once __DIR__ . '/../../config/db.php';

// Verificar si el CSRF token es válido
session_start();
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
    echo json_encode(['error' => 'Token CSRF inválido']);
    exit;
}

$pdo = DB::connect();
if (!$pdo) {
    die("Error de conexión");
}

if (isset($_POST['usuarios'])) {
    $usuarios = $_POST['usuarios']; // Array con los IDs de los usuarios seleccionados
    
    // Crear una lista de placeholders para los IDs
    $placeholders = implode(',', array_fill(0, count($usuarios), '?'));

    // Preparar la consulta para eliminar los usuarios seleccionados
    $stmt = $pdo->prepare("DELETE FROM users WHERE id IN ($placeholders)");
    
    // Ejecutar la consulta con los IDs de los usuarios seleccionados
    $stmt->execute($usuarios);

    // Verificar si la eliminación fue exitosa
    if ($stmt->rowCount() > 0) {
        echo json_encode(['success' => 'Usuarios eliminados correctamente']);
    } else {
        echo json_encode(['error' => 'No se pudo eliminar ningún usuario']);
    }
} else {
    echo json_encode(['error' => 'No se enviaron usuarios para eliminar']);
}

usuarios.php


PHP:
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);

require_once __DIR__ . '/../../config/config.php';
require_once __DIR__ . '/../../config/db.php';

// Funci贸n para registrar errores en un archivo de log
function log_error($message) {
    $log_file = __DIR__ . '/../logs/error_log.txt';  // Ruta al archivo de log
    $date = date('Y-m-d H:i:s');
    $log_message = "[$date] ERROR: $message" . PHP_EOL;
    file_put_contents($log_file, $log_message, FILE_APPEND);
}

$pdo = DB::connect();
if (!$pdo) {
    log_error('Error de conexi贸n a la base de datos.');
    die("Error de conexi贸n");
}

function obtenerUsuarios() {
    global $pdo;
    $stmt = $pdo->prepare("SELECT id, username, role FROM users");
    $stmt->execute();
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

$usuarios = obtenerUsuarios();
?>

<div class="usuarios-wrapper">
  <div class="usuarios-layout">

  <!-- SIDEBAR IZQUIERDO -->
  <aside class="sidebar-usuarios">
    <div class="sidebar-superior">
      <button id="create-user-btn" class="btn-crear-evento">
        <i class="fa-solid fa-plus"></i> CREAR
      </button>
      <div class="separador-crear"></div>
    </div>

    <div class="sidebar-inferior">
      <nav class="sidebar-nav">
        <a href="#" class="filter-option" data-filter="archivados"><i class="fa-solid fa-inbox"></i> Archivados</a>
        <a href="#" class="filter-option" data-filter="papelera"><i class="fa-solid fa-trash"></i> Papelera</a>
        <a href="#" class="filter-option" data-filter="favoritos"><i class="fa-solid fa-star"></i> Favoritos</a>
      </nav>
    </div>
  </aside>

  <!-- CONTENEDOR PRINCIPAL -->
  <div class="panel-eventos">
    <!-- BARRA DE ACCIONES -->
    <div class="barra-acciones">
      <div class="acciones-izquierda">
        <div class="acciones-masivas" style="display: none;">
          <button id="btnEliminarSeleccionados" class="btn-accion-masiva">
    <i class="fa-solid fa-trash"></i> Eliminar seleccionados
</button>

          <button id="btnFavoritos" class="btn-accion-masiva">
            <i class="fa-solid fa-star"></i> Favoritos
          </button>
        </div>
      </div>

      <div class="acciones-derecha filtros-busqueda">
        <select id="filtroRol">
          <option value="">Todos los roles</option>
          <option value="admin">Administrador</option>
          <option value="cliente">Cliente</option>
        </select>

        <select id="ordenarPor">
          <option value="az">Nombre A-Z</option>
          <option value="za">Nombre Z-A</option>
        </select>

        <div class="input-busqueda">
          <i class="fa-solid fa-magnifying-glass"></i>
          <input type="text" id="buscarUsuario" placeholder="Buscar usuario...">
        </div>

        <button id="resetFiltros" class="btn-reset">
          <i class="fa-solid fa-rotate-right"></i>
        </button>
      </div>
    </div>

    <!-- LISTA DE USUARIOS -->
    <div class="lista-usuarios-card">
      <div class="tarjeta-lista">
        <?php foreach ($usuarios as $usuario): ?>
          <div class="tarjeta-usuario">
            <div class="icono-usuario">
              <input type="checkbox" class="checkbox-usuario" data-id="<?= $usuario['id'] ?>">
              <i class="fa-regular fa-star estrella-favorito" data-id="<?= $usuario['id'] ?>"></i>
              <i class="fa-solid fa-user-circle"></i>
            </div>

            <div class="contenido-usuario">
              <h3><?= htmlspecialchars($usuario['username']) ?></h3>
              <div class="rol-select">
                <label for="rol-<?= $usuario['id'] ?>" class="visually-hidden"></label>
                <select class="select-rol" data-id="<?= $usuario['id'] ?>" id="rol-<?= $usuario['id'] ?>">
                  <option value="admin" <?= $usuario['role'] === 'admin' ? 'selected' : '' ?>>Administrador</option>
                  <option value="cliente" <?= $usuario['role'] === 'cliente' ? 'selected' : '' ?>>Cliente</option>
                </select>
              </div>
            </div>

            <div class="acciones-usuario">
              <button class="btn editar-usuario-btn" data-id="<?= $usuario['id'] ?>" title="Editar">
                <i class="fa-solid fa-pen-to-square"></i>
              </button>
              <button class="btn eliminar-usuario-btn" data-id="<?= $usuario['id'] ?>" title="Eliminar">
                <i class="fa-solid fa-trash-can"></i>
              </button>
            </div>
          </div>
        <?php endforeach; ?>
      </div>
    </div>
  </div>

</div>

<!-- Agregar el CSRF Token en meta tag -->
<meta name="csrf-token" content="<?= $_SESSION['csrf_token']; ?>"> <!-- Asegúrate de que esto esté en el <head> -->


<!-- POPUPS -->
<?php
  if (file_exists(__DIR__ . '/popup-crear-usuario.php')) {
    include __DIR__ . '/popup-crear-usuario.php';
  } else {
    echo "<!-- popup-crear-usuario.php no encontrado -->";
  }

  if (file_exists(__DIR__ . '/popup-editar-usuario.php')) {
    include __DIR__ . '/popup-editar-usuario.php';
  } else {
    echo "<!-- popup-editar-usuario.php no encontrado -->";
  }
?>

<!-- OVERLAY GLOBAL -->
<div id="popup-overlay" class="popup-overlay" style="display: none;"></div>

<div id="snackbar-container"></div>

<!-- JS -->
<script src="<?= BASE_URL ?>wp-content/novu-admin/public/assets/js/global.js"></script>
<script src="<?= BASE_URL ?>wp-content/novu-admin/public/assets/js/escritorio/usuarios.js"></script>



Cabe destacatar que no me deja hacer clic en el boton "Eliminar Seleccionados", asi que no se si eliminan masivamente o no, pq aja no deja hacer la accion no se si me explico, ya intente solucionarlo tambien con chatgpt pero cada vez me arruina más 🤣, si alguien sabe se lo agradezco tengo 2 dias en esto y no he avanzando nada mas por esa funcion
 
usa la consola a ver que errores te da... anda guardando en un archivo lo que recibis por _REQUEST asi sabes que recibe, etc... tenes que degugear, si el boton no te funciona... en la consola aparecera porque, sea error del js, o que... sino aparece nada, debugealo con alerts, a ver si estas recibiendo los datos, o con consolge.log...etc.
 
usa la consola a ver que errores te da... anda guardando en un archivo lo que recibis por _REQUEST asi sabes que recibe, etc... tenes que degugear, si el boton no te funciona... en la consola aparecera porque, sea error del js, o que... sino aparece nada, debugealo con alerts, a ver si estas recibiendo los datos, o con consolge.log...etc.
Ya logre que el boton funcionara, ahora si salta por lo menos el Snackback de "Error al eliminar usuarios", en consola salta esto:

1745834739459.webp


dice que es la BASE URL pero eso lo tengo bien (Creo), ya lo he revisado varias veces
 
ahi mismo te indica, error 404 es que no existe... tenes mal la ruta.. .fijate que se repite: wp-content/novu-admin/wp-content/novu-admin/
 
ahi mismo te indica, error 404 es que no existe... tenes mal la ruta.. .fijate que se repite: wp-content/novu-admin/wp-content/novu-admin/
Sii es que yo se que la ruta se repite pero el problema es que no se pq si tengo todo bien configurado en mi config/config.php y config/db.php, en mi index.php, osea no encuentro el por que la ruta sale asi mal, si en los demas botones todo sale bien
 
JavaScript:
    // Realizar la solicitud AJAX para eliminar usuarios seleccionados
    fetch(`${BASE_URL}wp-content/novu-admin/controllers/eliminar_masivo.php`, { // Usar BASE_URL correctamente
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        usuarios: idsSeleccionados,
        csrf_token: csrf_token,
      }),
    })
    .then(response => response.json())
    .then(data => {
      console.log('Respuesta del servidor:', data);
      if (data.success) {
        alert(data.success);
        location.reload(); // Recargar la página para actualizar la lista
      } else {
        alert(data.error);
      }
    })
    .catch(error => {
      console.error('Error:', error);
      alert('Hubo un error al eliminar los usuarios.');
    });
  });
 
La ruta correcta deberia ser: fetch(${BASE_URL}controllers/eliminar_masivo.php,

Ya que mi base url es miurl/wp-content/novu-admin/ pero aun asi no funciona dice "Uncaught ReferenceError: BASE_URL is not defined"
1745838681928.webp
 
es porque BASE_URL no existe, porque le pusiste otro nombre o la definiste dentro de otra función.
imprime antes de fetch post la BASE_URL, con:
console.log(BASE_URL);
 
es porque BASE_URL no existe, porque le pusiste otro nombre o la definiste dentro de otra función.
imprime antes de fetch post la BASE_URL, con:
console.log(BASE_URL);
Ya lo resolvi, pero igual no era eso, bueno si pero mi URL estaba bien e igual daba error habian otras funciones con esa misma url y todo funcionando, pero a esa en especifico que le tuve que colocar $window.location y asi lo resolvi
 
@Angelicahg no puedes llamar <?= BASE_URL ?> que es PHP en un archivo JS
 
Atrás
Arriba