Files
MVE/views/solicitud_importacion/crear.php

1632 lines
66 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php include __DIR__ . '/../partials/sidebar_importador.php'; ?>
<!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">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/choices.js/public/assets/styles/choices.min.css"/>
<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>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>
<!-- Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<!-- Animate.css para animaciones adicionales -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">
<style>
body { font-family: 'Segoe UI', sans-serif; background-color: #f4f6f9; }
/* Contenido principal: sin solaparse con sidebar/navbar */
.content { margin-top: 0; padding: 24px 20px; position: relative; z-index: 1; background-color: #f4f6f9; transition: margin-left 0.3s ease; }
@media (min-width: 768px) { .content { margin-left: var(--sidebar-width, 280px); } }
@media (max-width: 767.98px) { .content { margin-left: 0; } }
.card { border-radius: 12px; }
/* Animaciones personalizadas */
.card-hover { transition: all 0.3s ease; cursor: pointer; }
.card-hover:hover { transform: translateY(-8px) scale(1.02); box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.15) !important; }
.btn-pulse { animation: pulse 2s infinite; }
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.fade-in-up { animation: fadeInUp 0.8s ease-out; }
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(30px); }
to { opacity: 1; transform: translateY(0); }
}
/* Responsive animations */
@media (max-width: 768px) { .card-hover:hover { transform: translateY(-4px) scale(1.01); } }
/* Efecto de glow para elementos activos */
.btn.active { box-shadow: 0 0 20px rgba(var(--bs-primary-rgb), 0.5); }
/* Animación para el título */
.title-glow { text-shadow: 0 0 10px rgba(0, 123, 255, 0.3); }
/* Efecto para botones */
.btn-animated { transition: all 0.3s ease; position: relative; overflow: hidden; }
.btn-animated:hover { transform: translateY(-2px); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); }
.btn-animated::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); transition: left 0.5s; }
.btn-animated:hover::before { left: 100%; }
.hide { display: none !important; }
.alert { top: calc(var(--navbar-height, 70px) + 5px); left: calc(var(--sidebar-width, 280px) + 15px); right: 15px; position: fixed; z-index: 1050; width: calc(100% - var(--sidebar-width, 280px) - 30px); }
/* ========== ANIMACIONES PARA INPUTS TEXTO ========== */
.form-control:not(.no-animation) { transition: all 0.3s ease; border: 2px solid #dee2e6; position: relative; }
.form-control:not(.no-animation).shake { animation: shake 0.5s ease-in-out; }
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-5px); }
75% { transform: translateX(5px); }
}
/* Animación para los campos del formulario */
.form-group-animated { opacity: 0; transform: translateY(20px); animation: slideUp 0.6s ease-out forwards; }
.form-group-animated:nth-child(1) { animation-delay: 0.1s; }
.form-group-animated:nth-child(2) { animation-delay: 0.2s; }
.form-group-animated:nth-child(3) { animation-delay: 0.3s; }
.form-group-animated:nth-child(4) { animation-delay: 0.4s; }
.form-group-animated:nth-child(5) { animation-delay: 0.5s; }
.form-group-animated:nth-child(6) { animation-delay: 0.6s; }
.form-group-animated:nth-child(7) { animation-delay: 0.7s; }
.form-group-animated:nth-child(8) { animation-delay: 0.8s; }
.form-group-animated:nth-child(9) { animation-delay: 0.9s; }
.form-group-animated:nth-child(10) { animation-delay: 1.0s; }
@keyframes slideUp { to { opacity: 1; transform: translateY(0); } }
/* Estilos para las sugerencias de autocompletado */
#global-autocomplete-suggestions { box-shadow: 0 4px 12px rgba(0,0,0,0.15) !important; border: 1px solid #dee2e6 !important; width: calc(100% - 30px) !important; /* Ajusta según el padding de tu contenedor */ }
#global-autocomplete-suggestions .autocomplete-item { transition: background-color 0.15s ease; }
#global-autocomplete-suggestions .autocomplete-item:hover,
#global-autocomplete-suggestions .autocomplete-item.active { background-color: #f8f9fa !important; }
#global-autocomplete-suggestions .autocomplete-item:last-child { border-bottom: none; }
/* Estilos para validación */
.choices.required .choices__inner { border: 1px solid #ced4da; }
.choices.is-invalid .choices__inner { border: 1px solid #dc3545; background-color: #fff5f5; }
.choices.is-valid .choices__inner { border: 1px solid #28a745; background-color: #f5fff5; }
.choices__input { opacity: 1 !important; }
/* Estilos para el panel de pedimentos de referencia */
.pedimento-item {
background: #fff;
border: 1px solid #e9ecef;
border-radius: 6px;
padding: 8px;
margin-bottom: 6px;
cursor: pointer;
transition: all 0.2s ease;
font-size: 11px;
}
.pedimento-item:hover {
background-color: #e3f2fd;
border-color: #2196f3;
transform: translateX(2px);
}
.pedimento-item:active {
transform: scale(0.98);
}
.pedimento-numero {
font-weight: bold;
color: #1976d2;
font-size: 12px;
}
.pedimento-cliente {
color: #666;
font-size: 10px;
margin-top: 2px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.pedimento-meta {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 4px;
}
.pedimento-clave {
background: #e8f5e8;
color: #2e7d32;
padding: 2px 6px;
border-radius: 3px;
font-size: 9px;
font-weight: bold;
}
.pedimento-fecha {
color: #888;
font-size: 9px;
}
.pedimento-item.copiado {
background-color: #e8f5e8 !important;
border-color: #4caf50 !important;
}
.pedimento-item.copiado .pedimento-numero::after {
content: " ✓";
color: #4caf50;
}
/* Responsive para el panel */
@media (max-width: 991.98px) {
.col-lg-3 { margin-top: 20px; }
}
/* ============ OPTIMIZACIONES DE VELOCIDAD ============ */
/* Campos enfocados */
.form-control:focus, .form-select:focus {
border-color: #0d6efd;
box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.25);
background-color: #fff;
}
/* Indicador de campo siguiente */
.next-field-hint {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
color: #6c757d;
font-size: 12px;
pointer-events: none;
transition: all 0.3s ease;
opacity: 0;
}
.form-control:focus + .next-field-hint {
opacity: 1;
right: 8px;
}
/* Autocompletado mejorado */
.quick-select-bar {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 12px;
border-radius: 8px;
margin-bottom: 20px;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
}
.quick-btn {
background: rgba(255,255,255,0.2);
border: 1px solid rgba(255,255,255,0.3);
color: white;
padding: 6px 12px;
border-radius: 20px;
font-size: 12px;
margin: 2px;
transition: all 0.2s ease;
backdrop-filter: blur(10px);
}
.quick-btn:hover {
background: rgba(255,255,255,0.3);
transform: translateY(-1px);
color: white;
border-color: rgba(255,255,255,0.5);
}
.quick-btn.active {
background: rgba(255,255,255,0.9);
color: #333;
}
/* Calculadora automática */
.calc-helper {
position: absolute;
right: -35px;
top: 50%;
transform: translateY(-50%);
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 4px;
padding: 4px 8px;
font-size: 11px;
color: #666;
white-space: nowrap;
opacity: 0;
transition: all 0.3s ease;
pointer-events: none;
z-index: 10;
}
.calc-helper.show {
opacity: 1;
right: -120px;
}
/* Indicador de progreso */
.progress-indicator {
position: fixed;
top: calc(var(--navbar-height, 70px) + 10px);
right: 20px;
background: white;
border-radius: 8px;
padding: 10px 15px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
z-index: 1040;
min-width: 200px;
font-size: 13px;
}
.progress-bar-custom {
height: 4px;
background: linear-gradient(90deg, #28a745, #20c997, #17a2b8);
border-radius: 2px;
transition: width 0.3s ease;
}
/* Atajos de teclado */
.keyboard-shortcuts {
position: fixed;
bottom: 20px;
right: 20px;
background: rgba(0,0,0,0.8);
color: white;
padding: 10px 15px;
border-radius: 8px;
font-size: 11px;
opacity: 0;
transform: translateY(20px);
transition: all 0.3s ease;
z-index: 1050;
max-width: 300px;
}
.keyboard-shortcuts.show {
opacity: 1;
transform: translateY(0);
}
.shortcut-key {
background: rgba(255,255,255,0.2);
padding: 2px 6px;
border-radius: 3px;
margin: 0 2px;
font-family: monospace;
font-size: 10px;
}
/* Auto-save indicator */
.auto-save-indicator {
position: fixed;
top: calc(var(--navbar-height, 70px) + 10px);
left: 50%;
transform: translateX(-50%);
background: #28a745;
color: white;
padding: 8px 16px;
border-radius: 20px;
font-size: 12px;
opacity: 0;
transition: all 0.3s ease;
z-index: 1050;
}
.auto-save-indicator.show {
opacity: 1;
top: calc(var(--navbar-height, 70px) + 30px);
}
/* Templates rápidos */
.template-selector {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 8px;
padding: 15px;
margin-bottom: 20px;
}
.template-item {
background: white;
border: 1px solid #e9ecef;
border-radius: 6px;
padding: 10px;
margin: 5px 0;
cursor: pointer;
transition: all 0.2s ease;
font-size: 12px;
}
.template-item:hover {
border-color: #0d6efd;
background: #f8f9ff;
transform: translateX(3px);
}
.template-name {
font-weight: bold;
color: #495057;
}
.template-desc {
color: #6c757d;
margin-top: 3px;
}
/* Drag and drop para archivos */
.file-drop-zone {
border: 2px dashed #dee2e6;
border-radius: 8px;
padding: 20px;
text-align: center;
transition: all 0.3s ease;
background: #fafafa;
}
.file-drop-zone.dragover {
border-color: #0d6efd;
background: #f0f8ff;
}
.file-drop-zone.dragover .drop-text {
color: #0d6efd;
}
/* Validación en tiempo real */
.field-valid {
position: relative;
}
.field-valid::after {
content: "✓";
position: absolute;
right: 8px;
top: 50%;
transform: translateY(-50%);
color: #28a745;
font-weight: bold;
opacity: 0;
transition: opacity 0.3s ease;
}
.field-valid.is-valid::after {
opacity: 1;
}
/* Notificaciones flotantes mejoradas */
.floating-notification {
position: fixed;
top: 20px;
right: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 12px 20px;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
transform: translateX(400px);
transition: all 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
z-index: 9999;
max-width: 350px;
font-size: 14px;
}
.floating-notification.show {
transform: translateX(0);
}
.floating-notification.success {
background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
}
.floating-notification.warning {
background: linear-gradient(135deg, #ffc107 0%, #fd7e14 100%);
color: #000;
}
.floating-notification.error {
background: linear-gradient(135deg, #dc3545 0%, #e91e63 100%);
}
/* ✅ NUEVOS ESTILOS PARA EL MODAL DE ATAJOS */
.shortcut-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 0;
border-bottom: 1px solid #f8f9fa;
}
.shortcut-item:last-child {
border-bottom: none;
}
.shortcut-key {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 4px;
padding: 4px 8px;
font-family: 'Courier New', monospace;
font-weight: bold;
font-size: 12px;
color: #495057;
min-width: 80px;
text-align: center;
}
.shortcut-desc {
color: #6c757d;
font-size: 14px;
margin-left: 15px;
}
.feature-item {
padding: 8px 0;
}
.quick-help-item {
display: flex;
align-items: center;
}
.quick-help-item small {
color: #6c757d;
font-size: 12px;
}
/* Estilos para el botón de atajos rápidos */
#show-shortcuts-modal {
transition: all 0.3s ease;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
#show-shortcuts-modal:hover {
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
}
/* Mejoras para el toggle de templates */
#toggle-templates {
transition: all 0.3s ease;
}
#toggle-templates:hover {
transform: translateX(2px);
}
/* Estilos para las cards del panel derecho mejoradas */
.card .card-header {
border-bottom: 2px solid rgba(255,255,255,0.1);
}
.card .card-footer {
border-top: 1px solid rgba(0,0,0,0.1);
background: rgba(0,0,0,0.02) !important;
}
/* Animaciones para los elementos reorganizados */
.quick-select-bar {
animation: slideInDown 0.8s ease-out;
}
@keyframes slideInDown {
from {
opacity: 0;
transform: translateY(-30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Responsive para el modal */
@media (max-width: 768px) {
.modal-dialog {
margin: 0.5rem;
}
.shortcut-item {
flex-direction: column;
align-items: flex-start;
gap: 5px;
}
.shortcut-desc {
margin-left: 0;
font-size: 13px;
}
.quick-help-item {
flex-direction: column;
align-items: flex-start;
gap: 3px;
}
}
/* Mejoras para la barra de progreso */
.progress-indicator {
border-left: 4px solid #007bff;
transition: all 0.3s ease;
}
.progress-indicator:hover {
transform: scale(1.02);
box-shadow: 0 6px 16px rgba(0,0,0,0.2);
}
</style>
</head>
<body>
<?php if (!isset($_SESSION['id_agencia_en_uso']) || !$_SESSION['id_agencia_en_uso']): ?>
<div class="container mt-4">
<div class="row">
<div class="col-12">
<div class="alert alert-warning mt-4">
<h5>⚠️ No tienes una agencia activa vinculada.</h5>
<p>Para poder gestionar tus solicitudes de importación, primero debes <strong>vincularte a una agencia</strong>.</p>
<a href="/IMPORTADORES/vinculaciones/nuevaVinculacion" class="btn btn-primary btn-animated">Ir a Vinculaciones</a>
</div>
</div>
</div>
</div>
<?php return; ?>
<?php endif; ?>
<div class="content">
<div class="row align-items-center mb-4">
<div class="col">
<h4 class="mb-0 animate__animated animate__fadeInDown title_glow"> Nueva factura de Importación</h4>
</div>
<div class="col-auto">
<!-- Botón flotante de información/atajos -->
<button type="button" class="btn btn-info btn-sm rounded-pill" id="show-shortcuts-modal" data-bs-toggle="modal" data-bs-target="#shortcutsModal">
<i class="fas fa-info-circle me-1"></i>
<i class="fas fa-keyboard me-1"></i>
Atajos Rápidos
</button>
</div>
</div>
<!-- ✅ REORGANIZADO: Barra de acceso rápido más compacta -->
<div class="quick-select-bar mb-3">
<div class="row align-items-center">
<div class="col-auto">
<small class="text-white fw-bold"><i class="fas fa-zap me-1"></i> Acceso Rápido:</small>
</div>
<div class="col">
<div class="d-flex flex-wrap gap-1">
<button type="button" class="quick-btn" data-quick-fill="fecha-hoy" title="Establecer fecha de hoy">
<i class="fas fa-calendar-day me-1"></i>Hoy
</button>
<button type="button" class="quick-btn" data-quick-fill="moneda-usd" title="Moneda USD">
<i class="fas fa-dollar-sign me-1"></i>USD
</button>
<button type="button" class="quick-btn" data-quick-fill="vinculacion-no" title="Sin vinculación">
<i class="fas fa-times me-1"></i>Sin Vinc.
</button>
<button type="button" class="quick-btn" data-quick-fill="incoterm-fob" title="INCOTERM FOB">
<i class="fas fa-ship me-1"></i>FOB
</button>
<button type="button" class="quick-btn" data-quick-fill="pais-usa" title="País Estados Unidos">
<i class="fas fa-flag-usa me-1"></i>USA
</button>
<button type="button" class="quick-btn" data-quick-fill="tasa-general" title="Tasa preferencial General">
<i class="fas fa-percentage me-1"></i>General
</button>
</div>
</div>
</div>
</div>
<!-- ✅ NUEVO: Indicador de progreso más discreto -->
<div class="progress-indicator" id="progress-indicator" style="display: none;">
<div class="d-flex justify-content-between align-items-center mb-2">
<small><i class="fas fa-tasks me-1"></i>Progreso</small>
<small id="progress-text">0%</small>
</div>
<div class="progress-bar-custom" id="progress-bar" style="width: 0%;"></div>
</div>
<!-- ✅ MODIFICADO: Templates personalizados del cliente (con mejor inicialización) -->
<div class="template-selector collapse" id="template-selector">
<div class="d-flex justify-content-between align-items-center mb-3">
<h6 class="mb-0"><i class="fas fa-magic me-1"></i> Mis Templates Personalizados</h6>
<div>
<button type="button" class="btn btn-sm btn-outline-primary" id="refresh-templates" title="Actualizar templates">
<i class="fas fa-sync-alt"></i>
</button>
<a href="/IMPORTADORES/templates_rapidos/crear" class="btn btn-sm btn-success" target="_blank" title="Crear nuevo template">
<i class="fas fa-plus"></i> Crear Nuevo
</a>
</div>
</div>
<div id="templates-container">
<div class="text-center py-3" id="templates-loading">
<div class="spinner-border spinner-border-sm text-primary" role="status">
<span class="visually-hidden">Cargando...</span>
</div>
<div class="small text-muted mt-1">Cargando tus templates...</div>
</div>
<!-- Templates personalizados se cargarán aquí -->
</div>
</div>
<!-- ✅ REORGANIZADO: Toggle para mostrar templates con mejor funcionalidad -->
<div class="mb-3">
<button type="button" class="btn btn-outline-secondary btn-sm" id="toggle-templates"
data-bs-toggle="collapse" data-bs-target="#template-selector"
aria-expanded="false" aria-controls="template-selector">
<i class="fas fa-eye me-1"></i>
<span id="toggle-text">Mostrar Mis Templates</span>
</button>
<!-- ✅ NUEVO: Link directo para crear templates si no hay ninguno -->
<div class="mt-2" id="templates-quick-actions" style="display: none;">
<small class="text-muted d-block mb-1">
<i class="fas fa-lightbulb me-1"></i>
Los templates te ayudan a llenar formularios más rápido
</small>
<div class="d-flex gap-2 flex-wrap">
<a href="/IMPORTADORES/templates_rapidos/crear" class="btn btn-xs btn-outline-success" target="_blank">
<i class="fas fa-plus me-1"></i>Crear Mi Primer Template
</a>
<a href="/IMPORTADORES/templates_rapidos/lista" class="btn btn-xs btn-outline-info" target="_blank">
<i class="fas fa-list me-1"></i>Ver Todos los Templates
</a>
<button type="button" class="btn btn-xs btn-outline-warning" onclick="mostrarEjemploTemplates()">
<i class="fas fa-question-circle me-1"></i>¿Cómo funcionan?
</button>
</div>
</div>
</div>
<!-- Layout de dos columnas -->
<div class="row">
<!-- Formulario principal (columna izquierda) -->
<div class="col-lg-9">
<div class="card p-4 bg-white shadow-sm card-hover position-relative h-auto fade-in-up">
<form id="solicitudForm" action="/IMPORTADORES/solicitud_importacion/guardar" method="POST" enctype="multipart/form-data">
<!-- Sección principal -->
<div class="row">
<div class="col-md-4 mb-3 form-group-animated">
<label for="numero_factura" class="form-label">Número de Factura</label>
<div class="position-relative">
<input id="numero_factura" name="numero_factura" type="text" class="form-control field-valid" required data-field-name="factura">
<div class="next-field-hint">Tab → Fecha</div>
</div>
</div>
<div class="col-md-4 mb-3 form-group-animated">
<label for="fecha_factura" class="form-label">Fecha de Factura</label>
<div class="position-relative">
<input id="fecha_factura" name="fecha_factura" type="date" class="form-control field-valid" required data-field-name="fecha">
<div class="next-field-hint">Tab → Pedimento</div>
</div>
</div>
<div class="col-md-4 mb-3 form-group-animated">
<label for="pedimento" class="form-label">Pedimento <span class="text-muted">(opcional)</span></label>
<div class="position-relative">
<input id="pedimento" name="pedimento" type="text" class="form-control pedimento-input field-valid" autocomplete="off"
placeholder="Buscar pedimento..." data-field-name="pedimento">
<div class="next-field-hint">Tab → Proveedor</div>
<div id="pedimento-suggestions" class="bg-white border shadow-lg position-absolute w-100"
style="display: none; max-height: 200px; overflow-y: auto; z-index: 1050; border-radius: 4px; margin-top: 2px;">
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 mb-3">
<label for="proveedor_id" class="form-label">Proveedor</label>
<select id="proveedor_id" name="proveedor_id" class="form-select searchable field-valid" data-required="true" required data-field-name="proveedor">
<option value="">Cargando proveedores…</option>
</select>
</div>
</div>
<!-- Segunda fila: Patente, Incoterm, País, Moneda -->
<div class="row">
<div class="col-md-3 mb-3">
<label for="anexo22_apendice" class="form-label">Anexo 22 Apéndice</label>
<select id="anexo22_apendice" name="anexo22_apendice" class="form-select searchable" data-required="true" required>
<option value="">-- Selecciona Aduana --</option>
<?php foreach($aduanas as $a): ?>
<option value="<?= htmlspecialchars($a['aduana_seccion']) ?>">
<?= htmlspecialchars($a['aduana_seccion'].' '.$a['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-3 mb-3">
<label for="patente" class="form-label">Patente Aduanal</label>
<select id="patente" name="patente" class="form-select searchable" data-required="true" required>
<option value="">-- Selecciona Patente --</option>
<?php foreach($patentes as $pt): ?>
<option value="<?= htmlspecialchars($pt['id_agente']) ?>">
<?= htmlspecialchars($pt['patente'].' - '.$pt['agente_aduanal']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-3 mb-3">
<label for="incoterm" class="form-label">INCOTERM</label>
<select id="incoterm" name="incoterm" class="form-select searchable" data-required="true" 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-3 mb-3">
<label for="pais_proveedor" class="form-label">País (Proveedor)</label>
<select id="pais_proveedor" name="pais_proveedor" class="form-select searchable" data-required="true" required>
<option value="">-- Selecciona País --</option>
<?php foreach($paises as $p): ?>
<option value="<?= htmlspecialchars($p['id_pais']) ?>"><?= htmlspecialchars($p['nombre']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-3 mb-3">
<label for="tipo_moneda" class="form-label">Moneda</label>
<select id="tipo_moneda" name="tipo_moneda" class="form-select searchable" data-required="true" required>
<?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 form-group-animated">
<label for="valor_factura" class="form-label">Valor Factura</label>
<input id="valor_factura" name="valor_factura" type="number" step="0.01" min="0" class="form-control" required>
</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 searchable" data-required="true" required>
<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 searchable field-valid" data-required="true" required data-field-name="transportista">
<option value="">-- Selecciona --</option>
<?php foreach($transportistas as $t): ?>
<option value="<?= htmlspecialchars($t['id_transportista']) ?>">
<?= htmlspecialchars($t['clave_identificador'] . ' - ' . $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 searchable field-valid" data-required="true" required data-field-name="chofer">
<option value="">-- Selecciona Chofer --</option>
<?php foreach($choferes as $c): ?>
<option value="<?= htmlspecialchars($c['id_chofer']) ?>">
<?= htmlspecialchars($c['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-4 mb-3 form-group-animated">
<label for="foto_solicitud" class="form-label">Foto de la Carga (PIPA)</label>
<div class="file-drop-zone" id="file-drop-zone">
<div class="drop-text">
<i class="fas fa-cloud-upload-alt fa-2x mb-2 text-muted"></i>
<div>Arrastra la imagen aquí</div>
<div class="small text-muted">o</div>
<input id="foto_solicitud" name="foto_solicitud" type="file" class="form-control mt-2" accept="image/*" data-field-name="foto">
</div>
</div>
</div>
</div>
<!-- Partidas dinámicas -->
<hr>
<h5 class="form-group-animated">📦 Partidas</h5>
<div class="table-responsive">
<table class="table table-sm form-group-animated" id="tabla-partidas">
<thead>
<tr>
<th>Descripción</th>
<th>Cantidad Comercial</th>
<th>Cantidad de Tarifa</th>
<th>Unidad Comercial</th>
<th>Valor Factura</th>
<th>Peso Bruto</th>
<th>Tasa Preferencial</th>
<th class="hide">Precio Unitario</th>
<th class="hide">OMA (Factura)</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="position-relative">
<input name="partidas[0][descripcion]" class="form-control w-auto descripcion-input field-valid" required autocomplete="off" data-field-name="descripcion">
</div>
</td>
<td>
<div class="position-relative">
<input name="partidas[0][cantidad_comercial]" type="number" step="0.0001" class="form-control w-auto cantidad-comercial field-valid" min="0" required data-field-name="cantidad">
<div class="calc-helper" id="calc-cantidad-0"></div>
</div>
</td>
<td><input name="partidas[0][cantidad_tarifa]" type="number" step="0.0001" class="form-control w-auto field-valid" min="0" required data-field-name="tarifa"></td>
<td>
<div class="mb-3">
<select name="partidas[0][unidad_comercial_id]" class="form-select searchable field-valid" data-required="true" required data-field-name="unidad">
<option value="">-- Unidad --</option>
<?php foreach($unidades_medida as $um): ?>
<option value="<?= htmlspecialchars($um['id']) ?>"><?= htmlspecialchars($um['descripcion']) ?></option>
<?php endforeach; ?>
</select>
</div>
</td>
<td>
<div class="position-relative">
<input name="partidas[0][valor_factura]" type="number" step="0.01" class="form-control valor-partida w-auto field-valid" min="0" required data-field-name="valor">
<div class="calc-helper" id="calc-valor-0"></div>
</div>
</td>
<td><input name="partidas[0][peso_bruto]" type="number" step="0.0001" class="form-control w-auto field-valid" min="0" required data-field-name="peso"></td>
<td>
<div class="mb-3">
<select name="partidas[0][tasa_preferencial]" class="form-select searchable field-valid" data-required="true" required data-field-name="tasa">
<option value="">-- Selecciona --</option>
<option>General</option>
<option>TLC</option>
<option>PROSEC</option>
<option>ALADI</option>
<option>COMERCIALIZADORA</option>
</select>
</div>
</td>
<td class="hide"><input name="partidas[0][precio_unitario]" type="number" class="form-control w-auto"></td>
<td class="hide"><input name="partidas[0][oma_factura]" class="form-control w-auto"></td>
<td><button type="button" class="btn btn-danger btn-sm remove-row mt-auto w-auto btn-animated">✖️</button></td>
</tr>
</tbody>
</table>
</div>
<div class="form-group-animated">
<button type="button" class="btn btn-secondary btn-sm mt-auto w-auto btn-animated" id="add-partida"> Agregar partida</button>
</div>
<!-- Activo -->
<div class="form-check mt-4">
<input id="status" name="status" type="checkbox" class="hide form-check-input" checked>
<label for="status" class="hide form-check-label">Activo</label>
</div>
<!-- Botones finales -->
<div class="text-end mt-4 form-group-animated">
<button type="submit" class="btn btn-success mt-3 mt-auto w-auto btn-animated">Guardar</button>
<a href="/IMPORTADORES/solicitud_importacion/lista" class="btn btn-secondary mt-3 ms-2 mt-auto w-auto btn-animated">Cancelar</a>
</div>
</form>
</div>
</div>
<!-- Panel de referencia (columna derecha) - MEJORADO -->
<div class="col-lg-3">
<!-- Card de Pedimentos -->
<div class="card bg-light shadow-sm fade-in-up mb-3" style="animation-delay: 0.2s; position: sticky; top: calc(var(--navbar-height, 70px) + 20px);">
<div class="card-header bg-primary text-white py-2">
<h6 class="mb-0"><i class="fas fa-list-ul me-1"></i> Pedimentos Disponibles</h6>
</div>
<div class="card-body p-2" style="max-height: 300px; overflow-y: auto;">
<div id="pedimentos-referencia" class="text-center text-muted">
<div class="spinner-border spinner-border-sm" role="status">
<span class="visually-hidden">Cargando...</span>
</div>
<div class="small mt-1">Cargando pedimentos...</div>
</div>
</div>
<div class="card-footer bg-light py-2">
<small class="text-muted">
<i class="fas fa-info-circle me-1"></i>
Clic para copiar al formulario
</small>
</div>
</div>
<!-- Card de Ayuda Rápida -->
<div class="card bg-light shadow-sm fade-in-up" style="animation-delay: 0.3s;">
<div class="card-header bg-success text-white py-2">
<h6 class="mb-0"><i class="fas fa-lightbulb me-1"></i> Tips Rápidos</h6>
</div>
<div class="card-body p-3">
<div class="small">
<div class="mb-2">
<i class="fas fa-keyboard text-primary me-1"></i>
<strong>Ctrl+S</strong> para guardar
</div>
<div class="mb-2">
<i class="fas fa-plus text-success me-1"></i>
<strong>Ctrl+N</strong> nueva partida
</div>
<div class="mb-2">
<i class="fas fa-arrow-right text-info me-1"></i>
<strong>Tab</strong> siguiente campo
</div>
<div class="mb-0">
<i class="fas fa-search text-warning me-1"></i>
Escribe para buscar productos
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- ✅ NUEVO: Modal de Atajos Rápidos -->
<div class="modal fade" id="shortcutsModal" tabindex="-1" aria-labelledby="shortcutsModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header bg-primary text-white">
<h5 class="modal-title" id="shortcutsModalLabel">
<i class="fas fa-keyboard me-2"></i>
Atajos Rápidos y Guía de Uso
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row">
<!-- Atajos de Teclado -->
<div class="col-md-6">
<h6 class="text-primary mb-3">
<i class="fas fa-keyboard me-1"></i>
Atajos de Teclado
</h6>
<div class="shortcut-list">
<div class="shortcut-item mb-2">
<span class="shortcut-key">Ctrl + S</span>
<span class="shortcut-desc">Guardar formulario</span>
</div>
<div class="shortcut-item mb-2">
<span class="shortcut-key">Ctrl + N</span>
<span class="shortcut-desc">Agregar nueva partida</span>
</div>
<div class="shortcut-item mb-2">
<span class="shortcut-key">Tab</span>
<span class="shortcut-desc">Siguiente campo</span>
</div>
<div class="shortcut-item mb-2">
<span class="shortcut-key">↑ ↓</span>
<span class="shortcut-desc">Navegar sugerencias</span>
</div>
<div class="shortcut-item mb-2">
<span class="shortcut-key">Enter</span>
<span class="shortcut-desc">Seleccionar sugerencia</span>
</div>
<div class="shortcut-item mb-2">
<span class="shortcut-key">Esc</span>
<span class="shortcut-desc">Cerrar menús</span>
</div>
<div class="shortcut-item mb-2">
<span class="shortcut-key">Alt + T</span>
<span class="shortcut-desc">Mostrar/Ocultar templates</span>
</div>
</div>
</div>
<!-- Funciones Inteligentes -->
<div class="col-md-6">
<h6 class="text-success mb-3">
<i class="fas fa-magic me-1"></i>
Funciones Inteligentes
</h6>
<div class="feature-list">
<div class="feature-item mb-3">
<div class="fw-bold text-success">
<i class="fas fa-search me-1"></i>
Autocompletado Inteligente
</div>
<small class="text-muted">
Escribe en "Descripción" para buscar productos frecuentes
</small>
</div>
<div class="feature-item mb-3">
<div class="fw-bold text-info">
<i class="fas fa-calculator me-1"></i>
Cálculo Automático
</div>
<small class="text-muted">
Los totales y precios unitarios se calculan automáticamente
</small>
</div>
<div class="feature-item mb-3">
<div class="fw-bold text-warning">
<i class="fas fa-copy me-1"></i>
Copia de Pedimentos
</div>
<small class="text-muted">
Haz clic en cualquier pedimento del panel derecho para copiarlo
</small>
</div>
<div class="feature-item mb-3">
<div class="fw-bold text-primary">
<i class="fas fa-magic me-1"></i>
Templates Personalizados
</div>
<small class="text-muted">
Crea y usa templates para llenar formularios rápidamente
</small>
</div>
<div class="feature-item mb-0">
<div class="fw-bold text-secondary">
<i class="fas fa-cloud-upload-alt me-1"></i>
Drag & Drop
</div>
<small class="text-muted">
Arrastra imágenes directamente al área de carga
</small>
</div>
</div>
</div>
</div>
<hr>
<!-- Barra de Acceso Rápido Explicada -->
<div class="row">
<div class="col-12">
<h6 class="text-warning mb-3">
<i class="fas fa-zap me-1"></i>
Botones de Acceso Rápido
</h6>
<div class="row">
<div class="col-md-4">
<div class="quick-help-item mb-2">
<button class="btn btn-sm btn-outline-primary me-2" disabled>
<i class="fas fa-calendar-day"></i> Hoy
</button>
<small>Establece fecha actual</small>
</div>
<div class="quick-help-item mb-2">
<button class="btn btn-sm btn-outline-primary me-2" disabled>
<i class="fas fa-dollar-sign"></i> USD
</button>
<small>Moneda a USD</small>
</div>
</div>
<div class="col-md-4">
<div class="quick-help-item mb-2">
<button class="btn btn-sm btn-outline-primary me-2" disabled>
<i class="fas fa-times"></i> Sin Vinc.
</button>
<small>No existe vinculación</small>
</div>
<div class="quick-help-item mb-2">
<button class="btn btn-sm btn-outline-primary me-2" disabled>
<i class="fas fa-ship"></i> FOB
</button>
<small>INCOTERM FOB</small>
</div>
</div>
<div class="col-md-4">
<div class="quick-help-item mb-2">
<button class="btn btn-sm btn-outline-primary me-2" disabled>
<i class="fas fa-flag-usa"></i> USA
</button>
<small>País Estados Unidos</small>
</div>
<div class="quick-help-item mb-2">
<button class="btn btn-sm btn-outline-primary me-2" disabled>
<i class="fas fa-percentage"></i> General
</button>
<small>Tasa General (todas)</small>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
<i class="fas fa-times me-1"></i>
Cerrar
</button>
<button type="button" class="btn btn-primary" onclick="localStorage.setItem('shortcuts-shown', 'false')" data-bs-dismiss="modal">
<i class="fas fa-eye me-1"></i>
Mostrar al iniciar próxima vez
</button>
</div>
</div>
</div>
</div>
<!-- ✅ REMOVIDO: Indicadores flotantes antiguos (ahora están en el modal) -->
<!-- Choices.js JS -->
<script src="https://cdn.jsdelivr.net/npm/choices.js/public/assets/scripts/choices.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0/dist/js/select2.min.js"></script>
<script>
// ✅ CARGAR TEMPLATES DESDE BASE DE DATOS (VERSIÓN CORREGIDA)
function loadTemplatesFromDatabase() {
alert('DEBUG: loadTemplatesFromDatabase llamada');
console.log('🔄 Cargando templates desde la base de datos...');
const $container = $('#templates-container');
const $loading = $('#templates-loading');
console.log('🔄 Cargando templates desde la base de datos...');
$loading.show();
$.ajax({
url: '/IMPORTADORES/templates_rapidos/ajax_obtener_templates',
method: 'GET',
dataType: 'json',
beforeSend: function() {
alert('DEBUG: AJAX a /IMPORTADORES/templates_rapidos/ajax_obtener_templates');
},
timeout: 10000,
success: function(response) {
console.log('📦 Respuesta completa recibida:', response);
$loading.hide();
$container.empty();
// ✅ MANEJAR ERROR SI EXISTE
if (response.error) {
console.error('❌ Error del servidor:', response.error);
mostrarErrorTemplates($container, response.error, response.message);
return;
}
// ✅ NUEVA LÓGICA: Usar la respuesta mejorada del endpoint
const templates = response.templates || [];
const templatesPersonales = response.templates_personales || [];
const templatesOtros = response.templates_otros || [];
const count = response.count || 0;
const countPersonales = response.count_personales || 0;
console.log(`✅ Templates cargados:`, {
total: count,
personales: countPersonales,
otros: templatesOtros.length
});
// ✅ MOSTRAR TODOS LOS TEMPLATES (SIN FILTROS ADICIONALES)
if (templates && templates.length > 0) {
// Priorizar templates personales primero, luego otros
const templatesPriorizados = [
...templatesPersonales,
...templatesOtros.slice(0, 5) // Máximo 5 templates de otros
];
if (templatesPriorizados.length > 0) {
// Mostrar mensaje informativo
if (countPersonales > 0) {
$container.append(`
<div class="alert alert-info alert-sm py-2 mb-3">
<i class="fas fa-info-circle me-1"></i>
<strong>Tienes ${countPersonales} template${countPersonales > 1 ? 's' : ''} personalizado${countPersonales > 1 ? 's' : ''}</strong>
${templatesOtros.length > 0 ? ` + ${templatesOtros.length} disponible${templatesOtros.length > 1 ? 's' : ''} de tu agencia/sistema` : ''}
</div>
`);
}
templatesPriorizados.forEach(function(template, index) {
const esPersonal = template.es_mio === true;
const badgeColor = esPersonal ? 'primary' : (template.ambito === 'agencia' ? 'info' : 'secondary');
const badgeText = esPersonal ? 'Mío' : (template.ambito === 'agencia' ? 'Agencia' : 'Sistema');
const $item = $(`
<div class="template-item animate__animated animate__fadeInUp"
data-template-id="${template.id}"
style="animation-delay: ${index * 0.1}s;">
<div class="d-flex justify-content-between align-items-start mb-2">
<div class="template-name">
${template.icono || '📋'} ${template.nombre}
<span class="badge bg-${badgeColor} ms-2 small">${badgeText}</span>
</div>
${esPersonal ? `
<div class="dropdown">
<button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown">
<i class="fas fa-cog"></i>
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="#" onclick="editTemplate(${template.id})">
<i class="fas fa-edit me-1"></i>Editar
</a></li>
<li><a class="dropdown-item text-danger" href="#" onclick="deleteTemplate(${template.id})">
<i class="fas fa-trash me-1"></i>Eliminar
</a></li>
</ul>
</div>
` : ''}
</div>
<div class="template-desc">${template.descripcion || 'Template ' + badgeText.toLowerCase()}</div>
<div class="mt-2 d-flex justify-content-between align-items-center">
<small class="text-muted">
<i class="fas fa-mouse-pointer me-1"></i>Usado ${template.veces_usado || 0} veces
</small>
<button class="btn btn-sm btn-primary" onclick="aplicarTemplateDirecto(${template.id})">
<i class="fas fa-magic me-1"></i>Usar Template
</button>
</div>
</div>
`);
// Evento click para aplicar template (en toda la card excepto botones)
$item.on('click', function(e) {
if ($(e.target).closest('button, .dropdown, .dropdown-menu').length > 0) return;
aplicarTemplateDirecto(template.id);
});
$container.append($item);
});
// Mensaje adicional si hay más templates disponibles
if (templatesOtros.length > 5) {
$container.append(`
<div class="text-center mt-3">
<a href="/IMPORTADORES/templates_rapidos/lista" class="btn btn-sm btn-outline-info" target="_blank">
<i class="fas fa-list me-1"></i>
Ver todos los templates (${templates.length} disponibles)
</a>
</div>
`);
}
}
} else {
// No hay templates, mostrar mensaje de ayuda
mostrarMensajeSinTemplates($container);
}
},
error: function(xhr, status, error) {
console.error('❌ Error AJAX:', {
status: status,
error: error,
responseText: xhr.responseText,
statusCode: xhr.status
});
$loading.hide();
let errorMessage = 'Error desconocido';
let suggestion = '';
if (xhr.status === 403) {
errorMessage = 'No tienes permisos para ver los templates';
suggestion = 'Verifica que tengas una sesión activa';
} else if (xhr.status === 404) {
errorMessage = 'Endpoint de templates no encontrado';
suggestion = 'Verifica la configuración del servidor';
} else if (xhr.status === 500) {
errorMessage = 'Error interno del servidor';
suggestion = 'Revisa los logs del servidor';
} else if (status === 'timeout') {
errorMessage = 'La petición tardó demasiado tiempo';
suggestion = 'Verifica tu conexión a internet';
} else {
errorMessage = `Error ${xhr.status}: ${error}`;
suggestion = 'Error de comunicación con el servidor';
}
mostrarErrorTemplates($container, errorMessage, suggestion);
}
});
}
// ✅ NUEVA FUNCIÓN: Aplicar template directamente por ID
function aplicarTemplateDirecto(templateId) {
console.log('📝 Aplicando template ID:', templateId);
// Buscar el template en la respuesta cacheada o hacer petición
const $templateItem = $(`.template-item[data-template-id="${templateId}"]`);
// Efecto visual inmediato
$templateItem.addClass('animate__pulse');
setTimeout(() => $templateItem.removeClass('animate__pulse'), 1000);
// Hacer petición para obtener los detalles completos del template
$.ajax({
url: '/IMPORTADORES/templates_rapidos/ajax_obtener_templates',
method: 'GET',
dataType: 'json',
success: function(response) {
// Buscar en todas las colecciones posibles
let template = null;
if (response.templates && Array.isArray(response.templates)) {
template = response.templates.find(t => t.id == templateId);
}
if (!template && response.templates_personales && Array.isArray(response.templates_personales)) {
template = response.templates_personales.find(t => t.id == templateId);
}
if (!template && response.templates_otros && Array.isArray(response.templates_otros)) {
template = response.templates_otros.find(t => t.id == templateId);
}
if (template) {
applyDatabaseTemplate(template);
// Registrar uso del template
$.post('/IMPORTADORES/templates_rapidos/ajax_usar_template', {
id_template: templateId
});
showFloatingNotification(`Template "${template.nombre}" aplicado correctamente`, 'success');
} else {
showFloatingNotification('Template no encontrado', 'error');
}
},
error: function() {
showFloatingNotification('Error al aplicar template', 'error');
}
});
}
// ✅ FUNCIÓN MEJORADA: Mostrar mensaje cuando no hay templates
function mostrarMensajeSinTemplates($container) {
$container.html(`
<div class="text-center text-muted py-4">
<i class="fas fa-magic fa-3x mb-3 text-muted"></i>
<h6 class="text-muted">¡Crea tu primer template!</h6>
<p class="small text-muted mb-3">
Los templates te ayudan a llenar formularios automáticamente<br>
con configuraciones que usas frecuentemente
</p>
<div class="d-grid gap-2 d-md-block">
<a href="/IMPORTADORES/templates_rapidos/crear" class="btn btn-success btn-sm" target="_blank">
<i class="fas fa-plus me-1"></i>Crear Mi Primer Template
</a>
<button type="button" class="btn btn-outline-info btn-sm" onclick="mostrarEjemploTemplates()">
<i class="fas fa-question-circle me-1"></i>¿Cómo funcionan?
</button>
</div>
<div class="mt-3 p-3 bg-light rounded">
<small class="text-muted">
<strong>💡 Ejemplos de templates útiles:</strong><br>
🇨🇳 "Importación China" - FOB + CNY + General<br>
🇺🇸 "Importación USA" - FOB + USD + TLC<br>
🏢 "Comercializadora" - FOB + USD + COMERCIALIZADORA
</small>
</div>
</div>
`);
}
// ✅ NUEVAS FUNCIONES PARA GESTIÓN DE TEMPLATES
function editTemplate(templateId) {
window.open(`/IMPORTADORES/templates_rapidos/editar?id=${templateId}`, '_blank');
}
function deleteTemplate(templateId) {
Swal.fire({
title: '¿Eliminar template?',
text: 'Esta acción no se puede deshacer',
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#dc3545',
cancelButtonColor: '#6c757d',
confirmButtonText: 'Sí, eliminar',
cancelButtonText: 'Cancelar'
}).then((result) => {
if (result.isConfirmed) {
$.ajax({
url: `/IMPORTADORES/templates_rapidos/eliminar?id=${templateId}`,
method: 'GET',
success: function() {
showFloatingNotification('Template eliminado correctamente', 'success');
loadTemplatesFromDatabase(); // Recargar lista
},
error: function() {
showFloatingNotification('Error al eliminar template', 'error');
}
});
}
});
}
// ✅ FUNCIÓN PARA MOSTRAR EJEMPLO DE TEMPLATES
function mostrarEjemploTemplates() {
Swal.fire({
title: '🎯 ¿Cómo funcionan los Templates?',
html: `
<div class="text-start">
<div class="mb-3">
<h6 class="text-primary mb-2">
<i class="fas fa-magic me-1"></i>
¿Qué son los Templates?
</h6>
<p class="small text-muted mb-0">
Los templates son configuraciones predefinidas que te permiten llenar formularios de importación
automáticamente con valores que usas frecuentemente.
</p>
</div>
<div class="mb-3">
<h6 class="text-success mb-2">
<i class="fas fa-lightbulb me-1"></i>
Ejemplos prácticos:
</h6>
<div class="small">
<div class="mb-2">
<strong>📦 "Importación China":</strong><br>
<span class="text-muted">FOB + CNY + General + Sin vinculación</span>
</div>
<div class="mb-2">
<strong>🇺🇸 "Importación USA":</strong><br>
<span class="text-muted">FOB + USD + TLC + Estados Unidos</span>
</div>
<div class="mb-2">
<strong>🏢 "Comercializadora":</strong><br>
<span class="text-muted">FOB + USD + COMERCIALIZADORA + Con vinculación</span>
</div>
</div>
</div>
<div class="mb-3">
<h6 class="text-warning mb-2">
<i class="fas fa-rocket me-1"></i>
Beneficios:
</h6>
<ul class="small text-muted mb-0">
<li>Ahorra tiempo rellenando campos repetitivos</li>
<li>Evita errores al usar configuraciones probadas</li>
<li>Acelera el proceso de creación de solicitudes</li>
<li>Personalizable según tus necesidades</li>
</ul>
</div>
<div class="alert alert-info small">
<i class="fas fa-info-circle me-1"></i>
<strong>Tip:</strong> Crea un template para cada tipo de importación que manejes regularmente.
</div>
</div>
`,
icon: 'question',
showCancelButton: true,
confirmButtonText: '<i class="fas fa-plus me-1"></i>Crear Mi Primer Template',
cancelButtonText: 'Entendido',
confirmButtonColor: '#28a745',
cancelButtonColor: '#6c757d'
}).then((result) => {
if (result.isConfirmed) {
window.open('/IMPORTADORES/templates_rapidos/crear', '_blank');
}
});
}
// ✅ FUNCIÓN PARA MOSTRAR ERRORES DE TEMPLATES
function mostrarErrorTemplates($container, errorMessage, suggestion = '', serverResponse = '') {
$container.html(`
<div class="text-center text-danger py-3">
<i class="fas fa-exclamation-triangle fa-2x mb-2"></i>
<div class="fw-bold">Error al cargar templates</div>
<div class="small text-muted mt-1">${errorMessage}</div>
${suggestion ? `<div class="small text-info mt-1">${suggestion}</div>` : ''}
${serverResponse}
<div class="mt-3 d-grid gap-2 d-md-flex justify-content-center">
<button class="btn btn-sm btn-outline-primary" onclick="loadTemplatesFromDatabase()">
<i class="fas fa-redo-alt me-1"></i>Reintentar
</button>
<a href="/IMPORTADORES/templates_rapidos/crear" class="btn btn-sm btn-outline-success" target="_blank">
<i class="fas fa-plus me-1"></i>Crear Template
</a>
<button class="btn btn-sm btn-outline-info" onclick="abrirDiagnostico()">
<i class="fas fa-wrench me-1"></i>Diagnóstico
</button>
</div>
</div>
`);
}
// ✅ FUNCIÓN PARA ABRIR DIAGNÓSTICO
function abrirDiagnostico() {
window.open('/IMPORTADORES/test_templates.php', '_blank');
}
// ✅ MEJORAR LA INICIALIZACIÓN DEL TOGGLE DE TEMPLATES
$(document).ready(function() {
// Forzar carga de templates si el panel ya está expandido al cargar la página
if ($('#template-selector').hasClass('show')) {
alert('DEBUG: Panel de templates expandido al cargar');
loadTemplatesFromDatabase();
}
// Configurar el toggle de templates con eventos mejorados
$('#toggle-templates').on('click', function() {
alert('DEBUG: Click en toggle-templates');
const $this = $(this);
const $text = $('#toggle-text');
const $actions = $('#templates-quick-actions');
// Cambiar texto del botón según el estado
setTimeout(() => {
if ($('#template-selector').hasClass('show')) {
alert('DEBUG: Panel de templates expandido tras toggle');
$text.html('<i class="fas fa-eye-slash me-1"></i>Ocultar Templates');
$actions.slideDown(200);
// Cargar templates solo cuando se muestre
if ($('#templates-container').children().length <= 1) {
loadTemplatesFromDatabase();
}
} else {
$text.html('<i class="fas fa-eye me-1"></i>Mostrar Mis Templates');
$actions.slideUp(200);
}
}, 100);
});
// Botón de refresh templates
$('#refresh-templates').on('click', function() {
$(this).find('i').addClass('fa-spin');
loadTemplatesFromDatabase();
setTimeout(() => {
$(this).find('i').removeClass('fa-spin');
}, 1000);
});
// Mostrar siempre las acciones rápidas cuando no hay templates
$('#templates-quick-actions').show();
});
// ===================== CARGA DINÁMICA DE PROVEEDORES =====================
function cargarProveedores() {
const proveedorEl = document.getElementById('proveedor_id');
proveedorEl.innerHTML = '<option value="">Cargando proveedores…</option>';
fetch('/IMPORTADORES/solicitud_importacion/ajax_proveedores')
.then(res => res.json())
.then(json => {
proveedorEl.innerHTML = '<option value="">-- Selecciona Proveedor --</option>';
(json.results || []).forEach(item => {
const opt = document.createElement('option');
opt.value = item.id;
opt.textContent = item.text;
proveedorEl.appendChild(opt);
});
})
.catch(() => {
proveedorEl.innerHTML = '<option value="">Error cargando proveedores</option>';
});
}
// ===================== CARGA DINÁMICA DE PEDIMENTOS =====================
function cargarPedimentosReferencia() {
const panel = document.getElementById('pedimentos-referencia');
panel.innerHTML = '<div class="spinner-border spinner-border-sm" role="status"><span class="visually-hidden">Cargando...</span></div><div class="small mt-1">Cargando pedimentos...</div>';
fetch('/IMPORTADORES/solicitud_importacion/ajax_pedimentos_catalogo')
.then(res => res.json())
.then(json => {
if (!json || !json.data || !json.data.length) {
panel.innerHTML = '<div class="text-muted small">No hay pedimentos recientes.</div>';
return;
}
panel.innerHTML = '';
json.data.forEach(ped => {
const div = document.createElement('div');
div.className = 'pedimento-item';
div.innerHTML = `<span class="pedimento-numero">${ped.numero}</span><div class="pedimento-cliente">${ped.cliente || ''}</div><div class="pedimento-meta"><span class="pedimento-clave">${ped.clave || ''}</span><span class="pedimento-fecha">${ped.fecha || ''}</span></div>`;
div.onclick = function() {
const input = document.getElementById('pedimento');
input.value = ped.numero;
div.classList.add('copiado');
setTimeout(() => div.classList.remove('copiado'), 1200);
input.focus();
};
panel.appendChild(div);
});
})
.catch(() => {
panel.innerHTML = '<div class="text-danger small">Error al cargar pedimentos.</div>';
});
}
// ===================== INICIALIZACIÓN =====================
document.addEventListener('DOMContentLoaded', function() {
cargarProveedores();
cargarPedimentosReferencia();
});
</script>
</body>
</html>