HEX
Server: Apache/2.4.41 (Ubuntu)
System: Linux ip-172-31-42-149 5.15.0-1084-aws #91~20.04.1-Ubuntu SMP Fri May 2 07:00:04 UTC 2025 aarch64
User: ubuntu (1000)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /var/www/vhost/disk-apps/alq-cali.bikenow.co/resources/views/web_experiences/enroll/js.blade.php
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/intl-tel-input/17.0.19/js/intlTelInput.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/intl-tel-input/17.0.19/js/utils.js"></script>

<script>
    const loginInput = document.getElementById('loginInput');
    const loginButton = document.getElementById('loginSubmitBtn');
    const registerSubmitBtn = document.getElementById('registerSubmitBtn');

    function isValidEmail(email) {
        return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
    }

    function isValidDocument(doc) {
        return /^[0-9]{5,20}$/.test(doc); // ajusta la expresión si tus documentos tienen letras o un rango diferente
    }

    function showForm(type) {
        // Mostrar/Ocultar formularios
        document.getElementById('form-registered').style.display = (type === 'registered') ? 'block' : 'none';
        document.getElementById('form-new-user').style.display = (type === 'new') ? 'block' : 'none';

        // Activar botón correspondiente
        document.getElementById('btn-registered').classList.toggle('active', type === 'registered');
        document.getElementById('btn-new').classList.toggle('active', type === 'new');
    }

    let participantCount = 1;

    function checkParticipantLimit() {
        let enableParticipants = false;
        if (document.getElementById('enable_raffle')) {
            const enableRaffleValue = document.getElementById('enable_raffle').value;
            enableParticipants = enableRaffleValue === 'false' || enableRaffleValue === '0';
        }

        const addBtn = document.getElementById('addParticipantBtn');
        const enrollSubmitBtn = document.getElementById('enrollSubmitBtn');
        if (enableParticipants) {
            let entriesPerPurchase = 1;
            if (document.getElementById('entries_per_purchase')) {
                entriesPerPurchase = (parseInt(document.getElementById('entries_per_purchase').value) || 1) * (parseInt(document.getElementById('amount').value) || 1);
            }

            const maxParticipants = entriesPerPurchase;
            let currentCount = 1;
            if (document.getElementById('participants-container')) {
                currentCount = document.getElementById('participants-container')
                    .querySelectorAll('.participant-block').length;
            }
            if (currentCount >= maxParticipants && addBtn && enrollSubmitBtn) {
                addBtn.style.display = 'none';
                enrollSubmitBtn.disabled = false;
                enrollSubmitBtn.classList.toggle('active', true);
            } else if (enrollSubmitBtn) {
                enrollSubmitBtn.disabled = true;
                enrollSubmitBtn.classList.toggle('active', false);
            }
        } else {
            if (addBtn && enrollSubmitBtn) {
                addBtn.style.display = 'none';
                enrollSubmitBtn.disabled = false;
                enrollSubmitBtn.classList.toggle('active', true);
            }
        }

    }

    function addParticipant() {
        let entriesPerPurchase = 1;
        if (document.getElementById('entries_per_purchase')) {
            entriesPerPurchase = (parseInt(document.getElementById('entries_per_purchase').value) || 1) * (parseInt(document.getElementById('amount').value) || 1);
        }

        const maxParticipants = entriesPerPurchase;
        const container = document.getElementById('participants-container');
        const currentCount = container.querySelectorAll('.participant-block').length;

        if (currentCount >= maxParticipants && document.getElementById('addParticipantBtn')) {
            document.getElementById('addParticipantBtn').style.display = 'none';
            return;
        }

        participantCount++;
        const original = container.querySelector('.participant-block');
        const clone = original.cloneNode(true);

        // Cambiar título
        clone.querySelectorAll(".form-participant-header").forEach(group => {
            group.querySelectorAll('p').forEach(p => {
                p.remove(); // Eliminar el párrafo del DOM
            });
            group.querySelector('h3').innerText = 'Participante ' + participantCount;
        });

        clone.querySelectorAll(".form-group").forEach(group => {
            group.hidden = false; // Mostrar todos los campos
        });
        clone.querySelector('#editBuyerData').hidden = true; // Ocultar checkbox de edición

        // Cambiar el nombre de los inputs
        clone.querySelectorAll('input').forEach(input => {
            const name = input.getAttribute('name');
            if (name && name.startsWith('buyer_')) {
                input.setAttribute('name', name.replace('buyer_', 'companion' + participantCount + '_'));
            }
            if (name && name.includes('phone')) {
                if (!name.includes('code')) {
                    const iti = window.intlTelInput(input, {
                        initialCountry: "co", // o "auto" con geoIpLookup si deseas detección automática
                        preferredCountries: ["co", "us", "pa", "ec", "cl"], // Países preferidos
                        separateDialCode: true, // Esto separa el indicativo del número
                        utilsScript: "https://cdnjs.cloudflare.com/ajax/libs/intl-tel-input/17.0.19/js/utils.js",
                    });
                    const dialCodeInput = clone.querySelector('input[name="companion' + participantCount + '_dial_code"]');
                    const countryCodeInput = clone.querySelector('input[name="companion' + participantCount + '_country_code"]');
                    if (dialCodeInput) {
                        dialCodeInput.value = iti.getSelectedCountryData().dialCode;
                    }
                    if (countryCodeInput) {
                        countryCodeInput.value = iti.getSelectedCountryData().iso2;
                    }
                    input.addEventListener('countrychange', function() {
                        dialCodeInput.value = iti.getSelectedCountryData().dialCode;
                        countryCodeInput.value = iti.getSelectedCountryData().iso2;
                    });
                }
            }

            // Limpiar el valor del input
            input.value = '';
        });

        clone.querySelectorAll('select').forEach(select => {
            const name = select.getAttribute('name');
            if (name) {
                select.setAttribute('name', name.replace('buyer_', 'companion' + participantCount + '_'));
            }

            // Limpiar la selección
            select.selectedIndex = 0;
        });

        container.appendChild(clone);

        // Revalidar límite
        checkParticipantLimit();
    }

    function waitForOtpVerification(email, form) {
        return new Promise((resolve, reject) => {
            const modal = document.getElementById('otpModal');
            const input = document.getElementById('otpInput');
            const errorDiv = document.getElementById('otpError');
            const button = document.getElementById('verifyOtpBtn');
            const closeBtn = document.getElementById('closeOtpModal');

            // Mostrar modal
            modal.style.display = 'flex';
            input.value = '';
            errorDiv.textContent = '';
            button.disabled = true;

            input.focus();

            // Cerrar modal
            closeBtn.onclick = () => {
                modal.style.display = 'none';
                reject(new Error("Verificación cancelada."));
            };

            // Validar cantidad de dígitos
            input.addEventListener('input', () => {
                button.disabled = input.value.trim().length !== 6;
            });

            button.onclick = async () => {
                const code = input.value.trim();

                if (code.length !== 6) {
                    errorDiv.textContent = "Debes ingresar 6 dígitos.";
                    return;
                }

                errorDiv.textContent = "Verificando...";
                button.disabled = true;

                try {
                    const response = await fetch("{{ route('otp.verify') }}", {
                        method: "POST",
                        headers: {
                            "Content-Type": "application/json",
                            "X-CSRF-TOKEN": form.querySelector('input[name="_token"]').value,
                        },
                        body: JSON.stringify({
                            code,
                            email
                        })
                    });

                    const data = await response.json();

                    if (!response.ok || data.status !== 'success') {
                        errorDiv.textContent = data.message || "Código de validación inválido.";
                        button.disabled = false;
                        return;
                    }

                    modal.style.display = 'none';
                    resolve(); // Continuar login

                } catch (err) {
                    errorDiv.textContent = "Error de conexión. Intenta de nuevo.";
                    button.disabled = false;
                }
            };
        });
    }

    async function resendCode() {
        const input = document.getElementById('otpInput');
        const errorDiv = document.getElementById('otpError');
        const email = document.querySelector('input[name="login"]')?.value;

        if (!email) {
            errorDiv.textContent = "No se puede reenviar el código porque falta el correo.";
            return;
        }

        errorDiv.textContent = "Enviando nuevo código...";
        try {
            const response = await fetch("{{ route('otp.generate') }}", {
                method: "POST",
                headers: {
                    "X-CSRF-TOKEN": document.querySelector('input[name="_token"]').value
                },
                body: new URLSearchParams({
                    email
                })
            });

            const data = await response.json();

            if (!response.ok || data.status !== 'success') {
                errorDiv.textContent = data.message || "No se pudo reenviar el código.";
                return;
            }

            errorDiv.textContent = "Se envió un nuevo código a tu correo.";
            input.value = '';
            document.getElementById('verifyOtpBtn').disabled = true;
            input.focus();
        } catch (err) {
            errorDiv.textContent = "Error al reenviar el código.";
        }
    }

    toggleEditParticipantData = () => {
        document.querySelectorAll('.form-group').forEach(group => {
            group.hidden = !group.hidden;
        });
    }

    // Verificar al cargar la página
    document.addEventListener('DOMContentLoaded', function() {
        checkParticipantLimit();

        // Solo letras y espacios
        document.querySelectorAll('.only-letters').forEach(input => {
            input.addEventListener('input', () => {
                input.value = input.value.replace(/[^A-Za-zÁÉÍÓÚáéíóúÑñ\s]/g, '');
            });
        });

        // Solo números
        document.querySelectorAll('.only-numbers').forEach(input => {
            input.addEventListener('input', () => {
                input.value = input.value.replace(/[^0-9]/g, '');
            });
        });

        // Solo alfanumérico
        document.querySelectorAll('.only-alphanum').forEach(input => {
            input.addEventListener('input', () => {
                input.value = input.value.replace(/[^A-Za-z0-9]/g, '');
            });
        });

        document.querySelectorAll('select[name$="_document_type_id"]').forEach(select => {
            select.addEventListener('change', function() {
                const prefix = this.name.replace('_document_type_id', '');
                const documentInput = document.querySelector(`input[name="${prefix}_document"]`);

                if (documentInput) {
                    if (this.value) {
                        documentInput.disabled = false;
                        documentInput.setAttribute('required', 'required');
                    } else {
                        documentInput.disabled = true;
                        documentInput.value = '';
                        documentInput.removeAttribute('required');
                    }
                }
            });
        });

        document.querySelectorAll('input[name="confirm_email"]').forEach(confirmInput => {
            const container = confirmInput.closest('.form-group').parentNode;
            const emailInput = container.querySelector('input[name="email"]');
            const errorSpan = confirmInput.parentNode.querySelector('.error-message');

            function validateEmails() {
                const emailValue = emailInput.value.trim();
                const confirmValue = confirmInput.value.trim();

                if (emailValue && confirmValue && emailValue !== confirmValue) {
                    errorSpan.style.display = 'inline';
                    confirmInput.setCustomValidity("Los correos electrónicos no coinciden.");
                } else {
                    errorSpan.style.display = 'none';
                    confirmInput.setCustomValidity("");
                }
            }

            // Validar al escribir o salir del campo
            confirmInput.addEventListener('input', validateEmails);
            emailInput.addEventListener('input', validateEmails);
        });

        if (document.getElementById('enroll-form')) {
            document.getElementById('enroll-form').addEventListener('submit', function(e) {
                e.preventDefault(); // Evita que recargue

                const form = e.target;
                const url = form.action;
                const formData = new FormData(form);
                const submitButton = form.querySelector('button[type="submit"]');
                submitButton.disabled = true; // Deshabilitar botón para evitar múltiples envíos
                submitButton.classList.add('loading'); // Agregar clase de carga
                const originalText = submitButton.textContent; // Guardar texto original
                submitButton.textContent = 'Procesando... ⏳'; // opcional

                fetch(url, {
                        method: 'POST',
                        body: formData,
                        headers: {
                            'X-Requested-With': 'XMLHttpRequest',
                            'Accept': 'application/json',
                        }
                    })
                    .then(async response => {
                        const data = await response.json();

                        if (!response.ok) {
                            // Mostrar errores de validación con Swal
                            if (data.errors) {
                                const allErrors = Object.values(data.errors)
                                    .flat()
                                    .join('<br>');
                                throw new Error(allErrors);
                            } else {
                                throw new Error('Ocurrió un error al procesar tu inscripción. Inténtalo de nuevo más tarde.');
                            }
                        }

                        // Éxito
                        if (data.redirect) {
                            window.location.href = data.redirect;
                        } else {
                            Swal.fire({
                                icon: 'success',
                                title: 'Inscripción exitosa',
                                text: data.message || 'Te has inscrito correctamente.',
                                showConfirmButton: true,
                                confirmButtonText: 'Aceptar',
                                confirmButtonColor: '<?php echo $corporateIdentity->btnBox_color; ?>',
                                allowOutsideClick: false,
                                allowEscapeKey: false,
                                allowEnterKey: false
                            }).then(() => {
                                // Recargar la página o redirigir
                                window.location.href = "/web_experiences";
                            });
                        }
                    })
                    .then(data => {
                        if (data && data.redirect) {
                            window.location.href = data.redirect;
                        }
                    })
                    .catch(error => {
                        console.error(error);
                        Swal.fire({
                            icon: 'error',
                            title: 'Error',
                            text: error || "Ocurrio un error inesperado.",
                            showConfirmButton: true,
                            confirmButtonText: 'Aceptar',
                            confirmButtonColor: '<?php echo $corporateIdentity->btnBox_color; ?>',
                            allowOutsideClick: false,
                            allowEscapeKey: false,
                            allowEnterKey: false
                        });
                        submitButton.disabled = false; // Rehabilitar botón
                        submitButton.classList.remove('loading'); // Quitar clase de carga
                        submitButton.textContent = originalText; // Restaurar texto original
                    });
            });
        }

        if (document.getElementById('closeUserBtn')) {
            document.getElementById('closeUserBtn').addEventListener('click', function() {
                Swal.fire({
                    title: 'Alerta',
                    text: '¿Deseas quitar este participante?',
                    icon: 'warning',
                    showCancelButton: true,
                    confirmButtonText: 'Sí, quitar participante',
                    cancelButtonText: 'Cancelar',
                    confirmButtonColor: '<?php echo $corporateIdentity->btnBox_color; ?>',
                    cancelButtonColor: '#6c757d',
                    reverseButtons: true,
                    allowOutsideClick: false,
                    allowEscapeKey: false,
                    allowEnterKey: false
                }).then((result) => {
                    if (result.isConfirmed) {
                        fetch("{{ route('web_experiences.logout') }}", {
                            method: "POST",
                            headers: {
                                "X-CSRF-TOKEN": "{{ csrf_token() }}",
                                "Accept": "application/json",
                                "Content-Type": "application/json"
                            }
                        }).then(() => {
                            location.reload();
                        }).catch(() => {
                            Swal.fire('Error', 'No se pudo cerrar sesión.', 'error');
                        });
                    }
                });
            });
        }

        const form = document.getElementById('form-new-user');
        if (!form) return; // Asegurarse de que el formulario existe
        const submitButton = form.querySelector('.register-btn-new-user');

        const checkFormValidity = () => {
            if (form.checkValidity()) {
                submitButton.disabled = false;
                submitButton.classList.toggle('active', true);
            } else {
                submitButton.disabled = true;
                submitButton.classList.toggle('active', false);
            }
        };

        // Escuchar eventos en todos los inputs, selects y textareas
        const inputs = form.querySelectorAll('input, select, textarea');

        inputs.forEach(input => {
            input.addEventListener('input', checkFormValidity);
            input.addEventListener('change', checkFormValidity);
        });

        // Validación inicial por si ya hay datos precargados
        checkFormValidity();
    });

    if (loginInput) {
        loginInput.addEventListener('input', function() {
            const value = loginInput.value.trim();
            if (isValidEmail(value)) {
                loginButton.disabled = false;
                loginButton.classList.toggle('active', true);
            } else {
                loginButton.disabled = true;
                loginButton.classList.toggle('active', false);
            }
        });
    }

    if (document.getElementById('form-registered')) {
        document.getElementById('form-registered').addEventListener('submit', async function(e) {
            e.preventDefault(); // Evita recarga

            const form = e.target;
            const formData = new FormData(form);
            const errorDiv = document.getElementById('login-error');
            errorDiv.textContent = ''; // Limpia errores previos

            const submitButton = form.querySelector('button[type="submit"]');
            submitButton.disabled = true;
            submitButton.classList.add('loading');
            const originalText = submitButton.textContent;
            submitButton.textContent = 'Enviando código... ⏳';

            try {
                // 1. Paso: Generar OTP
                const otpFormData = new FormData();
                otpFormData.append('email', formData.get('login') || '');

                const otpResponse = await fetch("{{ route('otp.generate') }}", {
                    method: "POST",
                    headers: {
                        "X-CSRF-TOKEN": form.querySelector('input[name="_token"]').value,
                        "Accept": "application/json"
                    },
                    body: otpFormData
                });

                if (!otpResponse.ok) {
                    const errorData = await otpResponse.json();
                    throw new Error(errorData.message || "No se pudo generar el código de validación.");
                }

                const otpData = await otpResponse.json();
                if (otpData.status !== 'success') {
                    throw new Error(otpData.message || "Error al generar código.");
                }

                // 2. Mostrar modal OTP y esperar verificación
                await waitForOtpVerification(formData.get('login'), form);

                // 4. Si OTP válido, proceder al login
                submitButton.textContent = 'Validando acceso... ⏳';

                const loginResponse = await fetch("{{ route('login.by.document.or.email') }}", {
                    method: "POST",
                    headers: {
                        "X-CSRF-TOKEN": form.querySelector('input[name="_token"]').value,
                        "Accept": "application/json"
                    },
                    body: formData
                });

                if (!loginResponse.ok) {
                    const errorData = await loginResponse.json();
                    throw new Error(errorData.message || "Error en la autenticación.");
                }

                const loginData = await loginResponse.json();
                if (loginData.success) {
                    window.location.href = loginData.redirect || "{{ url()->current() }}";
                } else {
                    throw new Error(loginData.message || "Acceso denegado.");
                }

            } catch (error) {
                console.error(error);
                errorDiv.textContent = error.message || "Ocurrió un error inesperado.";
                submitButton.disabled = false;
                submitButton.classList.remove('loading');
                submitButton.textContent = originalText;
            }
        });
    }

    if (document.getElementById('form-new-user')) {
        document.getElementById('form-new-user').addEventListener('submit', async function(e) {
            e.preventDefault(); // Evita recarga

            if (!isValidPhoneNumber()) {
                Swal.fire({
                    icon: 'error',
                    title: 'Número de teléfono inválido',
                    text: 'Por favor, ingresa un número de teléfono válido.',
                    showConfirmButton: true,
                    confirmButtonText: 'Aceptar',
                    confirmButtonColor: '<?php echo $corporateIdentity->btnBox_color; ?>',
                    allowOutsideClick: false,
                    allowEscapeKey: false,
                    allowEnterKey: false
                });
                return;
            }

            const form = e.target;
            const formData = new FormData(form);
            const errorDiv = document.getElementById('register-error');
            errorDiv.textContent = ''; // Limpia errores previos
            const submitButton = form.querySelector('button[type="submit"]');
            submitButton.disabled = true; // Deshabilitar botón para evitar múltiples envíos
            submitButton.classList.add('loading'); // Agregar clase de carga
            const originalText = submitButton.textContent; // Guardar texto original
            submitButton.textContent = 'Enviando código... ⏳';

            try {
                // 1. Paso: Generar OTP
                const otpFormData = new FormData();
                otpFormData.append('email', formData.get('email') || '');

                const otpResponse = await fetch("{{ route('otp.generate') }}", {
                    method: "POST",
                    headers: {
                        "X-CSRF-TOKEN": form.querySelector('input[name="_token"]').value,
                        "Accept": "application/json"
                    },
                    body: otpFormData
                });

                if (!otpResponse.ok) {
                    const errorData = await otpResponse.json();
                    throw new Error(errorData.message || "No se pudo generar el código de validación.");
                }

                const otpData = await otpResponse.json();
                if (otpData.status !== 'success') {
                    throw new Error(otpData.message || "Error al generar código.");
                }

                // 2. Mostrar modal OTP y esperar verificación
                await waitForOtpVerification(formData.get('email'), form);

                // 4. Si OTP válido, proceder al registro
                submitButton.textContent = 'Validando registro... ⏳';

                const registerResponse = await fetch("{{ route('register.new.user') }}", {
                    method: "POST",
                    headers: {
                        "X-CSRF-TOKEN": form.querySelector('input[name="_token"]').value,
                        "Accept": "application/json"
                    },
                    body: formData
                });

                if (!registerResponse.ok) {
                    const errorData = await registerResponse.json();
                    throw new Error(errorData.message || "Error en el registro.");
                }

                const registerData = await registerResponse.json();
                if (registerData.success) {
                    window.location.href = registerData.redirect || "{{ url()->current() }}";
                } else {
                    throw new Error(registerData.message || "Registro denegado.");
                }

            } catch (error) {
                console.error(error);
                Swal.fire({
                    icon: 'error',
                    title: 'Error en la solicitud',
                    text: error.message || data.message || "Error de conexión. Intente de nuevo.",
                    showConfirmButton: true,
                    confirmButtonText: 'Aceptar',
                    confirmButtonColor: '<?php echo $corporateIdentity->btnBox_color; ?>',
                    allowOutsideClick: false,
                    allowEscapeKey: false,
                    allowEnterKey: false
                });
                errorDiv.textContent = error.message || "Ocurrió un error inesperado.";
                submitButton.disabled = false;
                submitButton.classList.remove('loading');
                submitButton.textContent = originalText;
            }
        });
    }

    $(document).ready(function() {
        function formatCurrency(value) {
            return new Intl.NumberFormat('es-CO', {
                style: 'currency',
                currency: <?php echo json_encode($corporateIdentity->currency); ?>,
                currencyDisplay: 'narrowSymbol',
                minimumFractionDigits: <?php echo json_encode($corporateIdentity->minimum_fraction_digits); ?>,
                maximumFractionDigits: <?php echo json_encode($corporateIdentity->maximum_fraction_digits); ?>,
            }).format(value);
        }

        $('.plan-price').each(function() {
            let amountText = $(this).text();
            let formatted = formatCurrency(amountText);
            $(this).text(formatted);
        });
    });

    const dialCodeInput = document.querySelector("#dial-code");
    const countryCodeInput = document.querySelector("#country-code");
    const phoneInput = document.querySelector("#phone");

    let iti;
    if (phoneInput) {
        iti = window.intlTelInput(phoneInput, {
            initialCountry: "co", // o "auto" con geoIpLookup si deseas detección automática
            preferredCountries: ["co", "us", "pa", "ec", "cl"], // Países preferidos
            separateDialCode: true, // Esto separa el indicativo del número
            utilsScript: "https://cdnjs.cloudflare.com/ajax/libs/intl-tel-input/17.0.19/js/utils.js",
        });
    }

    // Establecer el valor inicial al cargar
    if (dialCodeInput) {
        dialCodeInput.value = dialCode();
    }
    if (countryCodeInput) {
        countryCodeInput.value = countryCode();
    }

    if (phoneInput) {
        phoneInput.addEventListener('countrychange', function() {
            dialCodeInput.value = dialCode();
            countryCodeInput.value = countryCode();
        });
    }

    function dialCode() {
        return iti.getSelectedCountryData().dialCode;
    }

    function countryCode() {
        return iti.getSelectedCountryData().iso2;
    }

    function isValidPhoneNumber() {
        return iti.isValidNumber();
    }
</script>