Autosave: 20260203-063144
This commit is contained in:
parent
96d2546dba
commit
db4413f46e
5
db/migrations/049_create_sedes_table.sql
Normal file
5
db/migrations/049_create_sedes_table.sql
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS sedes (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
nombre VARCHAR(255) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
@ -1,180 +1,356 @@
|
|||||||
<?php
|
<?php die('Test 1'); ?><?php
|
||||||
$pageTitle = "Panel de Inventario";
|
session_start();
|
||||||
require_once 'layout_header.php';
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header("Location: login.php");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
require_once 'db/config.php';
|
require_once 'db/config.php';
|
||||||
|
|
||||||
// Determine the current section from the URL, default to 'dashboard'
|
$conn = db();
|
||||||
$seccion = isset($_GET['seccion']) ? $_GET['seccion'] : 'dashboard';
|
$feedback = '';
|
||||||
|
$feedback_type = 'info';
|
||||||
|
|
||||||
$message = '';
|
// ======= MANEJO DE ACCIONES (POST) =======
|
||||||
$message_type = '';
|
|
||||||
|
|
||||||
// Handle product registration form submission
|
// --- AGREGAR SEDE ---
|
||||||
if ($seccion === 'registro_producto' && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['nombre_producto'])) {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_sede'])) {
|
||||||
$nombre_producto = trim($_POST['nombre_producto']);
|
$nombre_sede = trim($_POST['nombre_sede']);
|
||||||
|
if (!empty($nombre_sede)) {
|
||||||
if (!empty($nombre_producto)) {
|
|
||||||
try {
|
try {
|
||||||
$pdo = db();
|
$sql = "INSERT INTO sedes (nombre) VALUES (:nombre)";
|
||||||
// Check if product already exists
|
$stmt = $conn->prepare($sql);
|
||||||
$stmt = $pdo->prepare("SELECT COUNT(*) FROM products WHERE nombre = ?");
|
$stmt->bindParam(':nombre', $nombre_sede);
|
||||||
$stmt->execute([$nombre_producto]);
|
$stmt->execute();
|
||||||
if ($stmt->fetchColumn() > 0) {
|
$feedback = 'Sede añadida correctamente.';
|
||||||
$message = "Error: El producto '{$nombre_producto}' ya existe.";
|
$feedback_type = 'success';
|
||||||
$message_type = "danger";
|
|
||||||
} else {
|
|
||||||
// Insert new product with default values
|
|
||||||
$stmt = $pdo->prepare("INSERT INTO products (nombre, unidades_disponibles, cobertura, show_on_panel, order_position) VALUES (?, 0, '[]', 1, 0)");
|
|
||||||
if ($stmt->execute([$nombre_producto])) {
|
|
||||||
$message = "Producto '{$nombre_producto}' registrado con éxito.";
|
|
||||||
$message_type = "success";
|
|
||||||
} else {
|
|
||||||
$message = "Error al registrar el producto.";
|
|
||||||
$message_type = "danger";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
$message = "Error de base de datos: " . $e->getMessage();
|
$feedback = 'Error al añadir la sede: ' . $e->getMessage();
|
||||||
$message_type = "danger";
|
$feedback_type = 'danger';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$message = "El nombre del producto no puede estar vacío.";
|
$feedback = 'El nombre de la sede no puede estar vacío.';
|
||||||
$message_type = "warning";
|
$feedback_type = 'warning';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- ELIMINAR SEDE ---
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_sede'])) {
|
||||||
|
$sede_id = $_POST['sede_id'];
|
||||||
|
try {
|
||||||
|
$sql = "DELETE FROM sedes WHERE id = :id";
|
||||||
|
$stmt = $conn->prepare($sql);
|
||||||
|
$stmt->bindParam(':id', $sede_id, PDO::PARAM_INT);
|
||||||
|
$stmt->execute();
|
||||||
|
$feedback = 'Sede eliminada correctamente.';
|
||||||
|
$feedback_type = 'success';
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$feedback = 'Error al eliminar la sede.';
|
||||||
|
$feedback_type = 'danger';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- REGISTRAR ENTRADA DE INVENTARIO ---
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['registrar_entrada'])) {
|
||||||
|
$producto_id = $_POST['producto_id'];
|
||||||
|
$cantidad = $_POST['cantidad'];
|
||||||
|
|
||||||
|
if (!empty($producto_id) && !empty($cantidad) && is_numeric($cantidad) && $cantidad > 0) {
|
||||||
|
try {
|
||||||
|
$conn->beginTransaction();
|
||||||
|
$stmt = $conn->prepare("UPDATE productos SET unidades_disponibles = unidades_disponibles + :cantidad WHERE id = :id");
|
||||||
|
$stmt->bindParam(':cantidad', $cantidad, PDO::PARAM_INT);
|
||||||
|
$stmt->bindParam(':id', $producto_id, PDO::PARAM_INT);
|
||||||
|
$stmt->execute();
|
||||||
|
$conn->commit();
|
||||||
|
$feedback = 'Stock actualizado correctamente.';
|
||||||
|
$feedback_type = 'success';
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$conn->rollBack();
|
||||||
|
$feedback = 'Error al actualizar el stock: ' . $e->getMessage();
|
||||||
|
$feedback_type = 'danger';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$feedback = 'Por favor, selecciona un producto e introduce una cantidad válida.';
|
||||||
|
$feedback_type = 'warning';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- REGISTRAR NUEVO PRODUCTO ---
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['registrar_producto'])) {
|
||||||
|
$nombre = trim($_POST['nombre']);
|
||||||
|
$unidades = (int)$_POST['unidades_disponibles'];
|
||||||
|
$precio = (float)$_POST['precio_unitario'];
|
||||||
|
$costo = (float)$_POST['costo_unitario'];
|
||||||
|
|
||||||
|
if (!empty($nombre) && $unidades >= 0 && $precio >= 0 && $costo >= 0) {
|
||||||
|
try {
|
||||||
|
$sql = "INSERT INTO productos (nombre, unidades_disponibles, precio_unitario, costo_unitario) VALUES (:nombre, :unidades, :precio, :costo)";
|
||||||
|
$stmt = $conn->prepare($sql);
|
||||||
|
$stmt->execute([':nombre' => $nombre, ':unidades' => $unidades, ':precio' => $precio, ':costo' => $costo]);
|
||||||
|
$feedback = 'Producto registrado correctamente.';
|
||||||
|
$feedback_type = 'success';
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$feedback = 'Error al registrar el producto: ' . $e->getMessage();
|
||||||
|
$feedback_type = 'danger';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$feedback = 'Por favor, completa todos los campos del producto correctamente.';
|
||||||
|
$feedback_type = 'warning';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Set the title based on the section
|
// ======= OBTENCIÓN DE DATOS (GET) =======
|
||||||
switch ($seccion) {
|
|
||||||
case 'entrada':
|
|
||||||
$pageTitle = "Registro de Entrada";
|
|
||||||
break;
|
|
||||||
case 'salida':
|
|
||||||
$pageTitle = "Registro de Salida";
|
|
||||||
break;
|
|
||||||
case 'registro_producto':
|
|
||||||
$pageTitle = "Registro de Nuevo Producto";
|
|
||||||
break;
|
|
||||||
case 'dashboard':
|
|
||||||
default:
|
|
||||||
$pageTitle = "Dashboard de Inventario";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// --- DATOS PARA GRÁFICOS ---
|
||||||
|
$productos_por_agotarse = $conn->query("SELECT nombre, unidades_disponibles FROM productos WHERE unidades_disponibles > 0 ORDER BY unidades_disponibles ASC LIMIT 5")->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
$productos_mas_stock = $conn->query("SELECT nombre, unidades_disponibles FROM productos ORDER BY unidades_disponibles DESC LIMIT 5")->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
// --- LISTA DE TODOS LOS PRODUCTOS ---
|
||||||
|
$productos = $conn->query("SELECT * FROM productos ORDER BY nombre ASC")->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
// --- LISTA DE SEDES ---
|
||||||
|
$sedes = $conn->query("SELECT * FROM sedes ORDER BY nombre ASC")->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
$pageTitle = "Panel de Inventario";
|
||||||
|
include 'layout_header.php';
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="container mt-4">
|
<div class="container-fluid mt-4">
|
||||||
<?php if ($message): ?>
|
<h2 class="mb-4">Panel de Inventario</h2>
|
||||||
<div class="alert alert-<?php echo $message_type; ?> alert-dismissible fade show" role="alert">
|
|
||||||
<?php echo htmlspecialchars($message); ?>
|
<?php if ($feedback): ?>
|
||||||
|
<div class="alert alert-<?php echo $feedback_type; ?> alert-dismissible fade show" role="alert">
|
||||||
|
<?php echo htmlspecialchars($feedback); ?>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php
|
<ul class="nav nav-tabs" id="inventoryTab" role="tablist">
|
||||||
// Display content based on the selected section
|
<li class="nav-item" role="presentation">
|
||||||
if ($seccion === 'entrada'):
|
<button class="nav-link active" id="dashboard-tab" data-bs-toggle="tab" data-bs-target="#dashboard" type="button" role="tab" aria-controls="dashboard" aria-selected="true">Dashboard</button>
|
||||||
?>
|
</li>
|
||||||
<div class="card">
|
<li class="nav-item" role="presentation">
|
||||||
<div class="card-header">
|
<button class="nav-link" id="register-product-tab" data-bs-toggle="tab" data-bs-target="#register-product" type="button" role="tab" aria-controls="register-product" aria-selected="false">Registrar Producto</button>
|
||||||
<h5 class="card-title mb-0">Registro de Entrada de Inventario</h5>
|
</li>
|
||||||
</div>
|
<li class="nav-item" role="presentation">
|
||||||
<div class="card-body">
|
<button class="nav-link" id="register-entry-tab" data-bs-toggle="tab" data-bs-target="#register-entry" type="button" role="tab" aria-controls="register-entry" aria-selected="false">Registrar Entrada</button>
|
||||||
<p>Esta sección está en construcción. Aquí podrás registrar la entrada de nuevo stock.</p>
|
</li>
|
||||||
</div>
|
<li class="nav-item" role="presentation">
|
||||||
</div>
|
<button class="nav-link" id="sedes-tab" data-bs-toggle="tab" data-bs-target="#sedes" type="button" role="tab" aria-controls="sedes" aria-selected="false">Sedes</button>
|
||||||
<?php
|
</li>
|
||||||
elseif ($seccion === 'salida'):
|
</ul>
|
||||||
?>
|
|
||||||
<div class="card">
|
<div class="tab-content py-4" id="inventoryTabContent">
|
||||||
<div class="card-header">
|
<!-- Pestaña Dashboard -->
|
||||||
<h5 class="card-title mb-0">Registro de Salida de Inventario</h5>
|
<div class="tab-pane fade show active" id="dashboard" role="tabpanel" aria-labelledby="dashboard-tab">
|
||||||
</div>
|
<div class="row">
|
||||||
<div class="card-body">
|
<div class="col-lg-6 mb-4">
|
||||||
<p>Esta sección está en construcción. Aquí podrás registrar la salida de stock por ventas u otros motivos.</p>
|
<div class="card h-100">
|
||||||
</div>
|
<div class="card-header"><h5 class="card-title mb-0">Productos por Agotarse</h5></div>
|
||||||
</div>
|
<div class="card-body d-flex justify-content-center align-items-center">
|
||||||
<?php
|
<canvas id="chartAgotarse" style="max-height: 300px;"></canvas>
|
||||||
elseif ($seccion === 'registro_producto'):
|
</div>
|
||||||
?>
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">
|
|
||||||
<h5 class="card-title mb-0">Registrar Nuevo Producto</h5>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<form method="POST" action="panel_inventario.php?seccion=registro_producto">
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="nombre_producto" class="form-label">Nombre del Producto</label>
|
|
||||||
<input type="text" class="form-control" id="nombre_producto" name="nombre_producto" required>
|
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary">Guardar Producto</button>
|
</div>
|
||||||
</form>
|
<div class="col-lg-6 mb-4">
|
||||||
|
<div class="card h-100">
|
||||||
|
<div class="card-header"><h5 class="card-title mb-0">Top 5 Productos con más Stock</h5></div>
|
||||||
|
<div class="card-body d-flex justify-content-center align-items-center">
|
||||||
|
<canvas id="chartMasStock" style="max-height: 300px;"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="card">
|
||||||
<?php
|
<div class="card-header"><h5 class="card-title mb-0">Stock General de Productos</h5></div>
|
||||||
else: // Default to dashboard
|
<div class="card-body">
|
||||||
// Fetch product data from the database
|
<div class="table-responsive">
|
||||||
try {
|
<table class="table table-striped table-hover">
|
||||||
$pdo = db();
|
<thead>
|
||||||
$stmt = $pdo->query("SELECT nombre, unidades_disponibles, cobertura FROM products ORDER BY nombre ASC");
|
|
||||||
$products = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
echo "<div class='alert alert-danger'>Error al conectar con la base de datos: " . $e->getMessage() . "</div>";
|
|
||||||
$products = [];
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">
|
|
||||||
<h5 class="card-title mb-0">Stock de Productos por Ciudad</h5>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-striped table-hover">
|
|
||||||
<thead class="thead-light">
|
|
||||||
<tr>
|
|
||||||
<th scope="col">Producto</th>
|
|
||||||
<th scope="col" class="text-center">Stock Total</th>
|
|
||||||
<th scope="col">Ciudades de Cobertura</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php if (empty($products)): ?>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3" class="text-center">No hay productos para mostrar.</td>
|
<th>Nombre</th>
|
||||||
|
<th class="text-center">Unidades Disponibles</th>
|
||||||
|
<th>Precio Unitario</th>
|
||||||
|
<th>Costo Unitario</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($productos as $producto): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?= htmlspecialchars($producto['nombre']) ?></td>
|
||||||
|
<td class="text-center"><?= htmlspecialchars($producto['unidades_disponibles']) ?></td>
|
||||||
|
<td>S/ <?= htmlspecialchars(number_format($producto['precio_unitario'], 2)) ?></td>
|
||||||
|
<td>S/ <?= htmlspecialchars(number_format($producto['costo_unitario'], 2)) ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php else: ?>
|
|
||||||
<?php foreach ($products as $product): ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo htmlspecialchars($product['nombre']); ?></td>
|
|
||||||
<td class="text-center"><?php echo htmlspecialchars($product['unidades_disponibles']); ?></td>
|
|
||||||
<td>
|
|
||||||
<?php
|
|
||||||
$cobertura_list = json_decode($product['cobertura'], true);
|
|
||||||
if (json_last_error() === JSON_ERROR_NONE && is_array($cobertura_list)) {
|
|
||||||
echo htmlspecialchars(implode(', ', $cobertura_list));
|
|
||||||
} else {
|
|
||||||
echo htmlspecialchars($product['cobertura']);
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<?php endif; ?>
|
<?php if (.empty($productos)): ?>
|
||||||
</tbody>
|
<tr><td colspan="4" class="text-center">No hay productos registrados.</td></tr>
|
||||||
</table>
|
<?php endif; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php
|
|
||||||
endif;
|
<!-- Pestaña Registrar Producto -->
|
||||||
?>
|
<div class="tab-pane fade" id="register-product" role="tabpanel" aria-labelledby="register-product-tab">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header"><h5 class="card-title mb-0">Registrar Nuevo Producto</h5></div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form action="panel_inventario.php" method="POST">
|
||||||
|
<input type="hidden" name="registrar_producto" value="1">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label for="nombre" class="form-label">Nombre del Producto</label>
|
||||||
|
<input type="text" class="form-control" id="nombre" name="nombre" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label for="unidades_disponibles" class="form-label">Unidades Disponibles</label>
|
||||||
|
<input type="number" class="form-control" id="unidades_disponibles" name="unidades_disponibles" min="0" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label for="precio_unitario" class="form-label">Precio Unitario (S/)</label>
|
||||||
|
<input type="number" class="form-control" id="precio_unitario" name="precio_unitario" step="0.01" min="0" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label for="costo_unitario" class="form-label">Costo Unitario (S/)</label>
|
||||||
|
<input type="number" class="form-control" id="costo_unitario" name="costo_unitario" step="0.01" min="0" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Registrar Producto</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Pestaña Registrar Entrada -->
|
||||||
|
<div class="tab-pane fade" id="register-entry" role="tabpanel" aria-labelledby="register-entry-tab">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header"><h5 class="card-title mb-0">Registrar Entrada de Inventario</h5></div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form action="panel_inventario.php" method="POST">
|
||||||
|
<input type="hidden" name="registrar_entrada" value="1">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="producto_id" class="form-label">Producto</label>
|
||||||
|
<select class="form-select" id="producto_id" name="producto_id" required>
|
||||||
|
<option value="">Selecciona un producto</option>
|
||||||
|
<?php foreach ($productos as $producto): ?>
|
||||||
|
<option value="<?= $producto['id'] ?>"><?= htmlspecialchars($producto['nombre']) ?></option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="cantidad" class="form-label">Cantidad a Ingresar</label>
|
||||||
|
<input type="number" class="form-control" id="cantidad" name="cantidad" min="1" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Registrar Entrada</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Pestaña Sedes -->
|
||||||
|
<div class="tab-pane fade" id="sedes" role="tabpanel" aria-labelledby="sedes-tab">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-5">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header"><h5 class="card-title mb-0">Añadir Nueva Sede</h5></div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form action="panel_inventario.php" method="POST">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="nombre_sede" class="form-label">Nombre de la Sede</label>
|
||||||
|
<input type="text" class="form-control" id="nombre_sede" name="nombre_sede" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" name="add_sede" class="btn btn-primary">Añadir Sede</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-7">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header"><h5 class="card-title mb-0">Sedes Existentes</h5></div>
|
||||||
|
<div class="card-body">
|
||||||
|
<ul class="list-group">
|
||||||
|
<?php foreach ($sedes as $sede): ?>
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
<?= htmlspecialchars($sede['nombre']) ?>
|
||||||
|
<form action="panel_inventario.php" method="POST" onsubmit="return confirm('¿Estás seguro de que quieres eliminar esta sede?');">
|
||||||
|
<input type="hidden" name="sede_id" value="<?= $sede['id'] ?>">
|
||||||
|
<button type="submit" name="delete_sede" class="btn btn-danger btn-sm">Eliminar</button>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php if (empty($sedes)): ?>
|
||||||
|
<li class="list-group-item">No hay sedes registradas.</li>
|
||||||
|
<?php endif; ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
// We need to re-include the header to update the title dynamically
|
<script>
|
||||||
if (isset($pageTitle)) {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
echo "<script>document.title = '" . htmlspecialchars($pageTitle) . "';</script>";
|
const createChart = (ctx, type, data, options) => {
|
||||||
echo "<script>document.querySelector('.content h1').textContent = '" . htmlspecialchars($pageTitle) . "';</script>";
|
if (!ctx) return;
|
||||||
}
|
new Chart(ctx, { type, data, options });
|
||||||
require_once 'layout_footer.php';
|
};
|
||||||
?>
|
|
||||||
|
const chartColors = [
|
||||||
|
'rgba(255, 99, 132, 0.7)', 'rgba(54, 162, 235, 0.7)', 'rgba(255, 206, 86, 0.7)',
|
||||||
|
'rgba(75, 192, 192, 0.7)', 'rgba(153, 102, 255, 0.7)'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Gráfico Productos por Agotarse
|
||||||
|
const ctxAgotarse = document.getElementById('chartAgotarse')?.getContext('2d');
|
||||||
|
const productosAgotarse = <?php echo json_encode($productos_por_agotarse); ?>;
|
||||||
|
if (ctxAgotarse && productosAgotarse.length > 0) {
|
||||||
|
createChart(ctxAgotarse, 'doughnut', {
|
||||||
|
labels: productosAgotarse.map(p => p.nombre),
|
||||||
|
datasets: [{
|
||||||
|
label: 'Unidades',
|
||||||
|
data: productosAgotarse.map(p => p.unidades_disponibles),
|
||||||
|
backgroundColor: chartColors,
|
||||||
|
}]
|
||||||
|
}, { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'bottom' } } });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gráfico Top 5 Productos con más Stock
|
||||||
|
const ctxMasStock = document.getElementById('chartMasStock')?.getContext('2d');
|
||||||
|
const productosMasStock = <?php echo json_encode($productos_mas_stock); ?>;
|
||||||
|
if (ctxMasStock && productosMasStock.length > 0) {
|
||||||
|
createChart(ctxMasStock, 'doughnut', {
|
||||||
|
labels: productosMasStock.map(p => p.nombre),
|
||||||
|
datasets: [{
|
||||||
|
label: 'Unidades',
|
||||||
|
data: productosMasStock.map(p => p.unidades_disponibles),
|
||||||
|
backgroundColor: chartColors.slice().reverse(),
|
||||||
|
}]
|
||||||
|
}, { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'bottom' } } });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mantener la pestaña activa después de recargar la página
|
||||||
|
const activeTab = localStorage.getItem('activeInventoryTab');
|
||||||
|
if (activeTab) {
|
||||||
|
const tabTrigger = new bootstrap.Tab(document.querySelector(activeTab));
|
||||||
|
tabTrigger.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
const tabElms = document.querySelectorAll('button[data-bs-toggle="tab"]');
|
||||||
|
tabElms.forEach(function(tabElm) {
|
||||||
|
tabElm.addEventListener('shown.bs.tab', function (event) {
|
||||||
|
localStorage.setItem('activeInventoryTab', event.target.getAttribute('data-bs-target'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<?php include 'layout_footer.php'; ?>
|
||||||
Loading…
x
Reference in New Issue
Block a user