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

View File

@@ -0,0 +1,142 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Panel de Administración - Usuarios</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>
</head>
<body>
<?php
include __DIR__ . '/../partials/sidebar_sistemas.php';
?>
<!-- 📄 CONTENIDO -->
<div class="content px-4">
<h3 class="mb-4">Administración de Usuarios</h3>
<!-- FORMULARIO -->
<form action="/IMPORTADORES/sistemas/guardar_usuario" method="POST" class="card p-4 mb-5 shadow-sm">
<h5 class="mb-3"> Nuevo Usuario</h5>
<div class="row g-3">
<div class="col-md-4">
<input name="nombre" class="form-control" placeholder="Nombre completo" required>
</div>
<div class="col-md-4">
<input name="email" type="email" class="form-control" placeholder="Correo electrónico" required>
</div>
<div class="col-md-2">
<input name="password" type="password" class="form-control" placeholder="Contraseña" required>
</div>
<div class="col-md-2">
<select name="tipo_usuario" class="form-select" required>
<option value="">Tipo</option>
<option value="agente_aduanal">Agente Aduanal</option>
<option value="importador">Importador</option>
</select>
</div>
</div>
<div class="text-end mt-4">
<button class="btn btn-success px-4">Registrar</button>
</div>
</form>
<!-- TABLA DE USUARIOS -->
<div class="card p-4 shadow-sm">
<h5 class="mb-3">👁️ Usuarios Registrados</h5>
<div class="table-responsive">
<table class="table table-striped table-hover align-middle">
<thead>
<tr>
<th>#</th>
<th>Nombre</th>
<th>Correo</th>
<th>Tipo</th>
<th>Estado</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
<?php if (!empty($usuarios)): ?>
<?php foreach ($usuarios as $u): ?>
<tr>
<td><?= $u['id_usuario'] ?></td>
<td><?= decrypt($u['nombre']) ?></td>
<td><?= decrypt($u['email']) ?></td>
<td><?= ucfirst($u['tipo_usuario']) ?></td>
<td>
<span class="badge <?= $u['activo'] ? 'bg-success' : 'bg-danger' ?>">
<?= $u['activo'] ? 'Activo' : 'Inactivo' ?>
</span>
</td>
<td>
<a href="/IMPORTADORES/sistemas/toggle_estado?id=<?= $u['id_usuario'] ?>" class="btn btn-sm btn-warning">Toggle</a>
<a href="/IMPORTADORES/sistemas/reset_password?id=<?= $u['id_usuario'] ?>" class="btn btn-sm btn-secondary">Reset</a>
</td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr>
<td colspan="6" class="text-center">No hay usuarios registrados aún.</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<?php if (isset($_GET['reset'], $_GET['pass'], $_GET['email']) && $_GET['reset'] === 'ok'): ?>
<script>
const nuevaPassword = "<?= htmlspecialchars($_GET["pass"]) ?>";
const emailUsuario = "<?= htmlspecialchars($_GET["email"]) ?>";
Swal.fire({
icon: 'success',
title: 'Contraseña restablecida',
html: `
Nueva contraseña generada:<br>
<strong style="font-size:18px;">${nuevaPassword}</strong>
<div class="mt-3">
<button class="btn btn-outline-primary btn-sm" onclick="copiarPassword()">📋 Copiar</button>
<button class="btn btn-outline-success btn-sm" onclick="enviarPorCorreo()">📧 Enviar por correo</button>
</div>
`,
showConfirmButton: false,
});
function copiarPassword() {
navigator.clipboard.writeText(nuevaPassword).then(() => {
Swal.fire('Copiado', 'La contraseña fue copiada al portapapeles.', 'success');
});
}
function enviarPorCorreo() {
fetch(`/IMPORTADORES/sistemas/enviar_password?email=${encodeURIComponent(emailUsuario)}&pass=${encodeURIComponent(nuevaPassword)}`)
.then(response => response.text())
.then(data => {
Swal.fire('Enviado', 'La contraseña fue enviada al correo del usuario.', 'success');
})
.catch(() => {
Swal.fire('Error', 'No se pudo enviar el correo.', 'error');
});
}
</script>
<?php endif; ?>
</body>
</html>

View File

@@ -0,0 +1,50 @@
<head>
<meta charset="UTF-8">
<title>Panel de Administración - Usuarios</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>
</head>
<?php
include __DIR__ . '/../partials/sidebar_sistemas.php';
?>
<div class="content px-4 pt-5 mt-4">
<h4>🕵️ Bitácora de Accesos</h4>
<table class="table table-hover mt-3 align-middle">
<thead class="table-dark">
<tr>
<th>#</th>
<th>ID Usuario</th>
<th>Correo</th>
<th>IP</th>
<th>Fecha</th>
<th>Éxito</th>
<th>Detalle</th>
</tr>
</thead>
<tbody>
<?php foreach ($registros as $r): ?>
<tr>
<td><?= $r['id'] ?></td>
<td><?= $r['id_usuario'] ?></td>
<td><?= htmlspecialchars($r['email']) ?></td>
<td><?= htmlspecialchars($r['ip']) ?></td>
<td><?= $r['fecha'] instanceof DateTime ? $r['fecha']->format('Y-m-d H:i') : htmlspecialchars($r['fecha']) ?></td>
<td>
<span class="badge <?= $r['exito'] ? 'bg-success' : 'bg-danger' ?>">
<?= $r['exito'] ? 'Sí' : 'No' ?>
</span>
</td>
<td><?= htmlspecialchars($r['detalle']) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>

View File

@@ -0,0 +1,42 @@
<head>
<meta charset="UTF-8">
<title>Panel de Administración - Usuarios</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>
</head>
<?php
include __DIR__ . '/../partials/sidebar_sistemas.php';
?>
<div class="content px-4 pt-5 mt-4">
<h4>🛠️ Bitácora de Cambios de Usuario</h4>
<table class="table table-hover mt-3 align-middle">
<thead class="table-dark">
<tr>
<th>#</th>
<th>ID Usuario</th>
<th>Acción</th>
<th>Descripción</th>
<th>Fecha</th>
</tr>
</thead>
<tbody>
<?php foreach ($registros as $r): ?>
<tr>
<td><?= $r['id_bitacora'] ?></td>
<td><?= $r['usuario_id'] ?></td>
<td><strong><?= htmlspecialchars($r['accion']) ?></strong></td>
<td><?= nl2br(htmlspecialchars($r['descripcion'])) ?></td>
<td><?= $r['fecha'] instanceof DateTime ? $r['fecha']->format('Y-m-d H:i') : htmlspecialchars($r['fecha']) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>

View File

@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Login Sistemas</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="bg-light">
<div class="container mt-5" style="max-width: 400px;">
<h4 class="mb-4 text-center">Acceso Administrativo</h4>
<form action="/IMPORTADORES/sistemas/login" method="POST">
<div class="mb-3">
<label class="form-label">Correo</label>
<input type="email" name="email" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">Contraseña</label>
<input type="password" name="clave" class="form-control" required>
</div>
<div class="d-grid">
<button class="btn btn-primary">Entrar</button>
</div>
</form>
</div>
</body>
</html>

View File

@@ -0,0 +1,86 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Dashboard | Agente Aduanal</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>
<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
require_once __DIR__ . '/../../app/helpers/crypto.php';
include __DIR__ . '/../partials/sidebar_agente.php';
?>
<!-- 📄 CONTENIDO -->
<div class="content">
<h4 class="mb-4">Panel principal del agente</h4>
<div class="row g-4">
<div class="col-md-4">
<div class="card shadow-sm p-3">
<h5 class="text-primary">Importadores activos</h5>
<p>Consulta los que ya fueron autorizados.</p>
<a href="/IMPORTADORES/importadores/activos" class="btn btn-primary btn-sm mt-2">Ver importadores</a>
</div>
</div>
<div class="col-md-4">
<div class="card shadow-sm p-3">
<h5 class="text-success">Solicitudes pendientes</h5>
<p>Valida nuevas solicitudes de registro.</p>
<a href="/IMPORTADORES/AGENTES/solicitudes_pendientes" class="btn btn-success btn-sm mt-2">Ver solicitudes</a>
</div>
</div>
<div class="col-md-4">
<div class="card shadow-sm p-3">
<h5 class="text-warning">Bitácora del sistema</h5>
<p>Revisa los accesos y acciones recientes.</p>
<a href="/IMPORTADORES/bitacoras/login" class="btn btn-warning btn-sm mt-2">Ver bitácora</a>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,89 @@
<?php
require_once __DIR__ . '/../../app/helpers/crypto.php';
include __DIR__ . '/../partials/sidebar_agente.php';
?>
<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>
<div class="content px-4 pt-5 mt-4">
<h4>✅ Importadores Activos</h4>
<table class="table table-hover mt-3 align-middle">
<thead class="table-dark">
<tr>
<th>#</th>
<th>Nombre</th>
<th>Correo</th>
<th>Fecha Registro</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
<?php foreach ($importadores as $i): ?>
<tr>
<td><?= $i['id_usuario'] ?></td>
<td><?= htmlspecialchars(($i['nombre'])) ?></td>
<td><?= htmlspecialchars($i['email']) ?></td>
<td><?= isset($i['creado_en']) && $i['creado_en'] instanceof DateTime ? $i['creado_en']->format('Y-m-d H:i') : '' ?></td>
<td>
<?php if (isset($i['activo']) && $i['activo'] == 1): ?>
<a href="/IMPORTADORES/agentes/toggle_estado?id=<?= $i['id_usuario'] ?>&success=1" class="btn btn-sm btn-danger">Suspender</a>
<?php else: ?>
<a href="/IMPORTADORES/agentes/toggle_estado?id=<?= $i['id_usuario'] ?>&success=1" class="btn btn-sm btn-success">Activar</a>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php if (isset($_GET['success'])): ?>
<script>
Swal.fire({
icon: 'success',
title: 'Estado actualizado',
text: 'El estado del usuario se ha actualizado correctamente.',
confirmButtonColor: '#198754'
});
</script>
<?php endif; ?>

View File

@@ -0,0 +1,85 @@
<?php
require_once __DIR__ . '/../../app/helpers/crypto.php';
include __DIR__ . '/../partials/sidebar_agente.php';
?>
<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>
<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>
<div class="content px-4 pt-5 mt-4">
<h4>📥 Solicitudes Pendientes</h4>
<table class="table table-hover mt-3 align-middle">
<thead class="table-dark">
<tr>
<th>#</th>
<th>Empresa</th>
<th>RFC</th>
<th>Correo</th>
<th>Teléfono</th>
<th>Fecha</th>
<th>Archivo SAT</th>
<th>Acción</th>
</tr>
</thead>
<tbody>
<?php foreach ($solicitudes as $s): ?>
<tr>
<td><?= $s['request_id'] ?></td>
<td><?= htmlspecialchars(decrypt($s['company_name'])) ?></td>
<td><?= htmlspecialchars(decrypt($s['rfc'])) ?></td>
<td><?= htmlspecialchars($s['email']) ?></td>
<td><?= htmlspecialchars($s['phone']) ?></td>
<td><?= $s['request_date'] ? $s['request_date']->format('Y-m-d H:i') : '' ?></td>
<td>
<?php if (!empty($s['opinion_file'])): ?>
<a href="/IMPORTADORES/ver_opinion.php?file=<?= urlencode($s['opinion_file']) ?>" target="_blank" class="btn btn-sm btn-outline-secondary">Ver PDF</a>
<?php else: ?>
<span class="text-muted">No adjunto</span>
<?php endif; ?>
</td>
<td>
<a href="/IMPORTADORES/agentes/aprobar_solicitud?id=<?= $s['request_id'] ?>" class="btn btn-sm btn-success">Aprobar</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>

115
views/choferes/crear.php Normal file
View File

@@ -0,0 +1,115 @@
<!-- views/choferes/crear.php -->
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>🚛 Nuevo Chofer</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>
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> Nuevo Chofer</h4>
<div class="card p-4 shadow-sm bg-white">
<!-- Se agrega enctype para subir archivos -->
<form action="/IMPORTADORES/choferes/guardar" method="POST" enctype="multipart/form-data">
<div class="mb-3">
<label for="transportista_id" class="form-label">Transportista</label>
<select name="transportista_id" id="transportista_id" class="form-select" required>
<option value="">-- Selecciona un transportista --</option>
<?php foreach ($transportistas as $t): ?>
<option value="<?= $t['id_transportista'] ?>">
<?= htmlspecialchars($t['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label for="nombre" class="form-label">Nombre</label>
<input name="nombre" id="nombre" type="text" class="form-control" required>
</div>
<div class="mb-3">
<label for="apellido" class="form-label">Apellido</label>
<input name="apellido" id="apellido" type="text" class="form-control" required>
</div>
<div class="mb-3">
<label for="numero_licencia" class="form-label">Número de Licencia</label>
<input name="numero_licencia" id="numero_licencia" type="text" class="form-control" required>
</div>
<div class="mb-3">
<label for="telefono" class="form-label">Teléfono</label>
<input name="telefono" id="telefono" type="tel" class="form-control">
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input name="email" id="email" type="email" class="form-control">
</div>
<div class="mb-3">
<label for="fecha_ingreso" class="form-label">Fecha de Ingreso</label>
<input name="fecha_ingreso" id="fecha_ingreso" type="date" class="form-control">
</div>
<!-- Nuevo campo para foto -->
<div class="mb-3">
<label for="foto" class="form-label">Foto del Chofer</label>
<input name="foto" id="foto" type="file" class="form-control" accept="image/*">
</div>
<button type="submit" class="btn btn-success">Guardar</button>
<a href="/IMPORTADORES/choferes/lista" class="btn btn-secondary ms-2">Cancelar</a>
</form>
</div>
</div>
</body>
</html>

125
views/choferes/editar.php Normal file
View File

@@ -0,0 +1,125 @@
<!-- views/choferes/editar.php -->
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>✏️ Editar Chofer #<?= (int)$chofer['id_chofer'] ?></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'; ?>
<br><br>
<div class="content">
<h4>✏️ Editar Chofer #<?= (int)$chofer['id_chofer'] ?></h4>
<div class="card p-4 shadow-sm bg-white">
<form action="/IMPORTADORES/choferes/actualizar" method="POST" enctype="multipart/form-data">
<input type="hidden" name="id_chofer" value="<?= (int)$chofer['id_chofer'] ?>">
<!-- Transportista -->
<div class="mb-3">
<label for="transportista_id" class="form-label">Transportista</label>
<select name="transportista_id" id="transportista_id" class="form-select" required>
<option value="">-- Selecciona un transportista --</option>
<?php foreach ($transportistas as $t): ?>
<option value="<?= $t['id_transportista'] ?>"
<?= $chofer['transportista_id'] == $t['id_transportista'] ? 'selected' : '' ?>>
<?= htmlspecialchars($t['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="row">
<!-- Nombre -->
<div class="col-md-6 mb-3">
<label for="nombre" class="form-label">Nombre</label>
<input name="nombre" id="nombre" type="text" class="form-control"
value="<?= htmlspecialchars($chofer['nombre']) ?>" required>
</div>
<!-- Apellido -->
<div class="col-md-6 mb-3">
<label for="apellido" class="form-label">Apellido</label>
<input name="apellido" id="apellido" type="text" class="form-control"
value="<?= htmlspecialchars($chofer['apellido']) ?>" required>
</div>
</div>
<div class="row">
<!-- Licencia -->
<div class="col-md-6 mb-3">
<label for="numero_licencia" class="form-label">Número de Licencia</label>
<input name="numero_licencia" id="numero_licencia" type="text" class="form-control"
value="<?= htmlspecialchars($chofer['numero_licencia']) ?>" required>
</div>
<!-- Teléfono -->
<div class="col-md-6 mb-3">
<label for="telefono" class="form-label">Teléfono</label>
<input name="telefono" id="telefono" type="tel" class="form-control"
value="<?= htmlspecialchars($chofer['telefono']) ?>">
</div>
</div>
<div class="row">
<!-- Email -->
<div class="col-md-6 mb-3">
<label for="email" class="form-label">Email</label>
<input name="email" id="email" type="email" class="form-control"
value="<?= htmlspecialchars($chofer['email']) ?>">
</div>
<!-- Fecha de Ingreso -->
<div class="col-md-6 mb-3">
<label for="fecha_ingreso" class="form-label">Fecha de Ingreso</label>
<input name="fecha_ingreso" id="fecha_ingreso" type="date" class="form-control"
value="<?= htmlspecialchars($chofer['fecha_ingreso']) ?>">
</div>
</div>
<!-- Foto actual -->
<div class="mb-3">
<label class="form-label">Foto Actual</label><br>
<?php if (!empty($chofer['foto_url'])): ?>
<img src="<?= htmlspecialchars($chofer['foto_url']) ?>" alt="Foto Chofer" width="100" class="mb-2">
<?php else: ?>
<span class="text-muted">Sin foto</span>
<?php endif; ?>
</div>
<!-- Cambiar foto -->
<div class="mb-3">
<label for="foto" class="form-label">Nueva Foto</label>
<input name="foto" id="foto" type="file" class="form-control" accept="image/*">
</div>
<!-- Activo -->
<div class="form-check mb-4">
<input name="status" id="status" type="checkbox" class="form-check-input"
<?= $chofer['status'] == 1 ? 'checked' : '' ?>>
<label for="status" class="form-check-label">Activo</label>
</div>
<button type="submit" class="btn btn-primary">Actualizar</button>
<a href="/IMPORTADORES/choferes/lista" class="btn btn-secondary ms-2">Cancelar</a>
</form>
</div>
</div>
</body>
</html>

128
views/choferes/lista.php Normal file
View File

@@ -0,0 +1,128 @@
<!-- views/choferes/lista.php -->
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>🚛 Mis Choferes</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 Choferes</h4>
<a href="/IMPORTADORES/choferes/crear" class="btn btn-success mb-3"> Nuevo Chofer</a>
<table class="table table-striped" id="tabla-choferes">
<thead>
<tr>
<th>#</th>
<th>Nombre Completo</th>
<th>Licencia</th>
<th>Teléfono</th>
<th>Email</th>
<th>Ingreso</th>
<th>Transportista</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
<?php foreach($choferes as $c): ?>
<tr>
<td><?= $c['id_chofer'] ?></td>
<td><?= htmlspecialchars($c['nombre_completo']) ?></td>
<td><?= htmlspecialchars($c['numero_licencia']) ?></td>
<td><?= htmlspecialchars($c['telefono']) ?></td>
<td><?= htmlspecialchars($c['email']) ?></td>
<td>
<?php
if ($c['created_at'] instanceof DateTime) {
echo $c['created_at']->format('Y-m-d');
} else {
echo htmlspecialchars($c['created_at']);
}
?>
</td>
<td><?= htmlspecialchars($c['transportista']) ?></td>
<td>
<a href="/IMPORTADORES/choferes/editar?id=<?= $c['id_chofer'] ?>" class="btn btn-sm btn-primary">✏️</a>
<button class="btn btn-sm btn-danger" onclick="confirmDeleteChofer(<?= $c['id_chofer'] ?>)">🗑️</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<script>
function confirmDeleteChofer(id) {
Swal.fire({
title: '¿Eliminar chofer?',
text: 'Será marcado como inactivo.',
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Sí, eliminar',
cancelButtonText: 'Cancelar',
confirmButtonColor: '#d33'
}).then(r => {
if (r.isConfirmed) {
window.location = `/IMPORTADORES/choferes/eliminar?id=${id}`;
}
});
}
<?php if(isset($_GET['deleted'])): ?>
Swal.fire('¡Hecho!','Chofer eliminado.','success');
<?php endif; ?>
<?php if(isset($_GET['created'])): ?>
Swal.fire('¡Listo!','Chofer creado.','success');
<?php endif; ?>
<?php if(isset($_GET['updated'])): ?>
Swal.fire('¡Listo!','Chofer actualizado.','success');
<?php endif; ?>
</script>
</body>
</html>

159
views/home/inicio.php Normal file
View File

@@ -0,0 +1,159 @@
<?php
require_once __DIR__ . '/../../config/database.php';
$conn = getConnection();
$sql = "SELECT TOP 1 * FROM configuracion_sistema";
$stmt = sqlsrv_query($conn, $sql);
$config = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
// Variables con valores por defecto
$nombre = $config['nombre_plataforma'] ?? 'Sistema Integral para Importadores de Hidrocarburos';
$siglas = $config['siglas'] ?? 'SIIH';
$logo = $config['logo_url'] ?? 'assets/img/logo_siih.png';
$color1 = explode(',', $config['colores_primarios'] ?? '#003366,#0055A5')[0];
$color2 = explode(',', $config['colores_primarios'] ?? '#003366,#0055A5')[1];
$mantenimiento = $config['modo_mantenimiento'] ?? 0;
$mensajeMantenimiento = $config['mensaje_mantenimiento'] ?? 'El sistema se encuentra en mantenimiento temporal. Por favor, vuelve más tarde.';
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title><?= htmlspecialchars($siglas) ?> | Inicio</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Bootstrap -->
<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>
<!-- Iconos -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet">
<style>
body {
background-color: #f4f6f9;
font-family: 'Segoe UI', sans-serif;
}
.navbar {
background-color: #fff;
}
.navbar .nav-link, .navbar-brand {
color:<?= $color1 ?> !important;
font-weight: 500;
}
.navbar .nav-link.active {
background-color: #F9F9F9;
border-radius: 5px;
}
.logo-siih {
height: 90px;
margin-right: 10px;
}
.hero {
background: linear-gradient(to right, <?= $color1 ?>, <?= $color2 ?>);
color: white;
padding: 80px 20px;
text-align: center;
}
.features {
background-color: white;
padding: 50px 0;
}
.features i {
font-size: 40px;
color: <?= $color1 ?>;
margin-bottom: 10px;
}
footer {
background-color: #e9ecef;
padding: 20px;
text-align: center;
font-size: 14px;
color: #666;
}
</style>
</head>
<body>
<!-- NAVBAR -->
<nav class="navbar navbar-expand-lg">
<div class="container">
<a class="navbar-brand d-flex align-items-center" href="#">
<img src="/IMPORTADORES/public/<?= htmlspecialchars($logo) ?>" alt="Logo" class="logo-siih">
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#nav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse justify-content-end" id="nav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="/IMPORTADORES/">Inicio</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/IMPORTADORES/registro">Registro</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/IMPORTADORES/login">Inicio sesión</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- ALERTA DE MANTENIMIENTO -->
<?php if ($mantenimiento): ?>
<div class="container mt-4">
<div class="alert alert-danger text-center" role="alert">
<i class="fas fa-triangle-exclamation me-2"></i>
<?= htmlspecialchars($mensajeMantenimiento) ?>
</div>
</div>
<?php endif; ?>
<!-- HERO -->
<section class="hero">
<div class="container">
<h1 class="display-5 mb-3"><?= htmlspecialchars($nombre) ?></h1>
<p class="lead">Una plataforma confiable para gestionar el registro y control de importadores de hidrocarburos en México.</p>
</div>
</section>
<!-- FEATURES -->
<section class="features text-center">
<div class="container">
<div class="row">
<div class="col-md-4">
<i class="fas fa-file-signature"></i>
<h5 class="mt-3">Registro en línea</h5>
<p>Los importadores pueden enviar su solicitud y documentación de forma digital.</p>
</div>
<div class="col-md-4">
<i class="fas fa-user-shield"></i>
<h5 class="mt-3">Autorización segura</h5>
<p>Las agencias aduanales validan manualmente cada solicitud antes de otorgar acceso.</p>
</div>
<div class="col-md-4">
<i class="fas fa-database"></i>
<h5 class="mt-3">Información centralizada</h5>
<p>Todas las solicitudes y datos se almacenan de forma segura y organizada.</p>
</div>
</div>
</div>
</section>
<!-- FOOTER -->
<footer class="fixed-bottom">
&copy; <?= date('Y') ?> <?= htmlspecialchars($siglas) ?> · <?= htmlspecialchars($nombre) ?> · Plataforma desarrollada por AduanaSoft
</footer>
</body>
</html>

View File

@@ -0,0 +1,99 @@
<?php
include __DIR__ . '/../partials/sidebar_importador.php';
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Dashboard | Importador</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>
<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>
<div class="content">
<br><br>
<h4 class="mb-4">📦 Panel del Importador</h4>
<div class="row g-4">
<div class="col-md-4">
<div class="card shadow-sm p-3">
<h5 class="text-primary">Transportes</h5>
<p>Gestiona y carga tus unidades de transporte.</p>
<a href="/IMPORTADORES/transportes" class="btn btn-primary btn-sm mt-2">Ver transportes</a>
</div>
</div>
<div class="col-md-4">
<div class="card shadow-sm p-3">
<h5 class="text-success">Transportistas</h5>
<p>Agrega o consulta los choferes que colaboran contigo.</p>
<a href="/IMPORTADORES/transportistas" class="btn btn-success btn-sm mt-2">Ver transportistas</a>
</div>
</div>
<div class="col-md-4">
<div class="card shadow-sm p-3">
<h5 class="text-info">Solicitud de Importación</h5>
<p>Inicia nuevas solicitudes de pedimentos.</p>
<a href="/IMPORTADORES/solicitudes" class="btn btn-info btn-sm mt-2">Nueva solicitud</a>
</div>
</div>
<div class="col-md-4">
<div class="card shadow-sm p-3">
<h5 class="text-warning">Configuración</h5>
<p>Administra los datos de tu empresa y preferencias.</p>
<a href="/IMPORTADORES/configuracion" class="btn btn-warning btn-sm mt-2">Configurar</a>
</div>
</div>
<div class="col-md-4">
<div class="card shadow-sm p-3">
<h5 class="text-danger">Cerrar sesión</h5>
<p>Salir del sistema de forma segura.</p>
<a href="/IMPORTADORES/sistemas/logout" class="btn btn-danger btn-sm mt-2">Logout</a>
</div>
</div>
</div>
</div>
</body>
</html>

138
views/login/index.php Normal file
View File

@@ -0,0 +1,138 @@
<?php
require_once __DIR__ . '/../../config/database.php';
$conn = getConnection();
$sql = "SELECT TOP 1 * FROM configuracion_sistema";
$stmt = sqlsrv_query($conn, $sql);
$config = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
$nombre = $config['nombre_plataforma'] ?? 'Sistema Integral para Importadores de Hidrocarburos';
$siglas = $config['siglas'] ?? 'SIIH';
$logo = $config['logo_url'] ?? 'assets/img/logo_siih.png';
$color1 = explode(',', $config['colores_primarios'] ?? '#003366,#0055A5')[0];
$color2 = explode(',', $config['colores_primarios'] ?? '#003366,#0055A5')[1];
$mantenimiento = $config['modo_mantenimiento'] ?? 0;
$mensajeMantenimiento = $config['mensaje_mantenimiento'] ?? 'El sistema se encuentra en mantenimiento temporal. Por favor, vuelve más tarde.';
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title><?= htmlspecialchars($siglas) ?> | Iniciar sesión</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<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://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet">
<style>
body {
background-color: #f4f6f9;
font-family: 'Segoe UI', sans-serif;
}
.navbar {
background-color: #fff;
}
.navbar .nav-link, .navbar-brand {
color:<?= $color1 ?> !important;
font-weight: 500;
}
.navbar .nav-link.active {
background-color: #F9F9F9;
border-radius: 5px;
}
.logo-siih {
height: 90px;
margin-right: 10px;
}
.login-container {
max-width: 420px;
margin: 80px auto;
background: white;
padding: 40px;
border-radius: 12px;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.08);
}
.form-control {
border-radius: 6px;
}
footer {
background-color: #e9ecef;
padding: 20px;
text-align: center;
font-size: 14px;
color: #666;
margin-top: 60px;
}
</style>
</head>
<body>
<!-- Navbar institucional -->
<nav class="navbar navbar-expand-lg">
<div class="container">
<a class="navbar-brand d-flex align-items-center text-dark" href="#">
<img src="/IMPORTADORES/public/<?= htmlspecialchars($logo) ?>" alt="Logo" class="logo-siih">
| Inicio de Importador
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse justify-content-end" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="/IMPORTADORES/">Inicio</a>
</li>
<li class="nav-item">
<a class="nav-link " aria-current="page" href="/IMPORTADORES/registro">Registro</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="/IMPORTADORES/login">Inicio sesión</a>
</li>
</ul>
</div>
</div>
</nav>
<?php if ($mantenimiento): ?>
<div class="container mt-4">
<div class="alert alert-danger text-center" role="alert">
<i class="fas fa-triangle-exclamation me-2"></i>
<?= htmlspecialchars($mensajeMantenimiento) ?>
</div>
</div>
<?php endif; ?>
<div class="login-container">
<h4 class="mb-4 text-center text-dark">Iniciar de sesión </h4>
<form action="/IMPORTADORES/login/validar" method="POST">
<div class="mb-3">
<label class="form-label">Correo electrónico</label>
<input type="email" name="email" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">Contraseña</label>
<input type="password" name="password" class="form-control" required>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-primary">Iniciar sesión</button>
</div>
</form>
</div>
<!-- FOOTER -->
<footer class="fixed-bottom">
&copy; <?= date('Y') ?> <?= htmlspecialchars($siglas) ?> · <?= htmlspecialchars($nombre) ?> · Plataforma desarrollada por AduanaSoft
</footer>
</body>
</html>

View File

@@ -0,0 +1,33 @@
<?php
session_start();
if (!isset($_SESSION['usuario_id']) || $_SESSION['tipo_usuario'] !== 'agente_aduanal') {
header('Location: /IMPORTADORES/login');
exit;
}
$nombreAgente = $_SESSION['usuario_nombre'];
?>
<!-- 🔷 NAVBAR -->
<nav class="navbar navbar-dark bg-dark">
<div class="container-fluid">
<span class="navbar-brand">SIIH | Agente Aduanal</span>
<div class="d-flex text-white">
Bienvenido, <?= htmlspecialchars($nombreAgente) ?>&nbsp;&nbsp;
<a href="/IMPORTADORES/sistemas/logout" class="btn btn-outline-light btn-sm">Cerrar sesión</a>
</div>
</div>
</nav>
<!-- 📘 SIDEBAR -->
<div class="sidebar d-none d-lg-block">
<nav class="nav flex-column">
<a href="/IMPORTADORES/AGENTES/dashboard" class="nav-link active">📊 Dashboard</a>
<a href="/IMPORTADORES/AGENTES/activos" class="nav-link">✅ Importadores Activos</a>
<a href="/IMPORTADORES/AGENTES/solicitudes_pendientes" class="nav-link">📥 Solicitudes de Registro</a>
<a href="/IMPORTADORES/bitacoras/login" class="nav-link">🕓 Bitácora</a>
</nav>
</div>

View File

@@ -0,0 +1,122 @@
<!-- views/partials/sidebar_importador.php -->
<?php
if (!isset($_SESSION['usuario_id']) || $_SESSION['tipo_usuario'] !== 'importador') {
header('Location: /IMPORTADORES/login');
exit;
}
?>
<nav class="navbar navbar-dark bg-dark fixed-top">
<div class="container-fluid">
<span class="navbar-brand">SIIH | Importador</span>
<div class="d-flex text-white">
Bienvenido, <?= htmlspecialchars($_SESSION['usuario_nombre']) ?>&nbsp;&nbsp;
<a href="/IMPORTADORES/sistemas/logout" class="btn btn-outline-light btn-sm">Cerrar sesión</a>
</div>
</div>
</nav>
<div class="sidebar bg-dark text-white pt-5">
<nav class="nav flex-column">
<!-- INICIO -->
<a href="/IMPORTADORES/importadores/dashboard"
class="nav-link px-3 py-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/importadores/dashboard' ? 'active' : '' ?>">
🏠 Inicio
</a>
<!-- TRANSPORTISTAS -->
<a class="nav-link px-3 py-2 d-flex justify-content-between align-items-center
<?= str_contains($_SERVER['REQUEST_URI'], '/transportistas') ? 'active' : '' ?>"
data-bs-toggle="collapse" href="#submenuTransportistas" role="button" aria-expanded="false">
👨‍✈️ Transportistas
<span class="badge bg-secondary">3</span>
</a>
<div class="collapse <?= str_contains($_SERVER['REQUEST_URI'], '/transportistas') ? 'show' : '' ?>" id="submenuTransportistas">
<nav class="nav flex-column ms-3">
<a href="/IMPORTADORES/transportistas/lista"
class="nav-link px-3 py-1 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/transportistas/lista' ? 'active' : '' ?>">
• Mis transportistas
</a>
<a href="/IMPORTADORES/transportistas/alta"
class="nav-link px-3 py-1 <?= str_contains($_SERVER['REQUEST_URI'], '/transportistas/alta') ? 'active' : '' ?>">
• Alta de transportista
</a>
<a href="/IMPORTADORES/transportistas/bulk_upload"
class="nav-link px-3 py-1 <?= str_contains($_SERVER['REQUEST_URI'], '/transportistas/bulk_upload') ? 'active' : '' ?>">
• Carga masiva
</a>
</nav>
</div>
<!-- TRANSPORTES -->
<a class="nav-link px-3 py-2 d-flex justify-content-between align-items-center
<?= str_contains($_SERVER['REQUEST_URI'], '/transportes') ? 'active' : '' ?>"
data-bs-toggle="collapse" href="#submenuTransportes" role="button" aria-expanded="false">
🚚 Transportes
<span class="badge bg-secondary">3</span>
</a>
<div class="collapse <?= str_contains($_SERVER['REQUEST_URI'], '/transportes') ? 'show' : '' ?>" id="submenuTransportes">
<nav class="nav flex-column ms-3">
<a href="/IMPORTADORES/transportes/lista"
class="nav-link px-3 py-1 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/transportes/lista' ? 'active' : '' ?>">
• Mis transportes
</a>
<a href="/IMPORTADORES/transportes/crear"
class="nav-link px-3 py-1 <?= str_contains($_SERVER['REQUEST_URI'], '/transportes/crear') ? 'active' : '' ?>">
• Nuevo transporte
</a>
<a href="/IMPORTADORES/transportes/masivo"
class="nav-link px-3 py-1 <?= str_contains($_SERVER['REQUEST_URI'], '/transportes/masivo') ? 'active' : '' ?>">
• Carga masiva
</a>
</nav>
</div>
<!-- CHOFERES -->
<a class="nav-link px-3 py-2 d-flex justify-content-between align-items-center
<?= str_contains($_SERVER['REQUEST_URI'], '/choferes') ? 'active' : '' ?>"
data-bs-toggle="collapse" href="#submenuChoferes" role="button" aria-expanded="false">
🚛 Choferes
<span class="badge bg-secondary">2</span>
</a>
<div class="collapse <?= str_contains($_SERVER['REQUEST_URI'], '/choferes') ? 'show' : '' ?>" id="submenuChoferes">
<nav class="nav flex-column ms-3">
<a href="/IMPORTADORES/choferes/lista"
class="nav-link px-3 py-1 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/choferes/lista' ? 'active' : '' ?>">
• Mis choferes
</a>
<a href="/IMPORTADORES/choferes/crear"
class="nav-link px-3 py-1 <?= str_contains($_SERVER['REQUEST_URI'], '/choferes/crear') ? 'active' : '' ?>">
• Nuevo chofer
</a>
</nav>
</div>
<!-- SOLICITUDES DE IMPORTACIÓN -->
<a class="nav-link px-3 py-2 d-flex justify-content-between align-items-center
<?= str_contains($_SERVER['REQUEST_URI'], '/solicitud_importacion') ? 'active' : '' ?>"
data-bs-toggle="collapse" href="#submenuSolicitudes" role="button" aria-expanded="false">
📄 Solicitudes Importación
<span class="badge bg-secondary">2</span>
</a>
<div class="collapse <?= str_contains($_SERVER['REQUEST_URI'], '/solicitud_importacion') ? 'show' : '' ?>" id="submenuSolicitudes">
<nav class="nav flex-column ms-3">
<a href="/IMPORTADORES/solicitud_importacion/lista"
class="nav-link px-3 py-1 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/solicitud_importacion/lista' ? 'active' : '' ?>">
• Mis solicitudes
</a>
<a href="/IMPORTADORES/solicitud_importacion/crear"
class="nav-link px-3 py-1 <?= str_contains($_SERVER['REQUEST_URI'], '/solicitud_importacion/crear') ? 'active' : '' ?>">
• Nueva solicitud
</a>
</nav>
</div>
<!-- CONFIGURACIÓN -->
<a href="/IMPORTADORES/configuracion"
class="nav-link px-3 py-2 <?= str_contains($_SERVER['REQUEST_URI'], '/configuracion') ? 'active' : '' ?>">
⚙️ Configuración
</a>
</nav>
</div>

View File

@@ -0,0 +1,76 @@
<style>
body {
font-family: 'Segoe UI', sans-serif;
}
.table td, .table th {
vertical-align: middle;
}
.sidebar {
width: 220px;
background-color: #343a40;
position: fixed;
top: 56px;
bottom: 0;
left: 0;
z-index: 1045;
padding-top: 1rem;
height: 100vh;
overflow-y: auto;
border-right: 1px solid #dee2e6;
}
.sidebar a {
color: white;
text-decoration: none;
}
.sidebar .nav-link.active,
.sidebar .nav-link:hover {
background-color: #495057;
}
.content {
margin-left: 230px;
margin-top: 70px;
}
@media (max-width: 991.98px) {
.sidebar {
position: relative;
width: 100%;
height: auto;
border-right: none;
}
.content {
margin-left: 0;
margin-top: 20px;
}
}
</style>
<!-- 🔷 NAVBAR -->
<nav class="navbar navbar-dark bg-dark fixed-top">
<div class="container-fluid">
<a class="navbar-brand" href="#">SIIH | Admin</a>
</div>
</nav>
<!-- 📘 SIDEBAR -->
<!-- 📘 SIDEBAR -->
<div class="sidebar text-white">
<nav class="nav flex-column">
<a href="/IMPORTADORES/sistemas/alta_usuarios" class="nav-link px-3 py-2 <?= $_GET['url'] === 'sistemas/alta_usuarios' ? 'active' : '' ?>">👥 Usuarios</a>
<a href="/IMPORTADORES/sistemas/bitacora_login" class="nav-link px-3 py-2 <?= $_GET['url'] === 'sistemas/bitacora_login' ? 'active' : '' ?>">🕵️ Bitácora Accesos</a>
<a href="/IMPORTADORES/sistemas/bitacora_usuarios" class="nav-link px-3 py-2 <?= $_GET['url'] === 'sistemas/bitacora_usuarios' ? 'active' : '' ?>">🛠️ Bitácora Usuarios</a>
<a href="#" class="nav-link px-3 py-2">📦 Configuración</a>
<a href="/IMPORTADORES/sistemas/logout" class="nav-link px-3 py-2 text-danger">🚪 Cerrar sesión</a>
</nav>
</div>

198
views/registro/form.php Normal file
View File

@@ -0,0 +1,198 @@
<?php
require_once __DIR__ . '/../../config/database.php';
$conn = getConnection();
// Consultar configuración del sistema
$sql = "SELECT TOP 1 * FROM configuracion_sistema";
$stmt = sqlsrv_query($conn, $sql);
$config = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
// Variables con valores por defecto
$nombre = $config['nombre_plataforma'] ?? 'Sistema Integral para Importadores de Hidrocarburos';
$siglas = $config['siglas'] ?? 'SIIH';
$logo = $config['logo_url'] ?? 'assets/img/logo_siih.png';
$color1 = explode(',', $config['colores_primarios'] ?? '#003366,#0055A5')[0];
$color2 = explode(',', $config['colores_primarios'] ?? '#003366,#0055A5')[1];
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title><?= htmlspecialchars($siglas) ?> | Registro de Importador</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Bootstrap 5 -->
<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>
<!-- SweetAlert2 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<!-- Google reCAPTCHA v2 -->
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<style>
body {
background-color: #f4f6f9;
font-family: 'Segoe UI', sans-serif;
}
.navbar {
background-color: #fff
}
.navbar .nav-link,
.navbar-brand {
color: <?= $color1 ?> !important;
font-weight: 500;
}
.navbar .nav-link.active {
background-color: #F9F9F9;
border-radius: 5px;
}
.card-form {
max-width: 900px;
margin: 50px auto;
padding: 40px;
background: #fff;
border-radius: 10px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
}
.form-label {
font-weight: 500;
}
.form-control, .form-select {
border-radius: 6px;
}
footer {
background-color: #e9ecef;
padding: 20px;
text-align: center;
font-size: 14px;
color: #666;
}
.recaptcha {
margin-top: 20px;
}
.logo-siih {
height: 90px;
margin-right: 10px;
}
</style>
</head>
<body>
<!-- Navbar institucional -->
<nav class="navbar navbar-expand-lg">
<div class="container">
<a class="navbar-brand d-flex align-items-center text-dark" href="#">
<img src="/IMPORTADORES/public/<?= htmlspecialchars($logo) ?>" alt="Logo" class="logo-siih">
| Registro de Importador
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse justify-content-end" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="/IMPORTADORES/">Inicio</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/IMPORTADORES/registro">Registro</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/IMPORTADORES/login">Inicio sesión</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- Contenedor del formulario -->
<div class="container card-form">
<form action="/IMPORTADORES/registro/enviar" method="POST" enctype="multipart/form-data" id="formRegistro">
<div class="row g-3">
<div class="col-md-6">
<label for="company_name" class="form-label">Nombre de la empresa *</label>
<input type="text" class="form-control" name="company_name" required>
</div>
<div class="col-md-6">
<label for="rfc" class="form-label">RFC *</label>
<input type="text" class="form-control" name="rfc" maxlength="13" required>
</div>
<div class="col-md-6">
<label for="email" class="form-label">Correo electrónico *</label>
<input type="email" class="form-control" name="email" required>
</div>
<div class="col-md-6">
<label for="phone" class="form-label">Teléfono *</label>
<input type="text" class="form-control" name="phone" required>
</div>
<div class="col-md-12">
<label for="opinion_file" class="form-label">Padron de importadores o encargo conferido (PDF) *</label>
<input type="file" class="form-control" name="opinion_file" id="opinion_file" accept=".pdf" required>
</div>
<div class="col-md-12 text-center recaptcha">
<div class="g-recaptcha" data-sitekey="6LfkMB8rAAAAAH-BEC1cMYij1HEhw4sTaEOl-UCA"></div>
</div>
<div class="col-md-12 text-end mt-4">
<button type="submit" class="btn btn-primary px-4 py-2">Enviar solicitud</button>
</div>
</div>
</form>
</div>
<div class="container ">
<div class="alert alert-warning" role="alert">
Una vez que envíes tu solicitud, será revisada manualmente por la agencia aduanal.
Recibirás una notificación por correo electrónico cuando tu registro sea aprobado, junto con las instrucciones para activar tu cuenta e iniciar sesión en la plataforma.
</div>
</div>
<!-- FOOTER -->
<footer class="fixed-bottom">
&copy; <?= date('Y') ?> <?= htmlspecialchars($siglas) ?> · <?= htmlspecialchars($nombre) ?> · Plataforma desarrollada por AduanaSoft
</footer>
<!-- Validación JS -->
<script>
document.getElementById('formRegistro').addEventListener('submit', function (e) {
const archivo = document.getElementById('opinion_file').files[0];
const recaptcha = grecaptcha.getResponse();
if (!archivo || archivo.type !== 'application/pdf') {
e.preventDefault();
Swal.fire("Error", "Solo se permite subir archivos PDF.", "error");
return;
}
if (recaptcha.length === 0) {
e.preventDefault();
Swal.fire("Verificación requerida", "Por favor completa el reCAPTCHA.", "warning");
return;
}
});
</script>
</body>
</html>

View File

@@ -0,0 +1,68 @@
<?php
require_once __DIR__ . '/../../config/database.php';
$conn = getConnection();
$sql = "SELECT TOP 1 * FROM configuracion_sistema";
$stmt = sqlsrv_query($conn, $sql);
$config = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
$nombre = $config['nombre_plataforma'] ?? 'Sistema Integral para Importadores de Hidrocarburos';
$siglas = $config['siglas'] ?? 'SIIH';
$logo = $config['logo_url'] ?? 'assets/img/logo_siih.png';
$color1 = explode(',', $config['colores_primarios'] ?? '#003366,#0055A5')[0];
$color2 = explode(',', $config['colores_primarios'] ?? '#003366,#0055A5')[1];
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Gracias por tu solicitud | <?= htmlspecialchars($siglas) ?></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<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 {
background-color: #f4f6f9;
font-family: 'Segoe UI', sans-serif;
text-align: center;
padding-top: 100px;
}
.swal2-popup {
font-size: 1.1rem !important;
animation: fadeInUp 0.6s ease-out;
}
@keyframes fadeInUp {
0% {
transform: translateY(20px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
</style>
</head>
<body>
<script>
document.addEventListener('DOMContentLoaded', function () {
Swal.fire({
icon: 'success',
title: '¡Gracias por tu solicitud!',
html: `<p>Tu información fue enviada correctamente.<br>Un agente aduanal revisará tu expediente y te contactará por correo.</p>`,
confirmButtonText: 'Volver al inicio',
confirmButtonColor: '<?= $color1 ?>',
allowOutsideClick: false,
allowEscapeKey: false
}).then((result) => {
if (result.isConfirmed) {
window.location.href = '/IMPORTADORES/';
}
});
});
</script>
</body>
</html>

View File

@@ -0,0 +1,167 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title> Nueva Solicitud de Importación</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; }
.card { border-radius: 12px; }
</style>
</head>
<body>
<?php include __DIR__ . '/../partials/sidebar_importador.php'; ?>
<br><br>
<div class="content">
<h4> Nueva Solicitud de Importación</h4>
<div class="card p-4 bg-white shadow-sm">
<form action="/IMPORTADORES/solicitud_importacion/guardar" method="POST" enctype="multipart/form-data">
<!-- Sección principal -->
<div class="row">
<div class="col-md-4 mb-3">
<label for="numero_factura" class="form-label">Número de Factura</label>
<input id="numero_factura" name="numero_factura" type="text" class="form-control" required>
</div>
<div class="col-md-4 mb-3">
<label for="fecha_factura" class="form-label">Fecha de Factura</label>
<input id="fecha_factura" name="fecha_factura" type="date" class="form-control" required>
</div>
<div class="col-md-4 mb-3">
<label for="anexo22_apendice" class="form-label">Anexo 22 Apéndice</label>
<select id="anexo22_apendice" name="anexo22_apendice" class="form-select" required>
<option value="">-- Selecciona Aduana --</option>
<?php foreach($aduanas as $a): ?>
<option value="<?= $a['aduana_seccion'] ?>"><?= htmlspecialchars($a['aduana_seccion'].' '.$a['nombre']) ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<!-- Segunda fila: Incoterm, País, Moneda -->
<div class="row">
<div class="col-md-4 mb-3">
<label for="incoterm" class="form-label">INCOTERM</label>
<select id="incoterm" name="incoterm" class="form-select" required>
<option value="">-- Selecciona Incoterm --</option>
<?php foreach($incoterms as $inc): ?>
<option value="<?= htmlspecialchars($inc['INCOTERM']) ?>"><?= htmlspecialchars($inc['INCOTERM'].' - '.$inc['DESCESPANOL']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-4 mb-3">
<label for="pais_proveedor" class="form-label">País (Proveedor)</label>
<select id="pais_proveedor" name="pais_proveedor" class="form-select">
<option value="">-- Selecciona País --</option>
<?php foreach($paises as $p): ?>
<option value="<?= $p['id_pais'] ?>"><?= htmlspecialchars($p['nombre']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-4 mb-3">
<label for="tipo_moneda" class="form-label">Moneda</label>
<select id="tipo_moneda" name="tipo_moneda" class="form-select">
<?php foreach(['MXN'=>'Peso Mexicano','USD'=>'Dólar USD','EUR'=>'Euro','CNY'=>'Yuan','GBP'=>'Libra GBP','JPY'=>'Yen'] as $code=>$label): ?>
<option value="<?= $code ?>"><?= "$label ($code)" ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<!-- Valor y vinculación -->
<div class="row">
<div class="col-md-8 mb-3">
<label for="valor_factura" class="form-label">Valor Factura</label>
<input id="valor_factura" name="valor_factura" type="number" step="0.01" class="form-control">
</div>
<div class="col-md-4 mb-3">
<label for="vinculacion" class="form-label">Vinculación</label>
<select id="vinculacion" name="vinculacion" class="form-select">
<option value="0">No existe</option>
<option value="1">Existe, no afecta</option>
<option value="2">Existe y afecta</option>
</select>
</div>
</div>
<!-- Transportista, Chofer, Foto Solicitud -->
<div class="row">
<div class="col-md-4 mb-3">
<label for="transportista_id" class="form-label">Transportista</label>
<select id="transportista_id" name="transportista_id" class="form-select" required>
<option value="">-- Selecciona --</option>
<?php foreach($transportistas as $t): ?>
<option value="<?= $t['id_transportista'] ?>"><?= htmlspecialchars($t['nombre']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-4 mb-3">
<label for="chofer_id" class="form-label">Chofer</label>
<select id="chofer_id" name="chofer_id" class="form-select" required>
<option value="">-- Selecciona Chofer --</option>
<?php foreach($choferes as $c): ?>
<option value="<?= $c['id_chofer'] ?>"><?= htmlspecialchars($c['nombre']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-4 mb-3">
<label for="foto_solicitud" class="form-label">Foto de la solicitud</label>
<input id="foto_solicitud" name="foto_solicitud" type="file" class="form-control" accept="image/*">
</div>
</div>
<!-- Partidas dinámicas -->
<hr>
<h5>📦 Partidas</h5>
<table class="table table-sm" id="tabla-partidas">
<thead>
<tr><th>Descripción</th><th>Precio Unitario</th><th></th></tr>
</thead>
<tbody>
<tr>
<td><input name="partidas[0][descripcion]" class="form-control"></td>
<td><input name="partidas[0][precio_unitario]" type="number" step="0.01" class="form-control"></td>
<td><button type="button" class="btn btn-danger btn-sm remove-row">✖️</button></td>
</tr>
</tbody>
</table>
<button type="button" class="btn btn-secondary btn-sm" id="add-partida"> Agregar partida</button>
<!-- Activo -->
<div class="form-check mt-4">
<input id="status" name="status" type="checkbox" class="form-check-input" checked>
<label for="status" class="form-check-label">Activo</label>
</div>
<!-- Botones finales -->
<button type="submit" class="btn btn-success mt-3">Guardar</button>
<a href="/IMPORTADORES/solicitud_importacion/lista" class="btn btn-secondary mt-3 ms-2">Cancelar</a>
</form>
</div>
</div>
<script>
document.getElementById('add-partida').addEventListener('click', () => {
const tbody = document.querySelector('#tabla-partidas tbody');
const idx = tbody.querySelectorAll('tr').length;
const row = document.createElement('tr');
row.innerHTML = `
<td><input name="partidas[\${idx}][descripcion]" class="form-control"></td>
<td><input name="partidas[\${idx}][precio_unitario]" type="number" step="0.01" class="form-control"></td>
<td><button type="button" class="btn btn-danger btn-sm remove-row">✖️</button></td>
`;
tbody.appendChild(row);
});
document.querySelector('#tabla-partidas tbody').addEventListener('click', e => {
if (e.target.matches('.remove-row')) e.target.closest('tr').remove();
});
</script>
</body>
</html>

View File

@@ -0,0 +1,199 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>✏️ Editar Solicitud #<?= (int)$factura['id_solicitud'] ?></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; }
.card { border-radius: 12px; }
</style>
</head>
<body>
<?php include __DIR__ . '/../partials/sidebar_importador.php'; ?>
<br><br>
<div class="content">
<h4>✏️ Editar Solicitud #<?= (int)$factura['id_solicitud'] ?></h4>
<div class="card p-4 bg-white shadow-sm">
<form action="/IMPORTADORES/solicitud_importacion/actualizar" method="POST" enctype="multipart/form-data">
<input type="hidden" name="id_solicitud" value="<?= (int)$factura['id_solicitud'] ?>">
<!-- Datos principales -->
<div class="row">
<div class="col-md-4 mb-3">
<label for="numero_factura" class="form-label">Número de Factura</label>
<input id="numero_factura" name="numero_factura" type="text" class="form-control"
value="<?= htmlspecialchars($factura['numero_factura']) ?>" required>
</div>
<div class="col-md-4 mb-3">
<label for="fecha_factura" class="form-label">Fecha de Factura</label>
<input id="fecha_factura" name="fecha_factura" type="date" class="form-control"
value="<?=
($factura['fecha_factura'] instanceof DateTime)
? htmlspecialchars($factura['fecha_factura']->format('Y-m-d'))
: htmlspecialchars($factura['fecha_factura'])
?>" required>
</div>
<div class="col-md-4 mb-3">
<label for="anexo22_apendice" class="form-label">Anexo 22 Apéndice</label>
<select id="anexo22_apendice" name="anexo22_apendice" class="form-select" required>
<option value="">-- Selecciona Aduana --</option>
<?php foreach ($aduanas as $a): ?>
<option value="<?= $a['aduana_seccion'] ?>"
<?= $factura['anexo22_apendice'] == $a['aduana_seccion'] ? 'selected' : '' ?>>
<?= htmlspecialchars($a['aduana_seccion'] . ' ' . $a['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="row">
<div class="col-md-4 mb-3">
<label for="incoterm" class="form-label">INCOTERM</label>
<select id="incoterm" name="incoterm" class="form-select">
<option value="">-- Selecciona Incoterm --</option>
<?php foreach ($incoterms as $inc): ?>
<option value="<?= htmlspecialchars($inc['INCOTERM']) ?>"
<?= $factura['incoterm'] === $inc['INCOTERM'] ? 'selected' : '' ?>>
<?= htmlspecialchars($inc['INCOTERM'] . ' - ' . $inc['DESCESPANOL']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-4 mb-3">
<label for="pais_proveedor" class="form-label">País (Proveedor)</label>
<select id="pais_proveedor" name="pais_proveedor" class="form-select">
<option value="">-- Selecciona País --</option>
<?php foreach ($paises as $p): ?>
<option value="<?= $p['id_pais'] ?>"
<?= $factura['pais_proveedor'] == $p['id_pais'] ? 'selected' : '' ?>>
<?= htmlspecialchars($p['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-4 mb-3">
<label for="tipo_moneda" class="form-label">Moneda</label>
<select id="tipo_moneda" name="tipo_moneda" class="form-select">
<?php
$currs = ['MXN'=>'Peso Mexicano','USD'=>'Dólar USD','EUR'=>'Euro','CNY'=>'Yuan','GBP'=>'Libra GBP','JPY'=>'Yen'];
foreach ($currs as $code => $label): ?>
<option value="<?= $code ?>"
<?= $factura['tipo_moneda']==$code ? 'selected' : '' ?>>
<?= "$label ($code)" ?>
</option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="row">
<div class="col-md-8 mb-3">
<label for="valor_factura" class="form-label">Valor Factura</label>
<input id="valor_factura" name="valor_factura" type="number" step="0.01" class="form-control"
value="<?= htmlspecialchars($factura['valor_factura']) ?>">
</div>
<div class="col-md-4 mb-3">
<label for="vinculacion" class="form-label">Vinculación</label>
<select id="vinculacion" name="vinculacion" class="form-select">
<option value="0" <?= $factura['vinculacion']==0?'selected':'' ?>>No existe</option>
<option value="1" <?= $factura['vinculacion']==1?'selected':'' ?>>Existe, no afecta</option>
<option value="2" <?= $factura['vinculacion']==2?'selected':'' ?>>Existe y afecta</option>
</select>
</div>
</div>
<div class="row">
<div class="col-md-4 mb-3">
<label for="transportista_id" class="form-label">Transportista</label>
<select id="transportista_id" name="transportista_id" class="form-select" required>
<?php foreach ($transportistas as $t): ?>
<option value="<?= $t['id_transportista'] ?>"
<?= $factura['transportista_id']==$t['id_transportista']?'selected':'' ?>>
<?= htmlspecialchars($t['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-4 mb-3">
<label for="chofer_id" class="form-label">Chofer</label>
<select id="chofer_id" name="chofer_id" class="form-select" required>
<?php foreach ($choferes as $c): ?>
<option value="<?= $c['id_chofer'] ?>"
<?= $factura['chofer_id']==$c['id_chofer']?'selected':'' ?>>
<?= htmlspecialchars($c['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-4 mb-3">
<label for="foto_solicitud" class="form-label">Nueva Foto de la solicitud</label>
<input id="foto_solicitud" name="foto_solicitud" type="file" class="form-control" accept="image/*">
</div>
</div>
<!-- Partidas dinámicas -->
<hr>
<h5>📦 Partidas</h5>
<table class="table table-sm" id="tabla-partidas">
<thead>
<tr><th>Descripción</th><th>Precio Unitario</th><th></th></tr>
</thead>
<tbody>
<?php if (!empty($partidas)): ?>
<?php foreach ($partidas as $i => $p): ?>
<tr>
<td><input name="partidas[<?= $i ?>][descripcion]" class="form-control" value="<?= htmlspecialchars($p['descripcion']) ?>"></td>
<td><input name="partidas[<?= $i ?>][precio_unitario]" type="number" step="0.01" class="form-control" value="<?= htmlspecialchars($p['precio_unitario']) ?>"></td>
<td><button type="button" class="btn btn-danger btn-sm remove-row">✖️</button></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr>
<td><input name="partidas[0][descripcion]" class="form-control"></td>
<td><input name="partidas[0][precio_unitario]" type="number" step="0.01" class="form-control"></td>
<td><button type="button" class="btn btn-danger btn-sm remove-row">✖️</button></td>
</tr>
<?php endif; ?>
</tbody>
</table>
<button type="button" class="btn btn-secondary btn-sm mb-3" id="add-partida"> Agregar partida</button>
<!-- Activo -->
<div class="form-check mb-4">
<input id="status" name="status" type="checkbox" class="form-check-input" <?= $factura['status']==1?'checked':'' ?>>
<label for="status" class="form-check-label">Activo</label>
</div>
<button type="submit" class="btn btn-primary">Actualizar</button>
<a href="/IMPORTADORES/solicitud_importacion/lista" class="btn btn-secondary ms-2">Cancelar</a>
</form>
</div>
</div>
<script>
document.getElementById('add-partida').addEventListener('click', function() {
var tbody = document.querySelector('#tabla-partidas tbody');
var idx = tbody.querySelectorAll('tr').length;
var row = document.createElement('tr');
row.innerHTML = '<td><input name="partidas[' + idx + '][descripcion]" class="form-control"></td>' +
'<td><input name="partidas[' + idx + '][precio_unitario]" type="number" step="0.01" class="form-control"></td>' +
'<td><button type="button" class="btn btn-danger btn-sm remove-row">✖️</button></td>';
tbody.appendChild(row);
});
document.querySelector('#tabla-partidas tbody').addEventListener('click', function(e) {
if (e.target.matches('.remove-row')) {
e.target.closest('tr').remove();
}
});
</script>
</body>
</html>

View File

@@ -0,0 +1,111 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>📄 Solicitudes de Importación</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>📄 Solicitudes de Importación</h4>
<a href="/IMPORTADORES/solicitud_importacion/crear" class="btn btn-success mb-3"> Nueva Solicitud</a>
<table class="table table-striped" id="tabla-solicitudes">
<thead>
<tr>
<th>#</th>
<th>Factura</th>
<th>Fecha</th>
<th>Pedimento</th>
<th>Incoterm</th>
<th>País Proveedor</th>
<th>Moneda</th>
<th>Valor</th>
<th>Vinculación</th>
<th>Transportista</th>
<th>PDF</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
<?php foreach($facturas as $f): ?>
<tr>
<td><?= $f['id_solicitud'] ?></td>
<td><?= htmlspecialchars($f['numero_factura']) ?></td>
<td><?= htmlspecialchars($f['fecha_factura']) ?></td>
<td><?= htmlspecialchars($f['numero_pedimento']) ?></td>
<td><?= htmlspecialchars($f['incoterm']) ?></td>
<td><?= htmlspecialchars($f['pais_proveedor']) ?></td>
<td><?= htmlspecialchars($f['tipo_moneda']) ?></td>
<td><?= number_format($f['valor_factura'],2) ?></td>
<td>
<?php
switch($f['vinculacion']) {
case 1: echo 'Existe, no afecta'; break;
case 2: echo 'Existe y afecta'; break;
default: echo 'No existe';
}
?>
</td>
<td><?= htmlspecialchars($f['transportista']) ?></td>
<td>
<a href="/IMPORTADORES/solicitud_importacion/pdf?id=<?= $f['id_solicitud'] ?>"
class="btn btn-sm btn-outline-secondary" target="_blank">
📄 PDF
</a>
</td>
<td>
<a href="/IMPORTADORES/solicitud_importacion/editar?id=<?= $f['id_solicitud'] ?>"
class="btn btn-sm btn-primary">✏️</a>
<button class="btn btn-sm btn-danger"
onclick="confirmDelete(<?= $f['id_solicitud'] ?>)">🗑️</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<script>
function confirmDelete(id) {
Swal.fire({
title: '¿Eliminar solicitud?',
text: 'Se marcará como inactiva.',
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Sí, eliminar',
cancelButtonText: 'Cancelar',
confirmButtonColor: '#d33'
}).then(r => {
if (r.isConfirmed) {
window.location = `/IMPORTADORES/solicitud_importacion/eliminar?id=${id}`;
}
});
}
<?php if(isset($_GET['deleted'])): ?>
Swal.fire('¡Hecho!','Solicitud eliminada.','success');
<?php endif; ?>
<?php if(isset($_GET['created'])): ?>
Swal.fire('¡Listo!','Solicitud creada.','success');
<?php endif; ?>
<?php if(isset($_GET['updated'])): ?>
Swal.fire('¡Listo!','Solicitud actualizada.','success');
<?php endif; ?>
</script>
</body>
</html>

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>

View File

@@ -0,0 +1,137 @@
<head>
<meta charset="UTF-8">
<title>Dashboard | Alta transportista</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>
<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>
<?php include __DIR__ . '/../partials/sidebar_importador.php'; ?>
<body>
<br><br><br>
<div class="content">
<h4 class="mb-4">🚛 Alta de Transportista</h4>
<form action="/IMPORTADORES/transportistas/guardar" method="POST" class="card p-4 shadow-sm">
<div class="row g-3">
<div class="col-md-4"><input name="clave" class="form-control" placeholder="Clave" required></div>
<div class="col-md-4"><input name="nombre" class="form-control" placeholder="Nombre completo" required></div>
<div class="col-md-4"><input name="rfc" class="form-control" placeholder="RFC" required></div>
<div class="col-md-4"><input name="curp" class="form-control" placeholder="CURP"></div>
<div class="col-md-4"><input name="telefono" class="form-control" placeholder="Teléfono" required></div>
<div class="col-md-4"><input name="caat" class="form-control" placeholder="Código CAAT" required></div>
<div class="col-md-4">
<select id="pais" name="pais" class="form-select" required>
<option value="">Selecciona país</option>
<?php foreach($paises as $p): ?>
<option value="<?= $p['id_pais'] ?>">
<?= htmlspecialchars($p['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-4">
<select id="estado" name="entidad" class="form-select" required disabled>
<option value="">Primero país…</option>
</select>
</div>
<div class="col-md-4">
<select id="ciudad" name="ciudad" class="form-select" required disabled>
<option value="">Primero estado…</option>
</select>
</div>
<div class="col-md-8"><input name="domicilio" class="form-control" placeholder="Domicilio completo" required></div>
</div>
<div class="text-end mt-4">
<button class="btn btn-success px-4">Guardar Transportista</button>
</div>
</form>
</div>
<script>
// 1) Cuando elige país → cargo estados
document.getElementById('pais').addEventListener('change', e => {
const pid = e.target.value;
const sel = document.getElementById('estado');
sel.innerHTML = '<option>Cargando…</option>';
sel.disabled = true;
document.getElementById('ciudad').innerHTML = '<option>Primero estado…</option>';
document.getElementById('ciudad').disabled = true;
fetch(`/IMPORTADORES/transportistas/estados?pais=${pid}`)
.then(r=>r.json())
.then(list=>{
sel.innerHTML = '<option value="">Selecciona estado</option>';
list.forEach(st => sel.add(new Option(st.nombre, st.id_estado)));
sel.disabled = false;
});
});
// 2) Cuando elige estado → cargo ciudades
document.getElementById('estado').addEventListener('change', e => {
const eid = e.target.value;
const sel = document.getElementById('ciudad');
sel.innerHTML = '<option>Cargando…</option>';
sel.disabled = true;
fetch(`/IMPORTADORES/transportistas/ciudades?estado=${eid}`)
.then(r=>r.json())
.then(list=>{
sel.innerHTML = '<option value="">Selecciona ciudad</option>';
list.forEach(ct => sel.add(new Option(ct.nombre, ct.id_ciudad)));
sel.disabled = false;
});
});
</script>
</body>
</html>

View File

@@ -0,0 +1,119 @@
<?php // views/transportistas/bulk_upload.php ?>
<?php
// Al principio de la vista, inicia sesión para leer los errores
session_start();
$errors = $_SESSION['import_errors'] ?? [];
$success = $_SESSION['import_success'] ?? false;
// Limpiar para que no se repitan
unset($_SESSION['import_errors'], $_SESSION['import_success']);
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>🚛 Carga Masiva de Transportistas</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>
<h4 class="mb-4">🚛 Carga Masiva de Transportistas</h4>
<div class="card p-4 shadow-sm">
<p>1. Descarga la plantilla, complétala con tus datos y luego súbela aquí.</p>
<a href="/IMPORTADORES/transportistas/template" class="btn btn-outline-secondary mb-4">
📥 Descargar Plantilla CSV
</a>
<form action="/IMPORTADORES/transportistas/importar" method="POST" enctype="multipart/form-data">
<div class="mb-3">
<label for="archivo_csv" class="form-label">Selecciona archivo CSV</label>
<input type="file" id="archivo_csv" name="archivo_csv" class="form-control" accept=".csv" required>
</div>
<button type="submit" class="btn btn-primary">🚀 Cargar Transportistas</button>
</form>
</div>
</div>
<script>
// Si la importación fue exitosa
<?php if ($success): ?>
Swal.fire({
icon: 'success',
title: '¡Carga completada!',
text: 'Todos los transportistas se importaron correctamente.',
confirmButtonColor: '#198754'
});
<?php endif; ?>
// Si hubo errores, muéstralos en una lista
<?php if (!empty($errors)):
// Construir HTML con la lista de errores
$html = '<ul style="text-align:left;">';
foreach ($errors as $e) {
$html .= '<li>' . htmlspecialchars($e) . '</li>';
}
$html .= '</ul>';
?>
Swal.fire({
icon: 'error',
title: 'Errores al importar',
html: <?= json_encode($html) ?>,
width: 600,
confirmButtonColor: '#d33'
});
<?php endif; ?>
</script>
</body>
</html>

View File

@@ -0,0 +1,169 @@
<?php
// views/transportistas/editar.php
session_start();
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>✏️ Editar Transportista</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>
<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">
<h4 class="mb-4">✏️ Editar Transportista #<?= $t['id_transportista'] ?></h4>
<form action="/IMPORTADORES/transportistas/actualizar" method="POST" class="card p-4 shadow-sm">
<input type="hidden" name="id_transportista" value="<?= $t['id_transportista'] ?>">
<div class="row g-3">
<div class="col-md-4">
<label class="form-label">Clave</label>
<input name="clave" value="<?= htmlspecialchars($t['clave_identificador']) ?>"
class="form-control" required>
</div>
<div class="col-md-4">
<label class="form-label">Nombre</label>
<input name="nombre" value="<?= htmlspecialchars($t['nombre']) ?>"
class="form-control" required>
</div>
<div class="col-md-4">
<label class="form-label">RFC</label>
<input name="rfc" value="<?= htmlspecialchars($t['rfc']) ?>"
class="form-control" required>
</div>
<div class="col-md-4">
<label class="form-label">CURP</label>
<input name="curp" value="<?= htmlspecialchars($t['curp']) ?>"
class="form-control">
</div>
<div class="col-md-4">
<label class="form-label">Teléfono</label>
<input name="telefono" value="<?= htmlspecialchars($t['telefono']) ?>"
class="form-control" required>
</div>
<div class="col-md-4">
<label class="form-label">Código CAAT</label>
<input name="caat" value="<?= htmlspecialchars($t['caat']) ?>"
class="form-control" required>
</div>
<div class="col-md-4">
<label class="form-label">País</label>
<select id="pais" name="pais" class="form-select" required>
<option value="">Selecciona país</option>
<?php foreach($paises as $p): ?>
<option value="<?= $p['id_pais'] ?>"
<?= $p['id_pais']==$t['pais']?'selected':'' ?>>
<?= htmlspecialchars($p['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-4">
<label class="form-label">Estado</label>
<select id="estado" name="entidad" class="form-select" required>
<option value="">Selecciona estado</option>
<?php foreach($estados as $e): ?>
<option value="<?= $e['id_estado'] ?>"
<?= $e['id_estado']==$t['entidad_federativa']?'selected':'' ?>>
<?= htmlspecialchars($e['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-4">
<label class="form-label">Ciudad</label>
<select id="ciudad" name="ciudad" class="form-select" required>
<option value="">Selecciona ciudad</option>
<?php foreach($ciudades as $c): ?>
<option value="<?= $c['id_ciudad'] ?>"
<?= $c['id_ciudad']==$t['ciudad']?'selected':'' ?>>
<?= htmlspecialchars($c['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-12">
<label class="form-label">Domicilio Completo</label>
<textarea name="domicilio" class="form-control" rows="3" required><?= htmlspecialchars($t['domicilio']) ?></textarea>
</div>
</div>
<div class="text-end mt-4">
<button class="btn btn-success px-4">💾 Guardar Cambios</button>
</div>
</form>
</div>
<script>
// Al cambiar país → recargar estados
document.getElementById('pais').addEventListener('change', function(){
const pid = this.value, selE = document.getElementById('estado');
selE.innerHTML = '<option>Cargando…</option>'; selE.disabled = true;
fetch(`/IMPORTADORES/transportistas/estados?pais=${pid}`)
.then(r=>r.json())
.then(list=>{
selE.innerHTML = '<option value="">Selecciona estado</option>';
list.forEach(e=> selE.add(new Option(e.nombre,e.id_estado)) );
selE.disabled = false;
// Dispara cambio para recargar ciudades
selE.dispatchEvent(new Event('change'));
});
});
// Al cambiar estado → recargar ciudades
document.getElementById('estado').addEventListener('change', function(){
const eid = this.value, selC = document.getElementById('ciudad');
selC.innerHTML = '<option>Cargando…</option>'; selC.disabled = true;
fetch(`/IMPORTADORES/transportistas/ciudades?estado=${eid}`)
.then(r=>r.json())
.then(list=>{
selC.innerHTML = '<option value="">Selecciona ciudad</option>';
list.forEach(c=> selC.add(new Option(c.nombre,c.id_ciudad)) );
selC.disabled = false;
});
});
</script>
</body>
</html>

View File

@@ -0,0 +1,161 @@
<!-- views/transportistas/lista.php -->
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>🚚 Mis Transportistas</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">
<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'; ?>
<div class="content">
<br>
<h4 class="mb-4">🚚 Mis Transportistas</h4>
<div class="card p-3 shadow-sm">
<table id="transportistas-table" class="display nowrap" style="width:100%">
<thead>
<tr>
<th>#</th>
<th>Clave</th>
<th>Nombre</th>
<th>RFC</th>
<th>Ciudad</th>
<th>Fecha Alta</th>
<th>Acciones</th>
</tr>
</thead>
</table>
</div>
</div>
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- DataTables JS -->
<script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>
<!-- Bootstrap JS -->
<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>
<script>
$(function(){
$('#transportistas-table').DataTable({
serverSide: true,
processing: true,
ajax: {
url: '/IMPORTADORES/transportistas/ajax_lista',
type: 'GET'
},
columns: [
{ data: 0 },
{ data: 1 },
{ data: 2 },
{ data: 3 },
{ data: 4 },
{ data: 5 },
{
data: null,
orderable: false,
searchable: false,
render: function(row) {
const id = row[0];
return `
<a href="/IMPORTADORES/transportistas/editar?id=${id}" class="btn btn-sm btn-primary">✏️</a>
<button class="btn btn-sm btn-danger" onclick="confirmDelete(${id})">🗑️</button>
`;
}
}
],
language: {
url: '//cdn.datatables.net/plug-ins/1.13.4/i18n/es-ES.json'
}
});
});
function confirmDelete(id) {
Swal.fire({
title: '¿Eliminar transportista?',
text: 'Esto sólo lo desactivará; no se podrá volver a usar.',
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Sí, eliminar',
cancelButtonText: 'Cancelar',
confirmButtonColor: '#d33'
}).then(result => {
if (result.isConfirmed) {
window.location = `/IMPORTADORES/transportistas/eliminar?id=${id}`;
}
});
}
// Mostrar alert de “borrado” al volver de la acción
<?php if (isset($_GET['deleted']) && $_GET['deleted']==='ok'): ?>
Swal.fire({
icon: 'success',
title: 'Transportista eliminado',
text: 'Ya no aparecerá en tu lista.',
confirmButtonColor: '#198754'
});
<?php endif; ?>
</script>
</body>
</html>