40097-vm/marketing_produccion.php
2026-05-10 16:22:58 +00:00

594 lines
32 KiB
PHP

<?php
$pageTitle = "Producción de Video";
include 'db/config.php';
include 'layout_header.php';
$db = db();
// Obtener productos para el select
$stmt_products = $db->query("SELECT id, nombre FROM products ORDER BY nombre ASC");
$productos = $stmt_products->fetchAll(PDO::FETCH_ASSOC);
// Obtener videos existentes
$stmt_videos = $db->query("SELECT mv.*, p.nombre as nombre_producto
FROM marketing_videos mv
LEFT JOIN products p ON mv.producto_id = p.id
ORDER BY mv.orden ASC, mv.fecha_creacion DESC");
$videos = $stmt_videos->fetchAll(PDO::FETCH_ASSOC);
?>
<style>
.table-excel {
font-size: 0.85rem;
}
.table-excel th {
background-color: #f8f9fa;
border-bottom: 2px solid #dee2e6;
white-space: nowrap;
text-transform: uppercase;
font-weight: 600;
color: #495057;
}
.table-excel td {
vertical-align: middle;
border-bottom: 1px solid #eee;
}
.img-preview {
width: 50px;
height: 50px;
object-fit: cover;
border-radius: 4px;
cursor: pointer;
}
.link-icon {
font-size: 1.1rem;
color: #0d6efd;
}
.link-icon:hover {
color: #0a58ca;
}
.status-badge {
font-size: 0.75rem;
padding: 0.35em 0.65em;
}
.editable:hover {
background-color: #f1f3f5;
cursor: pointer;
}
.inline-edit-input {
width: 100%;
padding: 2px 5px;
font-size: 0.85rem;
border: 1px solid #0d6efd;
border-radius: 3px;
}
</style>
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<h2 class="mb-0">Producción de Video</h2>
<p class="text-muted small">Vista de control estilo Excel</p>
</div>
<div>
<a href="marketing_assets.php" class="btn btn-outline-secondary me-2">
<i class="fas fa-folder-open"></i> Biblioteca de Assets
</a>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#nuevoVideoModal">
<i class="fas fa-plus"></i> Nuevo Pedido
</button>
</div>
</div>
<?php if (isset($_GET['success'])): ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
¡Operación realizada con éxito!
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<div class="card shadow-sm border-0">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover table-excel mb-0">
<thead>
<tr>
<th class="text-center">Orden</th>
<th>Fecha Entrega</th>
<th>Producto</th>
<th class="text-center">Imagen</th>
<th>Material</th>
<th>Ángulo</th>
<th class="text-center">Insp. Landing</th>
<th class="text-center">Insp. Video</th>
<th class="text-center">Link Video</th>
<th class="text-center">Link Landing</th>
<th class="text-center">Link Flyer</th>
<th class="text-center">Estado</th>
<th class="text-center">Acción</th>
</tr>
</thead>
<tbody>
<?php if (empty($videos)): ?>
<tr>
<td colspan="11" class="text-center py-4 text-muted">No hay pedidos registrados.</td>
</tr>
<?php else: ?>
<?php foreach ($videos as $v): ?>
<tr>
<td class="text-center fw-bold text-primary"><?php echo $v['orden']; ?></td>
<td>
<?php echo $v['fecha_entrega'] ? date('d/m/Y', strtotime($v['fecha_entrega'])) : '<span class="text-muted">-</span>'; ?>
</td>
<td class="fw-bold"><?php echo htmlspecialchars($v['nombre_producto'] ?: 'General'); ?></td>
<td class="text-center">
<?php if ($v['foto_producto']): ?>
<img src="<?php echo $v['foto_producto']; ?>" class="img-preview" alt="Ref" onclick="window.open(this.src)">
<?php else: ?>
<span class="text-muted small">Sin foto</span>
<?php endif; ?>
</td>
<td class="editable" data-id="<?php echo $v['id']; ?>" data-field="material">
<div class="text-truncate" style="max-width: 150px;" title="<?php echo htmlspecialchars($v['material']); ?>">
<?php echo htmlspecialchars($v['material'] ?: '-'); ?>
</div>
</td>
<td class="editable" data-id="<?php echo $v['id']; ?>" data-field="angulo_video">
<div class="text-truncate" style="max-width: 150px;" title="<?php echo htmlspecialchars($v['angulo_video']); ?>">
<?php echo htmlspecialchars($v['angulo_video'] ?: '-'); ?>
</div>
</td>
<td class="text-center">
<?php if ($v['link_inspiracion_landing']):
$links = explode(',', $v['link_inspiracion_landing']);
foreach ($links as $link):
$link = trim($link);
if (!$link) continue;
?>
<a href="<?php echo $link; ?>" target="_blank" class="link-icon d-inline-block me-1"><i class="fas fa-external-link-alt"></i></a>
<?php endforeach; ?>
<?php else: ?>
<span class="text-muted">-</span>
<?php endif; ?>
</td>
<td class="text-center">
<?php if ($v['link_inspiracion_video']):
$links = explode(',', $v['link_inspiracion_video']);
foreach ($links as $link):
$link = trim($link);
if (!$link) continue;
?>
<a href="<?php echo $link; ?>" target="_blank" class="link-icon text-danger d-inline-block me-1"><i class="fab fa-youtube"></i></a>
<?php endforeach; ?>
<?php else: ?>
<span class="text-muted">-</span>
<?php endif; ?>
</td>
<td class="text-center">
<?php if ($v['link_video']):
$links = explode(',', $v['link_video']);
foreach ($links as $link):
$link = trim($link);
if (!$link) continue;
?>
<a href="<?php echo $link; ?>" target="_blank" class="link-icon text-success d-inline-block me-1"><i class="fas fa-play-circle"></i></a>
<?php endforeach; ?>
<?php else: ?>
<span class="text-muted">-</span>
<?php endif; ?>
</td>
<td class="text-center">
<?php if ($v['link_landing']):
$links = explode(',', $v['link_landing']);
foreach ($links as $link):
$link = trim($link);
if (!$link) continue;
?>
<a href="<?php echo $link; ?>" target="_blank" class="link-icon text-info d-inline-block me-1"><i class="fas fa-globe"></i></a>
<?php endforeach; ?>
<?php else: ?>
<span class="text-muted">-</span>
<?php endif; ?>
</td>
<td class="text-center">
<?php if ($v['link_flyer']):
$links = explode(',', $v['link_flyer']);
foreach ($links as $link):
$link = trim($link);
if (!$link) continue;
?>
<a href="<?php echo $link; ?>" target="_blank" class="link-icon text-warning d-inline-block me-1"><i class="fas fa-file-image"></i></a>
<?php endforeach; ?>
<?php else: ?>
<span class="text-muted">-</span>
<?php endif; ?>
</td>
<td class="text-center editable" data-id="<?php echo $v['id']; ?>" data-field="estado">
<span class="badge status-badge <?php
echo $v['estado'] == 'PENDIENTE' ? 'bg-warning text-dark' :
($v['estado'] == 'EN PROCESO' ? 'bg-info' :
($v['estado'] == 'TERMINADO' ? 'bg-primary' :
($v['estado'] == 'OBSERVADO' ? 'bg-danger' :
($v['estado'] == 'APROBADO' ? 'bg-success' :
($v['estado'] == 'PUBLICADO' ? 'bg-dark' : 'bg-secondary')))));
?>">
<?php echo $v['estado']; ?>
</span>
</td>
<td class="text-center">
<button class="btn btn-sm btn-outline-primary" onclick="gestionarVideo(<?php echo htmlspecialchars(json_encode($v)); ?>)">
<i class="fas fa-edit"></i>
</button>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- Modal Nuevo Video -->
<div class="modal fade" id="nuevoVideoModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<form action="save_marketing_video.php" method="POST" enctype="multipart/form-data">
<div class="modal-header">
<h5 class="modal-title">Nuevo Pedido de Video</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row g-3">
<div class="col-md-2">
<label class="form-label">Orden</label>
<input type="number" name="orden" class="form-control" value="1">
</div>
<div class="col-md-5">
<label class="form-label">Fecha Entrega</label>
<input type="date" name="fecha_entrega" class="form-control">
</div>
<div class="col-md-5">
<label class="form-label">Producto</label>
<select name="producto_id" class="form-select">
<option value="">Seleccionar producto...</option>
<?php foreach ($productos as $p): ?>
<option value="<?php echo $p['id']; ?>"><?php echo htmlspecialchars($p['nombre']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6">
<label class="form-label">Imagen Referencia</label>
<input type="file" name="foto_producto" class="form-control" accept="image/*">
</div>
<div class="col-md-6">
<label class="form-label">Material</label>
<input type="text" name="material" class="form-control" placeholder="Ej: Acero, Plástico, etc.">
</div>
<div class="col-md-6">
<label class="form-label">Ángulo del Video</label>
<input type="text" name="angulo_video" class="form-control" placeholder="Ej: Cenital, 45 grados...">
</div>
<div class="col-md-6">
<label class="form-label d-flex justify-content-between">
Link Inspiración Landing
<button type="button" class="btn btn-sm btn-link p-0 text-decoration-none" onclick="addLinkInput('links_insp_landing_container', 'link_inspiracion_landing[]')">
<i class="fas fa-plus-circle"></i> Añadir otro
</button>
</label>
<div id="links_insp_landing_container">
<div class="input-group mb-2">
<input type="url" name="link_inspiracion_landing[]" class="form-control" placeholder="https://...">
<button class="btn btn-outline-danger" type="button" onclick="if(document.querySelectorAll('#links_insp_landing_container .input-group').length > 1) this.parentElement.remove()"><i class="fas fa-times"></i></button>
</div>
</div>
</div>
<div class="col-md-6">
<label class="form-label d-flex justify-content-between">
Link Inspiración Video
<button type="button" class="btn btn-sm btn-link p-0 text-decoration-none" onclick="addLinkInput('links_video_container', 'link_inspiracion_video[]')">
<i class="fas fa-plus-circle"></i> Añadir otro
</button>
</label>
<div id="links_video_container">
<div class="input-group mb-2">
<input type="url" name="link_inspiracion_video[]" class="form-control" placeholder="https://...">
<button class="btn btn-outline-danger" type="button" onclick="if(document.querySelectorAll('#links_video_container .input-group').length > 1) this.parentElement.remove()"><i class="fas fa-times"></i></button>
</div>
</div>
</div>
<div class="col-md-6">
<label class="form-label d-flex justify-content-between">
Link Video Final
<button type="button" class="btn btn-sm btn-link p-0 text-decoration-none" onclick="addLinkInput('links_video_final_container', 'link_video[]')">
<i class="fas fa-plus-circle"></i> Añadir otro
</button>
</label>
<div id="links_video_final_container">
<div class="input-group mb-2">
<input type="url" name="link_video[]" class="form-control" placeholder="https://...">
<button class="btn btn-outline-danger" type="button" onclick="if(document.querySelectorAll('#links_video_final_container .input-group').length > 1) this.parentElement.remove()"><i class="fas fa-times"></i></button>
</div>
</div>
</div>
<div class="col-md-6">
<label class="form-label d-flex justify-content-between">
Link de la Landing
<button type="button" class="btn btn-sm btn-link p-0 text-decoration-none" onclick="addLinkInput('links_landing_container', 'link_landing[]')">
<i class="fas fa-plus-circle"></i> Añadir otro
</button>
</label>
<div id="links_landing_container">
<div class="input-group mb-2">
<input type="url" name="link_landing[]" class="form-control" placeholder="https://...">
<button class="btn btn-outline-danger" type="button" onclick="if(document.querySelectorAll('#links_landing_container .input-group').length > 1) this.parentElement.remove()"><i class="fas fa-times"></i></button>
</div>
</div>
</div>
<div class="col-md-12">
<label class="form-label d-flex justify-content-between">
Link de Flyer
<button type="button" class="btn btn-sm btn-link p-0 text-decoration-none" onclick="addLinkInput('links_flyer_container', 'link_flyer[]')">
<i class="fas fa-plus-circle"></i> Añadir otro
</button>
</label>
<div id="links_flyer_container">
<div class="input-group mb-2">
<input type="url" name="link_flyer[]" class="form-control" placeholder="https://...">
<button class="btn btn-outline-danger" type="button" onclick="if(document.querySelectorAll('#links_flyer_container .input-group').length > 1) this.parentElement.remove()"><i class="fas fa-times"></i></button>
</div>
</div>
</div>
<div class="col-12">
<label class="form-label">Instrucciones Adicionales</label>
<textarea name="instrucciones" class="form-control" rows="3"></textarea>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="submit" class="btn btn-primary">Crear Pedido</button>
</div>
</form>
</div>
</div>
</div>
<!-- Modal Gestionar Video -->
<div class="modal fade" id="gestionarVideoModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<form action="save_marketing_video.php" method="POST">
<input type="hidden" name="action" value="update">
<input type="hidden" name="id" id="edit_id">
<div class="modal-header">
<h5 class="modal-title">Gestionar Pedido</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row g-3">
<div class="col-md-4">
<label class="form-label">Estado</label>
<select name="estado" id="edit_estado" class="form-select">
<option value="PENDIENTE">PENDIENTE</option>
<option value="EN PROCESO">EN PROCESO</option>
<option value="TERMINADO">TERMINADO</option>
<option value="OBSERVADO">OBSERVADO</option>
<option value="APROBADO">APROBADO</option>
<option value="PUBLICADO">PUBLICADO</option>
</select>
</div>
<div class="col-md-4">
<label class="form-label">Orden</label>
<input type="number" name="orden" id="edit_orden" class="form-control">
</div>
<div class="col-md-4">
<label class="form-label">Fecha Entrega</label>
<input type="date" name="fecha_entrega" id="edit_fecha_entrega" class="form-control">
</div>
<div class="col-md-6">
<label class="form-label">Material</label>
<input type="text" name="material" id="edit_material" class="form-control">
</div>
<div class="col-md-6">
<label class="form-label">Ángulo del Video</label>
<input type="text" name="angulo_video" id="edit_angulo_video" class="form-control">
</div>
<div class="col-md-6">
<label class="form-label d-flex justify-content-between">
Link Inspiración Landing
<button type="button" class="btn btn-sm btn-link p-0 text-decoration-none" onclick="addLinkInput('edit_links_insp_landing_container', 'link_inspiracion_landing[]')">
<i class="fas fa-plus-circle"></i> Añadir otro
</button>
</label>
<div id="edit_links_insp_landing_container">
<!-- Se llenará dinámicamente -->
</div>
</div>
<div class="col-md-6">
<label class="form-label d-flex justify-content-between">
Link Inspiración Video
<button type="button" class="btn btn-sm btn-link p-0 text-decoration-none" onclick="addLinkInput('edit_links_video_container', 'link_inspiracion_video[]')">
<i class="fas fa-plus-circle"></i> Añadir otro
</button>
</label>
<div id="edit_links_video_container">
<!-- Se llenará dinámicamente -->
</div>
</div>
<div class="col-md-6">
<label class="form-label d-flex justify-content-between">
Link Video Final
<button type="button" class="btn btn-sm btn-link p-0 text-decoration-none" onclick="addLinkInput('edit_links_video_final_container', 'link_video[]')">
<i class="fas fa-plus-circle"></i> Añadir otro
</button>
</label>
<div id="edit_links_video_final_container">
<!-- Se llenará dinámicamente -->
</div>
</div>
<div class="col-md-6">
<label class="form-label d-flex justify-content-between">
Link de la Landing
<button type="button" class="btn btn-sm btn-link p-0 text-decoration-none" onclick="addLinkInput('edit_links_landing_container', 'link_landing[]')">
<i class="fas fa-plus-circle"></i> Añadir otro
</button>
</label>
<div id="edit_links_landing_container">
<!-- Se llenará dinámicamente -->
</div>
</div>
<div class="col-md-12">
<label class="form-label d-flex justify-content-between">
Link de Flyer
<button type="button" class="btn btn-sm btn-link p-0 text-decoration-none" onclick="addLinkInput('edit_links_flyer_container', 'link_flyer[]')">
<i class="fas fa-plus-circle"></i> Añadir otro
</button>
</label>
<div id="edit_links_flyer_container">
<!-- Se llenará dinámicamente -->
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cerrar</button>
<button type="submit" class="btn btn-success">Guardar Cambios</button>
</div>
</form>
</div>
</div>
</div>
<script>
function addLinkInput(containerId, inputName, value = '') {
const container = document.getElementById(containerId);
const div = document.createElement('div');
div.className = 'input-group mb-2';
div.innerHTML = `
<input type="url" name="${inputName}" class="form-control" placeholder="https://..." value="${value}">
<button class="btn btn-outline-danger" type="button" onclick="this.parentElement.remove()"><i class="fas fa-times"></i></button>
`;
container.appendChild(div);
}
function gestionarVideo(video) {
document.getElementById('edit_id').value = video.id;
document.getElementById('edit_estado').value = video.estado;
document.getElementById('edit_orden').value = video.orden || 0;
document.getElementById('edit_fecha_entrega').value = video.fecha_entrega || '';
document.getElementById('edit_material').value = video.material || '';
document.getElementById('edit_angulo_video').value = video.angulo_video || '';
// Llenar links dinámicos
const fillLinks = (containerId, inputName, data) => {
const container = document.getElementById(containerId);
container.innerHTML = '';
if (data) {
const links = data.split(',');
links.forEach(link => {
if (link.trim()) addLinkInput(containerId, inputName, link.trim());
});
}
if (container.innerHTML === '') {
addLinkInput(containerId, inputName);
}
};
fillLinks('edit_links_insp_landing_container', 'link_inspiracion_landing[]', video.link_inspiracion_landing);
fillLinks('edit_links_video_container', 'link_inspiracion_video[]', video.link_inspiracion_video);
fillLinks('edit_links_video_final_container', 'link_video[]', video.link_video);
fillLinks('edit_links_landing_container', 'link_landing[]', video.link_landing);
fillLinks('edit_links_flyer_container', 'link_flyer[]', video.link_flyer);
var myModal = new bootstrap.Modal(document.getElementById('gestionarVideoModal'));
myModal.show();
}
document.addEventListener('DOMContentLoaded', function() {
const editableCells = document.querySelectorAll('.editable');
editableCells.forEach(cell => {
cell.addEventListener('dblclick', function() {
if (this.querySelector('input') || this.querySelector('select')) return;
const id = this.getAttribute('data-id');
const field = this.getAttribute('data-field');
const currentValue = this.innerText.trim() === '-' ? '' : this.innerText.trim();
let input;
if (field === 'estado') {
input = document.createElement('select');
input.className = 'form-select form-select-sm inline-edit-input';
const options = ['PENDIENTE', 'EN PROCESO', 'TERMINADO', 'OBSERVADO', 'APROBADO', 'PUBLICADO'];
options.forEach(opt => {
const option = document.createElement('option');
option.value = opt;
option.text = opt;
if (opt === currentValue) option.selected = true;
input.appendChild(option);
});
} else {
input = document.createElement('input');
input.type = 'text';
input.className = 'form-control form-control-sm inline-edit-input';
input.value = currentValue;
}
const originalContent = this.innerHTML;
this.innerHTML = '';
this.appendChild(input);
input.focus();
const saveChange = () => {
const newValue = input.value;
if (newValue === currentValue) {
this.innerHTML = originalContent;
return;
}
fetch('update_marketing_video_field.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ id, field, value: newValue })
})
.then(response => response.json())
.then(data => {
if (data.success) {
if (field === 'estado') {
let badgeClass = 'bg-secondary';
if (newValue === 'PENDIENTE') badgeClass = 'bg-warning text-dark';
else if (newValue === 'EN PROCESO') badgeClass = 'bg-info';
else if (newValue === 'TERMINADO') badgeClass = 'bg-primary';
else if (newValue === 'OBSERVADO') badgeClass = 'bg-danger';
else if (newValue === 'APROBADO') badgeClass = 'bg-success';
else if (newValue === 'PUBLICADO') badgeClass = 'bg-dark';
this.innerHTML = `<span class="badge status-badge ${badgeClass}">${newValue}</span>`;
} else {
this.innerHTML = `<div class="text-truncate" style="max-width: 150px;" title="${newValue}">${newValue || '-'}</div>`;
}
} else {
alert('Error: ' + data.error);
this.innerHTML = originalContent;
}
})
.catch(error => {
console.error('Error:', error);
this.innerHTML = originalContent;
});
};
input.addEventListener('blur', saveChange);
input.addEventListener('keydown', function(e) {
if (e.key === 'Enter') {
input.blur();
} else if (e.key === 'Escape') {
cell.innerHTML = originalContent;
}
});
});
});
});
</script>
<?php include 'layout_footer.php'; ?>