223 lines
8.1 KiB
PHP
223 lines
8.1 KiB
PHP
<?php
|
|
session_start();
|
|
require_once 'db/config.php';
|
|
require_once 'layout_header.php';
|
|
|
|
$pdo = db();
|
|
|
|
// Fetch banner text
|
|
$stmt_banner = $pdo->prepare('SELECT valor FROM configuracion WHERE clave = ?');
|
|
$stmt_banner->execute(['banner_text']);
|
|
$banner_text = $stmt_banner->fetchColumn();
|
|
if (empty($banner_text)) {
|
|
$banner_text = '¡Define tu frase motivacional en la sección de Información de Producto!';
|
|
}
|
|
|
|
// Fetch Kanban columns
|
|
$stmt_columns = $pdo->query('SELECT id, nombre FROM kanban_columns ORDER BY orden ASC');
|
|
$columns = $stmt_columns->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
// If no columns exist, create default ones
|
|
if (empty($columns)) {
|
|
$default_columns = ['Backlog', 'En Proceso', 'Hecho'];
|
|
$stmt_insert = $pdo->prepare('INSERT INTO kanban_columns (nombre, orden) VALUES (?, ?)');
|
|
foreach ($default_columns as $index => $name) {
|
|
$stmt_insert->execute([$name, $index + 1]);
|
|
}
|
|
// Re-fetch columns
|
|
$stmt_columns = $pdo->query('SELECT id, nombre FROM kanban_columns ORDER BY orden ASC');
|
|
$columns = $stmt_columns->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
// Fetch info cards and group them by column
|
|
$stmt_cards = $pdo->query('
|
|
SELECT
|
|
ip.id,
|
|
ip.texto_informativo,
|
|
ip.imagen_url,
|
|
ip.column_id,
|
|
p.nombre as producto_nombre
|
|
FROM
|
|
info_productos ip
|
|
LEFT JOIN
|
|
products p ON ip.producto_id = p.id
|
|
ORDER BY
|
|
ip.id ASC
|
|
');
|
|
$cards = $stmt_cards->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
|
|
|
|
|
|
$cards_by_column = [];
|
|
foreach ($cards as $card) {
|
|
$column_id = $card['column_id'] ?: 'unassigned';
|
|
$cards_by_column[$column_id][] = $card;
|
|
}
|
|
|
|
?>
|
|
|
|
<style>
|
|
@keyframes marquee {
|
|
0% { transform: translateX(-100%); }
|
|
100% { transform: translateX(100%); }
|
|
}
|
|
.motivational-banner {
|
|
background-color: rgba(255, 255, 255, 0.2);
|
|
color: #333;
|
|
padding: 15px 0;
|
|
margin: 0 auto 20px auto;
|
|
border-radius: 8px;
|
|
max-width: 80%;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
font-style: italic;
|
|
font-weight: 500;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
}
|
|
.motivational-banner p {
|
|
display: inline-block;
|
|
padding-left: 100%;
|
|
animation: marquee 15s linear infinite;
|
|
margin: 0;
|
|
}
|
|
.kanban-board {
|
|
display: flex;
|
|
overflow-x: auto;
|
|
overflow-y: hidden;
|
|
padding: 20px 10px;
|
|
background: linear-gradient(to right, #e8f5e9, #c8e6c9);
|
|
border-radius: 8px;
|
|
height: calc(100vh - 200px);
|
|
}
|
|
.kanban-column {
|
|
flex: 1 0 300px;
|
|
margin: 0 10px;
|
|
background-color: rgba(255, 255, 255, 0.7);
|
|
backdrop-filter: blur(5px);
|
|
border-radius: 8px;
|
|
padding: 10px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
max-height: 100%;
|
|
}
|
|
.kanban-cards-container {
|
|
overflow-y: auto;
|
|
flex-grow: 1;
|
|
padding-right: 5px;
|
|
}
|
|
.kanban-column-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 15px;
|
|
}
|
|
.kanban-column-header h5 {
|
|
font-size: 1rem;
|
|
font-weight: bold;
|
|
margin: 0;
|
|
}
|
|
.kanban-card {
|
|
background-color: #fff;
|
|
border-radius: 3px;
|
|
box-shadow: 0 1px 0 rgba(9,30,66,.25);
|
|
padding: 10px;
|
|
margin-bottom: 10px;
|
|
}
|
|
.kanban-card img {
|
|
max-width: 100%;
|
|
border-radius: 3px;
|
|
}
|
|
</style>
|
|
|
|
<div class="container-fluid mt-4">
|
|
<div class="motivational-banner">
|
|
<p><?php echo htmlspecialchars($banner_text); ?></p>
|
|
</div>
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<div>
|
|
<h2>Tablero Kanban</h2>
|
|
<p>Visualiza el flujo de trabajo de la información de tus productos.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="kanban-board">
|
|
<?php foreach ($columns as $column) : ?>
|
|
<div class="kanban-column" data-column-id="<?= $column['id'] ?>">
|
|
<div class="kanban-column-header">
|
|
<h5><?= htmlspecialchars($column['nombre']) ?></h5>
|
|
</div>
|
|
<div class="kanban-cards-container">
|
|
<?php if (isset($cards_by_column[$column['id']])) : ?>
|
|
<?php foreach ($cards_by_column[$column['id']] as $card) : ?>
|
|
<div class="kanban-card" data-card-id="<?= $card['id'] ?>">
|
|
<?php if (!empty($card['imagen_url'])) : ?>
|
|
<img src="<?= htmlspecialchars($card['imagen_url']) ?>" class="card-img-top" alt="Imagen del producto">
|
|
<?php endif; ?>
|
|
<div class="card-body" style="padding: 10px 0 0 0;">
|
|
<?php if (!empty($card['producto_nombre'])) : ?>
|
|
<h6 class="card-title" style="margin-bottom: 5px; font-weight: bold;"><?= htmlspecialchars($card['producto_nombre']) ?></h6>
|
|
<?php endif; ?>
|
|
<p class="card-text" id="texto-info-<?= $card['id'] ?>" style="font-size: 0.9rem;"><?= nl2br(htmlspecialchars($card['texto_informativo'])) ?></p>
|
|
<button class="btn btn-sm btn-outline-secondary mt-2" onclick="copiarTexto(this, 'texto-info-<?= $card['id'] ?>')">
|
|
<i class="fas fa-copy"></i> Copiar Texto
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
|
|
<!-- Unassigned column -->
|
|
<div class="kanban-column" data-column-id="unassigned">
|
|
<div class="kanban-column-header">
|
|
<h5>Sin Asignar</h5>
|
|
</div>
|
|
<div class="kanban-cards-container">
|
|
<?php if (isset($cards_by_column['unassigned'])) : ?>
|
|
<?php foreach ($cards_by_column['unassigned'] as $card) : ?>
|
|
<div class="kanban-card" data-card-id="<?= $card['id'] ?>">
|
|
<?php if (!empty($card['imagen_url'])) : ?>
|
|
<img src="<?= htmlspecialchars($card['imagen_url']) ?>" class="card-img-top" alt="Imagen del producto">
|
|
<?php endif; ?>
|
|
<div class="card-body" style="padding: 10px 0 0 0;">
|
|
<?php if (!empty($card['producto_nombre'])) : ?>
|
|
<h6 class="card-title" style="margin-bottom: 5px; font-weight: bold;"><?= htmlspecialchars($card['producto_nombre']) ?></h6>
|
|
<?php endif; ?>
|
|
<p class="card-text" id="texto-info-<?= $card['id'] ?>" style="font-size: 0.9rem;"><?= nl2br(htmlspecialchars($card['texto_informativo'])) ?></p>
|
|
<button class="btn btn-sm btn-outline-secondary mt-2" onclick="copiarTexto(this, 'texto-info-<?= $card['id'] ?>')">
|
|
<i class="fas fa-copy"></i> Copiar Texto
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
function copiarTexto(button, elementId) {
|
|
const textToCopy = document.getElementById(elementId).innerText;
|
|
navigator.clipboard.writeText(textToCopy).then(() => {
|
|
const originalIcon = 'fas fa-copy';
|
|
const originalText = ' Copiar Texto';
|
|
|
|
button.querySelector('i').className = 'fas fa-check';
|
|
button.lastChild.nodeValue = ' ¡Copiado!';
|
|
|
|
setTimeout(() => {
|
|
button.querySelector('i').className = originalIcon;
|
|
button.lastChild.nodeValue = originalText;
|
|
}, 2000);
|
|
}).catch(err => {
|
|
console.error('Error al copiar texto: ', err);
|
|
alert('Error al copiar texto.');
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<?php require_once 'layout_footer.php'; ?>
|