inicio
This commit is contained in:
2025-05-05 11:03:01 -06:00
commit c73e3f2327
185 changed files with 17573 additions and 0 deletions

129
views/transportes/crear.php Normal file
View File

@@ -0,0 +1,129 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title> Nuevo Transporte</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<style>
table.dataTable thead th { background:#343a40; color:#fff; }
body {
font-family: 'Segoe UI', sans-serif;
background-color: #f4f6f9;
}
.sidebar {
width: 220px;
height: 100vh;
background-color: #343a40;
position: fixed;
top: 0;
left: 0;
padding-top: 60px;
}
.sidebar .nav-link {
color: #ccc;
padding: 12px 20px;
}
.sidebar .nav-link:hover,
.sidebar .nav-link.active {
background-color: #495057;
color: #fff;
}
.sidebar .nav-link {
color: #ccc;
padding: 12px 20px;
}
.sidebar .nav-link:hover, .sidebar .nav-link.active {
background-color: #495057;
color: #fff;
}
.content {
margin-left: 220px;
padding: 40px 20px;
}
.navbar {
position: fixed;
top: 0;
width: 100%;
z-index: 1000;
}
.card {
border-radius: 12px;
}
</style>
</head>
<body>
<?php include __DIR__ . '/../partials/sidebar_importador.php'; ?>
<div class="content">
<br> <br>
<h4> Nuevo Transporte</h4>
<form id="formTransCrear" action="/IMPORTADORES/transportes/guardar" method="POST" enctype="multipart/form-data" class="card p-4 shadow-sm">
<div class="row g-3">
<div class="col-md-6">
<label class="form-label">Vehículo *</label>
<input name="vehiculo" id="vehiculo" class="form-control" required>
</div>
<div class="col-md-6">
<label class="form-label">Identificador fiscal *</label>
<input name="identificador_fiscal" id="identFiscal" class="form-control" required>
</div>
<div class="col-md-6">
<label class="form-label">Foto (opcional)</label>
<input type="file" name="foto" id="foto" class="form-control" accept="image/*">
</div>
<div class="col-md-6">
<label class="form-label">Transportista *</label>
<select name="id_transportista" id="transportista" class="form-select" required>
<option value="">Selecciona...</option>
<?php foreach($transportistas as $tr): ?>
<option value="<?= $tr['id_transportista'] ?>">
<?= htmlspecialchars($tr['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="text-end mt-4">
<button type="submit" class="btn btn-success">Guardar</button>
</div>
</form>
</div>
<script>
document.getElementById('formTransCrear').addEventListener('submit', function(e) {
// Campos que validamos:
const veh = document.getElementById('vehiculo').value.trim();
const fisc = document.getElementById('identFiscal').value.trim();
const trans = document.getElementById('transportista').value;
const fotoF = document.getElementById('foto').files[0];
if (!veh) {
e.preventDefault();
return Swal.fire({ icon:'error', title:'Vehículo requerido', text:'Por favor ingresa el nombre del vehículo.' });
}
if (!fisc) {
e.preventDefault();
return Swal.fire({ icon:'error', title:'Identificador fiscal requerido', text:'Por favor ingresa el identificador fiscal.' });
}
if (!trans) {
e.preventDefault();
return Swal.fire({ icon:'error', title:'Transportista no seleccionado', text:'Debes elegir un transportista.' });
}
if (fotoF && fotoF.size > 2 * 1024 * 1024) { // 2 MB
e.preventDefault();
return Swal.fire({ icon:'error', title:'Foto demasiado grande', text:'La imagen no debe exceder 2 MB.' });
}
// Si todas las validaciones pasan, el formulario se envía.
});
</script>
</body>
</html>

View File

@@ -0,0 +1,134 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title> Editar Transporte # <?= $t['id_transporte'] ?></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<style>
table.dataTable thead th { background:#343a40; color:#fff; }
body {
font-family: 'Segoe UI', sans-serif;
background-color: #f4f6f9;
}
.sidebar {
width: 220px;
height: 100vh;
background-color: #343a40;
position: fixed;
top: 0;
left: 0;
padding-top: 60px;
}
.sidebar .nav-link {
color: #ccc;
padding: 12px 20px;
}
.sidebar .nav-link:hover, .sidebar .nav-link.active {
background-color: #495057;
color: #fff;
}
.content {
margin-left: 220px;
padding: 40px 20px;
}
.navbar {
position: fixed;
top: 0;
width: 100%;
z-index: 1000;
}
.card {
border-radius: 12px;
}
.preview{
width: 40%;
}
</style>
</head>
<body>
<?php include __DIR__ . '/../partials/sidebar_importador.php'; ?>
<div class="content">
<br><br>
<h4>✏️ Editar Transporte #<?= $t['id_transporte'] ?></h4>
<form id="formTransEdit" action="/IMPORTADORES/transportes/actualizar" method="POST" enctype="multipart/form-data" class="card p-4 shadow-sm">
<input type="hidden" name="id_transporte" value="<?= $t['id_transporte'] ?>">
<div class="row g-3">
<div class="col-md-6">
<label class="form-label">Vehículo *</label>
<input name="vehiculo" id="vehEdit" class="form-control"
value="<?= htmlspecialchars($t['vehiculo']) ?>" required>
</div>
<div class="col-md-6">
<label class="form-label">Identificador fiscal *</label>
<input name="identificador_fiscal" id="fiscEdit" class="form-control"
value="<?= htmlspecialchars($t['identificador_fiscal']) ?>" required>
</div>
<div class="col-md-6">
<label class="form-label">Foto actual</label><br>
<?php if($t['foto_url']): ?>
<img src="<?= $t['foto_url'] ?>" class="preview">
<?php else: ?>
<span class="text-muted">Sin foto</span>
<?php endif; ?>
</div>
<div class="col-md-6">
<label class="form-label">Reemplazar foto (opcional)</label>
<input type="file" name="foto" id="fotoEdit" class="form-control" accept="image/*">
</div>
<div class="col-md-6">
<label class="form-label">Transportista *</label>
<select name="id_transportista" id="trEdit" class="form-select" required>
<?php foreach($transportistas as $tr): ?>
<option value="<?= $tr['id_transportista'] ?>"
<?= $tr['id_transportista']==$t['id_transportista']?'selected':'' ?>>
<?= htmlspecialchars($tr['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="text-end mt-4">
<button type="submit" class="btn btn-primary">Actualizar</button>
</div>
</form>
</div>
<script>
document.getElementById('formTransEdit').addEventListener('submit', function(e) {
const veh = document.getElementById('vehEdit').value.trim();
const fisc = document.getElementById('fiscEdit').value.trim();
const trans = document.getElementById('trEdit').value;
const fotoF = document.getElementById('fotoEdit').files[0];
if (!veh) {
e.preventDefault();
return Swal.fire({ icon:'error', title:'Vehículo requerido', text:'Por favor ingresa el nombre del vehículo.' });
}
if (!fisc) {
e.preventDefault();
return Swal.fire({ icon:'error', title:'Identificador fiscal requerido', text:'Por favor ingresa el identificador fiscal.' });
}
if (!trans) {
e.preventDefault();
return Swal.fire({ icon:'error', title:'Transportista no seleccionado', text:'Debes elegir un transportista.' });
}
if (fotoF && fotoF.size > 2 * 1024 * 1024) {
e.preventDefault();
return Swal.fire({ icon:'error', title:'Foto demasiado grande', text:'La imagen no debe exceder 2 MB.' });
}
// Si todo OK, se envía
});
</script>
</body>
</html>

View File

@@ -0,0 +1,122 @@
<?php
if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login');
exit;
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>📂 Importación Masiva de Transportes</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<style>
body {
font-family: 'Segoe UI', sans-serif;
background-color: #f4f6f9;
}
.sidebar {
width: 220px;
height: 100vh;
background-color: #343a40;
position: fixed;
top: 0;
left: 0;
padding-top: 60px;
}
.sidebar .nav-link {
color: #ccc;
padding: 12px 20px;
}
.sidebar .nav-link:hover, .sidebar .nav-link.active {
background-color: #495057;
color: #fff;
}
.content {
margin-left: 220px;
padding: 40px 20px;
}
.navbar {
position: fixed;
top: 0;
width: 100%;
z-index: 1000;
}
.card {
border-radius: 12px;
}
</style>
</head>
<body>
<?php include __DIR__ . '/../partials/sidebar_importador.php'; ?>
<div class="content">
<br><br>
<h4>📂 Importación Masiva de Transportes</h4>
<?php if (isset($_SESSION['import_result'])):
$res = $_SESSION['import_result'];
unset($_SESSION['import_result']);
?>
<script>
Swal.fire({
title: 'Importación completada',
html:
'✅ Registros importados: <?= $res['imported'] ?>.<br>' +
'<?php foreach ($res['errors'] as $err) {
echo htmlspecialchars($err) . '<br>';
} ?>',
icon: 'info',
width: 600
});
</script>
<?php endif; ?>
<div class="card p-4 shadow-sm">
<form action="/IMPORTADORES/transportes/importarGuardar" method="POST" enctype="multipart/form-data">
<div class="mb-3">
<label class="form-label">Archivo CSV *</label>
<input type="file" name="csv" accept=".csv" class="form-control" required>
</div>
<p>Descarga la plantilla y llena las columnas: <code>vehiculo, identificador_fiscal, id_transportista</code>.</p>
<a href="/IMPORTADORES/public/downloads/transportes_masivo_template.csv" class="btn btn-outline-secondary mb-3">
📥 Descargar plantilla
</a><br>
<button type="submit" class="btn btn-primary">Importar</button>
</form>
</div>
</div>
</body>
</html>
<script>
document.addEventListener('DOMContentLoaded', function() {
const Toast = Swal.mixin({
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 3000,
timerProgressBar: true
});
// Éxito: cuantos se importaron
if (<?= $imported ?> > 0) {
Toast.fire({
icon: 'success',
title: `✅ Importados: <?= $imported ?>`
});
}
// Errores: uno por toast
JSON.parse('<?= addslashes($errors) ?>').forEach(err => {
Toast.fire({
icon: 'error',
title: err
});
});
});
</script>

117
views/transportes/lista.php Normal file
View File

@@ -0,0 +1,117 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>🚚 Mis Transportes</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<style>
table.dataTable thead th { background:#343a40; color:#fff; }
body {
font-family: 'Segoe UI', sans-serif;
background-color: #f4f6f9;
}
.sidebar {
width: 220px;
height: 100vh;
background-color: #343a40;
position: fixed;
top: 0;
left: 0;
padding-top: 60px;
}
.sidebar .nav-link {
color: #ccc;
padding: 12px 20px;
}
.sidebar .nav-link:hover, .sidebar .nav-link.active {
background-color: #495057;
color: #fff;
}
.content {
margin-left: 220px;
padding: 40px 20px;
}
.navbar {
position: fixed;
top: 0;
width: 100%;
z-index: 1000;
}
.card {
border-radius: 12px;
}
</style>
</head>
<body>
<?php include __DIR__ . '/../partials/sidebar_importador.php'; ?>
<br> <br>
<div class="content">
<h4>🚚 Mis Transportes</h4>
<a href="/IMPORTADORES/transportes/crear" class="btn btn-success mb-3"> Nuevo Transporte</a>
<table class="table table-striped">
<thead>
<tr>
<th>#</th><th>Vehículo</th><th>Ident. Fiscal</th>
<th>Foto</th><th>Transportista</th>
<th>Alta</th><th>Acciones</th>
</tr>
</thead>
<tbody>
<?php foreach($transportes as $t): ?>
<tr>
<td><?= $t['id_transporte'] ?></td>
<td><?= htmlspecialchars($t['vehiculo']) ?></td>
<td><?= htmlspecialchars($t['identificador_fiscal']) ?></td>
<td>
<?php if($t['foto_url']): ?>
<img src="<?= $t['foto_url'] ?>" width="50">
<?php endif; ?>
</td>
<td><?= htmlspecialchars($t['transportista']) ?></td>
<td><?= $t['creado_en']->format('Y-m-d') ?></td>
<td>
<a href="/IMPORTADORES/transportes/editar?id=<?= $t['id_transporte'] ?>"
class="btn btn-sm btn-primary">✏️</a>
<button class="btn btn-sm btn-danger"
onclick="confirmDelete(<?= $t['id_transporte'] ?>)">
🗑️
</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<script>
function confirmDelete(id) {
Swal.fire({
title: '¿Eliminar transporte?',
text: 'Será eliminado.',
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Sí, eliminar',
cancelButtonText: 'Cancelar',
confirmButtonColor: '#d33'
}).then(r => {
if (r.isConfirmed) {
window.location = `/IMPORTADORES/transportes/eliminar?id=${id}`;
}
});
}
<?php if(isset($_GET['deleted'])): ?>
Swal.fire('¡Hecho!','Transporte eliminado.','success');
<?php endif; ?>
</script>
</body>
</html>