va-tracker-middleware/public/js/va-register.js

1208 lines
48 KiB
JavaScript

// 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 = '<option value="" disabled selected></option>';
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 = '<option value="" disabled selected></option>';
// // 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 (!validateEmail(payoneerAccount)) {
showError('Please enter a valid email address for Payoneer', '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 (!validateEmail(veemAccount)) {
showError('Please enter a valid email address for Veem', '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;
formData.status = document.getElementById('status').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 validateVeemEmail(input) {
const wiseError = document.getElementById('veem-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 Veem';
wiseError.style.display = 'block';
input.style.border = '1px solid #ef4444';
return false;
}
}
return true;
}
function validatePayoneerEmail(input) {
const wiseError = document.getElementById('payoneer-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 Payoneer';
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('Invalid Skype ID', 'skype', 3);
return false;
} else {
input.style.border = '';
return true;
}
}