const startDate = new Date(`${dv.current()["Start Date"]}`);
const endDate = new Date(`${dv.current()["End Date"]}`);
const MIN_SESSION_HOURS = 0.5; // 30 minutes
// Helper – render a number with at most 2 decimals
const fmt = n => parseFloat(n.toFixed(2)).toString();
// ──────────────────────────────────────────────────────────
// Fetch pages with the #clienthours tag in the right folder
let pages = dv
.pages('"100 CPD Record" and #clienthours')
.where(p => {
const fileDate = new Date(p.date);
const hrs = Number(p.hours) || 0;
return fileDate >= startDate && fileDate <= endDate && hrs >= MIN_SESSION_HOURS;
})
.sort(p => p.date, "asc");
// Debug info
dv.paragraph(`Total records fetched: ${pages.length}`);
if (pages.length === 0) {
dv.paragraph("No records found for the specified query.");
} else {
// ────────────── Aggregate by “medium” ──────────────
const groupedData = {};
let grandTotalHrs = 0;
pages.forEach(p => {
const medium = p.medium || "No medium";
if (!groupedData[medium]) {
groupedData[medium] = { medium, totalHours: 0 };
}
const hrs = p.hours || 0;
groupedData[medium].totalHours += hrs;
grandTotalHrs += hrs;
});
// ─────────────── Build table rows ────────────────
const tableData = Object.values(groupedData)
.map(g => {
const pct = fmt((g.totalHours / grandTotalHrs) * 100); // % of total
return [
`**${g.medium} Total**`,
`**${fmt(g.totalHours)}**`,
`**${pct}%**`
];
})
.sort((a, b) => a[0].localeCompare(b[0])); // alphabetical
// Grand‑total row
tableData.push([
"**Grand Total**",
`**${fmt(grandTotalHrs)}**`,
"**100%**"
]);
// Render
dv.table(["Medium", "Total Hours", "Percentage of Total"], tableData);
}