$.ajaxSetup({ headers: { 'Authorization': 'Bearer ', 'X-User-Token': 'es', } }); if(axios) { axios.defaults.headers.common['X-User-Lang'] = 'es'; axios.defaults.headers.common['Authorization'] = 'Bearer '; } const AppInstance = function() { this.auth = { signIn: false, user: {"cl_pueblo": ""} } this.authToken = ''; this.baseUrl = 'https://tulicenciapr.com/'; this.baseApiUrl = 'https://api.tulicenciapr.com:2053/api'; } AppInstance.prototype = { route: function(uri, params = {}) { return route(uri, params); }, apiUrl: function(uri) { return `${this.baseApiUrl}${uri}` }, getStepItem: function (name, def = null, formIndex = 0) { var nameKey = `stepForm-${formIndex}-${name}` return localStorage.getItem(nameKey) ? localStorage.getItem(nameKey) : def; }, setStepItem: function (name, value = '', formIndex = 0) { var nameKey = `stepForm-${formIndex}-${name}` localStorage.setItem(nameKey, _.toString(value)); } } window['App'] = new AppInstance(); const TranslatorInstance = function() { this.lang = 'es'; this.translations = []; this.load(); } TranslatorInstance.prototype = { load: function () { var self = this; axios.get(`https://api.tulicenciapr.com:2053/api/Translation/Json/es?`) .then(function(response) { self.translations = response.data; }) }, replaceArgs: function(template, args) { return template.replace(/\{(\d+)\}/g, function(match, index) { return args[index] !== undefined ? args[index] : match; }) }, translate: function(name, trans = '', args = []) { if (Array.isArray(trans)) { args = trans; trans = undefined; } const value = this.translations[name.toLowerCase()] ?? trans ?? name; var text = typeof value === "string" && value.includes("::") ? value.split("::")[1] : value; return this.replaceArgs(text, args); }, t: function(name, trans = '', args = []) { return this.translate(name, trans, args); } } window['Translator'] = new TranslatorInstance(); /** * Validaciones */ $.validator.methods.email = function (value, element) { return this.optional(element) || /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/.test(value); }; $.validator.addMethod("license-number", function (value, element) { return this.optional(element) || /^[A-Za-z0-9]+$/.test(value); }, 'La licencia solo puede contener letras y números, sin espacios ni símbolos.'); $.extend($.validator.messages, { required: 'Este campo es requerido', email: 'Ingrese un correo electrónico válido', numbers: 'Solo se permiten números', minlength: $.validator.format('El campo no puede tener menos de {0} caracteres'), maxlength: $.validator.format('El campo no puede tener más de {0} caracteres'), equalTo: 'Ingrese el mismo valor de nuevo', digits: 'Solo se permiten dígitos', letters: 'Solo se permiten letras', range: $.validator.format('El valor debe estar entre {0} y {1}'), max: $.validator.format('El valor máximo del campo es {0}'), min: $.validator.format('El valor mínimo del campo es {0}'), phone: 'Formato de teléfono inválido. Ej: (999) 999-9994', username: 'Solo se permiten letras, números y guiones bajos', password: 'La contraseña debe contener al menos 8 caracteres, una letra mayúscula, un número y un carácter especial.', card: 'Ingrese un número de tarjeta válido (Visa, MasterCard, Amex, etc.).', 'email-exists': 'Este correo ingresado ya se encuentrado registrado.', 'username-exists': 'El usuario ingresado ya existe en nuestros registros.', 'min-age': 'No cumples con la edad mínima requerida.', }); const phoneFormat = function(value) { if (!value) return value; const phoneNumber = value.replace(/[^\d]/g, ""); const phoneNumberLength = phoneNumber.length; if (phoneNumberLength < 4) { return phoneNumber } if (phoneNumberLength < 7) { return `(${phoneNumber.slice(0, 3)}) ${phoneNumber.slice(3)}`; } return `(${phoneNumber.slice(0, 3)}) ${phoneNumber.slice(3, 6)}-${phoneNumber.slice(6, 10)}`; } const detectCardType = function (numero) { const value = numero.replace(/\D/g, ''); // eliminar espacios o guiones const cardPatterns = { visa: /^4\d{0,15}$/, mastercard: /^(5[1-5]|2[2-7])\d{0,14}$/, amex: /^3[47]\d{0,13}$/, discover: /^6(?:011|5)/, diners: /^3(?:0[0-5]|[68])/, jcb: /^(?:2131|1800|35)/ }; for (let tipo in cardPatterns) { if (cardPatterns[tipo].test(value)) { return tipo; } } return null; } $('input[data-rule-phone="true"]').on('input', function(e) { $(this).val(phoneFormat(e.currentTarget.value)); }); $('input[data-rule-card="true"]').on('input', function(e) { const numberCard = $(this).val(); const typeCard = detectCardType(numberCard); const $output = $(this).closest('.input-group').find('.input-icon'); if (typeCard) { $output.html(`Tarjeta`); } else { $output.html(`Tarjeta`); } }); $.validator.addMethod("numbers", function(value, element) { return this.optional(element) || /^[0-9]+$/.test(value); }); $.validator.addMethod("letters", function(value, element) { return this.optional(element) || /^[a-zA-ZáéíóúÁÉÍÓÚñÑ\s]+$/.test(value); }); $.validator.addMethod("phone", function(value, element) { return this.optional(element) || /^\(\d{3}\)\s\d{3}-\d{4}$/.test(value); }); $.validator.addMethod("username", function (value, element) { return this.optional(element) || /^[A-Za-z0-9_]+$/.test(value); }); $.validator.addMethod("password", function (value, element) { return this.optional(element) || /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{8,}$/.test(value); }); $.validator.addMethod("card", function (value, element) { if (this.optional(element)) return true; // Eliminar espacios y guiones value = value.replace(/[\s-]/g, ''); // Validar solo números if (!/^\d+$/.test(value)) return false; // Tipos de tarjeta comunes (regex) const cardPatterns = { visa: /^4\d{12}(?:\d{3})?$/, // 13 o 16 dígitos mastercard: /^5[1-5]\d{14}|^2[2-7]\d{14}$/, // MasterCard 51–55 o 2221–2720 amex: /^3[47]\d{13}$/, // American Express discover: /^6(?:011|5\d{2})\d{12}$/, // Discover diners: /^3(?:0[0-5]|[68]\d)\d{11}$/, // Diners Club jcb: /^(?:2131|1800|35\d{3})\d{11}$/ // JCB }; // Comprobar coincidencia con algún tipo let isValidType = false; for (let key in cardPatterns) { if (cardPatterns[key].test(value)) { isValidType = true; break; } } if (!isValidType) return false; // Validar con algoritmo Luhn let sum = 0; let shouldDouble = false; for (let i = value.length - 1; i >= 0; i--) { let digit = parseInt(value.charAt(i), 10); if (shouldDouble) { digit *= 2; if (digit > 9) digit -= 9; } sum += digit; shouldDouble = !shouldDouble; } return (sum % 10) === 0; }); $.validator.addMethod("email-exists", function(value, element, param) { let isValid = false; $.ajax({ url: `https://api.tulicenciapr.com:2053/api/Usuario/ListarCorreos?query=${value}`, type: "GET", dataType: "json", async: false, success: function(response) { isValid = response.length === 0; }, error: function() { isValid = false; } }); return isValid; }); $.validator.addMethod("username-exists", function(value, element, param) { let isValid = false; $.ajax({ url: `https://api.tulicenciapr.com:2053/api/Usuario/ListarUsuarios?query=${value}`, type: "GET", dataType: "json", async: false, success: function(response) { isValid = response.length === 0; }, error: function() { isValid = false; } }); return isValid; }); $.validator.addMethod("min-age", function (value, element, param) { if (!value) return false; const inputDate = new Date(value); const today = new Date(); let age = today.getFullYear() - inputDate.getFullYear(); const monthDiff = today.getMonth() - inputDate.getMonth(); const dayDiff = today.getDate() - inputDate.getDate(); if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) { age--; } return age >= parseInt(param); }); /** ** * */ $('[name="licenseCategory"]').on('change', function(e) { var licenseCategory = $(this).val(); var $vehicleType = $('[name="vehicleType"]'); $vehicleType.closest('.field').toggleClass('!hidden', licenseCategory !== 'Chofer'); if(licenseCategory !== 'Chofer') { $vehicleType.val(''); } }); $('[name="identificationType"]').on('change', function() { var identificationType = $(this).val(); if(identificationType === 'Seguro Social') { $('[name="identificationNumber"]').attr('maxlength', 4); $('[name="identificationNumber"]').attr('readonly', 'true'); $('[name="identificationNumber"]').val(App.auth.user.cl_numeroSeguro); $('[name="identificationNumber"]').val(App.auth.user.cl_numeroSeguro); App.setStepItem('identificationNumber', App.auth.user.cl_numeroSeguro) } else { $('[name="identificationNumber"]').attr('maxlength', 9); $('[name="identificationNumber"]').removeAttr('readonly'); $('[name="identificationNumber"]').val(''); App.setStepItem('identificationNumber') } }); $('[name="addressResidential"]').on('change', function() { $('#addressResidentialContainer').toggleClass('hidden', $(this).val() === 'Sí'); }); $(document).ready(function() { $(`[name="licenseCategory"]`).val(App.getStepItem('licenseCategory', 'Conductor')).trigger('change'); $(`[name="identificationType"][value="${App.getStepItem('identificationType', 'Seguro Social')}"]`).prop('checked', true).trigger('change'); $(`[name="identificationNumber"]`).val(App.getStepItem('identificationNumber')); $('[name="licenseNumber"]').val(App.auth.user.cl_numeroLicencia); $('[name="town"]').val(App.auth.user.cl_pueblo.pl_id).trigger('change'); $('[name="zip"]').val(App.auth.user.cl_zip).trigger('change'); $('#addressResidentialContainer').toggleClass('hidden', $('[name="addressResidential"]').val() === 'No'); }); (function() { if (window.__pageTransitionInstalled) return; window.__pageTransitionInstalled = true; function ensureTransitionLayer() { if (document.getElementById('global-page-transition')) { return; } const style = document.createElement('style'); style.id = 'global-page-transition-style'; style.textContent = [ '#global-page-transition{position:fixed;inset:0;z-index:99999;display:flex;align-items:center;justify-content:center;opacity:0;visibility:hidden;transition:opacity .2s ease;}', '#global-page-transition.is-visible{opacity:1;visibility:visible;}', '#global-page-transition .gpt-box{display:flex;flex-direction:column;align-items:center;gap:10px;padding:16px 20px;border-radius:14px;background:rgba(255,255,255,.78);backdrop-filter:blur(3px);}', '#global-page-transition .gpt-spin{width:40px;height:40px;border-radius:999px;border:4px solid rgba(5,150,105,.2);border-top-color:#059669;animation:gpt-spin .75s linear infinite;}', '#global-page-transition .gpt-text{font-family:inherit;font-size:14px;line-height:1.2;font-weight:600;color:#065f46;}', '@keyframes gpt-spin{to{transform:rotate(360deg);}}' ].join(''); document.head.appendChild(style); const layer = document.createElement('div'); layer.id = 'global-page-transition'; layer.setAttribute('aria-hidden', 'true'); layer.innerHTML = '
Cargando...
'; document.body.appendChild(layer); } function showTransition(message) { ensureTransitionLayer(); const layer = document.getElementById('global-page-transition'); if (!layer) return; const bodyBg = window.getComputedStyle(document.body).backgroundColor; layer.style.background = bodyBg && bodyBg !== 'rgba(0, 0, 0, 0)' ? bodyBg : '#f3faf4'; const text = layer.querySelector('.gpt-text'); if (text && message) { text.textContent = message; } layer.classList.add('is-visible'); layer.setAttribute('aria-hidden', 'false'); } function hideTransition() { const layer = document.getElementById('global-page-transition'); if (!layer) return; layer.classList.remove('is-visible'); layer.setAttribute('aria-hidden', 'true'); } document.addEventListener('DOMContentLoaded', function() { ensureTransitionLayer(); }); window.addEventListener('pageshow', function() { hideTransition(); }); document.addEventListener('click', function(event) { const link = event.target.closest('a'); if (!link) return; const href = link.getAttribute('href'); if (!href || href.startsWith('#') || href.startsWith('javascript:')) return; if (link.target === '_blank' || link.hasAttribute('download')) return; if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; const url = new URL(link.href, window.location.href); if (!/^https?:$/.test(url.protocol)) return; showTransition('Cargando...'); }, false); document.addEventListener('submit', function(event) { const form = event.target; if (!(form instanceof HTMLFormElement)) return; if (form.target && form.target.toLowerCase() === '_blank') return; if (event.defaultPrevented) { hideTransition(); return; } if (typeof form.checkValidity === 'function' && !form.checkValidity()) { hideTransition(); return; } if (window.jQuery && jQuery.fn && jQuery.fn.valid) { const validator = jQuery(form).data('validator'); if (validator && !jQuery(form).valid()) { hideTransition(); return; } } showTransition('Procesando...'); }, false); })();