From da3deac57b5ad076c0b02a514c5a9779e61bb84c Mon Sep 17 00:00:00 2001 From: =bhagwanSingh Date: Thu, 18 Dec 2025 16:45:08 +0530 Subject: [PATCH 1/4] A --- .../va/vaProjects/vaProjectLog.controller.js | 215 +++++++++--------- 1 file changed, 108 insertions(+), 107 deletions(-) diff --git a/src/controllers/va/vaProjects/vaProjectLog.controller.js b/src/controllers/va/vaProjects/vaProjectLog.controller.js index da0de73..4582d3b 100644 --- a/src/controllers/va/vaProjects/vaProjectLog.controller.js +++ b/src/controllers/va/vaProjects/vaProjectLog.controller.js @@ -1,3 +1,4 @@ +import mongoose from "mongoose"; import { LoggedModel, WorkTrackModel, ProjectModel, VAModel } from "../../../models/vaModel.js"; import authFetch from "../../../utils/authFetch.js"; import getDayNumber from "../../../utils/getDayNumber.js"; @@ -6,10 +7,10 @@ import getDayNumber from "../../../utils/getDayNumber.js"; function getDayRange(date = new Date()) { const start = new Date(date); start.setUTCHours(0, 0, 0, 0); - + const end = new Date(date); end.setUTCHours(23, 59, 59, 999); - + return { start, end }; } @@ -17,7 +18,7 @@ function formatHoursToReadable(hours) { const wholeHours = Math.floor(hours); const decimalMinutes = (hours - wholeHours) * 60; const wholeMinutes = Math.round(decimalMinutes); - + if (wholeHours > 0 && wholeMinutes > 0) { return `${wholeHours}h ${wholeMinutes}m`; } else if (wholeHours > 0) { @@ -30,11 +31,11 @@ function formatHoursToReadable(hours) { // Helper function to parse ISO time string function parseISOTimeString(timeString) { if (!timeString) return new Date(); - + try { // Parse ISO string directly const parsedDate = new Date(timeString); - + // Check if the date is valid if (isNaN(parsedDate.getTime())) { throw new Error('Invalid date'); @@ -66,84 +67,84 @@ function getCurrentUTCTime() { // function parseTimeToMinutes(timeString) { // if (!timeString) return null; - + // const [hours, minutes] = timeString.split(':').map(Number); // return hours * 60 + (minutes || 0); // } // function parseDelayToMinutes(delayString) { // if (!delayString) return 0; - + // if (delayString.includes('h')) { // const hours = parseInt(delayString.replace('h', '').trim()); // return hours * 60; // } else if (delayString.includes('m')) { // return parseInt(delayString.replace('m', '').trim()); // } - + // return parseInt(delayString) || 0; // Default to minutes if no unit specified // } // function checkScheduleCompliance(currentTime, project, vaStatus, type) { // const warnings = []; - + // // If project doesn't have schedule or VA is PARTTIME with flexible allowed, no schedule restrictions // if (!project.vaWorkingScheduleStart || !project.vaWorkingScheduleEnd) { // return { isCompliant: true, warnings }; // } - + // const currentDate = new Date(currentTime); // const currentMinutes = currentDate.getUTCHours() * 60 + currentDate.getUTCMinutes(); - + // const scheduleStartMinutes = parseTimeToMinutes(project.vaWorkingScheduleStart); // const scheduleEndMinutes = parseTimeToMinutes(project.vaWorkingScheduleEnd); // const allowedStartDelay = parseDelayToMinutes(project.vaWorkingDelayAllowedStart); // const allowedEndDelay = parseDelayToMinutes(project.vaWorkingDelayAllowedEnd); - + // // Calculate allowed time ranges // const allowedStartMinutes = scheduleStartMinutes - allowedStartDelay; // const allowedEndMinutes = scheduleEndMinutes + allowedEndDelay; - + // console.log(`Schedule Check - Current: ${currentMinutes}, Start: ${scheduleStartMinutes}, End: ${scheduleEndMinutes}, Allowed Start: ${allowedStartMinutes}, Allowed End: ${allowedEndMinutes}`); - + // // Check for PARTTIME with flexible schedule // if (vaStatus === "PARTTIME" && project.isFlexibleAllowed) { // return { isCompliant: true, warnings }; // } - + // // For all other cases, check schedule compliance // if (type === "LOGIN") { // // Check if login is too early // if (currentMinutes < allowedStartMinutes) { // warnings.push("early_login"); // } - + // // Check if login is after shift end // if (currentMinutes > scheduleEndMinutes) { // warnings.push("working_after_shift_end"); // } - + // // Check if login is within allowed range // // const isWithinAllowedRange = currentMinutes >= allowedStartMinutes && currentMinutes <= allowedEndMinutes; - + // return { // isCompliant: true, // Allow login regardless of time // warnings // }; - + // } else if (type === "LOGOUT") { // // Check if logout is too late // if (currentMinutes > allowedEndMinutes) { // warnings.push("late_logout"); // } - + // // For logout, we're generally more permissive - allow logout even if late // return { // isCompliant: true, // Allow logout regardless of time // warnings // }; // } - + // return { isCompliant: true, warnings }; // } @@ -151,7 +152,7 @@ function getCurrentUTCTime() { async function closePreviousSession(vaId, lastLog, logTime = new Date()) { try { const currentTime = logTime; - + // Find all open work tracks for this VA and project (where to is not set or totalTime is 0) const openWorkTracks = await WorkTrackModel.find({ vaId, @@ -162,22 +163,22 @@ async function closePreviousSession(vaId, lastLog, logTime = new Date()) { { to: null } ] }); - + // console.log(`Found ${openWorkTracks.length} open work tracks to close`); - + // Close all open work tracks for (const workTrack of openWorkTracks) { const fromTime = new Date(workTrack.from); const totalTimeMs = currentTime - fromTime; - + // Update the work track with end time and total time workTrack.to = currentTime; workTrack.totalTime = totalTimeMs; await workTrack.save(); - + // console.log(`Closed work track ${workTrack._id} with duration: ${totalTimeMs}ms`); } - + // Create a logout log entry const logoutLog = await LoggedModel.create({ loggedType: "LOGOUT", @@ -186,18 +187,18 @@ async function closePreviousSession(vaId, lastLog, logTime = new Date()) { projectId: lastLog.projectId, time: currentTime // Use same timestamp for consistent logging }); - + // console.log(`Created logout log: ${logoutLog._id}`); try { const salesforceUrl = `${process.env.SF_DOCTRACKER_API_URL}services/apexrest/docva/api/va-project-log`; const sfDataSync = { - "_id": logoutLog._id, - "loggedType": "LOGOUT", - "vaId": vaId, - "vaEmail": lastLog.vaEmail, - "projectId": lastLog.projectId, - "time": logoutLog.time, - } + "_id": logoutLog._id, + "loggedType": "LOGOUT", + "vaId": vaId, + "vaEmail": lastLog.vaEmail, + "projectId": lastLog.projectId, + "time": logoutLog.time, + } const response = await authFetch(salesforceUrl, { method: 'POST', @@ -208,7 +209,7 @@ async function closePreviousSession(vaId, lastLog, logTime = new Date()) { }, body: JSON.stringify(sfDataSync) }); - + if (!response.ok) { const errorText = await response.text(); throw new Error(`Salesforce API responded with status ${response.status}: ${errorText}`); @@ -216,7 +217,7 @@ async function closePreviousSession(vaId, lastLog, logTime = new Date()) { const result = await response.json(); // console.log("✅ Successfully synced VA data to Salesforce:", result); - + return { closedWorkTracks: openWorkTracks.length, logoutLogId: logoutLog._id, @@ -225,13 +226,13 @@ async function closePreviousSession(vaId, lastLog, logTime = new Date()) { } catch (error) { console.error("Failed to sync with Salesforce:", error.message); console.log(error) - + // Create a custom error to distinguish Salesforce errors const salesforceError = new Error(`Salesforce sync failed: ${error.message}`); salesforceError.isSalesforceError = true; throw salesforceError; } - + } catch (error) { console.error("Error closing previous session:", error); throw error; @@ -244,7 +245,7 @@ async function va_project_log_callback(req, res) { const payload = req.body || {}; const { vaId, vaEmail, projectId, type, time: receivedTimeString } = payload; // console.log("Received payload:", payload); - + if (!vaId || !vaEmail || !projectId || !type) { return res.status(400).send("Missing required properties"); } @@ -252,11 +253,11 @@ async function va_project_log_callback(req, res) { // Determine the log time based on received time (both in UTC) const currentTime = getCurrentUTCTime(); // Current UTC time let logTime = currentTime; - + if (receivedTimeString) { // Parse the received ISO time string const receivedTime = parseISOTimeString(receivedTimeString); - + // Check if the difference is less than 10 seconds if (isTimeWithinThreshold(receivedTime, currentTime, 10)) { logTime = receivedTime; @@ -296,7 +297,7 @@ async function va_project_log_callback(req, res) { const { logId } = payload; const workTrackData = await WorkTrackModel.find({ - logId: logId + logId: new mongoose.Types.ObjectId(logId) }); // console.log(`Found work track data for logout:`, workTrackData); @@ -311,23 +312,23 @@ async function va_project_log_callback(req, res) { if (updatedLogs.length > 0) { const lastLogIndex = updatedLogs.length - 1; const lastLogEntry = updatedLogs[lastLogIndex]; - + // Update the last log's 'to' time and recalculate its totalTime const lastLogFromTime = new Date(lastLogEntry.from); const lastLogTotalTime = Math.abs(toLogTime - lastLogFromTime); - + updatedLogs[lastLogIndex] = { ...lastLogEntry, to: toLogTime, totalTime: lastLogTotalTime }; - + // console.log(`Updated last log in array - from: ${lastLogFromTime.toISOString()}, to: ${toLogTime.toISOString()}, totalTime: ${lastLogTotalTime}ms`); } const updateResult = await WorkTrackModel.updateOne( { _id: workTrackData[0]._id }, - { + { $set: { to: toLogTime, totalTime: totalTimeMs, @@ -356,10 +357,10 @@ async function va_project_log_callback(req, res) { } // Create the logout log entry - const createdLog = await LoggedModel.create({ - loggedType: type, - vaId, - vaEmail, + const createdLog = await LoggedModel.create({ + loggedType: type, + vaId, + vaEmail, projectId, time: logTime }); @@ -367,13 +368,13 @@ async function va_project_log_callback(req, res) { try { const salesforceUrl = `${process.env.SF_DOCTRACKER_API_URL}services/apexrest/docva/api/va-project-log`; const sfData = { - "_id": createdLog._id, - "loggedType": type, - "vaId": vaId, - "vaEmail": vaEmail, - "projectId": projectId, - "time": createdLog.time, - } + "_id": createdLog._id, + "loggedType": type, + "vaId": vaId, + "vaEmail": vaEmail, + "projectId": projectId, + "time": createdLog.time, + } const response = await authFetch(salesforceUrl, { method: 'POST', @@ -382,18 +383,18 @@ async function va_project_log_callback(req, res) { }, body: JSON.stringify(sfData) }); - + if (!response.ok) { const errorText = await response.text(); throw new Error(`Salesforce API responded with status ${response.status}: ${errorText}`); } const result = await response.json(); - - return res.status(201).json({ - success: true, - message: `${type} Successfully`, - logId: createdLog._id, + + return res.status(201).json({ + success: true, + message: `${type} Successfully`, + logId: createdLog._id, SyncSalesforce: result, timeUsed: receivedTimeString ? 'received' : 'current', actualTime: createdLog.time, @@ -401,11 +402,11 @@ async function va_project_log_callback(req, res) { } catch (error) { console.error("Failed to sync with Salesforce:", error.message); console.log(error) - + // Still return success since the logout was recorded locally - return res.status(201).json({ - success: true, - message: `${type} Successfully (Salesforce sync failed)`, + return res.status(201).json({ + success: true, + message: `${type} Successfully (Salesforce sync failed)`, logId: createdLog._id, timeUsed: receivedTimeString ? 'received' : 'current', actualTime: createdLog.time, @@ -423,15 +424,15 @@ async function va_project_log_callback(req, res) { projectId, from: { $gte: start, $lte: end } }); - + const totalTodayMs = todayWorkEntries.reduce((total, entry) => { return total + (entry.totalTime || 0); }, 0); - + const totalTodayHours = totalTodayMs / (1000 * 60 * 60); const dayNumber = getDayNumber(logTime); - + // Check if daily hours are already completed if (project.dedicatedHours[dayNumber] > 0 && totalTodayHours >= project.dedicatedHours[dayNumber]) { return res.status(400).json({ @@ -456,10 +457,10 @@ async function va_project_log_callback(req, res) { // console.log(`Previous session closed: ${closeResult.closedWorkTracks} work tracks, logout log: ${closeResult.logoutLogId}`); // Now proceed to create new login - const createdLog = await LoggedModel.create({ - loggedType: "LOGIN", - vaId, - vaEmail, + const createdLog = await LoggedModel.create({ + loggedType: "LOGIN", + vaId, + vaEmail, projectId, time: logTime }); @@ -467,13 +468,13 @@ async function va_project_log_callback(req, res) { try { const salesforceUrl = `${process.env.SF_DOCTRACKER_API_URL}services/apexrest/docva/api/va-project-log`; const sfData = { - "_id": createdLog._id, - "loggedType": "LOGIN", - "vaId": vaId, - "vaEmail": vaEmail, - "projectId": projectId, - "time": createdLog.time, - } + "_id": createdLog._id, + "loggedType": "LOGIN", + "vaId": vaId, + "vaEmail": vaEmail, + "projectId": projectId, + "time": createdLog.time, + } const response = await authFetch(salesforceUrl, { method: 'POST', @@ -484,7 +485,7 @@ async function va_project_log_callback(req, res) { }, body: JSON.stringify(sfData) }); - + if (!response.ok) { const errorText = await response.text(); throw new Error(`Salesforce API responded with status ${response.status}: ${errorText}`); @@ -492,11 +493,11 @@ async function va_project_log_callback(req, res) { const result = await response.json(); // console.log("✅ Successfully synced VA data to Salesforce:", result); - - return res.status(201).json({ - success: true, - message: `${type} Successfully`, - logId: createdLog._id, + + return res.status(201).json({ + success: true, + message: `${type} Successfully`, + logId: createdLog._id, SyncSalesforce: result, previousSession: { closedWorkTracks: closeResult.closedWorkTracks, @@ -509,7 +510,7 @@ async function va_project_log_callback(req, res) { } catch (error) { console.error("Failed to sync with Salesforce:", error.message); console.log(error) - + // Create a custom error to distinguish Salesforce errors const salesforceError = new Error(`Salesforce sync failed: ${error.message}`); salesforceError.isSalesforceError = true; @@ -518,10 +519,10 @@ async function va_project_log_callback(req, res) { } } - const createdLog = await LoggedModel.create({ - loggedType: type, - vaId, - vaEmail, + const createdLog = await LoggedModel.create({ + loggedType: type, + vaId, + vaEmail, projectId, time: logTime }); @@ -529,13 +530,13 @@ async function va_project_log_callback(req, res) { try { const salesforceUrl = `${process.env.SF_DOCTRACKER_API_URL}services/apexrest/docva/api/va-project-log`; const sfData = { - "_id": createdLog._id, - "loggedType": type, - "vaId": vaId, - "vaEmail": vaEmail, - "projectId": projectId, - "time": createdLog.time, - } + "_id": createdLog._id, + "loggedType": type, + "vaId": vaId, + "vaEmail": vaEmail, + "projectId": projectId, + "time": createdLog.time, + } const response = await authFetch(salesforceUrl, { method: 'POST', @@ -546,7 +547,7 @@ async function va_project_log_callback(req, res) { }, body: JSON.stringify(sfData) }); - + if (!response.ok) { const errorText = await response.text(); throw new Error(`Salesforce API responded with status ${response.status}: ${errorText}`); @@ -554,11 +555,11 @@ async function va_project_log_callback(req, res) { const result = await response.json(); // console.log("✅ Successfully synced VA data to Salesforce:", result); - - res.status(201).json({ - success: true, - message: `${type} Successfully`, - logId: createdLog._id, + + res.status(201).json({ + success: true, + message: `${type} Successfully`, + logId: createdLog._id, SyncSalesforce: result, timeUsed: receivedTimeString ? 'received' : 'current', actualTime: createdLog.time, @@ -567,7 +568,7 @@ async function va_project_log_callback(req, res) { } catch (error) { console.error("Failed to sync with Salesforce:", error.message); console.log(error) - + // Create a custom error to distinguish Salesforce errors const salesforceError = new Error(`Salesforce sync failed: ${error.message}`); salesforceError.isSalesforceError = true; From d4cdc94bbdf6824824d5abb2c8e575602ef8d0a8 Mon Sep 17 00:00:00 2001 From: Aakash Date: Thu, 18 Dec 2025 17:55:11 +0530 Subject: [PATCH 2/4] Added company name in client registration --- public/js/va-client-register.js | 154 +++++++++++++++--- src/controllers/client/vaClient.controller.js | 4 +- src/services/salesforce.service.js | 1 + src/services/vaClient.service.js | 4 +- views/va_client_register.ejs | 9 + 5 files changed, 145 insertions(+), 27 deletions(-) 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 @@
+
+
+ + +
+ +
From 39f415b6850615f3a893a96b4dffe02627439ec4 Mon Sep 17 00:00:00 2001 From: =bhagwanSingh Date: Thu, 18 Dec 2025 19:51:58 +0530 Subject: [PATCH 3/4] a --- src/server.js | 18 + views/client/dashboard-dashboard.ejs | 537 ++++++++++++++------------- 2 files changed, 298 insertions(+), 257 deletions(-) diff --git a/src/server.js b/src/server.js index 2657eb4..d2a461d 100644 --- a/src/server.js +++ b/src/server.js @@ -521,6 +521,24 @@ app.post("/post-test", (req, res) => { return res.status(200).json({ "success": true, "message": "POST request received", "data": req.body }) }); +app.get("/tnyk/:sf_token", (req, res) => { + const sf_token = req.params.sf_token; + console.log("Received token:", sf_token); + + try { + const decoded = jwt.verify(sf_token, process.env.JWT_SECRET_SF_TOKEN); + if (decoded) { + res.render('client/dashboard-dashboard', { sf_token: sf_token }); + } else { + res.render('not_found', { title: "Client" }); + } + } catch (error) { + res.render('not_found', { title: "Client" }); + } + + +}); + app.use((req, res) => { res.status(404).render("not_found", { title: "404 - Page Not Found" diff --git a/views/client/dashboard-dashboard.ejs b/views/client/dashboard-dashboard.ejs index 8c65c78..91049bb 100644 --- a/views/client/dashboard-dashboard.ejs +++ b/views/client/dashboard-dashboard.ejs @@ -1,5 +1,6 @@ + @@ -7,6 +8,7 @@ +
- +
- + @@ -122,7 +124,8 @@
-

Virtual Assistants 0 VAs

+

Virtual Assistants 0 + VAs

@@ -170,7 +173,7 @@ Projects 0 - +
@@ -203,7 +206,7 @@ - + - + + + \ No newline at end of file From 0c14e26937410e1d6cbbcdbc1923733a3e903041 Mon Sep 17 00:00:00 2001 From: =bhagwanSingh Date: Fri, 19 Dec 2025 18:59:26 +0530 Subject: [PATCH 4/4] Added Mac Build Download URL --- views/download_tracker.ejs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/views/download_tracker.ejs b/views/download_tracker.ejs index d2e626b..7e19618 100644 --- a/views/download_tracker.ejs +++ b/views/download_tracker.ejs @@ -171,12 +171,20 @@ // -------- Download -------- downloadBtn.addEventListener("click", () => { + const activeBtn = document.querySelector(".os-btn.active") + const os = activeBtn.dataset.os; const link = document.createElement("a"); - link.href = `/public/builds/build-1.1.1.1/windows/VA Tracker-Setup-1.1.1.exe`; - link.setAttribute("download", ""); - link.click() + if(os === "mac") { + link.href = `/public/builds/build-1.1.1.1/mac/VA Tracker-1.1.1-universal.dmg`; + link.setAttribute("download", ""); + } else if (os === "windows") { + link.href = `/public/builds/build-1.1.1.1/windows/VA Tracker-Setup-1.1.1.exe`; + link.setAttribute("download", ""); + } + + link.click() // window.location.href = ``; });