Files
MVE/views/locaciones/alta_locaciones.php
2025-07-14 13:27:15 -06:00

374 lines
16 KiB
PHP
Raw 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
$tipoUsuario = $_SESSION['tipo_usuario'] ?? null;
if ($tipoUsuario === 'agente_aduanal') {
include __DIR__ . '/../partials/sidebar_agente.php';
} elseif ($tipoUsuario === 'admin_agencia') {
include __DIR__ . '/../partials/sidebar_agencia.php';
} else {
// Sidebar por defecto o error
echo "<!-- ⚠️ No se encontró sidebar para el tipo de usuario -->";
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>🗺️ Nuevas Locaciones</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>
<!-- 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; }
.sidebar { width: 220px; height: 100vh; background-color: #343a40; position: fixed; top: 0; left: 0; padding-top: 56px; z-index: 1040; }
.sidebar .nav-link { font-weight: bold; color: white; transition: all 0.3s ease; }
.sidebar .nav-link:hover, .sidebar .nav-link.active { background-color: #495057; color: #fff; }
.content { margin-top: 56px; padding: 40px 20px; position: relative; z-index: 1; background-color: #f4f6f9; transition: margin-left 0.3s ease; }
@media (min-width: 768px) { .content { margin-left: 250px; } }
@media (max-width: 767.98px) {
.content { margin-left: 0; }
.sidebar .nav-link { font-weight: normal; color: #343a40; background-color: transparent; }
.sidebar .nav-link:hover, .sidebar .nav-link.active { background-color: #e9ecef; color: #212529; }
}
.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; }
/* ========== 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):focus { border-color: #0d6efd; box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.25), 0 0 20px rgba(13, 110, 253, 0.3); transform: translateY(-2px); }
.form-control:not(.no-animation):not(:placeholder-shown) { /*border-color: #198754; background-color: #f8fff9;*/ }
.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); }
}
/* Floating labels para inputs texto */
.form-floating-custom { position: relative; margin-bottom: 1.5rem; }
.form-floating-custom .form-control { padding: 1rem 0.75rem 0.5rem 0.75rem; height: auto; }
.form-floating-custom .form-label { position: absolute; top: 0.75rem; left: 0.75rem; transition: all 0.3s ease; pointer-events: none; color: #6c757d; z-index: 2; }
.form-floating-custom .form-control:focus ~ .form-label,
.form-floating-custom .form-control:not(:placeholder-shown) ~ .form-label { top: 0.25rem; font-size: 0.75rem; color: #0d6efd; font-weight: 600; }
.input-pulse:hover:not(.no-animation) { animation: inputPulse 0.6s ease-in-out; }
@keyframes inputPulse {
0% { transform: scale(1); }
50% { transform: scale(1.02); }
100% { transform: scale(1); }
}
.input-gradient:not(.no-animation) { position: relative; overflow: hidden; }
.input-gradient:not(.no-animation)::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%;
background: linear-gradient(90deg, transparent, rgba(13, 110, 253, 0.3), transparent); transition: left 0.5s; pointer-events: none; z-index: 1; }
.input-gradient:not(.no-animation):focus::before { left: 100%; }
.form-control.valid:not(.no-animation) { /*border-color: #198754; background: linear-gradient(45deg, #fff, #f8fff9);*/ animation: successGlow 1s ease-in-out; }
@keyframes successGlow {
0% { box-shadow: 0 0 5px rgba(25, 135, 84, 0.5); }
50% { box-shadow: 0 0 20px rgba(25, 135, 84, 0.8); }
100% { box-shadow: 0 0 5px rgba(25, 135, 84, 0.5); }
}
/* 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); } }
</style>
</head>
<body>
<div class="content">
<h4 class="mb-4 animate__animated animate__fadeInDown title_glow">🗺️ Nuevas Locaciones</h4>
<div class="row g-3">
<!-- Nuevo Estado -->
<div class="col-md form-group-animated">
<div class="card p-4 bg-white shadow-sm card-hover position-relative h-auto">
<form id="estadoForm">
<h4 class="mb-4 text-dark"> Nuevo Estado</h4><br>
<!-- País -->
<div class="col-md-12 form-group-animated">
<label for="paisEstado" class="form-label">País *</label>
<select id="paisEstado" name="pais" class="form-select" required>
<option value="">-- Selecciona un país --</option>
<?php foreach($paises as $p): ?>
<option value="<?= $p['id_pais'] ?>">
<?= htmlspecialchars($p['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
</div><br><br><br>
<!-- Estado -->
<div class="col-md-12 form-group-animated">
<label for="entidadEstado" class="form-label">Entidad / Provincia *</label>
<input id="entidadEstado" name="entidad" class="form-control" required>
</div><br><br>
<div class="col-md-4 d-flex align-items-end form-group-animated">
<button type="submit" class="btn btn-success W-100 btn-animated">
<i class="fas fa-plus"></i> Registrar Estado
</button>
<a href="/IMPORTADORES/locaciones/lista" class="btn btn-secondary ms-2 W-100 btn-animated">Cancelar</a>
</div>
</form>
</div>
</div>
<!-- Nueva Ciudad -->
<div class="col-md form-group-animated">
<div class="card p-4 bg-white shadow-sm card-hover position-relative h-auto">
<form id="ciudadForm" action="/IMPORTADORES/locaciones/guadarCiudad" method="POST" enctype="multipart/form-data">
<h4 class="mb-4 text-dark"> Nueva Ciudad</h4>
<!-- País -->
<div class="col-md-12 form-group-animated">
<label for="paisCiudad" class="form-label">País *</label>
<select id="paisCiudad" name="pais" class="form-select" required>
<option value="">-- Selecciona un país --</option>
<?php foreach($paises as $p): ?>
<option value="<?= $p['id_pais'] ?>">
<?= htmlspecialchars($p['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
</div><br>
<!-- Estado -->
<div class="col-md-12 form-group-animated">
<label for="entidadCiudad" class="form-label">Entidad / Provincia *</label>
<select id="estadoCiudad" name="entidad" class="form-select" required disabled>
<option value="">Primero país…</option>
</select>
</div><br>
<!-- Ciudad -->
<div class="col-md-12 form-group-animated">
<label for="nombreCiudad" class="form-label">Ciudad *</label>
<input id="nombreCiudad" name="ciudad" class="form-control" required>
</div><br>
<div class="col-md-4 d-flex align-items-end form-group-animated">
<button type="submit" class="btn btn-success W-100 btn-animated">
<i class="fas fa-plus"></i> Registrar Ciudad
</button>
<a href="/IMPORTADORES/locaciones/lista" class="btn btn-secondary ms-2 W-100 btn-animated">Cancelar</a>
</div>
</form>
</div>
</div>
</div>
</div>
<script>
// Función para cargar estados
function cargarEstados(paisId, selectElement) {
selectElement.innerHTML = '<option>Cargando...</option>';
selectElement.disabled = true;
fetch(`/IMPORTADORES/locaciones/estados?pais=${paisId}`)
.then(response => response.json())
.then(estados => {
selectElement.innerHTML = '<option value="">-- Selecciona un estado --</option>';
estados.forEach(estado => {
const option = new Option(estado.nombre, estado.id_estado);
selectElement.add(option);
});
selectElement.disabled = false;
})
.catch(error => {
console.error('Error:', error);
selectElement.innerHTML = '<option value="">Error al cargar</option>';
});
}
// Evento para cargar estados cuando se selecciona país en formulario de ciudad
document.getElementById('paisCiudad').addEventListener('change', function(e) {
const paisId = e.target.value;
const estadoSelect = document.getElementById('estadoCiudad');
if (paisId) {
cargarEstados(paisId, estadoSelect);
} else {
estadoSelect.innerHTML = '<option value="">Primero selecciona un país...</option>';
estadoSelect.disabled = true;
}
});
// Formulario de nuevo estado
document.getElementById('estadoForm').addEventListener('submit', function(e) {
e.preventDefault();
// Obtener valores directamente
const paisSelect = document.getElementById('paisEstado');
const entidadInput = document.getElementById('entidadEstado');
const paisValue = paisSelect.value;
const entidadValue = entidadInput.value.trim();
// Validación en frontend
if (!paisValue) {
Swal.fire({ icon: 'warning', title: 'Campo requerido', text: 'Debe seleccionar un país' });
return;
}
if (!entidadValue) {
Swal.fire({ icon: 'warning', title: 'Campo requerido', text: 'Debe ingresar el nombre del estado' });
return;
}
// Crear FormData manualmente
const formData = new FormData();
formData.append('pais', paisValue);
formData.append('entidad', entidadValue);
const submitBtn = this.querySelector('button[type="submit"]');
const originalText = submitBtn.innerHTML;
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Guardando...';
submitBtn.disabled = true;
// Debug: mostrar lo que se va a enviar
console.log('Enviando:', {
pais: paisValue,
entidad: entidadValue
});
fetch('/IMPORTADORES/locaciones/guardarEstado', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
Swal.fire({ icon: 'success', title: '¡Éxito!', text: data.message, timer: 2000, showConfirmButton: false });
this.reset();
} else {
Swal.fire({ icon: 'error', title: 'Error', text: data.message });
}
})
.catch(error => {
console.error('Error:', error);
Swal.fire({ icon: 'error', title: 'Error', text: 'Ocurrió un error al procesar la solicitud' });
})
.finally(() => {
submitBtn.innerHTML = originalText;
submitBtn.disabled = false;
});
});
// Formulario de nueva ciudad
document.getElementById('ciudadForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
const submitBtn = this.querySelector('button[type="submit"]');
const originalText = submitBtn.innerHTML;
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Guardando...';
submitBtn.disabled = true;
fetch('/IMPORTADORES/locaciones/guardarCiudad', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
Swal.fire({ icon: 'success', title: '¡Éxito!', text: data.message, timer: 2000, showConfirmButton: false });
this.reset();
// Resetear el select de estados
document.getElementById('estadoCiudad').innerHTML = '<option value="">Primero selecciona país</option>';
document.getElementById('estadoCiudad').disabled = true;
} else {
Swal.fire({ icon: 'error', title: 'Error', text: data.message });
}
})
.catch(error => {
console.error('Error:', error);
Swal.fire({ icon: 'error', title: 'Error', text: 'Ocurrió un error al procesar la solicitud' });
})
.finally(() => {
submitBtn.innerHTML = originalText;
submitBtn.disabled = false;
});
});
// Script para manejar las animaciones de validación
document.addEventListener('DOMContentLoaded', function() {
const inputs = document.querySelectorAll('input.form-control');
inputs.forEach(input => {
// Validación en tiempo real
input.addEventListener('input', function() {
if (this.checkValidity()) {
this.classList.remove('shake');
this.classList.add('valid');
} else {
this.classList.remove('valid');
}
});
// Efecto shake en campos inválidos
input.addEventListener('invalid', function() {
this.classList.add('shake');
setTimeout(() => {
this.classList.remove('shake');
}, 500);
});
});
// Validación del formulario
document.getElementById('formAltaPatente').addEventListener('submit', function(e) {
e.preventDefault();
let isValid = true;
inputs.forEach(input => {
if (!input.checkValidity()) {
input.classList.add('shake');
isValid = false;
}
});
});
});
</script>
</body>
</html>