Files
2026-06-30 15:00:32 -03:00

429 lines
16 KiB
PHP

<?php
include("../db.php");
if (!isset($_SESSION['rol']) || $_SESSION['rol'] !== 'admin') {
header("Location: ../login.php?error=acceso_denegado");
exit();
}
$mensaje = "";
$tipo_mensaje = "";
if (isset($_GET['status'])) {
if ($_GET['status'] === 'ok_manual') {
$mensaje = "¡Producto agregado con éxito!";
$tipo_mensaje = "success";
} elseif ($_GET['status'] === 'ok_csv') {
$cant = isset($_GET['cant']) ? (int)$_GET['cant'] : 0;
$mensaje = "Catálogo actualizado — $cant productos procesados desde el CSV.";
$tipo_mensaje = "success";
} elseif ($_GET['status'] === 'error') {
$mensaje = "Hubo un problema al procesar la solicitud. Verificá los formatos de los datos.";
$tipo_mensaje = "error";
}
}
$query_productos = "SELECT id, nombre, precio, stock, imagen, categoria FROM productos WHERE activo = 1 ORDER BY categoria ASC, nombre ASC";
$res_productos = mysqli_query($conexion, $query_productos);
$todos_productos = mysqli_fetch_all($res_productos, MYSQLI_ASSOC);
// Categorías únicas para los filtros
$categorias_unicas = array_unique(array_column($todos_productos, 'categoria'));
sort($categorias_unicas);
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Inventario - La Pecosa</title>
<link rel="stylesheet" href="../css/all.min.css">
<link rel="stylesheet" href="admin_style.css">
<style>
/* ── ALERT ── */
.alert-ui {
padding: 13px 16px;
border-radius: 8px;
margin-bottom: 22px;
font-weight: 600;
font-size: 0.875rem;
display: flex;
align-items: center;
gap: 8px;
}
.alert-ui.success { background: #f0fdf4; color: #166534; border: 1px solid #bbf7d0; }
.alert-ui.error { background: #fef2f2; color: #991b1b; border: 1px solid #fee2e2; }
/* ── GRID FORMULARIOS ── */
.grid-forms {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin-bottom: 28px;
}
@media (max-width: 860px) { .grid-forms { grid-template-columns: 1fr; } }
.form-card {
background: #fff;
border: 1px solid #e5e7eb;
border-radius: 12px;
padding: 22px 24px;
}
.form-card-title {
font-size: 0.95rem;
font-weight: 700;
color: #111827;
margin-bottom: 18px;
display: flex;
align-items: center;
gap: 8px;
}
.form-card-title .fc-icon {
width: 28px;
height: 28px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.8rem;
flex-shrink: 0;
}
.fc-icon.red { background: #fee2e2; color: #dc2626; }
.fc-icon.green { background: #dcfce7; color: #16a34a; }
/* ── FORM FIELDS ── */
.fg { margin-bottom: 13px; }
.fg label {
display: block;
font-size: 0.8rem;
font-weight: 600;
color: #374151;
margin-bottom: 5px;
}
.fg input[type="text"],
.fg input[type="number"],
.fg input[type="file"],
.fg select {
width: 100%;
padding: 9px 11px;
border: 1px solid #d1d5db;
border-radius: 7px;
font-size: 0.875rem;
outline: none;
transition: border-color 0.2s;
box-sizing: border-box;
}
.fg input:focus, .fg select:focus { border-color: #dc2626; }
.fg-row { display: flex; gap: 12px; }
.fg-row .fg { flex: 1; }
.csv-hint {
background: #f0fdf4;
border-left: 3px solid #16a34a;
border-radius: 0 6px 6px 0;
padding: 10px 12px;
font-size: 0.8rem;
color: #166534;
margin-bottom: 14px;
line-height: 1.5;
}
.csv-hint code {
display: block;
margin-top: 4px;
font-family: monospace;
font-size: 0.78rem;
letter-spacing: 0.2px;
}
.btn-submit {
width: 100%;
padding: 11px;
border: none;
border-radius: 7px;
font-weight: 700;
font-size: 0.9rem;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 7px;
transition: opacity 0.15s, transform 0.15s;
margin-top: 4px;
}
.btn-submit:hover { opacity: 0.88; transform: translateY(-1px); }
.btn-submit.red { background: #dc2626; color: #fff; }
.btn-submit.green { background: #16a34a; color: #fff; }
/* ── SECCIÓN CATÁLOGO ── */
.catalogo-card {
background: #fff;
border: 1px solid #e5e7eb;
border-radius: 12px;
overflow: hidden;
}
.catalogo-header {
padding: 16px 22px;
border-bottom: 1px solid #f3f4f6;
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 12px;
}
.catalogo-header h2 {
font-size: 1rem;
font-weight: 700;
color: #111827;
display: flex;
align-items: center;
gap: 7px;
margin: 0;
}
.catalogo-header h2 i { color: #dc2626; }
/* ── FILTROS DE CATEGORÍA ── */
.cat-filters {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.cat-btn {
background: #f3f4f6;
border: 1px solid #e5e7eb;
border-radius: 20px;
padding: 5px 13px;
font-size: 0.78rem;
font-weight: 600;
color: #4b5563;
cursor: pointer;
transition: all 0.15s;
white-space: nowrap;
}
.cat-btn:hover { background: #fee2e2; border-color: #fca5a5; color: #dc2626; }
.cat-btn.active { background: #dc2626; border-color: #dc2626; color: #fff; }
/* ── CONTADOR ── */
.cat-count {
font-size: 0.78rem;
color: #9ca3af;
padding: 6px 22px;
border-bottom: 1px solid #f3f4f6;
}
#cat-count-num { font-weight: 700; color: #374151; }
/* ── TABLA ── */
.admin-table td { font-size: 0.875rem; vertical-align: middle; }
.admin-table tr:last-child td { border-bottom: none; }
.img-preview {
width: 46px;
height: 46px;
object-fit: cover;
border-radius: 7px;
border: 1px solid #e5e7eb;
}
.cat-chip {
background: #f1f5f9;
color: #475569;
padding: 3px 8px;
border-radius: 4px;
font-size: 0.78rem;
font-weight: 600;
}
.stock-ok { color: #374151; }
.stock-warn { color: #92400e; font-weight: 700; }
.stock-zero { color: #991b1b; font-weight: 700; }
tr.sin-stock { background: #fff5f5; }
.no-results {
text-align: center;
color: #9ca3af;
padding: 40px 14px;
font-size: 0.9rem;
}
.no-results i { font-size: 1.5rem; display: block; margin-bottom: 8px; }
</style>
</head>
<body>
<?php include("sidebar.php"); ?>
<div class="main-content">
<div class="page-header">
<h1><i class="fa-solid fa-boxes-stacked"></i> Gestión de inventario y menú</h1>
</div>
<?php if (!empty($mensaje)): ?>
<div class="alert-ui <?php echo $tipo_mensaje; ?>">
<i class="fa-solid <?php echo $tipo_mensaje === 'success' ? 'fa-circle-check' : 'fa-circle-exclamation'; ?>"></i>
<?php echo $mensaje; ?>
</div>
<?php endif; ?>
<!-- FORMULARIOS -->
<div class="grid-forms">
<!-- Agregar producto manual -->
<div class="form-card">
<div class="form-card-title">
<span class="fc-icon red"><i class="fa-solid fa-plus"></i></span>
Agregar un producto
</div>
<form action="procesar_manual.php" method="POST" enctype="multipart/form-data">
<div class="fg">
<label>Nombre del producto</label>
<input type="text" name="nombre" placeholder="Ej: Pizza especial La Pecosa" required>
</div>
<div class="fg">
<label>Categoría</label>
<select name="categoria" required>
<option value="Carne">Carne</option>
<option value="Verdura">Verdura</option>
<option value="Vinoteca">Vinoteca</option>
<option value="Bebidas">Bebidas</option>
<option value="Lácteos">Lácteos</option>
<option value="Panadería">Panadería</option>
<option value="Limpieza">Limpieza</option>
<option value="Almacén">Almacén</option>
</select>
</div>
<div class="fg-row">
<div class="fg">
<label>Precio ($)</label>
<input type="number" name="precio" placeholder="4500" min="0" step="0.01" required>
</div>
<div class="fg">
<label>Stock inicial</label>
<input type="number" name="stock" placeholder="20" min="0" required>
</div>
</div>
<div class="fg">
<label>Foto del producto</label>
<input type="file" name="imagen" accept="image/*" required>
</div>
<button type="submit" class="btn-submit red">
<i class="fa-solid fa-floppy-disk"></i> Guardar en menú
</button>
</form>
</div>
<!-- Carga masiva CSV -->
<div class="form-card" style="display:flex; flex-direction:column; justify-content:space-between;">
<div>
<div class="form-card-title">
<span class="fc-icon green"><i class="fa-solid fa-file-csv"></i></span>
Carga masiva del catálogo (.csv)
</div>
<p style="font-size:0.855rem; color:#6b7280; line-height:1.55; margin-bottom:14px;">
Armá el Excel y guardalo como CSV para actualizar precios o stocks de forma masiva sin cargar producto por producto.
</p>
<div class="csv-hint">
<strong>Estructura de columnas requerida (separado por punto y coma):</strong>
<code>id ; nombre ; precio ; categoria ; imagen ; activo ; stock</code>
</div>
</div>
<form action="importar_csv.php" method="POST" enctype="multipart/form-data">
<div class="fg">
<label>Seleccionar archivo CSV</label>
<input type="file" name="archivo_csv" accept=".csv" required>
</div>
<button type="submit" class="btn-submit green">
<i class="fa-solid fa-upload"></i> Procesar catálogo
</button>
</form>
</div>
</div>
<!-- CATÁLOGO CON FILTROS -->
<div class="catalogo-card">
<div class="catalogo-header">
<h2><i class="fa-solid fa-list"></i> Productos en la plataforma</h2>
<div class="cat-filters">
<button class="cat-btn active" onclick="filtrarCat(this, 'todos')">Todos</button>
<?php foreach ($categorias_unicas as $cat): ?>
<button class="cat-btn" onclick="filtrarCat(this, '<?php echo htmlspecialchars($cat); ?>')">
<?php echo htmlspecialchars($cat); ?>
</button>
<?php endforeach; ?>
</div>
</div>
<div class="cat-count">
Mostrando <span id="cat-count-num"><?php echo count($todos_productos); ?></span> productos
</div>
<div style="overflow-x:auto;">
<table class="admin-table" id="tabla-productos">
<thead>
<tr>
<th>Foto</th>
<th>ID</th>
<th>Nombre</th>
<th>Categoría</th>
<th>Precio</th>
<th>Stock</th>
</tr>
</thead>
<tbody id="tbody-productos">
<?php foreach ($todos_productos as $prod):
$sin_stock = ($prod['stock'] <= 0);
$stock_clase = $sin_stock ? 'stock-zero' : ($prod['stock'] <= 5 ? 'stock-warn' : 'stock-ok');
?>
<tr class="prod-row <?php echo $sin_stock ? 'sin-stock' : ''; ?>"
data-cat="<?php echo htmlspecialchars($prod['categoria']); ?>">
<td>
<img src="../<?php echo htmlspecialchars($prod['imagen']); ?>"
class="img-preview" alt="<?php echo htmlspecialchars($prod['nombre']); ?>">
</td>
<td style="color:#9ca3af;">#<?php echo $prod['id']; ?></td>
<td><strong><?php echo htmlspecialchars($prod['nombre']); ?></strong></td>
<td><span class="cat-chip"><?php echo htmlspecialchars($prod['categoria']); ?></span></td>
<td>$<?php echo number_format($prod['precio'], 2, ',', '.'); ?></td>
<td class="<?php echo $stock_clase; ?>">
<?php if ($sin_stock): ?>
<i class="fa-solid fa-triangle-exclamation"></i> Sin stock
<?php elseif ($prod['stock'] <= 5): ?>
<i class="fa-solid fa-circle-exclamation"></i> <?php echo $prod['stock']; ?> un.
<?php else: ?>
<?php echo $prod['stock']; ?> un.
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div id="no-results" class="no-results" style="display:none;">
<i class="fa-solid fa-box-open"></i>
No hay productos en esta categoría.
</div>
</div>
</div>
</div>
<script>
function filtrarCat(btn, cat) {
// Actualizar botón activo
document.querySelectorAll('.cat-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
const filas = document.querySelectorAll('.prod-row');
let visible = 0;
filas.forEach(fila => {
const mostrar = cat === 'todos' || fila.dataset.cat === cat;
fila.style.display = mostrar ? '' : 'none';
if (mostrar) visible++;
});
document.getElementById('cat-count-num').textContent = visible;
document.getElementById('no-results').style.display = visible === 0 ? 'block' : 'none';
}
</script>
</body>
</html>