diff --git a/public/images/downloads.png b/public/images/downloads.png new file mode 100644 index 0000000..e1f5720 Binary files /dev/null and b/public/images/downloads.png differ diff --git a/public/images/mac-os-logo.png b/public/images/mac-os-logo.png new file mode 100644 index 0000000..605d0b3 Binary files /dev/null and b/public/images/mac-os-logo.png differ diff --git a/public/images/windows.png b/public/images/windows.png new file mode 100644 index 0000000..c98b377 Binary files /dev/null and b/public/images/windows.png differ diff --git a/public/js/va-register.js b/public/js/va-register.js index 5f73dbf..2c65a26 100644 --- a/public/js/va-register.js +++ b/public/js/va-register.js @@ -594,7 +594,7 @@ nextStep(5); setTimeout(() => { - window.location.href = '/login'; + window.location.href = '/download-tracker'; }, 1000); } else { // Handle server errors diff --git a/src/server.js b/src/server.js index 12e6771..b3376c9 100644 --- a/src/server.js +++ b/src/server.js @@ -16,6 +16,7 @@ import { fileURLToPath } from 'url'; import apiRoutes from './routes/index.js' import { render_reset_form } from "./controllers/passwordReset.controllers.js"; +import jwt from "jsonwebtoken"; const app = express(); @@ -53,10 +54,38 @@ app.use(bodyParser.text()); // API Route app.use('/api', apiRoutes); -app.get('/varegister/:sf_token?', (req, res) => { - // const { sf_token } = useParams(); +app.get("/download-tracker", (req, res) => { + res.render("download_tracker", { + version: "3.2.1" + }); +}); + +app.get("/download-file", (req, res) => { + const os = req.query.os || "windows"; + + if (os === "windows") { + return res.download("./files/docTracker-3.2.1.exe"); + } else { + return res.download("./files/docTracker-3.2.1.dmg"); + } +}); + + +app.get('/varegister/:sf_token?', (req, res) => { + const { sf_token } = req.params; + + try { + const decoded = jwt.verify(sf_token, process.env.JWT_SECRET_SF_TOKEN); + + if (decoded) { + res.render('va_register', { title: "VA Registration" }); + } else { + res.render('not_found', { title: "VA Registration" }); + } + } catch (error) { + res.render('not_found', { title: "VA Registration" }); + } - res.render('va_register', { title: "VA Registration" }); // if(verified) { // res.render('va_register', { title: "VA Registration" }); // } else { @@ -137,14 +166,27 @@ app.get('/client/virtual-assistants', async (req, res) => { // } // }); -app.get("/live/:projectId/:clientId", (req, res) => { - const { projectId, clientId } = req.params; +app.get("/live/:projectId/:vaId", async (req, res) => { + const { projectId, vaId } = req.params; - if(!projectId || !clientId){ - return res.status(400).send({"message": "Page not found"}); + if (!projectId || !vaId) { + return res.status(400).send({ "message": "Page not found" }); } - res.render("va_live_tracker", { title: "VA Live Tracker", projectId, clientId }) + let clientId = null; + try { + const clientRes = await ProjectModel.findById(projectId); + if (clientRes) { + clientId = clientRes.clientId.toString(); + } + } catch (err) { + console.error("Error fetching client for project:", err.message); + return; + } + + if (!clientId) return res.status(400).send({ "message": "Page not found" }); + + res.render("va_live_tracker", { title: "VA Live Tracker", projectId, vaId, clientId }) }) // Handling Socket @@ -242,7 +284,7 @@ io.on("connection", (socket) => { console.log("User connected:", socket.id); // Register role and ID (client or VA) - socket.on("register", async ({ role, id }) => { + socket.on("register", async ({ role, id, projectId = null, clientId = null }) => { if (role === "va") { socket.data.role = "va"; socket.data.vaId = id; @@ -251,10 +293,19 @@ io.on("connection", (socket) => { if (role === "client") { socket.data.role = "client"; - socket.data.clientId = id; + socket.data.vaId = id; + socket.data.projectId = projectId; + socket.data.clientId = null + + if (!projectId || !clientId) { + console.log("projectId is missing in register payload"); + return; + } + + socket.data.clientId = clientId; // 🧩 Get allowed VAs for this client - const client = await ClientModel.findById(id) + const client = await ClientModel.findById(clientId) .populate("projectIds") // to access their projects .populate("vaIds"); // optional if you track directly @@ -370,8 +421,6 @@ app.get("/client/forgot-password", (req, res) => { }) // Handling Socket -import jwt from "jsonwebtoken"; - io.use(async (socket, next) => { try { const token = socket.handshake.auth?.token; @@ -415,7 +464,7 @@ io.use(async (socket, next) => { console.log(a, b, c, "vaProjClientId vs clientData.clientId"); - vaSocketRespectToClient.set(vaProjClientId.toString(), socket.id) + vaSocketRespectToClient.set(`${vaProjClientId.toString()}-${vaUser._id.toString()}`, socket.id) console.log("✅ Authenticated VA:", vaUser.userDetails.email); return next(); @@ -523,10 +572,10 @@ io.on("connection", (socket) => { socket.on("selectApp", ({ appTitle, clientId }) => { console.log(`VA selected app: ${appTitle}`); - const sssrrrr = vaSocketRespectToClient.get(clientId); - console.log(vaSocketRespectToClient.get(clientId), sssrrrr, "vaSocketRespectToClient[clientId]") + const sssrrrr = vaSocketRespectToClient.get(`${clientId}-${socket.data.vaId}`); + console.log(vaSocketRespectToClient.get(`${clientId}-${socket.data.vaId}`), sssrrrr, "vaSocketRespectToClient[clientId]") // You can forward this info to the respective Electron client - socket.to(vaSocketRespectToClient.get(clientId)).emit("appToCapture", { appTitle }); + socket.to(vaSocketRespectToClient.get(`${clientId}-${socket.data.vaId}`)).emit("appToCapture", { appTitle }); }); socket.on("getVisibleApps", async ({ token, apps }) => { @@ -596,6 +645,13 @@ io.on("connection", (socket) => { // console.log(`Express started on http://localhost:${PORT}`); // }); + +app.use((req, res) => { + res.status(404).render("not_found", { + title: "404 - Page Not Found" + }); +}); + server.listen(PORT, () => { mongoose .connect( diff --git a/views/download_tracker.ejs b/views/download_tracker.ejs new file mode 100644 index 0000000..a10ef66 --- /dev/null +++ b/views/download_tracker.ejs @@ -0,0 +1,180 @@ + + + + + + + Download DocTracker + + + + + +
+

Download DocTracker

+ +

+ Let your clients see your real-time work logs, ensuring
+ you get paid accurately for every minute you've put in. +

+ +
+
+ windows + Windows +
+
+ macos + MacOS +
+
+ +
+ + +
+
+ + + + + + \ No newline at end of file diff --git a/views/not_found.ejs b/views/not_found.ejs new file mode 100644 index 0000000..e0a32cf --- /dev/null +++ b/views/not_found.ejs @@ -0,0 +1,129 @@ + + + + + + + 404 - Page Not Found + + + + + + +
+ 404 Icon +

404

+

Oops! The page you're looking for does not exist.

+ Go Home +
+ + + + + + + \ No newline at end of file diff --git a/views/va_live_tracker.ejs b/views/va_live_tracker.ejs index cb9006a..52c7473 100644 --- a/views/va_live_tracker.ejs +++ b/views/va_live_tracker.ejs @@ -3,144 +3,282 @@ - Live Screen Feed - -