// Form data object const formData = { userDetails: {} }; // Current step tracking let currentStep = 1; // Countries and states data const countries = [ { code: 'US', name: 'United States' }, { code: 'CA', name: 'Canada' }, { code: 'GB', name: 'United Kingdom' }, { code: 'AU', name: 'Australia' }, { code: 'IN', name: 'India' }, { code: 'DE', name: 'Germany' }, { code: 'FR', name: 'France' }, { code: 'BR', name: 'Brazil' }, { code: 'JP', name: 'Japan' }, { code: 'CN', name: 'China' }, { code: 'MX', name: 'Mexico' }, { code: 'ES', name: 'Spain' }, { code: 'IT', name: 'Italy' }, { code: 'NL', name: 'Netherlands' }, { code: 'SE', name: 'Sweden' }, { code: 'NO', name: 'Norway' }, { code: 'DK', name: 'Denmark' }, { code: 'FI', name: 'Finland' }, { code: 'BE', name: 'Belgium' }, { code: 'CH', name: 'Switzerland' }, { code: 'AT', name: 'Austria' }, { code: 'PT', name: 'Portugal' }, { code: 'IE', name: 'Ireland' }, { code: 'PL', name: 'Poland' }, { code: 'CZ', name: 'Czech Republic' }, { code: 'HU', name: 'Hungary' }, { code: 'RO', name: 'Romania' }, { code: 'GR', name: 'Greece' }, { code: 'TR', name: 'Turkey' }, { code: 'SA', name: 'Saudi Arabia' }, { code: 'AE', name: 'United Arab Emirates' }, { code: 'ZA', name: 'South Africa' }, { code: 'NG', name: 'Nigeria' }, { code: 'EG', name: 'Egypt' }, { code: 'KE', name: 'Kenya' }, { code: 'AR', name: 'Argentina' }, { code: 'CO', name: 'Colombia' }, { code: 'PE', name: 'Peru' }, { code: 'CL', name: 'Chile' }, { code: 'VE', name: 'Venezuela' }, { code: 'KR', name: 'South Korea' }, { code: 'SG', name: 'Singapore' }, { code: 'MY', name: 'Malaysia' }, { code: 'TH', name: 'Thailand' }, { code: 'ID', name: 'Indonesia' }, { code: 'PH', name: 'Philippines' }, { code: 'VN', name: 'Vietnam' }, { code: 'PK', name: 'Pakistan' }, { code: 'BD', name: 'Bangladesh' }, { code: 'LK', name: 'Sri Lanka' }, { code: 'NP', name: 'Nepal' }, { code: 'RU', name: 'Russia' }, { code: 'UA', name: 'Ukraine' }, { code: 'IL', name: 'Israel' }, { code: 'NZ', name: 'New Zealand' }, { code: 'HK', name: 'Hong Kong' }, { code: 'TW', name: 'Taiwan' } ]; // const states = { // 'US': [ // { code: 'CA', name: 'California' }, { code: 'TX', name: 'Texas' }, { code: 'FL', name: 'Florida' }, // { code: 'NY', name: 'New York' }, { code: 'IL', name: 'Illinois' }, { code: 'PA', name: 'Pennsylvania' }, // { code: 'OH', name: 'Ohio' }, { code: 'GA', name: 'Georgia' }, { code: 'NC', name: 'North Carolina' }, // { code: 'MI', name: 'Michigan' } // ], // 'CA': [ // { code: 'ON', name: 'Ontario' }, { code: 'QC', name: 'Quebec' }, { code: 'BC', name: 'British Columbia' }, // { code: 'AB', name: 'Alberta' }, { code: 'MB', name: 'Manitoba' }, { code: 'SK', name: 'Saskatchewan' } // ], // 'GB': [ // { code: 'ENG', name: 'England' }, { code: 'SCT', name: 'Scotland' }, { code: 'WLS', name: 'Wales' }, // { code: 'NIR', name: 'Northern Ireland' } // ], // 'AU': [ // { code: 'NSW', name: 'New South Wales' }, { code: 'VIC', name: 'Victoria' }, { code: 'QLD', name: 'Queensland' }, // { code: 'WA', name: 'Western Australia' }, { code: 'SA', name: 'South Australia' }, { code: 'TAS', name: 'Tasmania' } // ], // 'IN': [ // { code: 'MH', name: 'Maharashtra' }, { code: 'TN', name: 'Tamil Nadu' }, { code: 'UP', name: 'Uttar Pradesh' }, // { code: 'KA', name: 'Karnataka' }, { code: 'GJ', name: 'Gujarat' }, { code: 'RJ', name: 'Rajasthan' } // ], // 'DE': [ // { code: 'BW', name: 'Baden-Württemberg' }, { code: 'BY', name: 'Bavaria' }, { code: 'BE', name: 'Berlin' }, // { code: 'HB', name: 'Bremen' }, { code: 'HH', name: 'Hamburg' }, { code: 'HE', name: 'Hesse' } // ], // 'FR': [ // { code: 'ARA', name: 'Auvergne-Rhône-Alpes' }, { code: 'BFC', name: 'Bourgogne-Franche-Comté' }, // { code: 'BRE', name: 'Brittany' }, { code: 'CVL', name: 'Centre-Val de Loire' }, // { code: 'COR', name: 'Corsica' }, { code: 'GES', name: 'Grand Est' } // ], // 'BR': [ // { code: 'SP', name: 'São Paulo' }, { code: 'RJ', name: 'Rio de Janeiro' }, { code: 'MG', name: 'Minas Gerais' }, // { code: 'BA', name: 'Bahia' }, { code: 'RS', name: 'Rio Grande do Sul' }, { code: 'PR', name: 'Paraná' } // ], // 'JP': [ // { code: 'TK', name: 'Tokyo' }, { code: 'OS', name: 'Osaka' }, { code: 'KY', name: 'Kyoto' }, // { code: 'HK', name: 'Hokkaido' }, { code: 'OK', name: 'Okinawa' }, { code: 'KN', name: 'Kanagawa' } // ], // 'CN': [ // { code: 'BJ', name: 'Beijing' }, { code: 'SH', name: 'Shanghai' }, { code: 'TJ', name: 'Tianjin' }, // { code: 'CQ', name: 'Chongqing' }, { code: 'GD', name: 'Guangdong' }, { code: 'JS', name: 'Jiangsu' } // ] // }; // Initialize the form document.addEventListener('DOMContentLoaded', function() { // Populate country dropdown const countrySelect = document.getElementById('country'); countrySelect.innerHTML = ''; countries.forEach(country => { const option = document.createElement('option'); option.value = country.code; option.textContent = country.name; countrySelect.appendChild(option); }); autoDetectCountry(); // Add event listener for country change // countrySelect.addEventListener('change', function() { // const countryCode = this.value; // const stateSelect = document.getElementById('state'); // // Show loading // document.getElementById('state-loading').style.display = 'block'; // // Clear current states // stateSelect.innerHTML = ''; // // Simulate API delay // setTimeout(() => { // if (countryCode && states[countryCode]) { // states[countryCode].forEach(state => { // const option = document.createElement('option'); // option.value = state.code; // option.textContent = state.name; // stateSelect.appendChild(option); // }); // } // // Hide loading // document.getElementById('state-loading').style.display = 'none'; // }, 500); // }); // Add input event listeners to handle label animation document.querySelectorAll('.input-field:not(.dob)').forEach(input => { setTimeout(() => { if (input.value) { input.nextElementSibling.style.top = '4px'; input.nextElementSibling.style.fontSize = '12px'; input.nextElementSibling.style.transform = 'none'; } }, 100); input.addEventListener('animationstart', function() { if (this.value) { this.nextElementSibling.style.top = '4px'; this.nextElementSibling.style.fontSize = '12px'; this.nextElementSibling.style.transform = 'none'; } }); input.addEventListener('input', function() { if (this.value) { this.nextElementSibling.style.top = '4px'; this.nextElementSibling.style.fontSize = '12px'; this.nextElementSibling.style.transform = 'none'; } else { this.nextElementSibling.style.top = '50%'; this.nextElementSibling.style.fontSize = '14px'; this.nextElementSibling.style.transform = 'translateY(-50%)'; } }); input.addEventListener('focus', function() { this.nextElementSibling.style.top = '4px'; this.nextElementSibling.style.fontSize = '12px'; this.nextElementSibling.style.transform = 'none'; }); input.addEventListener('blur', function() { if (!this.value) { this.nextElementSibling.style.top = '50%'; this.nextElementSibling.style.fontSize = '14px'; this.nextElementSibling.style.transform = 'translateY(-50%)'; } }); }); // Handle select field label animation document.querySelectorAll('.select-field').forEach(select => { setTimeout(() => { if (select.value) { select.nextElementSibling.style.top = '4px'; select.nextElementSibling.style.fontSize = '12px'; select.nextElementSibling.style.transform = 'none'; } }, 100); select.addEventListener('change', function() { if (this.value) { this.nextElementSibling.style.top = '4px'; this.nextElementSibling.style.fontSize = '12px'; this.nextElementSibling.style.transform = 'none'; } else { this.nextElementSibling.style.top = '50%'; this.nextElementSibling.style.fontSize = '14px'; this.nextElementSibling.style.transform = 'translateY(-50%)'; } }); select.addEventListener('focus', function() { this.nextElementSibling.style.top = '4px'; this.nextElementSibling.style.fontSize = '12px'; this.nextElementSibling.style.transform = 'none'; }); select.addEventListener('blur', function() { if (!this.value) { this.nextElementSibling.style.top = '50%'; this.nextElementSibling.style.fontSize = '14px'; this.nextElementSibling.style.transform = 'translateY(-50%)'; } }); }); // Step navigation for desktop document.querySelectorAll('.step').forEach(step => { step.addEventListener('click', function() { const stepNum = parseInt(this.getAttribute('data-step')); if (stepNum <= currentStep || stepNum === getMaxCompletedStep() + 1) { goToStep(stepNum); } }); }); // Step navigation for mobile document.querySelectorAll('.mobile-step').forEach(step => { step.addEventListener('click', function() { const stepNum = parseInt(this.getAttribute('data-step')); if (stepNum <= currentStep || stepNum === getMaxCompletedStep() + 1) { goToStep(stepNum); } }); }); }); async function autoDetectCountry() { const countrySelect = document.getElementById('country'); // const loadingElement = document.getElementById('country-loading'); try { // loadingElement.style.display = 'block'; // Using ipapi.co API (free tier available) const response = await fetch('https://ipapi.co/json/'); if (!response.ok) { throw new Error('Geolocation service unavailable'); } const data = await response.json(); if (data && data.country_code) { const detectedCountryCode = data.country_code; const detectedCountryName = data.country_name; // Find if the detected country is in our list const countryExists = countries.find(country => country.code === detectedCountryCode ); if (countryExists) { // Set the country in dropdown countrySelect.value = detectedCountryCode; // Trigger the change event to update UI countrySelect.dispatchEvent(new Event('change')); // Show success message console.log(`Auto-detected country: ${detectedCountryName}`); } else { console.log('Detected country not in supported list'); } } } catch (error) { console.log('Could not auto-detect country:', error.message); // Fallback: Use browser's geolocation API as backup fallbackGeolocation(); } finally { // loadingElement.style.display = 'none'; } } // Fallback geolocation using browser's navigator.geolocation function fallbackGeolocation() { if (!navigator.geolocation) { console.log('Geolocation is not supported by this browser'); return; } navigator.geolocation.getCurrentPosition( async function(position) { try { const { latitude, longitude } = position.coords; // Use OpenStreetMap Nominatim API for reverse geocoding const response = await fetch( `https://nominatim.openstreetmap.org/reverse?format=json&lat=${latitude}&lon=${longitude}` ); if (response.ok) { const data = await response.json(); if (data && data.address && data.address.country_code) { const countryCode = data.address.country_code.toUpperCase(); const countrySelect = document.getElementById('country'); const countryExists = countries.find(country => country.code === countryCode ); if (countryExists) { countrySelect.value = countryCode; countrySelect.dispatchEvent(new Event('change')); console.log(`Fallback geolocation detected: ${data.address.country}`); } } } } catch (error) { console.log('Fallback geolocation failed:', error); } }, function(error) { console.log('Browser geolocation error:', error.message); }, { enableHighAccuracy: false, timeout: 10000, maximumAge: 600000 // 10 minutes } ); } // Function to navigate to any step (for tab navigation) function goToStep(step) { // Only allow navigation to completed steps or the next step if (step > currentStep && step > getMaxCompletedStep() + 1) { return; } // Hide current step document.getElementById(`step-${currentStep}`).classList.remove('active'); document.querySelectorAll(`.step[data-step="${currentStep}"]`).forEach(el => { el.classList.remove('active'); }); document.querySelectorAll(`.mobile-step[data-step="${currentStep}"]`).forEach(el => { el.classList.remove('active'); }); // Show target step document.getElementById(`step-${step}`).classList.add('active'); document.querySelectorAll(`.step[data-step="${step}"]`).forEach(el => { el.classList.add('active'); }); document.querySelectorAll(`.mobile-step[data-step="${step}"]`).forEach(el => { el.classList.add('active'); }); currentStep = step; } // Function to get the maximum completed step function getMaxCompletedStep() { const completedSteps = document.querySelectorAll('.step.completed'); let maxStep = 0; completedSteps.forEach(step => { const stepNum = parseInt(step.getAttribute('data-step')); if (stepNum > maxStep) maxStep = stepNum; }); return maxStep; } async function handleNextStep(step) { await nextStep(step); } // Function to navigate to next step async function nextStep(step) { // Validate current step before proceeding if (!(await validateStep(currentStep))) { return; } // Save current step data saveStepData(currentStep); // Mark current step as completed document.querySelectorAll(`.step[data-step="${currentStep}"]`).forEach(el => { el.classList.add('completed'); const stepNumber = el.querySelector('.step-number'); stepNumber.textContent = '✓'; stepNumber.style.backgroundColor = '#000000'; stepNumber.style.borderColor = '#000000'; stepNumber.style.color = 'white'; }); document.querySelectorAll(`.mobile-step[data-step="${currentStep}"]`).forEach(el => { el.classList.add('completed'); const stepNumber = el.querySelector('.step-number'); stepNumber.textContent = '✓'; stepNumber.style.backgroundColor = '#000000'; stepNumber.style.borderColor = '#000000'; stepNumber.style.color = 'white'; }); // Hide current step document.getElementById(`step-${currentStep}`).classList.remove('active'); document.querySelectorAll(`.step[data-step="${currentStep}"]`).forEach(el => { el.classList.remove('active'); }); document.querySelectorAll(`.mobile-step[data-step="${currentStep}"]`).forEach(el => { el.classList.remove('active'); }); // Show next step document.getElementById(`step-${step}`).classList.add('active'); document.querySelectorAll(`.step[data-step="${step}"]`).forEach(el => { el.classList.add('active'); }); document.querySelectorAll(`.mobile-step[data-step="${step}"]`).forEach(el => { el.classList.add('active'); }); currentStep = step; } // Function to navigate to previous step function prevStep(step) { // Hide current step document.getElementById(`step-${currentStep}`).classList.remove('active'); document.querySelectorAll(`.step[data-step="${currentStep}"]`).forEach(el => { el.classList.remove('active'); }); document.querySelectorAll(`.mobile-step[data-step="${currentStep}"]`).forEach(el => { el.classList.remove('active'); }); // Show previous step document.getElementById(`step-${step}`).classList.add('active'); document.querySelectorAll(`.step[data-step="${step}"]`).forEach(el => { el.classList.add('active'); }); document.querySelectorAll(`.mobile-step[data-step="${step}"]`).forEach(el => { el.classList.add('active'); }); currentStep = step; } // Function to validate current step async function validateStep(step) { let isValid = true; const form = document.getElementById(getFormId(step)); // Hide any previous errors for this step hideError(step); clearFieldErrors(); if (form) { // For account setup step if (step === 1) { const email = document.getElementById('email').value; const password = document.getElementById('password').value; const confirmPassword = document.getElementById('confirmPassword').value; if(!email && !password) { showError('', 'email', step); showError('', 'password', step); showError('Please enter a valid email address and password', 'confirmPassword', step); isValid = false; return isValid; } // Email validation if (!validateEmail(email)) { showError('Please enter a valid email address', 'email', step); isValid = false; } else { // Email verification - wait for the result const isEmailVerified = await verifyEmail(email); if (!isEmailVerified) { showError('Email already registered. Please use a different email address.', 'email', step); isValid = false; } } // Password validation if (password.length < 8) { showError('Password must be at least 8 characters long', 'password', step); isValid = false; } if (password !== confirmPassword) { document.getElementById('password-match-error').style.display = 'block'; document.getElementById('confirmPassword').classList.add('field-error'); showError('Passwords do not match', 'confirmPassword', step); isValid = false; } else { document.getElementById('password-match-error').style.display = 'none'; document.getElementById('confirmPassword').classList.remove('field-error'); } } // For personal information step if (step === 2) { const firstName = document.getElementById('firstName').value; if (!firstName) { document.getElementById('profile-incomplete').style.display = 'block'; document.getElementById('firstName').classList.add('field-error'); showError('First name is required', 'firstName', step); isValid = false; } else { document.getElementById('profile-incomplete').style.display = 'none'; document.getElementById('firstName').classList.remove('field-error'); } // Age validation const age = document.getElementById('age').value; if (age && (age < 18 || age > 100)) { showError('You age must be 18 years or older to register', 'age', step); isValid = false; } // Country and state validation const country = document.getElementById('country').value; const state = document.getElementById('state').value; if (!country) { showError('Please select your country', 'country', step); isValid = false; } if (!state) { showError('Please select your state/region', 'state', step); isValid = false; } // Validate other required fields const requiredFields = form.querySelectorAll('[required]'); requiredFields.forEach(field => { if (!field.value.trim()) { isValid = false; field.classList.add('field-error'); if (isValid === false) { showError(`Please fill in ${field.labels[0]?.textContent || 'this field'}`, field.id, step); } } else { field.classList.remove('field-error'); } }); } if (step === 3) { // Phone number validation const phone = document.getElementById('phone').value; if (!phone) { showError('Please enter your phone number', 'phone', step); isValid = false; } else if (!validatePhoneNumberStrict(phone)) { document.getElementById('phone-error').style.display = 'block'; document.getElementById('phone').classList.add('field-error'); showError('Please enter a valid phone number (10-15 digits)', 'phone', step); isValid = false; } else { document.getElementById('phone-error').style.display = 'none'; document.getElementById('phone').classList.remove('field-error'); } // Validate other required fields in step 3 const requiredFields = form.querySelectorAll('[required]'); requiredFields.forEach(field => { if (!field.value.trim()) { isValid = false; field.classList.add('field-error'); } else { field.classList.remove('field-error'); } }); } // For payment step if (step === 4) { const selectedPayment = document.querySelector('.payment-option.selected'); if (!selectedPayment) { showError('Please select a payment method', null, step); isValid = false; } else { const paymentMethod = selectedPayment.getAttribute('onclick').match(/'([^']+)'/)[1]; if (paymentMethod === 'payoneer') { // const payoneerAccount = document.getElementById('payoneerAccount').value; // if (!payoneerAccount) { // showError('Please enter your Payoneer account number', 'payoneerAccount', step); // isValid = false; // } } else if (paymentMethod === 'veem') { const veemAccount = document.getElementById('veemAccount').value; if (!veemAccount) { showError('Please enter your Veem account number', 'veemAccount', step); isValid = false; } } else if (paymentMethod === 'wise') { const wiseEmail = document.getElementById('wiseEmail').value; if (!wiseEmail) { showError('Please enter your Wise email address', 'wiseEmail', step); isValid = false; } else if (!validateEmail(wiseEmail)) { showError('Please enter a valid email address for Wise', 'wiseEmail', step); isValid = false; } } } } // For other steps if (step !== 1 && step !== 2 && step !== 4) { const requiredFields = form.querySelectorAll('[required]'); requiredFields.forEach(field => { if (!field.value.trim()) { isValid = false; field.classList.add('field-error'); } else { field.classList.remove('field-error'); } }); } } return isValid; } // Email validation function function validateEmail(email) { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); } // Function to get form ID based on step function getFormId(step) { switch(step) { case 1: return 'account-form'; case 2: return 'personal-form'; case 3: return 'contact-form'; case 4: return 'payment-form'; default: return ''; } } // Function to save step data to formData object function saveStepData(step) { switch(step) { case 1: formData.userDetails.email = document.getElementById('email').value; formData.userDetails.password = document.getElementById('password').value; break; case 2: formData.userDetails.firstName = document.getElementById('firstName').value; formData.userDetails.lastName = document.getElementById('lastName').value; formData.userDetails.age = document.getElementById('age').value; formData.userDetails.dob = document.getElementById('dob').value; formData.userDetails.address = document.getElementById('address').value; formData.userDetails.city = document.getElementById('city').value; formData.userDetails.state = document.getElementById('state').value; formData.userDetails.country = document.getElementById('country').value; break; case 3: formData.userDetails.phone = document.getElementById('phone').value; formData.userDetails.skype = document.getElementById('skype').value; break; case 4: const selectedPayment = document.querySelector('.payment-option.selected'); if (selectedPayment) { const paymentMethod = selectedPayment.getAttribute('onclick').match(/'([^']+)'/)[1]; formData.userDetails.paymentMethod = paymentMethod; // if (document.getElementById('payoneerAccount').value) { // formData.userDetails.payoneerAccount = document.getElementById('payoneerAccount').value; // } if (document.getElementById('veemAccount').value) { formData.userDetails.veemAccount = document.getElementById('veemAccount').value; } if (paymentMethod === 'wise') { formData.userDetails.wiseEmail = document.getElementById('wiseEmail').value; } } break; } } // Function to select payment method function selectPaymentMethod(method) { // Remove selected class from all options document.querySelectorAll('.payment-option').forEach(option => { option.classList.remove('selected'); }); // Hide all payment details document.querySelectorAll('.payment-details').forEach(details => { details.style.display = 'none'; }); // Add selected class to clicked option event.currentTarget.classList.add('selected'); // Show appropriate payment details if (method === 'payoneer') { // document.getElementById('payoneer-details').style.display = 'block'; } else if (method === 'veem') { document.getElementById('veem-details').style.display = 'block'; } else if (method === 'wise') { document.getElementById('wise-details').style.display = 'block'; } } function validateWiseEmail(input) { const wiseError = document.getElementById('wise-email-error'); const value = input.value.trim(); // Remove any validation styling first input.style.border = ''; wiseError.style.display = 'none'; if (value.length > 0) { // Check if it's a valid email if (!validateEmail(value)) { wiseError.textContent = 'Please enter a valid email address for Wise'; wiseError.style.display = 'block'; input.style.border = '1px solid #ef4444'; return false; } } return true; } // Function to generate a strong password function generatePassword() { const length = 12; const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*"; let password = ""; // Ensure at least one of each required character type password += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[Math.floor(Math.random() * 26)]; password += "abcdefghijklmnopqrstuvwxyz"[Math.floor(Math.random() * 26)]; password += "0123456789"[Math.floor(Math.random() * 10)]; password += "!@#$%^&*"[Math.floor(Math.random() * 8)]; // Fill the rest randomly for (let i = password.length; i < length; i++) { password += charset.charAt(Math.floor(Math.random() * charset.length)); } // Shuffle the password password = password.split('').sort(() => 0.5 - Math.random()).join(''); // Set the password field document.getElementById('password').value = password; document.getElementById('confirmPassword').value = password; // Trigger input events to update UI document.getElementById('password').dispatchEvent(new Event('input')); document.getElementById('confirmPassword').dispatchEvent(new Event('input')); } // Function to toggle password visibility function togglePasswordVisibility() { const passwordField = document.getElementById('password'); const confirmField = document.getElementById('confirmPassword'); const toggleButton = document.querySelector('.password-toggle'); if (passwordField.type === 'password') { passwordField.type = 'text'; confirmField.type = 'text'; toggleButton.textContent = 'Hide Password'; } else { passwordField.type = 'password'; confirmField.type = 'password'; toggleButton.textContent = 'Show Password'; } } // Function to submit the form async function submitForm() { // Validate current step if (!validateStep(currentStep)) { return; } // Save current step data saveStepData(currentStep); // Show loading state const submitBtn = document.querySelector('#payment-form .btn-primary'); const originalText = submitBtn.textContent; submitBtn.textContent = 'Processing...'; submitBtn.disabled = true; try { // Send data to server using fetch // console.log('Submitting form data:', formData); const response = await fetch('/api/v1/va/register', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(formData) }); if (response.ok) { // Success - move to success step // Mark current step as completed document.querySelectorAll(`.step[data-step="${currentStep}"]`).forEach(el => { el.classList.add('completed'); const stepNumber = el.querySelector('.step-number'); stepNumber.textContent = '✓'; stepNumber.style.backgroundColor = '#000000'; stepNumber.style.borderColor = '#000000'; stepNumber.style.color = 'white'; }); document.querySelectorAll(`.mobile-step[data-step="${currentStep}"]`).forEach(el => { el.classList.add('completed'); const stepNumber = el.querySelector('.step-number'); stepNumber.textContent = '✓'; stepNumber.style.backgroundColor = '#000000'; stepNumber.style.borderColor = '#000000'; stepNumber.style.color = 'white'; }); nextStep(5); setTimeout(() => { window.location.href = '/download-tracker'; }, 1000); } else { // Handle server errors showError('There was an error submitting your registration. Please try again.', null, 4); } } catch (error) { // Handle network errors console.error('Error:', error); showError('There was a network error. Please check your connection and try again.', null, 4); } finally { // Restore button state submitBtn.textContent = originalText; submitBtn.disabled = false; } } async function verifyEmail(email) { try { const response = await fetch('/api/v1/va/verify-va-email', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({"email": email}) }); if (response.ok) { return false; } else { return true; } } catch (error) { // Handle network errors console.error('Error:', error); showError('There was a network error. Please check your connection and try again.', null, 1); return false; } } // Function to calculate age from date of birth function calculateAge(dob) { if (!dob) return ''; const birthDate = new Date(dob); const today = new Date(); let age = today.getFullYear() - birthDate.getFullYear(); const monthDiff = today.getMonth() - birthDate.getMonth(); // Adjust age if birthday hasn't occurred this year yet if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) { age--; } return age; } // Function to handle date of birth change and update age function handleDOBChange() { const dob = document.getElementById('dob').value; const ageInput = document.getElementById('age'); if (dob) { const age = calculateAge(dob); ageInput.value = age; // Trigger input event to update the label position ageInput.dispatchEvent(new Event('input')); // Validate age if (age < 18) { // alert('You must be 18 years or older to register'); // showError('You Age must be 18 years or older to register', 'dob'); showError('You Age must be 18 years or older to register', 'age'); ageInput.style.border = '1px solid #ef4444'; } else if (age > 100) { // alert('Please enter a valid age'); // showError('Please enter a valid age', 'dob'); showError('Please enter a valid age', 'age'); ageInput.style.border = '1px solid #ef4444'; } else { ageInput.style.border = ''; } } else { // Clear age if DOB is cleared ageInput.value = ''; ageInput.dispatchEvent(new Event('input')); } } // Function to handle age manual input and update DOB (optional) function handleAgeChange() { const age = document.getElementById('age').value; const dobInput = document.getElementById('dob'); if (age && age >= 18 && age <= 100) { // Calculate approximate DOB based on age const today = new Date(); const birthYear = today.getFullYear() - age; const approximateDOB = `${birthYear}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`; // You can set this as the DOB or just leave it for reference // dobInput.value = approximateDOB; // dobInput.dispatchEvent(new Event('change')); } } // Function to validate phone number in real-time function validatePhoneNumber(input) { const phoneError = document.getElementById('phone-error'); const value = input.value; // Remove any non-digit characters const digitsOnly = value.replace(/\D/g, ''); // Update the input value with digits only if (value !== digitsOnly) { input.value = digitsOnly; } // Validate length if (digitsOnly.length > 0 && (digitsOnly.length < 10 || digitsOnly.length > 15)) { phoneError.style.display = 'block'; input.style.border = '1px solid #ef4444'; return false; } else { phoneError.style.display = 'none'; input.style.border = ''; return true; } } // Function to validate phone number on form submission function validatePhoneNumberStrict(phone) { const phoneRegex = /^[0-9]{10,15}$/; return phoneRegex.test(phone); } // Function to validate Payoneer account number function validatePayoneerAccount(input) { const payoneerError = document.getElementById('payoneer-error'); const value = input.value.trim(); // Remove any validation styling first input.style.border = ''; payoneerError.style.display = 'none'; if (value.length > 0) { // Check length if (value.length < 5 || value.length > 20) { payoneerError.textContent = 'Payoneer account must be 5-20 digits'; payoneerError.style.display = 'block'; input.style.border = '1px solid #ef4444'; return false; } // Check if contains only digits if (!/^\d+$/.test(value)) { payoneerError.textContent = 'Payoneer account must contain digits only'; payoneerError.style.display = 'block'; input.style.border = '1px solid #ef4444'; return false; } // Check if all zeros if (/^0+$/.test(value)) { payoneerError.textContent = 'Payoneer account cannot be all zeros'; payoneerError.style.display = 'block'; input.style.border = '1px solid #ef4444'; return false; } } return true; } // Function to validate Veem account number function validateVeemAccount(input) { const veemError = document.getElementById('veem-error'); const value = input.value.trim(); // Remove any validation styling first input.style.border = ''; veemError.style.display = 'none'; if (value.length > 0) { // Check length if (value.length < 8 || value.length > 25) { veemError.textContent = 'Veem account must be 8-25 digits'; veemError.style.display = 'block'; input.style.border = '1px solid #ef4444'; return false; } // Check if contains only digits if (!/^\d+$/.test(value)) { veemError.textContent = 'Veem account must contain digits only'; veemError.style.display = 'block'; input.style.border = '1px solid #ef4444'; return false; } // Check if all zeros if (/^0+$/.test(value)) { veemError.textContent = 'Veem account cannot be all zeros'; veemError.style.display = 'block'; input.style.border = '1px solid #ef4444'; return false; } } return true; } function showError(message, fieldId = null, step = null) { // Determine the current step if not provided const currentStep = step || getCurrentStep(); const errorContainer = document.getElementById(`step-${currentStep}-error`); const errorMessage = document.getElementById(`step-${currentStep}-error-message`); if (errorContainer && errorMessage) { errorMessage.textContent = message; errorContainer.style.display = 'block'; // Scroll to error container errorContainer.scrollIntoView({ behavior: 'smooth', block: 'center' }); // Highlight specific field if provided if (fieldId) { const field = document.getElementById(fieldId); if (field) { field.classList.add('field-error'); // Remove error after 5 seconds setTimeout(() => { field.classList.remove('field-error'); }, 5000); } } // Auto-hide error after 8 seconds setTimeout(() => { hideError(currentStep); }, 8000); } } function hideError(step = null) { if (step) { // Hide specific step error const errorContainer = document.getElementById(`step-${step}-error`); if (errorContainer) { errorContainer.style.display = 'none'; } } else { // Hide all step errors for (let i = 1; i <= 5; i++) { const errorContainer = document.getElementById(`step-${i}-error`); if (errorContainer) { errorContainer.style.display = 'none'; } } } } function clearFieldErrors() { document.querySelectorAll('.field-error').forEach(field => { field.classList.remove('field-error'); }); } function getCurrentStep() { return currentStep; } function handleChangeSelect(selectElement) { const selectedValue = selectElement.value; let option = selectElement.querySelector('option:disabled'); if (selectedValue !== "") { option.style.display = "none"; } else { option.style.display = ""; } } function validateSkypeId(input) { const value = input.value.trim(); if (value && !/^[a-zA-Z][a-zA-Z0-9\.,\-_]+$/.test(value)) { input.style.border = '1px solid #ef4444'; showError('Skype ID must start with a letter and can only contain letters, numbers, dots, hyphens, and underscores', 'skype', 3); return false; } else { input.style.border = ''; return true; } }