Dashboard: show what an upgrade buys, not just what it costs

The upgrade panel showed a price, a funded badge and a button. Nothing on it
said what the member would get. 53 of 87 qualified members in the org are
parked at Ascensus, and a panel that reads as a bill is part of why.

It now leads with what the rung unlocks, in the member's own numbers: the
generation it extends reach to, how many people they already have sitting
there, and what each of those pays when they climb. genCounts already existed
in getOrgShare; this just points it at the member instead of at the admin.

The line that matters most is arithmetic, not persuasion: because every rung
costs exactly twice the last, the first catch at the new level is exactly
double what the upgrade cost. That is Lesson 8's whole argument, and the
panel now makes it where the decision is actually taken rather than leaving
it in a lesson nobody opens at the right moment.

Wrapped in try/catch — if the org walk fails the panel renders as before.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-08-31 05:18:10 -05:00
parent c86a583488
commit 25eddf19c4
2 changed files with 32 additions and 0 deletions
+19
View File
@@ -192,8 +192,27 @@
const ns=d.nextStep||{};
if(ns.kind!=='upgrade'||d.directCount<2){el.innerHTML='';return;}
const name=LEVELS[ns.nextLevel-1]||('Level '+ns.nextLevel);
// What this rung buys, in their own numbers. A price with no reason attached
// is just a bill — this is the reason.
const op=ns.opens||{};
let why='';
if(op.perCatch>0){
const gname=LEVELS[op.gen]||('Level '+(op.gen+1));
const have=(op.genSize!=null&&op.genSize>0)
? `You already have <strong style="color:var(--text)">${op.genSize} ${op.genSize===1?'person':'people'}</strong> there.`
: `That generation is still filling.`;
why=`<div style="background:rgba(78,214,203,.07);border:1px solid rgba(78,214,203,.25);border-radius:12px;padding:13px 15px;margin:0 0 12px;font-size:13.5px;line-height:1.6">
<strong style="color:var(--teal)">What this unlocks:</strong> ${esc(name)} extends your reach to
<strong style="color:var(--text)">generation ${op.gen}</strong>. ${have}
Each of them pays you <strong style="color:var(--gold)">${fmt(op.perCatch)} POL</strong> when they buy ${esc(gname)}.
<div style="margin-top:7px;color:var(--muted)">Your first catch at this level is <strong style="color:var(--text)">${fmt(op.perCatch)} POL</strong> —
exactly <strong style="color:var(--text)">double</strong> what this upgrade costs, because every rung is twice the last.
That is the whole idea behind <a href="/training#lesson-8" style="color:var(--teal)">Lesson 8 — time your upgrades to your catches</a>.</div>
</div>`;
}
el.innerHTML=`<div class="table-card" style="margin:0 0 18px;border-color:rgba(240,197,109,.45)">
<h2 style="margin:0 0 4px">⬆️ Upgrade to ${esc(name)} — right from this page</h2>
${why}
<p style="color:var(--muted);font-size:13px;margin:0 0 12px">Exact cost <strong>${fmt(ns.cost)} POL</strong>, read live from the contract. Connect the wallet that owns position #${d.id}, confirm once, done. ${ns.funded?'<strong style="color:var(--ok)">Your wallet already covers it ✓</strong>':'Your wallet does not cover it yet — you can time it to your next catches, or top up below.'}</p>
<button id="upgGo" class="btn btn-primary">Connect &amp; upgrade to ${esc(name)} →</button>
${ns.funded?'':`<button id="upgFund" class="btn btn-secondary" style="margin-left:8px">💳 Buy POL with card</button>`}