Tabla Responsiva bootstrap 5 tabla categorias
vista tabla resolucion pantallas pc escritorio
vista tabla resolucion pantallas mobiles
Aquí tienes una versión simplificada que mantiene tu estructura actual pero la hace completamente responsiva:
<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Tabla Responsiva</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"> <style> .img-producto { width: 50px; height: 50px; object-fit: cover; border-radius: 4px; } /* Estilos para móviles */ @media (max-width: 768px) { .table-responsive { border: 1px solid #dee2e6; border-radius: 0.375rem; } .mobile-hidden { display: none; } .mobile-product-card { border-bottom: 1px solid #dee2e6; padding: 1rem; background: white; } .mobile-product-card:last-child { border-bottom: none; } .mobile-product-info { display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem; } .mobile-actions { display: flex; gap: 0.5rem; justify-content: center; } .mobile-actions .btn { flex: 1; max-width: 120px; } } </style> </head> <body> <!-- Vista Desktop (se muestra en pantallas grandes) --> <div class="d-none d-md-block"> <div class="table-responsive"> <table class="table table-striped table-hover align-middle"> <thead class="table-dark"> <tr> <th>Id</th> <th>Imagen</th> <th>Nombre</th> <th>Accion</th> <th>Accion</th> </tr> </thead> <tbody id="tabla-productos"> <tr> <td colspan="5" class="text-center"> <div class="spinner-border text-primary" role="status"> <span class="visually-hidden">Cargando...</span> </div> </td> </tr> </tbody> </table> </div> </div> <!-- Vista Mobile (se muestra en pantallas pequeñas) --> <div class="d-md-none" id="mobile-productos"> <div class="table-responsive"> <div class="text-center py-3"> <div class="spinner-border text-primary" role="status"> <span class="visually-hidden">Cargando...</span> </div> </div> </div> </div> <script> let paginaActual = 1; let terminoBusqueda = ''; let categoriaSeleccionada = ''; function cargarProductos(pagina = 1, busqueda = '', categoria = '') { const tbody = document.getElementById('tabla-productos'); const mobileContainer = document.getElementById('mobile-productos'); // Mostrar loading en ambas vistas tbody.innerHTML = '<tr><td colspan="5" class="text-center"><div class="spinner-border text-primary"></div></td></tr>'; mobileContainer.innerHTML = '<div class="text-center py-3"><div class="spinner-border text-primary"></div></div>'; fetch('productos.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ busqueda, categoria, pagina }) }) .then(response => response.json()) .then(data => { if (!data.productos || !Array.isArray(data.productos)) { tbody.innerHTML = '<tr><td colspan="5" class="text-center text-muted">No hay productos</td></tr>'; mobileContainer.innerHTML = '<div class="text-center text-muted py-3">No hay productos</div>'; return; } // Renderizar vista Desktop tbody.innerHTML = data.productos.map(p => ` <tr> <td>${p.id}</td> <td> <img src="fotos/${p.foto}" alt="${p.nombre}" class="img-producto" onerror="this.src='noimagen.png'"> </td> <td>${p.nombre}</td> <td> <button class="btn btn-sm btn-outline-primary me-1" onclick="editarProducto(${p.id})"> Editar </button> </td> <td> <button class="btn btn-sm btn-outline-danger" onclick="eliminarProducto(${p.id})"> Eliminar </button> </td> </tr> `).join(''); // Renderizar vista Mobile mobileContainer.innerHTML = data.productos.map(p => ` <div class="mobile-product-card"> <div class="mobile-product-info"> <img src="fotos/${p.foto}" alt="${p.nombre}" class="img-producto" onerror="this.src='noimagen.png'"> <div> <strong class="d-block">${p.nombre}</strong> <small class="text-muted">ID: ${p.id}</small> </div> </div> <div class="mobile-actions"> <button class="btn btn-sm btn-outline-primary" onclick="editarProducto(${p.id})"> Editar </button> <button class="btn btn-sm btn-outline-danger" onclick="eliminarProducto(${p.id})"> Eliminar </button> </div> </div> `).join(''); // Actualizar paginación paginaActual = data.pagina_actual; terminoBusqueda = busqueda; categoriaSeleccionada = categoria; document.getElementById('info-pagina').textContent = `Página ${data.pagina_actual} de ${data.total_paginas}`; document.getElementById('btn-anterior').disabled = data.pagina_actual <= 1; document.getElementById('btn-siguiente').disabled = data.pagina_actual >= data.total_paginas; }) .catch(() => { tbody.innerHTML = '<tr><td colspan="5" class="text-center text-danger">Error al cargar</td></tr>'; mobileContainer.innerHTML = '<div class="text-center text-danger py-3">Error al cargar</div>'; }); } // Funciones de ejemplo (mantienen tu código original) function editarProducto(id) { console.log('Editar producto:', id); // Tu lógica de edición aquí } function eliminarProducto(id) { if (confirm('¿Estás seguro de eliminar este producto?')) { console.log('Eliminar producto:', id); // Tu lógica de eliminación aquí } } // Cargar productos al iniciar document.addEventListener('DOMContentLoaded', function() { cargarProductos(); }); </script> </body> </html>
Tabla Responsiva bootstrap 5 tabla productos
vista tabla resolucion pantallas pc escritorio<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tabla Responsiva</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
.img-producto {
width: 50px;
height: 50px;
object-fit: cover;
border-radius: 4px;
}
/* Estilos para móviles */
@media (max-width: 768px) {
.table-responsive {
border: 1px solid #dee2e6;
border-radius: 0.375rem;
}
.mobile-product-card {
border-bottom: 1px solid #dee2e6;
padding: 1rem;
background: white;
}
.mobile-product-card:last-child {
border-bottom: none;
}
.mobile-product-header {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1rem;
}
.mobile-product-details {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5rem;
margin-bottom: 1rem;
}
.mobile-detail-item {
display: flex;
flex-direction: column;
}
.mobile-detail-label {
font-size: 0.75rem;
color: #6c757d;
font-weight: 500;
}
.mobile-detail-value {
font-size: 0.875rem;
font-weight: 500;
}
.mobile-actions {
display: flex;
gap: 0.5rem;
justify-content: center;
}
.mobile-actions .btn {
flex: 1;
max-width: 120px;
}
}
</style>
</head>
<body>
<!-- Vista Desktop (se muestra en pantallas grandes) -->
<div class="d-none d-md-block">
<div class="table-responsive">
<table class="table table-striped table-hover align-middle">
<thead class="table-dark">
<tr>
<th>Id</th>
<th>Foto</th>
<th>Cod.Barra</th>
<th>Nombre</th>
<th>Precio</th>
<th>Categoría</th>
<th>Accion</th>
<th>Accion</th>
</tr>
</thead>
<tbody id="tabla-productos">
<tr>
<td colspan="8" class="text-center">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Cargando...</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Vista Mobile (se muestra en pantallas pequeñas) -->
<div class="d-md-none" id="mobile-productos">
<div class="table-responsive">
<div class="text-center py-3">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Cargando...</span>
</div>
</div>
</div>
</div>
<script>
let paginaActual = 1;
let terminoBusqueda = '';
let categoriaSeleccionada = '';
function cargarProductos(pagina = 1, busqueda = '', categoria = '') {
const tbody = document.getElementById('tabla-productos');
const mobileContainer = document.getElementById('mobile-productos');
// Mostrar loading en ambas vistas
tbody.innerHTML = '<tr><td colspan="8" class="text-center"><div class="spinner-border text-primary"></div></td></tr>';
mobileContainer.innerHTML = '<div class="text-center py-3"><div class="spinner-border text-primary"></div></div>';
fetch('productos.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ busqueda, categoria, pagina })
})
.then(response => response.json())
.then(data => {
if (!data.productos || !Array.isArray(data.productos)) {
tbody.innerHTML = '<tr><td colspan="8" class="text-center text-muted">No hay productos</td></tr>';
mobileContainer.innerHTML = '<div class="text-center text-muted py-3">No hay productos</div>';
return;
}
// Renderizar vista Desktop
tbody.innerHTML = data.productos.map(producto => `
<tr>
<td>${producto.id}</td>
<td>
<img src="fotos/${producto.foto}" alt="${producto.nombre}" class="img-producto"
onerror="this.src='noimagen.png'">
</td>
<td>
${producto.barra}
<button class="btn btn-sm btn-outline-primary me-1" onclick="generarEtiqueta(${producto.barra}, '${producto.nombre.replace(/'/g, "\\'")}')">
Cod.Barra
</button>
</td>
<td>${producto.nombre}</td>
<td>$ ${parseFloat(producto.precio).toFixed(2)}</td>
<td>${producto.categoria || '—'}</td>
<td>
<button class="btn btn-sm btn-outline-primary me-1" onclick="editarProducto(${producto.id})">
Editar
</button>
</td>
<td>
<button class="btn btn-sm btn-outline-danger" onclick="eliminarProducto(${producto.id})">
Eliminar
</button>
</td>
</tr>
`).join('');
// Renderizar vista Mobile
mobileContainer.innerHTML = data.productos.map(producto => `
<div class="mobile-product-card">
<div class="mobile-product-header">
<img src="fotos/${producto.foto}" alt="${producto.nombre}" class="img-producto"
onerror="this.src='noimagen.png'">
<div>
<strong class="d-block">${producto.nombre}</strong>
<small class="text-muted">ID: ${producto.id}</small>
</div>
</div>
<div class="mobile-product-details">
<div class="mobile-detail-item">
<span class="mobile-detail-label">Código Barra</span>
<span class="mobile-detail-value">${producto.barra}</span>
</div>
<div class="mobile-detail-item">
<span class="mobile-detail-label">Precio</span>
<span class="mobile-detail-value">$ ${parseFloat(producto.precio).toFixed(2)}</span>
</div>
<div class="mobile-detail-item">
<span class="mobile-detail-label">Categoría</span>
<span class="mobile-detail-value">${producto.categoria || '—'}</span>
</div>
</div>
<div class="mobile-actions">
<button class="btn btn-sm btn-outline-primary" onclick="generarEtiqueta(${producto.barra}, '${producto.nombre.replace(/'/g, "\\'")}')">
Cod.Barra
</button>
<button class="btn btn-sm btn-outline-primary" onclick="editarProducto(${producto.id})">
Editar
</button>
<button class="btn btn-sm btn-outline-danger" onclick="eliminarProducto(${producto.id})">
Eliminar
</button>
</div>
</div>
`).join('');
// Actualizar paginación
actualizarPaginacion(data);
})
.catch(error => {
console.error('Error al cargar productos:', error);
tbody.innerHTML = '<tr><td colspan="8" class="text-center text-danger">Error al cargar los productos</td></tr>';
mobileContainer.innerHTML = '<div class="text-center text-danger py-3">Error al cargar los productos</div>';
});
}
function actualizarPaginacion(data) {
paginaActual = data.pagina_actual;
terminoBusqueda = busqueda;
categoriaSeleccionada = categoria;
document.getElementById('info-pagina').textContent = `Página ${data.pagina_actual} de ${data.total_paginas}`;
document.getElementById('btn-anterior').disabled = data.pagina_actual <= 1;
document.getElementById('btn-siguiente').disabled = data.pagina_actual >= data.total_paginas;
}
// Funciones de ejemplo
function generarEtiqueta(codigoBarra, nombre) {
console.log('Generar etiqueta para:', codigoBarra, nombre);
// Tu lógica de generación de etiqueta aquí
}
function editarProducto(id) {
console.log('Editar producto:', id);
// Tu lógica de edición aquí
}
function eliminarProducto(id) {
if (confirm('¿Estás seguro de eliminar este producto?')) {
console.log('Eliminar producto:', id);
// Tu lógica de eliminación aquí
}
}
// Cargar productos al iniciar
document.addEventListener('DOMContentLoaded', function() {
cargarProductos();
});
</script>
</body>
</html>




Comentarios
Publicar un comentario