Files

63 lines
4.5 KiB
JavaScript

(() => {
'use strict';
const root = document.getElementById('stats-studio');
if (!root) return;
const status = document.getElementById('studio-status');
const data = document.getElementById('stats-data');
if (!data || typeof Chart === 'undefined') return;
const chartData = JSON.parse(data.textContent);
const clear = document.getElementById('clear-selection');
const tbody = document.getElementById('evidence-body');
let selectionScope = 'trend';
const original = [...tbody.children].map(row => row.cloneNode(true));
const pagination = root.querySelector('.studio-pagination');
const period = document.getElementById('evidence-period');
const originalPagination = [...pagination.children].map(node => node.cloneNode(true));
let pending = null;
clear.onclick = () => { pending?.abort(); period.value = ''; tbody.replaceChildren(...original.map(row => row.cloneNode(true))); pagination.replaceChildren(...originalPagination.map(node => node.cloneNode(true))); clear.hidden = true; document.getElementById('evidence-heading').textContent = `Contributing ${root.dataset.source}`; status.textContent = ''; };
period.onchange = () => { if (period.value) loadBucket(period.value,1,selectionScope); else clear.click(); };
async function loadBucket(bucket, page = 1, scope = 'trend') {
selectionScope=scope;
pending?.abort();
const controller = new AbortController(); pending = controller;
const url = new URL('/stats/runs', location.origin);
url.search = new URLSearchParams({query:root.dataset.query,bucket,page,scope});
status.textContent = 'Loading contributing runs…';
try {
const response = await fetch(url, {signal:controller.signal});
if (!response.ok) throw new Error();
const result = await response.json();
tbody.replaceChildren();
result.rows.forEach(row => {
const tr = document.createElement('tr'); const td = document.createElement('td');
const a = document.createElement(row.id?'a':'span'); if(row.id)a.href = `/activities/${row.id}`; a.textContent = `${row.title} · ${row.date}`;
td.append(a); tr.append(td);
(row.activity_ids||[]).forEach(id=>{const link=document.createElement('a');link.href=`/activities/${id}`;link.textContent=` · Run #${id}`;td.append(link);});
if (root.dataset.showPrevious === 'true') {
const detail=document.createElement('small');detail.className='previous-run';
detail.append('Previous: ');
if(row.previous_run){const previous=document.createElement('a');previous.href=`/activities/${row.previous_run.id}`;previous.textContent=`${row.previous_run.date} · ${row.previous_run.title}`;detail.append(previous);}else detail.append('No earlier recorded run');
td.append(detail);
}
[`${row.distance} km`, ...row.values].forEach(text => { const cell = document.createElement('td'); cell.textContent = text; tr.append(cell); });
tbody.append(tr);
});
document.getElementById('evidence-heading').textContent = `${bucket} · ${result.count} ${root.dataset.source}`;
period.value = bucket;
pagination.replaceChildren();
const label = document.createElement('span'); label.textContent = `Page ${result.page} of ${result.pages} · selected period`; pagination.append(label);
[[result.page > 1, 'Previous', result.page - 1], [result.page < result.pages, 'Next', result.page + 1]].forEach(([show, name, target]) => {
if (!show) return; const button = document.createElement('button'); button.type = 'button'; button.className = 'button secondary'; button.textContent = name; button.onclick = () => loadBucket(bucket, target, scope); pagination.append(button);
});
clear.hidden = false; status.textContent = 'Selected period loaded.';
} catch (error) { if (error.name !== 'AbortError') status.textContent = 'Could not load this period. Try again.'; }
}
root.querySelectorAll('[data-bucket]').forEach(button=>button.onclick=()=>loadBucket(button.dataset.bucket,1,'group'));
const plots=document.getElementById('analysis-plots');
if(plots)StrideCharts.render(plots,chartData,bucket=>loadBucket(bucket));
const insightPanel=document.getElementById('analysis-insights');
if(insightPanel)StrideCharts.insights(insightPanel,JSON.parse(document.getElementById('insights-data').textContent),bucket=>loadBucket(bucket,1,'group'));
const initialBucket=new URL(location.href).searchParams.get('bucket');
if(initialBucket)loadBucket(initialBucket,1,new URL(location.href).searchParams.get('scope')||'trend');
})();