Files
MVE/views/transportistas/alta.php
2025-07-18 12:21:26 -06:00

487 lines
26 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> Alta de 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>
<!-- SweetAlert2 -->
<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; }
.navbar { position: fixed; top: 0; width: 100%; z-index: 1050; }
@media (min-width: 768px) { .content { margin-left: 250px; } }
@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%; }
/* ========== 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); }
}
.input-typing:not(.no-animation) { position: relative; }
.input-typing:not(.no-animation)::after { content: '|'; position: absolute; right: 10px; top: 50%; transform: translateY(-50%); opacity: 0; animation: blink 1s infinite; color: #0d6efd; }
.input-typing:not(.no-animation):focus::after { opacity: 1; }
@keyframes blink {
0%, 50% { opacity: 1; }
51%, 100% { opacity: 0; }
}
.input-ripple:not(.no-animation) { position: relative; overflow: hidden; }
.input-ripple:not(.no-animation)::before { content: ''; position: absolute; top: 50%; left: 50%; width: 0; height: 0;
background: rgba(13, 110, 253, 0.2); border-radius: 50%; transform: translate(-50%, -50%); transition: width 0.3s, height 0.3s; pointer-events: none; }
.input-ripple:not(.no-animation):focus::before { width: 300px; height: 300px; }
/* 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); } }
/* ========== ANIMACIONES PARA SELECT ========== */
.form-select { transition: all 0.3s ease; border: 2px solid #dee2e6; position: relative; cursor: pointer;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m1 6 7 7 7-7'/%3e%3c/svg%3e");
background-repeat: no-repeat; background-position: right 0.75rem center; background-size: 16px 12px; padding: 1rem 2.5rem 0.5rem 0.75rem; height: auto; min-height: 3.5rem; }
.form-select: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);
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%230d6efd' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m1 6 7 7 7-7'/%3e%3c/svg%3e"); }
.form-select:not([value=""]):valid { border-color: #198754; background-color: #f8fff9;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23198754' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m1 6 7 7 7-7'/%3e%3c/svg%3e"); }
.form-select[value=""] { border-color: #dee2e6; background-color: #fff; }
/* Floating labels para select */
.form-floating-custom .form-select ~ .form-label { position: absolute; top: 50%; left: 0.75rem; transform: translateY(-50%); pointer-events: none;
transition: all 0.3s ease; color: #6c757d; font-size: 0.875rem; background: white; padding: 0 0.25rem; z-index: 1; opacity: 0; }
.form-floating-custom .form-select:focus ~ .form-label { opacity: 1; top: 0; transform: translateY(-50%) scale(0.85); color: #0d6efd; font-weight: 600; }
.form-floating-custom .form-select:not([value=""]):valid ~ .form-label { opacity: 1; top: 0; transform: translateY(-50%) scale(0.85); color: #0d6efd; font-weight: 600; }
.form-select.shake { animation: shake 0.5s ease-in-out; }
.select-pulse:hover { animation: inputPulse 0.6s ease-in-out; }
.select-gradient { position: relative; overflow: hidden; }
.select-gradient::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; }
.select-gradient:focus::before { left: 100%; }
.form-select.valid { border-color: #198754; background-color: #f8fff9; animation: successGlow 1s ease-in-out; }
.select-arrow-rotate { transition: all 0.3s ease; }
.select-arrow-rotate:focus { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%230d6efd' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m1 10 7-7 7 7'/%3e%3c/svg%3e"); }
.select-ripple { position: relative; overflow: hidden; }
.select-ripple::after { content: ''; position: absolute; top: 50%; left: 50%; width: 0; height: 0;
background: rgba(13, 110, 253, 0.2); border-radius: 50%; transform: translate(-50%, -50%); transition: width 0.3s, height 0.3s; pointer-events: none; }
.select-ripple:focus::after { width: 300px; height: 300px; }
.select-scale { transition: transform 0.2s ease; }
.select-scale:hover {transform: scale(1.02); }
.select-scale:focus { transform: scale(1.02) translateY(-2px); }
.form-select option { padding: 0.5rem; transition: all 0.2s ease; }
.form-select option:hover { background-color: #f8f9fa; }
.select-status { position: relative; }
.select-status::after { content: ''; position: absolute; right: 2.5rem; top: 50%; transform: translateY(-50%);
width: 8px; height: 8px; border-radius: 50%; background-color: #dc3545; opacity: 0; transition: opacity 0.3s ease; }
.select-status.valid::after { background-color: #198754; opacity: 1; }
.select-status:invalid::after { background-color: #dc3545; opacity: 1; }
</style>
</head>
<body>
<div class="content">
<h4 class="mb-4 animate__animated animate__fadeInDown title_glow"> Alta de Transportista</h4>
<form action="/IMPORTADORES/transportistas/guardar" method="POST" class="card p-4 shadow-sm card-hover position-relative h-auto fade-in-up" id="formAltaTransportista">
<!-- Hidden para persona moral -->
<input type="hidden" name="es_persona_moral" id="es_persona_moral" value="0">
<!-- Switch Persona Moral -->
<div class="row mb-3">
<div class="col-md-4 d-flex align-items-end">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="personaMoralSwitch">
<label class="form-check-label" for="personaMoralSwitch">Es Persona Moral</label>
</div>
</div>
</div>
<div class="row g-3">
<div class="col-md-4 form-group-animated">
<div class="form-floating-custom">
<input name="clave" id="clave" type="text" class="form-control input-pulse input-gradient" maxlength="8" placeholder=" " required>
<label for="clave" class="form-label">Clave *</label>
</div>
</div>
<div class="col-md-4 form-group-animated">
<div class="form-floating-custom">
<input name="nombre" id="nombre" type="text" class="form-control input-pulse input-gradient" placeholder=" " required>
<label for="nombre" class="form-label" id="labelNombre">Nombre *</label>
</div>
</div>
<div class="col-md-4 form-group-animated">
<div class="form-floating-custom">
<input name="rfc" id="rfc" type="text" class="form-control input-pulse input-gradient" maxlength="13" placeholder=" " required>
<label for="rfc" class="form-label">RFC *</label>
</div>
</div>
<div class="col-md-4 form-group-animated">
<div class="form-floating-custom">
<input name="curp" id="curp" type="text" class="form-control input-pulse input-gradient" maxlength="18" placeholder=" ">
<label for="curp" class="form-label">CURP *</label>
</div>
</div>
<div class="col-md-4 form-group-animated">
<div class="form-floating-custom">
<input name="telefono" id="telefono" type="text" class="form-control input-pulse input-gradient" maxlength="11" placeholder=" " required>
<label for="telefono" class="form-label">Teléfono *</label>
</div>
</div>
<div class="col-md-4 form-group-animated">
<div class="form-floating-custom">
<input name="caat" id="caat" type="text" class="form-control input-pulse input-gradient" maxlength="20" placeholder=" " required>
<label for="caat" class="form-label">Código caat *</label>
</div>
</div>
<div class="col-md-4 form-group-animated">
<div class="form-floating-custom">
<select id="pais" name="pais" class="form-select select-pulse select-gradient select-arrow-rotate select-status" 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>
<label for="pais" class="form-label">País</label>
</div>
</div>
<div class="col-md-4 form-group-animated">
<div class="form-floating-custom">
<select id="entidad" name="entidad" class="form-select select-pulse select-gradient select-arrow-rotate select-status" required disabled>
<option value="">Primero país…</option>
</select>
<label for="entidad" class="form-label">Entidad</label>
</div>
</div>
<div class="col-md-4 form-group-animated">
<div class="form-floating-custom">
<select id="ciudad" name="ciudad" class="form-select select-pulse select-gradient select-arrow-rotate select-status" required disabled>
<option value="">Primero estado…</option>
</select>
<label for="ciudad" class="form-label">Ciudad</label>
</div>
</div>
<div class="col-md-12 form-group-animated">
<div class="form-floating-custom">
<input name="domicilio" id="domicilio" type="text" class="form-control input-pulse input-gradient" maxlength="100" placeholder=" " required>
<label for="domicilio" class="form-label">Domicilio *</label>
</div>
</div>
</div>
<div class="text-end mt-4 form-group-animated">
<button class="btn btn-success px-4 mt-auto w-auto btn-animated">Guardar Transportista</button>
<a href="/IMPORTADORES/transportistas/lista" class="btn btn-secondary ms-2 mt-auto w-auto btn-animated">Cancelar</a>
</div>
</form>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Referencias a elementos del DOM
const form = document.getElementById('formAltaTransportista');
const inputs = document.querySelectorAll('input.form-control, select.form-select');
const selects = document.querySelectorAll('.form-select');
// Configurar validación en tiempo real para inputs
inputs.forEach(input => {
input.addEventListener('input', function() {
if (this.checkValidity()) {
this.classList.remove('shake');
this.classList.add('valid');
} else {
this.classList.remove('valid');
}
});
input.addEventListener('invalid', function() {
this.classList.add('shake');
setTimeout(() => {
this.classList.remove('shake');
}, 500);
});
});
// Configurar selects
selects.forEach(select => {
select.addEventListener('change', function() {
updateSelectState(this);
});
updateSelectState(select);
});
function updateSelectState(select) {
select.setAttribute('value', select.value);
if (select.value && select.value !== '') {
select.classList.add('valid');
select.classList.remove('invalid');
} else {
select.classList.remove('valid');
if (select.hasAttribute('required') && select.closest('form')?.classList.contains('was-validated')) {
select.classList.add('invalid');
}
}
}
// Event listener para el formulario
if (form) {
form.addEventListener('submit', function(e) {
e.preventDefault();
const rfc = document.getElementById('rfc').value.trim().toUpperCase();
const curp = document.getElementById('curp').value.trim();
const telefono = document.getElementById('telefono').value.trim();
const clave = document.getElementById('clave').value.trim();
const nombre = document.getElementById('nombre').value.trim();
const caat = document.getElementById('caat').value.trim();
const pais = document.getElementById('pais').value;
const entidad = document.getElementById('entidad').value;
const ciudad = document.getElementById('ciudad').value;
const domicilio = document.getElementById('domicilio').value.trim();
const curpRegex = /^[A-Z]{4}[0-9]{6}[HM](AS|BC|BS|CC|CL|CM|CS|CH|DF|DG|GT|GR|HG|JC|MC|MN|MS|NT|NL|OC|PL|QT|QR|SP|SL|SR|TC|TS|TL|VZ|YN|ZS)[A-Z]{3}[A-Z0-9]{2}$/;
const rfcRegex = /^[A-ZÑ&]{3,4}\d{6}[A-Z0-9]{3}$/;
const telefonoRegex = /^\d{3}\s\d{7}$/;
if (!clave) {
Swal.fire({ icon: 'warning', title: 'Campo requerido', text: 'La clave es obligatoria.', confirmButtonColor: '#dc3545'});
document.getElementById('clave').focus();
return;
}
if (clave.length>8) {
Swal.fire({ icon: 'error', title: 'Clave inválida', text: 'La clave no puede tener más de 8 caracteres.', confirmButtonColor: '#dc3545'});
document.getElementById('clave').focus();
return;
}
if (!nombre) {
Swal.fire({ icon: 'warning', title: 'Campo requerido', text: 'El nombre es obligatorio.', confirmButtonColor: '#dc3545'});
document.getElementById('nombre').focus();
return;
}
if (!rfc) {
Swal.fire({ icon: 'warning', title: 'Campo requerido', text: 'El RFC es obligatorio.', confirmButtonColor: '#dc3545'});
document.getElementById('rfc').focus();
return;
}
if (!rfcRegex.test(rfc)) {
Swal.fire({ icon: 'error', title: 'RFC inválido', text: 'El RFC debe tener 12 o 13 caracteres con el formato correcto (ej. ABC123456XYZ).', confirmButtonColor: '#dc3545'});
document.getElementById('rfc').focus();
return;
}
if (curp && !curpRegex.test(curp)) {
Swal.fire({ icon: 'error', title: 'CURP inválido', text: 'El CURP no tiene el formato correcto.', confirmButtonColor: '#dc3545'});
document.getElementById('curp').focus();
return;
}
if (!telefono) {
Swal.fire({ icon: 'warning', title: 'Campo requerido', text: 'El teléfono es obligatorio.', confirmButtonColor: '#dc3545'});
document.getElementById('telefono').focus();
return;
}
if (!telefonoRegex.test(telefono)) {
Swal.fire({ icon: 'error', title: 'Teléfono inválido', text: 'Debe tener 10 dígitos en el formato: 3 dígitos (LADA), espacio, y 7 dígitos (ej. 123 4567890).', confirmButtonColor:'#dc3545'});
document.getElementById('telefono').focus();
return;
}
if (telefono.length>11) {
Swal.fire({ icon: 'error', title: 'Teléfono inválido', text: 'El teléfono no puede tener más de 11 caracteres.', confirmButtonColor: '#dc3545'});
document.getElementById('telefono').focus();
return;
}
if (!caat) {
Swal.fire({ icon: 'warning', title: 'Campo requerido', text: 'El código caat es obligatorio.', confirmButtonColor: '#dc3545'});
document.getElementById('caat').focus();
return;
}
if (!pais) {
Swal.fire({ icon: 'warning', title: 'Campo requerido', text: 'Debe seleccionar un país.', confirmButtonColor: '#dc3545'});
document.getElementById('pais').focus();
return;
}
if (!entidad) {
Swal.fire({ icon: 'warning', title: 'Campo requerido', text: 'Debe seleccionar un estado.', confirmButtonColor: '#dc3545'});
document.getElementById('entidad').focus();
return;
}
if (!ciudad) {
Swal.fire({ icon: 'warning', title: 'Campo requerido', text: 'Debe seleccionar una ciudad.', confirmButtonColor: '#dc3545'});
document.getElementById('ciudad').focus();
return;
}
if (!domicilio) {
Swal.fire({ icon: 'warning', title: 'Campo requerido', text: 'El domicilio es obligatorio.', confirmButtonColor: '#dc3545'});
document.getElementById('domicilio').focus();
return;
}
// Actualizar valores procesados
const rfcElement = document.getElementById('rfc');
const curpElement = document.getElementById('curp');
if (rfcElement) rfcElement.value = rfc;
if (curpElement) curpElement.value = curp;
// Si todas las validaciones son correctas: Enviar el formulario
this.submit();
// Validar campos
let isValid = true;
inputs.forEach(input => {
if (!input.checkValidity()) {
input.classList.add('shake');
isValid = false;
}
});
})
}
document.getElementById('pais').addEventListener('change', e => {
const pid = e.target.value;
const estadoSelect = document.getElementById('entidad');
const ciudadSelect = document.getElementById('ciudad');
estadoSelect.innerHTML = '<option value="">Cargando…</option>';
estadoSelect.disabled = true;
ciudadSelect.innerHTML = '<option value="">Primero estado…</option>';
ciudadSelect.disabled = true;
if (!pid) { estadoSelect.innerHTML = '<option value="">Primero país…</option>'; return; }
fetch(`/IMPORTADORES/transportistas/estados?pais=${pid}`)
.then(r => { if (!r.ok) throw new Error('Error al cargar estados'); return r.json(); })
.then(list => {
estadoSelect.innerHTML = '<option value="">-- Selecciona un Estado --</option>';
list.forEach(st => estadoSelect.add(new Option(st.nombre, st.id_estado)));
estadoSelect.disabled = false;
})
.catch(() => {
estadoSelect.innerHTML = '<option value="">Error al cargar</option>';
Swal.fire({ icon:'error', title:'Error', text:'No se pudieron cargar los estados', confirmButtonColor:'#dc3545'});
});
});
document.getElementById('entidad').addEventListener('change', e => {
const eid = e.target.value;
const ciudadSelect = document.getElementById('ciudad');
ciudadSelect.innerHTML = '<option value="">Cargando…</option>';
ciudadSelect.disabled = true;
if (!eid) { ciudadSelect.innerHTML = '<option value="">Primero estado…</option>'; return; }
fetch(`/IMPORTADORES/transportistas/ciudades?estado=${eid}`)
.then(r => { if (!r.ok) throw new Error('Error al cargar ciudades'); return r.json(); })
.then(list => {
ciudadSelect.innerHTML = '<option value="">-- Seleciona una ciudad --</option>';
list.forEach(ct => ciudadSelect.add(new Option(ct.nombre, ct.id_ciudad)));
ciudadSelect.disabled = false;
})
.catch(() => {
ciudadSelect.innerHTML = '<option value="">Error al cargar</option>';
Swal.fire({ icon:'error', title:'Error', text:'No se pudieron cargar las ciudades', confirmButtonColor:'#dc3545'});
});
});
// Switch Persona Moral
document.getElementById('personaMoralSwitch')?.addEventListener('change', function() {
const checked = this.checked;
const label = document.getElementById('labelNombre');
const curp = document.getElementById('curp');
const hidden = document.getElementById('es_persona_moral');
if (label) {
label.textContent = checked ? 'Razón Social *' : 'Nombre *';
}
if (curp && hidden) {
if (checked) {
curp.value = '';
curp.disabled = true;
curp.removeAttribute('required');
hidden.value = '1';
} else {
curp.disabled = false;
curp.setAttribute('required', 'required');
hidden.value = '0';
}
}
});
});
</script>
</body>
</html>