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
+13
View File
@@ -590,6 +590,19 @@ async function handleApi(req,res,pathname){
let funded=null;
try{ if(r.account&&cost){ const bal=await chain.balanceOf(r.account); if(bal!=null) funded=bal>=cost; } }catch(e){}
r.nextStep={kind:'upgrade',nextLevel:lvl+1,cost,funded};
// What the upgrade actually BUYS. The panel used to show a price with no
// reason attached, which is how 53 qualified members read it and closed
// the tab. Owning level L catches generation L, so this rung opens the
// generation numbered nextLevel — and because upgrade costs double every
// rung, the first catch there is exactly twice what this rung costs.
try{
const opensGen=lvl+1;
const perCatch=(r.upgradeCosts&&r.upgradeCosts[tier]&&r.upgradeCosts[tier][lvl])||0;
const share=chain.getOrgShare(id);
const genSize=(share&&share.ready&&share.found&&Array.isArray(share.genCounts))
? (share.genCounts[opensGen-1]||0) : null;
r.nextStep.opens={gen:opensGen,perCatch,genSize};
}catch(e){}
}else{
r.nextStep={kind:'max'};
}