diff --git a/public/css/dashboard.css b/public/css/dashboard.css index c56f08c..7ffb796 100644 --- a/public/css/dashboard.css +++ b/public/css/dashboard.css @@ -961,4 +961,4 @@ tr[data-vaid]:hover { .detail-item span { text-align: left; } -} \ No newline at end of file +} diff --git a/src/controllers/client/dashboard/clientDashboardProjects.controller.js b/src/controllers/client/dashboard/clientDashboardProjects.controller.js new file mode 100644 index 0000000..d7b77cc --- /dev/null +++ b/src/controllers/client/dashboard/clientDashboardProjects.controller.js @@ -0,0 +1,100 @@ +import { ClientModel, ProjectModel, VAModel } from "../../../models/vaModel.js"; +import jwt from "jsonwebtoken"; + +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) { + return `${wholeHours}h`; + } else { + return `${wholeMinutes}m`; + } +} + +// Getting client dashboard data - all VAs and projects +async function client_dashboard_projects(req, res) { + try { + const accessToken = req.headers.token; + + if (!accessToken) { + return res.status(401).json({ success: false, message: "Missing token" }); + } + + const decoded = jwt.verify(accessToken, process.env.JWT_SECRET_ACCESS_TOKEN); + + if (!decoded || !decoded.email) { + return res.status(401).json({ success: false, message: "Invalid token" }); + } + + const clientEmail = decoded.email; + const clientUser = await ClientModel.findOne({ "userDetails.email": clientEmail }); + if (!clientUser) { + return res.status(404).json({ success: false, message: "Client not found" }); + } + + // Get all VA IDs and Project IDs assigned to this client + const clientVaIds = clientUser.vaIds || []; + const clientProjectIds = clientUser.projectIds || []; + + // Get all VAs assigned to this client (with required fields only) + const allAssignedVAs = await VAModel.find({ + _id: { $in: clientVaIds } + }) + .select('userDetails.firstName userDetails.lastName userDetails.email status') + .lean() + .exec(); + + // Get All Projects of client with required fields + const clientProjects = await ProjectModel.find({ + _id: { $in: clientProjectIds } + }) + .select('name hourlyRate vaAssigned dedicatedHours status') + .lean() + .exec(); + + // Format VAs with only required fields + const vasFormatted = allAssignedVAs.map((va) => ({ + id: va._id, + firstName: va.userDetails?.firstName || '', + lastName: va.userDetails?.lastName || '', + email: va.userDetails?.email || '', + status: va.status || '' + })); + + // Format projects with only required fields + const projectsFormatted = clientProjects.map((project) => ({ + id: project._id, + name: project.name, + hourlyRate: project.hourlyRate, + vaAssigned: project.vaAssigned.length || 0, + dedicatedHours: formatHoursToReadable(project.dedicatedHours) || 0, + status: project.status || '' + })); + + return res.status(200).json({ + success: true, + data: { + vas: vasFormatted, + projects: projectsFormatted + }, + counts: { + totalVAs: vasFormatted.length, + totalProjects: projectsFormatted.length + } + }); + + } catch (error) { + console.error("Client dashboard error:", error); + return res.status(500).json({ + success: false, + message: "Internal Server Error", + error: error.message + }); + } +} + +export { client_dashboard_projects }; \ No newline at end of file diff --git a/src/routes/v1/client.routes.js b/src/routes/v1/client.routes.js index 79bc669..382d722 100644 --- a/src/routes/v1/client.routes.js +++ b/src/routes/v1/client.routes.js @@ -11,6 +11,7 @@ import { clientAuthValidator } from "../../middlewares/auth.middleware.js"; import { client_dashboard } from "./../../controllers/client/dashboard/clientDashboard.controller.js"; import { client_dashboard_va_log } from "../../controllers/client/dashboard/clientDashboardVaLog.controller.js"; import { client_verify_email } from "../../controllers/client/vaClientEmailVerify.controller.js"; +import { client_dashboard_projects } from "../../controllers/client/dashboard/clientDashboardProjects.controller.js" // clients routes clientRoutes.post("/register", va_register_client); // Register a new VA @@ -26,7 +27,8 @@ clientRoutes.get("/:clientId/projects/:projectId", va_clients_projects_callback) // dashboard API's clientRoutes.get("/dashboard", clientAuthValidator, client_dashboard); // VA Clients Projects Callback -clientRoutes.post("/dashboard/va-report", clientAuthValidator, client_dashboard_va_log); // VA Clients Projects Callback +clientRoutes.post("/dashboard/va-report", clientAuthValidator, client_dashboard_va_log); // VA details +clientRoutes.get("/dashboard-projects", clientAuthValidator, client_dashboard_projects); // VA Clients Projects Callback diff --git a/src/server.js b/src/server.js index 17cc29a..83552a0 100644 --- a/src/server.js +++ b/src/server.js @@ -159,6 +159,16 @@ app.get('/client/virtual-assistants', async (req, res) => { } }); +app.get('/client/projects', async (req, res) => { + try { + // const vaData = await virtualAssistantService.getClientVAs(req.user.id); + res.render('client/dashboard-projects'); + } catch (error) { + console.error('Projects error:', error); + res.status(500).render('client/dashboard-projects', { error: 'Failed to load virtual assistants' }); + } +}); + app.get("/live/:projectId/:vaId", async (req, res) => { const { projectId, vaId } = req.params; diff --git a/views/client/dashboard-dashboard.ejs b/views/client/dashboard-dashboard.ejs index 640438c..0dede01 100644 --- a/views/client/dashboard-dashboard.ejs +++ b/views/client/dashboard-dashboard.ejs @@ -29,12 +29,12 @@ Virtual Assistants - + + +
TT
+ + + + + +
+ +
+
+ +
+
+

Projects 0 Projects

+
+
+
+ + + + + + + + + + + + + +
NameHourly RateTotal VA AssignedDedicated HoursStatus
+
+ +
+
+

+ +
+
+

Virtual Assistants 0 VAs

+
+
+
+ + + + + + + + + + + +
NameEmailStatus
+
+ +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/views/client/dashboard-virtual-assistants.ejs b/views/client/dashboard-virtual-assistants.ejs index 2d6610a..cd5fbf6 100644 --- a/views/client/dashboard-virtual-assistants.ejs +++ b/views/client/dashboard-virtual-assistants.ejs @@ -29,12 +29,12 @@ Virtual Assistants -