diff --git a/app/main.py b/app/main.py
index a8223fb..a12a3f4 100644
--- a/app/main.py
+++ b/app/main.py
@@ -292,7 +292,8 @@ PAGE_HTML = """
@@ -318,7 +319,7 @@ PAGE_HTML = """
Source |
Allowance |
Credits |
- Spend |
+ Spend (since reset) |
Remaining |
Reset |
Adjust |
@@ -376,7 +377,8 @@ async function load() {
const d = await r.json();
$('tot-members').textContent = d.totals.members;
$('tot-active').textContent = d.totals.active;
- $('tot-spend').textContent = fmt(d.totals.total_spend);
+ $('tot-spend-cycle').textContent = fmt(d.totals.total_spend);
+ $('tot-spend-all').textContent = fmt(d.totals.total_all_time_spend ?? d.totals.total_spend);
membersData = d.members || [];
if (currentView === 'members') renderMembers();
} catch (e) {
@@ -391,6 +393,7 @@ let currentView = 'members';
let memberSort = { key: 'email', dir: 1 };
let modelSort = { key: 'spend', dir: -1 };
let rangeDays = 0; // 0 = all time
+let spendMode = 'cycle'; // 'cycle' | 'all' — Spend column in Members view (cycle = since the member's own reset)
function arrowFor(key, sortState) {
if (sortState.key !== key) return '';
@@ -427,11 +430,21 @@ function setRange(days) {
}
function sortMembers(key) {
+ // Clicking the Spend header toggles the value shown (since-reset ↔ all-time)
+ // before sorting; other headers just sort.
+ if (key === 'spend') {
+ spendMode = spendMode === 'cycle' ? 'all' : 'cycle';
+ $('spend-mode-label').textContent = spendMode === 'cycle' ? 'since reset' : 'all-time';
+ }
memberSort = { key, dir: memberSort.key === key ? -memberSort.dir : 1 };
clearArrows('members', memberSort);
render();
}
+function memberSpend(m) {
+ return spendMode === 'all' ? (m.all_time_spend ?? m.spend ?? 0) : (m.spend ?? 0);
+}
+
function sortModels(key) {
modelSort = { key, dir: modelSort.key === key ? -modelSort.dir : -1 };
clearArrows('models', modelSort);
@@ -446,6 +459,7 @@ function render() {
function renderMembers() {
const rows = [...membersData].sort((a, b) => {
let va = a[memberSort.key], vb = b[memberSort.key];
+ if (memberSort.key === 'spend') { va = memberSpend(a); vb = memberSpend(b); }
if (memberSort.key === 'active' || memberSort.key === 'activated') { va = va ? 1 : 0; vb = vb ? 1 : 0; }
if (typeof va === 'string' || typeof vb === 'string') {
return String(va ?? '').localeCompare(String(vb ?? '')) * memberSort.dir;
@@ -472,7 +486,7 @@ function renderMembers() {
'' + src + ' | ' +
'' + fmt(m.balance) + ' | ' +
'' + creditsPill + ' | ' +
- '' + fmt(m.spend) + ' | ' +
+ '' + fmt(memberSpend(m)) + ' | ' +
'' + fmt(m.remaining) + ' | ' +
'' + esc(reset) + ' | ' +
'' +
|