diff --git a/public/js/va-client-register.js b/public/js/va-client-register.js index 23b6c77..85108eb 100644 --- a/public/js/va-client-register.js +++ b/public/js/va-client-register.js @@ -521,12 +521,12 @@ async function validateStep(step) { } if (!firstName) { isValid = false; - showError('First Name is Required', null, step); + showError('First Name is Required', 'first-name', step); return isValid; } if (!lastName) { isValid = false; - showError('Last Name is Required', null, step); + showError('Last Name is Required', 'last-name', step); return isValid; } @@ -545,6 +545,25 @@ async function validateStep(step) { document.getElementById('confirmPassword').classList.remove('field-error'); } + // Validate other required fields + const requiredFields = form.querySelectorAll('[required]'); + requiredFields.forEach(field => { + if (field.id !== 'email' && !field.value.trim()) { + isValid = false; + field.classList.add('field-error'); + } else if (field.id !== 'email') { + field.classList.remove('field-error'); + } + }); + } else if (step === 2) { + const companyName = document.getElementById('company-name').value; + + if (!companyName) { + isValid = false; + showError('Company Name is Required', 'company-name', step); + return isValid; + } + // Validate other required fields const requiredFields = form.querySelectorAll('[required]'); requiredFields.forEach(field => { @@ -639,6 +658,7 @@ function saveStepData(step) { formData.userDetails.password = document.getElementById('password').value; break; case 2: + formData.userDetails.name = document.getElementById('company-name').value; formData.userDetails.address = document.getElementById('address').value; formData.userDetails.city = document.getElementById('city').value; formData.userDetails.state = document.getElementById('state').value; @@ -882,28 +902,29 @@ async function detectLocation() { await populateStates(countryCode, 'state'); await populateStates(countryCode, 'billing-state'); - const stateSelect = document.getElementById('state'); - const billingStateSelect = document.getElementById('billing-state'); + // auto populate state if region matches + // const stateSelect = document.getElementById('state'); + // const billingStateSelect = document.getElementById('billing-state'); - if (stateSelect && region) { - const matchedState = Array.from(stateSelect.options).find( - opt => opt.text.toLowerCase() === region.toLowerCase() - ); - if (matchedState) { - stateSelect.value = matchedState.value; - stateSelect.dispatchEvent(new Event('change')); - } - } + // if (stateSelect && region) { + // const matchedState = Array.from(stateSelect.options).find( + // opt => opt.text.toLowerCase() === region.toLowerCase() + // ); + // if (matchedState) { + // stateSelect.value = matchedState.value; + // stateSelect.dispatchEvent(new Event('change')); + // } + // } - if (billingStateSelect && region) { - const matchedBillingState = Array.from(billingStateSelect.options).find( - opt => opt.text.toLowerCase() === region.toLowerCase() - ); - if (matchedBillingState) { - billingStateSelect.value = matchedBillingState.value; - billingStateSelect.dispatchEvent(new Event('change')); - } - } + // if (billingStateSelect && region) { + // const matchedBillingState = Array.from(billingStateSelect.options).find( + // opt => opt.text.toLowerCase() === region.toLowerCase() + // ); + // if (matchedBillingState) { + // billingStateSelect.value = matchedBillingState.value; + // billingStateSelect.dispatchEvent(new Event('change')); + // } + // } } catch (error) { console.error('Error detecting location:', error); @@ -1092,7 +1113,7 @@ document.addEventListener('DOMContentLoaded', function() { // Handle use business address checkbox document.getElementById('use-business-address').addEventListener('change', function() { if (this.checked) { - document.getElementById('billing-name').value = formData.userDetails.firstName || ''; + document.getElementById('billing-name').value = formData.userDetails.name || ''; document.getElementById('billing-address').value = formData.userDetails.address || ''; document.getElementById('billing-city').value = formData.userDetails.city || ''; document.getElementById('billing-state').value = formData.userDetails.state || ''; @@ -1439,6 +1460,93 @@ function preventInvalidLastNameChars(event) { return false; } +// Function to validate company name +function validateCompanyName(input) { + const errorElement = document.getElementById('company-name-error'); + const value = input.value; + + // Check various invalid patterns + const validationResult = validateCompanyNameContent(value); + + if (!validationResult.isValid && value.trim().length > 0) { + errorElement.textContent = validationResult.message; + errorElement.style.display = 'block'; + input.classList.add('field-error'); + return false; + } else { + errorElement.style.display = 'none'; + input.classList.remove('field-error'); + return true; + } +} + +function validateCompanyNameContent(companyName) { + const trimmed = companyName.trim(); + + if (trimmed.length === 0) { + return { isValid: false, message: 'Company name is required' }; + } + + // Check minimum length + if (trimmed.length < 2) { + return { isValid: false, message: 'Company name must be at least 2 characters' }; + } + + // Remove whitespace for content analysis + const content = trimmed.replace(/\s/g, ''); + + // Check if contains only special characters + if (/^[^a-zA-Z0-9]+$/.test(content)) { + return { isValid: false, message: 'Company name cannot be only special characters' }; + } + + // Check if contains at least some valid content (letters or numbers) + if (!/[a-zA-Z0-9]/.test(content)) { + return { isValid: false, message: 'Company name must contain letters or numbers' }; + } + + // Optional: Check for excessive special characters (more than 50%) + const specialCharCount = (content.match(/[^a-zA-Z0-9]/g) || []).length; + if (specialCharCount > content.length / 2) { + return { isValid: false, message: 'Company name contains too many special characters' }; + } + + return { isValid: true, message: '' }; +} + +// Function to prevent invalid character input in real-time +function preventInvalidCompanyNameChars(event) { + const charCode = event.which ? event.which : event.keyCode; + const key = event.key; + + // Allow: letters, numbers, spaces, hyphens, apostrophes, ampersands, periods, commas + // Also allow common editing keys + if ((charCode >= 65 && charCode <= 90) || // A-Z + (charCode >= 97 && charCode <= 122) || // a-z + (charCode >= 48 && charCode <= 57) || // 0-9 + charCode === 32 || // space + charCode === 45 || // hyphen + charCode === 39 || // apostrophe + charCode === 38 || // ampersand (&) + charCode === 46 || // period (.) + charCode === 44 || // comma (,) + charCode === 8 || // backspace + charCode === 9 || // tab + charCode === 37 || // left arrow + charCode === 39 || // right arrow + charCode === 16 || // shift + charCode === 17 || // ctrl + charCode === 18 || // alt + charCode === 91 || // cmd (Mac) + /^[a-zA-Z0-9\s\-'&.,]$/.test(key)) { // allowed characters + return true; + } + + // Prevent invalid characters + event.preventDefault(); + return false; +} + // Function to validate ZIP code in real-time function validateZipCode(input) { let errorElement; diff --git a/src/controllers/client/vaClient.controller.js b/src/controllers/client/vaClient.controller.js index 87695cc..897b8f9 100644 --- a/src/controllers/client/vaClient.controller.js +++ b/src/controllers/client/vaClient.controller.js @@ -25,10 +25,10 @@ async function va_register_client(req, res) { try { const payload = req.body || {}; const { userDetails } = payload; - if (!userDetails || !userDetails.email || !userDetails.firstName || !userDetails.lastName || !userDetails.password) { + if (!userDetails || !userDetails.email || !userDetails.firstName || !userDetails.lastName || !userDetails.password || !userDetails.name) { return res.status(400).json({ success: false, - message: "Missing required fields: firstName, lastName, email, and password are required" + message: "Missing required fields: firstName, lastName, email, company name and password are required" }); } diff --git a/src/services/salesforce.service.js b/src/services/salesforce.service.js index 78d4d9a..fd3b4b8 100644 --- a/src/services/salesforce.service.js +++ b/src/services/salesforce.service.js @@ -46,6 +46,7 @@ class SalesforceService { return { userDetails: { _id: _id, + name: userDetails.name, firstName: userDetails.firstName, lastName: userDetails.lastName, email: userDetails.email.toLowerCase(), diff --git a/src/services/vaClient.service.js b/src/services/vaClient.service.js index a55deff..d9b99d0 100644 --- a/src/services/vaClient.service.js +++ b/src/services/vaClient.service.js @@ -75,7 +75,7 @@ class VaClientService { // Define allowed fields for update (excluding password) const allowedFields = [ - "firstName", "lastName", "address", "city", "state", "zip", + "name", "firstName", "lastName", "address", "city", "state", "zip", "billingName", "billingEmail", "billingAddress", "billingCity", "billingState", "billingZip", "position", "signatoryName", "signatoryEmail", "paymentMethod", "bankName", "accountNumber", @@ -273,7 +273,7 @@ class VaClientService { userDetails: { firstName: userDetails.firstName, lastName: userDetails.lastName, - name: `${userDetails.firstName} ${userDetails.lastName}`, + name: userDetails.name, email: userDetails.email.toLowerCase(), password: hashedPassword, address: userDetails.address || null, diff --git a/views/va_client_register.ejs b/views/va_client_register.ejs index 517c09f..a1c5346 100644 --- a/views/va_client_register.ejs +++ b/views/va_client_register.ejs @@ -152,6 +152,15 @@