va-tracker-middleware/public/js/pages/dashboard.js

143 lines
4.2 KiB
JavaScript

const API_BASE = "/api/v1/client";
/* ------------------ Utils ------------------ */
function formatTime(seconds) {
if (!seconds) return "No Record";
const h = Math.floor(seconds / 3600);
const m = Math.floor((seconds % 3600) / 60);
return h ? `${h}h ${m}m` : `${m}m`;
}
/* ------------------ DOM Elements ------------------ */
const vaModal = document.getElementById("vaModal");
const modalVAName = document.getElementById("modalVAName");
const modalProjectsTableBody = document.getElementById("modalProjectsTableBody");
const modalNoProjects = document.getElementById("modalNoProjects");
const vaTableBody = document.getElementById("vaTableBody");
const vaEmptyState = document.getElementById("vaEmptyState");
/* ------------------ Modal Controls ------------------ */
function openVAModal(va) {
modalVAName.textContent = va.name || "VA Details";
const projects = va.projects || [];
if (projects.length === 0) {
modalProjectsTableBody.innerHTML = "";
modalNoProjects.style.display = "block";
} else {
modalNoProjects.style.display = "none";
modalProjectsTableBody.innerHTML = projects
.map(createProjectRow)
.join("");
}
vaModal.style.display = "flex";
document.body.style.overflow = "hidden";
}
function closeVAModal() {
vaModal.style.display = "none";
document.body.style.overflow = "auto";
}
/* Outside click close */
vaModal.addEventListener("click", (e) => {
if (e.target === vaModal) closeVAModal();
});
/* ESC key close */
document.addEventListener("keydown", (e) => {
if (e.key === "Escape") closeVAModal();
});
/* ------------------ Table Builders ------------------ */
function createProjectRow(project) {
return `
<tr>
<td>${project.name}</td>
<td>$${project.hourlyRate}/hr</td>
<td>${project.totalWorkedTime}</td>
<td>${project.isCurrentlyWorking ? "Working" : "Inactive"}</td>
</tr>
`;
}
function createVATableRow(va, index) {
return `
<tr class="va-row" data-index="${index}">
<td>
<span class="status ${va.isCurrentlyActive ? "active" : "inactive"}">
${va.isCurrentlyActive ? "Active" : "Inactive"}
</span>
</td>
<td>${va.name}</td>
<td>${va.lastProject?.name || "-"}</td>
<td>${va.projectsAssigned || 0}</td>
<td>${va.currentSessionDuration || "No Record Found"}</td>
<td>
${
va.isCurrentlyActive
? `<a href="/live/${va.lastProjectId}/${va.id}" target="_blank">Live</a>`
: "-"
}
</td>
</tr>
`;
}
setInterval(loadDashboardData, 30000);
/* ------------------ Load Dashboard ------------------ */
async function loadDashboardData() {
const res = await fetchWithAuth(`${API_BASE}/dashboard`);
if (!res) return;
const result = await res.json();
if (!result.success) return;
const { summary, data } = result;
document.getElementById("activeVaCount").textContent = summary.activeVAs;
document.getElementById("totalVaCount").textContent = summary.totalVAs;
document.getElementById("totalProjects").textContent = summary.totalProjects;
document.getElementById("vaListCount").textContent = `${summary.totalVAs} VAs`;
const allVAs = data.allVAs || [];
if (allVAs.length === 0) {
vaTableBody.innerHTML = "";
vaEmptyState.style.display = "block";
return;
}
vaEmptyState.style.display = "none";
/* store globally for modal */
window.allVAs = allVAs;
vaTableBody.innerHTML = allVAs
.map((va, index) => createVATableRow(va, index))
.join("");
/* Row click handlers */
document.querySelectorAll(".va-row").forEach(row => {
row.addEventListener("click", (e) => {
if (e.target.tagName === "A") return; // ignore Live click
const index = row.dataset.index;
openVAModal(window.allVAs[index]);
});
});
}
/* ------------------ Init ------------------ */
document.addEventListener("DOMContentLoaded", loadDashboardData);