Badges count qualifying buyers across linked positions (never regress); line chips light on any of a member's positions; buyers tile notes linked-position buyers
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -1099,7 +1099,12 @@ const server = http.createServer(async (req, res) => {
|
||||
try {
|
||||
const mm = await chain.member(memberId);
|
||||
out.buyerCount = mm.buyerCount;
|
||||
const bal = await ads.balances((await myMemberIds(s)).ids, s.email);
|
||||
const mine = await myMemberIds(s);
|
||||
// linked positions are the member's own: their qualifying buyers count toward the account (Jim, 2026-09-14)
|
||||
out.buyerCountMain = mm.buyerCount; out.buyerCountPositions = 0;
|
||||
for (const id of mine.ids) if (id && id !== memberId) { try { out.buyerCountPositions += (await chain.member(id)).buyerCount || 0; } catch (e) {} }
|
||||
out.buyerCountAll = out.buyerCountMain + out.buyerCountPositions; // badges count every position; levels the contract pays #main on depend on buyerCount alone
|
||||
const bal = await ads.balances(mine.ids, s.email);
|
||||
out.credits = bal.total; out.creditedCredits = bal.credited; out.earnedCredits = bal.earned; out.inCampaigns = bal.inCampaigns; out.availableCredits = bal.available;
|
||||
} catch (e) { out.chainReadError = true; }
|
||||
let earned = 0n, n = 0;
|
||||
@@ -1114,12 +1119,13 @@ const server = http.createServer(async (req, res) => {
|
||||
// achievement milestones (same ladder as the Overview stepper) + one-time credit
|
||||
// bonuses — computed AFTER buyerCount is read from chain above (else always 0)
|
||||
{
|
||||
const bc = out.buyerCount || 0;
|
||||
const bc = out.buyerCountAll != null ? out.buyerCountAll : (out.buyerCount || 0);
|
||||
const reached = [];
|
||||
if (out.memberId) reached.push('payouts');
|
||||
if (bc >= 1) reached.push('firstBuyer');
|
||||
if (bc >= 2) reached.push('level2');
|
||||
if (bc >= 5) reached.push('level3');
|
||||
try { for (const k of await ads.milestonesOf(out.email)) if (!reached.includes(k)) reached.push(k); } catch (e) {} // a badge once earned stays earned
|
||||
out.milestonesReached = reached;
|
||||
if (out.email && reached.length) out.milestonesGranted = await ads.grantMilestones(out.email, reached);
|
||||
}
|
||||
@@ -1677,6 +1683,9 @@ const server = http.createServer(async (req, res) => {
|
||||
const label = a => a.username ? '@' + a.username : (a.memberId ? 'member #' + a.memberId : 'member');
|
||||
for (const a of [meAcct, ...levels.flatMap(L => L.members)].filter(Boolean)) { const n = label(a); if (a.username) byTok[String(a.username).toLowerCase()] = n; if (a.code) byTok[String(a.code).toLowerCase()] = n; if (a.memberId) byTok[String(a.memberId)] = n; }
|
||||
const sponsorOf = m => { const t = String(m.sponsorRef || '').toLowerCase(); if (!t) return null; if (meAcct && (t === String(meAcct.username || '').toLowerCase() || t === String(meAcct.code || '').toLowerCase() || t === String(meAcct.memberId || ''))) return 'you'; return byTok[t] || ('@' + t); };
|
||||
// a member's linked positions are theirs too: a qualifying buy from one of them lights their chip
|
||||
const posIds = {}; for (const m of levels.flatMap(L => L.members)) { try { posIds[m.email] = (await accounts.positions(m.email)).map(p => p.memberId).filter(Boolean); } catch (e) { posIds[m.email] = []; } }
|
||||
const idsOf = m => [m.memberId, ...(posIds[m.email] || [])].filter(Boolean);
|
||||
const out = levels.map(L => ({ level: L.level, members: L.members.map(m => ({
|
||||
memberId: m.memberId || 0,
|
||||
sponsor: sponsorOf(m),
|
||||
@@ -1684,8 +1693,8 @@ const server = http.createServer(async (req, res) => {
|
||||
ref: m.code || null, // opens the activity drop-down (Clinton's ask, 2026-09-14): any of the three levels
|
||||
email: L.level === 1 ? m.email : null, // directs only
|
||||
joined: m.created,
|
||||
qualified: !!(m.memberId && qualified.has(m.memberId)),
|
||||
earnedWei: (m.memberId && earnedBy[m.memberId]) || '0' })) }));
|
||||
qualified: idsOf(m).some(id => qualified.has(id)),
|
||||
earnedWei: idsOf(m).reduce((n, id) => n + BigInt(earnedBy[id] || '0'), 0n).toString() })) }));
|
||||
// the member's own linked positions sit on level 1 too, labelled as theirs
|
||||
if (own.length) {
|
||||
if (!out.find(L => L.level === 1)) out.unshift({ level: 1, members: [] });
|
||||
|
||||
Reference in New Issue
Block a user