Autosave: 20260505-030332
This commit is contained in:
parent
5a30279f6c
commit
4f3867406b
BIN
assets/uploads/marketing_images/69f9563f75358.webp
Normal file
BIN
assets/uploads/marketing_images/69f9563f75358.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 61 KiB |
BIN
assets/uploads/marketing_images/69f95a0b3cbf6.jpg
Normal file
BIN
assets/uploads/marketing_images/69f95a0b3cbf6.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
10
db/migrations/037_create_marketing_videos_table.sql
Normal file
10
db/migrations/037_create_marketing_videos_table.sql
Normal file
@ -0,0 +1,10 @@
|
||||
CREATE TABLE IF NOT EXISTS marketing_videos (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
producto_id INT NULL,
|
||||
foto_producto VARCHAR(255) NULL,
|
||||
instrucciones TEXT NULL,
|
||||
link_video VARCHAR(255) NULL,
|
||||
estado ENUM('Pendiente', 'En Proceso', 'Terminado', 'Aprobado') DEFAULT 'Pendiente',
|
||||
fecha_creacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (producto_id) REFERENCES products(id) ON DELETE SET NULL
|
||||
);
|
||||
7
db/migrations/038_update_marketing_videos_columns.sql
Normal file
7
db/migrations/038_update_marketing_videos_columns.sql
Normal file
@ -0,0 +1,7 @@
|
||||
ALTER TABLE marketing_videos
|
||||
ADD COLUMN fecha_entrega DATE NULL AFTER fecha_creacion,
|
||||
ADD COLUMN angulo_video TEXT NULL AFTER instrucciones,
|
||||
ADD COLUMN link_inspiracion_landing VARCHAR(255) NULL AFTER angulo_video,
|
||||
ADD COLUMN link_inspiracion_video VARCHAR(255) NULL AFTER link_inspiracion_landing,
|
||||
ADD COLUMN link_landing VARCHAR(255) NULL AFTER link_video,
|
||||
ADD COLUMN orden INT DEFAULT 0 AFTER id;
|
||||
1
db/migrations/039_add_link_flyer_to_marketing_videos.sql
Normal file
1
db/migrations/039_add_link_flyer_to_marketing_videos.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE marketing_videos ADD COLUMN link_flyer VARCHAR(255) NULL AFTER link_landing;
|
||||
1
db/migrations/039_add_material_to_marketing_videos.sql
Normal file
1
db/migrations/039_add_material_to_marketing_videos.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE marketing_videos ADD COLUMN material TEXT AFTER foto_producto;
|
||||
7
db/migrations/045_create_marketing_assets_table.sql
Normal file
7
db/migrations/045_create_marketing_assets_table.sql
Normal file
@ -0,0 +1,7 @@
|
||||
CREATE TABLE IF NOT EXISTS marketing_assets (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
nombre VARCHAR(255) NOT NULL,
|
||||
categoria ENUM('Logo', 'Intro/Outro', 'Música', 'Gráficos', 'Otros') DEFAULT 'Otros',
|
||||
archivo_path VARCHAR(255) NOT NULL,
|
||||
fecha_subida TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
24
delete_marketing_asset.php
Normal file
24
delete_marketing_asset.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
include 'db/config.php';
|
||||
$db = db();
|
||||
|
||||
if (isset($_GET['id'])) {
|
||||
$id = $_GET['id'];
|
||||
|
||||
// Obtener la ruta del archivo para borrarlo del servidor
|
||||
$stmt = $db->prepare("SELECT archivo_path FROM marketing_assets WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$asset = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($asset) {
|
||||
if (file_exists($asset['archivo_path'])) {
|
||||
unlink($asset['archivo_path']);
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("DELETE FROM marketing_assets WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
}
|
||||
}
|
||||
|
||||
header("Location: marketing_assets.php");
|
||||
exit;
|
||||
@ -1,14 +1,148 @@
|
||||
<?php
|
||||
$pageTitle = "Biblioteca de Assets";
|
||||
include 'db/config.php';
|
||||
include 'layout_header.php';
|
||||
$db = db();
|
||||
|
||||
// Obtener todos los assets
|
||||
$stmt = $db->query("SELECT * FROM marketing_assets ORDER BY categoria ASC, nombre ASC");
|
||||
$assets = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Agrupar por categoría
|
||||
$categorias = [
|
||||
'Logo' => [],
|
||||
'Intro/Outro' => [],
|
||||
'Música' => [],
|
||||
'Gráficos' => [],
|
||||
'Otros' => []
|
||||
];
|
||||
|
||||
foreach ($assets as $asset) {
|
||||
$categorias[$asset['categoria']][] = $asset;
|
||||
}
|
||||
?>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Biblioteca de Recursos de Marketing</h5>
|
||||
<p>Aquí podrás subir y organizar logos, intros de video, música y otros materiales que la editora deba utilizar de forma recurrente.</p>
|
||||
<div class="alert alert-info">
|
||||
<i class="bi bi-info-circle me-1"></i> Esta sección está en desarrollo. Pronto podrás gestionar tus archivos aquí.
|
||||
|
||||
<main id="main" class="main">
|
||||
<div class="pagetitle d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h1>Biblioteca de Assets</h1>
|
||||
<nav>
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="index.php">Home</a></li>
|
||||
<li class="breadcrumb-item">Marketing</li>
|
||||
<li class="breadcrumb-item active">Assets</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#subirAssetModal">
|
||||
<i class="bi bi-cloud-arrow-up"></i> Subir Nuevo Recurso
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<section class="section">
|
||||
<div class="row">
|
||||
<?php foreach ($categorias as $cat => $items): ?>
|
||||
<div class="col-12 mb-4">
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center bg-light">
|
||||
<h5 class="card-title mb-0 py-0"><?php echo $cat; ?> <span class="badge bg-secondary ms-2"><?php echo count($items); ?></span></h5>
|
||||
</div>
|
||||
<div class="card-body pt-3">
|
||||
<?php if (empty($items)): ?>
|
||||
<p class="text-muted mb-0">No hay archivos en esta categoría.</p>
|
||||
<?php else: ?>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nombre</th>
|
||||
<th>Fecha</th>
|
||||
<th class="text-end">Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($items as $item): ?>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<?php
|
||||
$ext = pathinfo($item['archivo_path'], PATHINFO_EXTENSION);
|
||||
$icon = 'bi-file-earmark';
|
||||
if (in_array($ext, ['jpg', 'jpeg', 'png', 'svg'])) $icon = 'bi-image';
|
||||
if (in_array($ext, ['mp4', 'mov', 'avi'])) $icon = 'bi-play-btn';
|
||||
if (in_array($ext, ['mp3', 'wav'])) $icon = 'bi-music-note-beamed';
|
||||
?>
|
||||
<i class="bi <?php echo $icon; ?> fs-4 me-3 text-primary"></i>
|
||||
<span><?php echo htmlspecialchars($item['nombre']); ?></span>
|
||||
</div>
|
||||
</td>
|
||||
<td><?php echo date('d/m/Y', strtotime($item['fecha_subida'])); ?></td>
|
||||
<td class="text-end">
|
||||
<a href="<?php echo $item['archivo_path']; ?>" download class="btn btn-sm btn-outline-success" title="Descargar">
|
||||
<i class="bi bi-download"></i>
|
||||
</a>
|
||||
<button class="btn btn-sm btn-outline-danger" onclick="eliminarAsset(<?php echo $item['id']; ?>)" title="Eliminar">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Modal Subir Asset -->
|
||||
<div class="modal fade" id="subirAssetModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form action="save_marketing_asset.php" method="POST" enctype="multipart/form-data">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Subir Recurso</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Nombre del Recurso</label>
|
||||
<input type="text" name="nombre" class="form-control" placeholder="Ej: Logo Principal Blanco" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Categoría</label>
|
||||
<select name="categoria" class="form-select" required>
|
||||
<option value="Logo">Logo</option>
|
||||
<option value="Intro/Outro">Intro/Outro</option>
|
||||
<option value="Música">Música</option>
|
||||
<option value="Gráficos">Gráficos</option>
|
||||
<option value="Otros">Otros</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Archivo</label>
|
||||
<input type="file" name="archivo" class="form-control" required>
|
||||
<div class="form-text">Soporta imágenes, videos y audio.</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-primary">Subir Archivo</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
function eliminarAsset(id) {
|
||||
if (confirm('¿Estás seguro de que deseas eliminar este recurso?')) {
|
||||
window.location.href = 'delete_marketing_asset.php?id=' + id;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<?php include 'layout_footer.php'; ?>
|
||||
@ -13,73 +13,186 @@ $productos = $stmt_products->fetchAll(PDO::FETCH_ASSOC);
|
||||
$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.fecha_creacion DESC");
|
||||
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">
|
||||
<h2>Gestión de Producción</h2>
|
||||
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#nuevoVideoModal">
|
||||
<i class="fas fa-plus"></i> Nuevo Pedido de Video
|
||||
</button>
|
||||
<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">
|
||||
¡Pedido creado con éxito!
|
||||
¡Operación realizada con éxito!
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="row">
|
||||
<?php if (empty($videos)): ?>
|
||||
<div class="col-12 text-center py-5">
|
||||
<i class="fas fa-video fa-4x text-muted mb-3"></i>
|
||||
<p class="text-muted">No hay pedidos de video registrados aún.</p>
|
||||
<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']): ?>
|
||||
<a href="<?php echo $v['link_inspiracion_landing']; ?>" target="_blank" class="link-icon"><i class="fas fa-external-link-alt"></i></a>
|
||||
<?php else: ?>
|
||||
<span class="text-muted">-</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<?php if ($v['link_inspiracion_video']): ?>
|
||||
<a href="<?php echo $v['link_inspiracion_video']; ?>" target="_blank" class="link-icon text-danger"><i class="fab fa-youtube"></i></a>
|
||||
<?php else: ?>
|
||||
<span class="text-muted">-</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<?php if ($v['link_video']): ?>
|
||||
<a href="<?php echo $v['link_video']; ?>" target="_blank" class="link-icon text-success"><i class="fas fa-play-circle"></i></a>
|
||||
<?php else: ?>
|
||||
<span class="text-muted">-</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<?php if ($v['link_landing']): ?>
|
||||
<a href="<?php echo $v['link_landing']; ?>" target="_blank" class="link-icon text-info"><i class="fas fa-globe"></i></a>
|
||||
<?php else: ?>
|
||||
<span class="text-muted">-</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<?php if ($v['link_flyer']): ?>
|
||||
<a href="<?php echo $v['link_flyer']; ?>" target="_blank" class="link-icon text-warning"><i class="fas fa-file-image"></i></a>
|
||||
<?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' : 'bg-success'));
|
||||
?>">
|
||||
<?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>
|
||||
<?php else: ?>
|
||||
<?php foreach ($videos as $v): ?>
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card h-100 shadow-sm">
|
||||
<div class="position-relative">
|
||||
<?php if ($v['foto_producto']): ?>
|
||||
<img src="<?php echo $v['foto_producto']; ?>" class="card-img-top" alt="Producto" style="height: 200px; object-fit: cover;">
|
||||
<?php else: ?>
|
||||
<div class="bg-light d-flex align-items-center justify-content-center" style="height: 200px;">
|
||||
<i class="fas fa-image fa-3x text-muted"></i>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<span class="position-absolute top-0 end-0 m-2 badge <?php
|
||||
echo $v['estado'] == 'Pendiente' ? 'bg-warning' :
|
||||
($v['estado'] == 'En Proceso' ? 'bg-info' :
|
||||
($v['estado'] == 'Terminado' ? 'bg-primary' : 'bg-success'));
|
||||
?>">
|
||||
<?php echo $v['estado']; ?>
|
||||
</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h5 class="card-title"><?php echo htmlspecialchars($v['nombre_producto'] ?: 'Producto General'); ?></h5>
|
||||
<p class="card-text text-muted small">
|
||||
<?php echo nl2br(htmlspecialchars(substr($v['instrucciones'], 0, 100))); ?>...
|
||||
</p>
|
||||
<div class="d-flex justify-content-between align-items-center mt-3">
|
||||
<small class="text-muted"><i class="far fa-calendar-alt"></i> <?php echo date('d/m/Y', strtotime($v['fecha_creacion'])); ?></small>
|
||||
<?php if ($v['link_video']): ?>
|
||||
<a href="<?php echo $v['link_video']; ?>" target="_blank" class="btn btn-sm btn-success">
|
||||
<i class="fas fa-play"></i> Ver Video
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-white border-top-0">
|
||||
<button class="btn btn-outline-primary btn-sm w-100" onclick="verDetalles(<?php echo $v['id']; ?>)">
|
||||
<i class="fas fa-edit"></i> Gestionar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal Nuevo Video -->
|
||||
@ -93,8 +206,16 @@ $videos = $stmt_videos->fetchAll(PDO::FETCH_ASSOC);
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Producto Relacionado</label>
|
||||
<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): ?>
|
||||
@ -103,12 +224,32 @@ $videos = $stmt_videos->fetchAll(PDO::FETCH_ASSOC);
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Foto de Referencia / Ángulo</label>
|
||||
<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">Link Inspiración Landing</label>
|
||||
<input type="url" name="link_inspiracion_landing" class="form-control" placeholder="https://...">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Link Inspiración Video</label>
|
||||
<input type="url" name="link_inspiracion_video" class="form-control" placeholder="https://...">
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<label class="form-label">Link de Flyer</label>
|
||||
<input type="url" name="link_flyer" class="form-control" placeholder="https://...">
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label">Instrucciones Detalladas</label>
|
||||
<textarea name="instrucciones" class="form-control" rows="4" placeholder="Describe el ángulo, la música, el estilo del video, etc."></textarea>
|
||||
<label class="form-label">Instrucciones Adicionales</label>
|
||||
<textarea name="instrucciones" class="form-control" rows="3"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -121,11 +262,176 @@ $videos = $stmt_videos->fetchAll(PDO::FETCH_ASSOC);
|
||||
</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="Aprobado">Aprobado</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">Link Inspiración Landing</label>
|
||||
<input type="url" name="link_inspiracion_landing" id="edit_link_insp_landing" class="form-control">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Link Inspiración Video</label>
|
||||
<input type="url" name="link_inspiracion_video" id="edit_link_insp_video" class="form-control">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Link Video Final</label>
|
||||
<input type="url" name="link_video" id="edit_link_video" class="form-control">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Link de la Landing</label>
|
||||
<input type="url" name="link_landing" id="edit_link_landing" class="form-control">
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<label class="form-label">Link de Flyer</label>
|
||||
<input type="url" name="link_flyer" id="edit_link_flyer" class="form-control">
|
||||
</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 verDetalles(id) {
|
||||
// Por ahora solo mostramos un mensaje, luego implementaremos la edición
|
||||
alert("Funcionalidad de edición para el ID " + id + " en desarrollo.");
|
||||
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 || '';
|
||||
document.getElementById('edit_link_insp_landing').value = video.link_inspiracion_landing || '';
|
||||
document.getElementById('edit_link_insp_video').value = video.link_inspiracion_video || '';
|
||||
document.getElementById('edit_link_video').value = video.link_video || '';
|
||||
document.getElementById('edit_link_landing').value = video.link_landing || '';
|
||||
document.getElementById('edit_link_flyer').value = 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', 'Aprobado'];
|
||||
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 === 'Aprobado') badgeClass = 'bg-success';
|
||||
|
||||
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'; ?>
|
||||
29
save_marketing_asset.php
Normal file
29
save_marketing_asset.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
include 'db/config.php';
|
||||
$db = db();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
$nombre = $_POST['nombre'] ?? '';
|
||||
$categoria = $_POST['categoria'] ?? 'Otros';
|
||||
|
||||
if (isset($_FILES['archivo']) && $_FILES['archivo']['error'] == 0) {
|
||||
$uploadDir = 'assets/uploads/marketing_assets/';
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0777, true);
|
||||
}
|
||||
|
||||
$fileName = time() . '_' . basename($_FILES['archivo']['name']);
|
||||
$targetPath = $uploadDir . $fileName;
|
||||
|
||||
if (move_uploaded_file($_FILES['archivo']['tmp_name'], $targetPath)) {
|
||||
$stmt = $db->prepare("INSERT INTO marketing_assets (nombre, categoria, archivo_path) VALUES (?, ?, ?)");
|
||||
$stmt->execute([$nombre, $categoria, $targetPath]);
|
||||
|
||||
header("Location: marketing_assets.php?success=1");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
header("Location: marketing_assets.php?error=1");
|
||||
exit;
|
||||
@ -9,29 +9,110 @@ if (!isset($_SESSION['user_id'])) {
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
$db = db();
|
||||
$producto_id = !empty($_POST['producto_id']) ? $_POST['producto_id'] : null;
|
||||
$instrucciones = $_POST['instrucciones'] ?? '';
|
||||
$foto_path = null;
|
||||
$action = $_POST['action'] ?? 'create';
|
||||
|
||||
// Manejo de la subida de foto
|
||||
if (isset($_FILES['foto_producto']) && $_FILES['foto_producto']['error'] == 0) {
|
||||
$target_dir = "assets/uploads/marketing_images/";
|
||||
$file_extension = pathinfo($_FILES["foto_producto"]["name"], PATHINFO_EXTENSION);
|
||||
$file_name = uniqid() . '.' . $file_extension;
|
||||
$target_file = $target_dir . $file_name;
|
||||
if ($action == 'update') {
|
||||
// Lógica para actualizar (Editora o Tú)
|
||||
$id = $_POST['id'];
|
||||
$estado = $_POST['estado'];
|
||||
$link_video = $_POST['link_video'] ?? '';
|
||||
$link_landing = $_POST['link_landing'] ?? '';
|
||||
$link_flyer = $_POST['link_flyer'] ?? '';
|
||||
$material = $_POST['material'] ?? '';
|
||||
$fecha_entrega = !empty($_POST['fecha_entrega']) ? $_POST['fecha_entrega'] : null;
|
||||
$orden = !empty($_POST['orden']) ? $_POST['orden'] : 0;
|
||||
$angulo_video = $_POST['angulo_video'] ?? '';
|
||||
$link_inspiracion_landing = $_POST['link_inspiracion_landing'] ?? '';
|
||||
$link_inspiracion_video = $_POST['link_inspiracion_video'] ?? '';
|
||||
|
||||
if (move_uploaded_file($_FILES["foto_producto"]["tmp_name"], $target_file)) {
|
||||
$foto_path = $target_file;
|
||||
try {
|
||||
$stmt = $db->prepare("UPDATE marketing_videos SET
|
||||
estado = ?,
|
||||
link_video = ?,
|
||||
link_landing = ?,
|
||||
link_flyer = ?,
|
||||
material = ?,
|
||||
fecha_entrega = ?,
|
||||
orden = ?,
|
||||
angulo_video = ?,
|
||||
link_inspiracion_landing = ?,
|
||||
link_inspiracion_video = ?
|
||||
WHERE id = ?");
|
||||
$stmt->execute([
|
||||
$estado,
|
||||
$link_video,
|
||||
$link_landing,
|
||||
$link_flyer,
|
||||
$material,
|
||||
$fecha_entrega,
|
||||
$orden,
|
||||
$angulo_video,
|
||||
$link_inspiracion_landing,
|
||||
$link_inspiracion_video,
|
||||
$id
|
||||
]);
|
||||
header('Location: marketing_produccion.php?success=updated');
|
||||
} catch (PDOException $e) {
|
||||
echo "Error: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $db->prepare("INSERT INTO marketing_videos (producto_id, foto_producto, instrucciones, estado) VALUES (?, ?, ?, 'Pendiente')");
|
||||
$stmt->execute([$producto_id, $foto_path, $instrucciones]);
|
||||
} else {
|
||||
// Lógica para crear (Tú)
|
||||
$producto_id = !empty($_POST['producto_id']) ? $_POST['producto_id'] : null;
|
||||
$instrucciones = $_POST['instrucciones'] ?? '';
|
||||
$fecha_entrega = !empty($_POST['fecha_entrega']) ? $_POST['fecha_entrega'] : null;
|
||||
$orden = !empty($_POST['orden']) ? $_POST['orden'] : 0;
|
||||
$angulo_video = $_POST['angulo_video'] ?? '';
|
||||
$link_inspiracion_landing = $_POST['link_inspiracion_landing'] ?? '';
|
||||
$link_inspiracion_video = $_POST['link_inspiracion_video'] ?? '';
|
||||
$link_flyer = $_POST['link_flyer'] ?? '';
|
||||
$material = $_POST['material'] ?? '';
|
||||
|
||||
header('Location: marketing_produccion.php?success=1');
|
||||
} catch (PDOException $e) {
|
||||
echo "Error: " . $e->getMessage();
|
||||
$foto_path = null;
|
||||
|
||||
if (isset($_FILES['foto_producto']) && $_FILES['foto_producto']['error'] == 0) {
|
||||
$target_dir = "assets/uploads/marketing_images/";
|
||||
if (!is_dir($target_dir)) {
|
||||
mkdir($target_dir, 0777, true);
|
||||
}
|
||||
$file_extension = pathinfo($_FILES["foto_producto"]["name"], PATHINFO_EXTENSION);
|
||||
$file_name = uniqid() . '.' . $file_extension;
|
||||
$target_file = $target_dir . $file_name;
|
||||
|
||||
if (move_uploaded_file($_FILES["foto_producto"]["tmp_name"], $target_file)) {
|
||||
$foto_path = $target_file;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $db->prepare("INSERT INTO marketing_videos (
|
||||
producto_id,
|
||||
foto_producto,
|
||||
material,
|
||||
instrucciones,
|
||||
estado,
|
||||
fecha_entrega,
|
||||
orden,
|
||||
angulo_video,
|
||||
link_inspiracion_landing,
|
||||
link_inspiracion_video,
|
||||
link_flyer
|
||||
) VALUES (?, ?, ?, ?, 'Pendiente', ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->execute([
|
||||
$producto_id,
|
||||
$foto_path,
|
||||
$material,
|
||||
$instrucciones,
|
||||
$fecha_entrega,
|
||||
$orden,
|
||||
$angulo_video,
|
||||
$link_inspiracion_landing,
|
||||
$link_inspiracion_video,
|
||||
$link_flyer
|
||||
]);
|
||||
header('Location: marketing_produccion.php?success=created');
|
||||
} catch (PDOException $e) {
|
||||
echo "Error: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
46
update_marketing_video_field.php
Normal file
46
update_marketing_video_field.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['error' => 'Acceso no autorizado.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
if (!$data || !isset($data['id']) || !isset($data['field']) || !isset($data['value'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Datos incompletos.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$video_id = $data['id'];
|
||||
$field = $data['field'];
|
||||
$value = $data['value'];
|
||||
|
||||
// Whitelist allowed fields for security
|
||||
$allowed_fields = ['material', 'estado', 'angulo_video'];
|
||||
if (!in_array($field, $allowed_fields)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Campo no permitido.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
$sql = "UPDATE marketing_videos SET $field = ? WHERE id = ?";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$value, $video_id]);
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'Campo actualizado correctamente.'
|
||||
]);
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Error al actualizar la base de datos: ' . $e->getMessage()]);
|
||||
}
|
||||
?>
|
||||
Loading…
x
Reference in New Issue
Block a user