143 lines
4.2 KiB
JavaScript
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);
|