Added password option in client registration

This commit is contained in:
Aakash Mittal 2025-12-17 12:27:19 +05:30
parent efa6ce929e
commit 5f043ed80a
4 changed files with 97 additions and 9 deletions

View File

@ -492,9 +492,11 @@ async function validateStep(step) {
} else if (step === 1) {
const email = document.getElementById('email').value;
const companyName = document.getElementById('company-name').value;
if (!validateEmail(email) && !companyName) {
const password = document.getElementById('password').value;
const confirmPassword = document.getElementById('confirmPassword').value;
if (!validateEmail(email) && !companyName && !password && !confirmPassword) {
isValid = false;
showError('Both Fields are Required', null, step);
showError('Fields are Required', null, step);
let requiredFields1 = form.querySelectorAll('[required]');
requiredFields1.forEach(field => {
if (!field.value.trim()) {
@ -522,6 +524,21 @@ async function validateStep(step) {
return isValid;
}
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');
}
// Validate other required fields
const requiredFields = form.querySelectorAll('[required]');
requiredFields.forEach(field => {
@ -612,6 +629,7 @@ function saveStepData(step) {
case 1:
formData.userDetails.name = document.getElementById('company-name').value;
formData.userDetails.email = document.getElementById('email').value;
formData.userDetails.password = document.getElementById('password').value;
break;
case 2:
formData.userDetails.address = document.getElementById('address').value;
@ -1954,4 +1972,52 @@ function preventInvalidAccountHolderChars(event) {
event.preventDefault();
return false;
}
}
// 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';
}
}

View File

@ -25,10 +25,10 @@ async function va_register_client(req, res) {
try {
const payload = req.body || {};
const { userDetails } = payload;
if (!userDetails || !userDetails.email || !userDetails.name) {
if (!userDetails || !userDetails.email || !userDetails.name || !userDetails.password) {
return res.status(400).json({
success: false,
message: "Missing required fields: name and email are required"
message: "Missing required fields: name, email, and password are required"
});
}

View File

@ -18,7 +18,7 @@ class VaClientService {
}
// Sanitize and prepare data
const clientData = this.sanitizeClientData(data);
const clientData = await this.sanitizeClientData(data);
const response = await this.clientRepository.create(clientData);
if(response) {
@ -263,13 +263,17 @@ class VaClientService {
}
// Helper method to sanitize data
sanitizeClientData(payload) {
async sanitizeClientData(payload) {
const { userDetails } = payload;
const saltRounds = 10;
const hashedPassword = await bcrypt.hash(userDetails.password, saltRounds);
return {
userDetails: {
name: userDetails.name,
email: userDetails.email.toLowerCase(),
password: hashedPassword,
address: userDetails.address || null,
city: userDetails.city || null,
state: userDetails.state || null,

View File

@ -111,6 +111,24 @@
<label for="email" class="input-label">Email *</label>
</div>
</div>
<div class="form-group">
<div class="input-container">
<input type="password" id="password" class="input-field" placeholder=" " required autocomplete="new-password">
<label for="password" class="input-label">Create Password *</label>
</div>
</div>
<div class="form-group">
<div class="input-container">
<input type="password" id="confirmPassword" class="input-field" placeholder=" " required autocomplete="new-password">
<label for="confirmPassword" class="input-label">Confirm Password *</label>
</div>
<div class="invalid-feedback" id="password-match-error" style="display: none; color: #dc3545; font-size: 12px; margin-top: 5px;">Passwords do not match</div>
<div class="password-actions">
<button type="button" class="password-toggle" onclick="togglePasswordVisibility()">Show Password</button>
<button type="button" class="password-generate" onclick="generatePassword()">Generate Strong Password</button>
</div>
</div>
<div class="form-actions">
<div></div> <!-- Empty div for spacing -->
<button type="button" class="btn btn-primary" onclick="handleNextStep(2)">Continue</button>
@ -242,7 +260,7 @@
<div class="error-message" id="step-4-error-message"></div>
</div>
<p style="margin-bottom: 20px; color: #6b7280; font-size: 14px;">
We will use the details below in the agreement that we will send to your prior to entering the project.
We will use the details below in the agreement that we will send to your prior to starting the project.
</p>
<form id="signatory-form">
<div class="form-group">
@ -322,7 +340,7 @@
</div>
</div>
<div class="payment-option" onclick="selectPaymentOption('bank')">
<h4>Bank Account (ACR)</h4>
<h4>Bank Account (ACH)</h4>
<p>Direct bank transfer</p>
</div>
<div id="bank-details" class="payment-details">