From 6a9cd96b8c5023f6229549ff5214e410cc0ec95d Mon Sep 17 00:00:00 2001 From: martbost Date: Thu, 13 Aug 2026 14:58:31 -0500 Subject: [PATCH] Qualified dashboards promote the next unqualified position in their leg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of only pointing at the team rotator, a qualified member's share card now runs the moving-link wave automatically: breadth-first, left-to-right, the first position below them with fewer than 2 directs becomes "next in line" — their QR, page link, and join CTA all carry that position's ID. When it qualifies, the card rotates to the next one. Falls back to the team rotator when the whole leg is qualified. Co-Authored-By: Claude Fable 5 --- chain.js | 11 +++++++++++ public/my.js | 11 ++++++++++- server.js | 1 + 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/chain.js b/chain.js index 38e9f39..86faafe 100644 --- a/chain.js +++ b/chain.js @@ -438,6 +438,17 @@ async function memberPublic(id) { out.income = inc.map(p => ({ fromId: p.fromId, pol: p.pol, ts: p.ts, desc: describeIncome(p.fromTier, p.level, p.pol) })).reverse().slice(0, 50); } catch (e) { out.income = []; } out.subtree = getSubtree(id, 99); // full leg — the dashboard drills down client-side + // moving-link automation: the first position below (breadth-first, left→right) + // that still needs directs is where a qualified member's effort goes next + if (out.subtree) { + const q = [out.subtree.left, out.subtree.right].filter(Boolean); + while (q.length) { + const n = q.shift(); + if ((n.directCount || 0) < 2) { out.nextInLine = { id: n.id, directCount: n.directCount || 0, levelName: n.levelName }; break; } + if (n.left) q.push(n.left); + if (n.right) q.push(n.right); + } + } const chain = []; const seen = new Set([id]); let cur = m.uplineId; diff --git a/public/my.js b/public/my.js index 8127bea..e787d03 100644 --- a/public/my.js +++ b/public/my.js @@ -91,7 +91,16 @@ if(!el)return; const dashUrl=`https://rmcircle.saasy.top/my/${d.id}`; if(d.directCount>=2){ - el.innerHTML=`

★ Qualified This position has its 2 directs, so its referral link is retired under the team strategy. Send new members through the team rotation — the current sponsor is always live on the start page.

Team QR code
Open the Team Sponsor Page →

This QR sends prospects to the team rotation — show it or print it.

`; + const nx=d.nextInLine; + if(nx){ + const nxDash=`https://rmcircle.saasy.top/my/${nx.id}`; + el.innerHTML=`

★ Qualified Your link is retired — now the effort moves down. Next in line: #${nx.id} (${nx.directCount}/2 directs). Help them get their 2 — share their page or send prospects the join button, which carries #${nx.id} as sponsor.

Join under #${nx.id} →

${esc(nxDash)}

When #${nx.id} reaches 2/2 this rotates to the next position in your leg — the qualification wave keeps moving down. General traffic can still go through the team rotation.

`; + const qr=document.getElementById('dQr');if(qr)qr.innerHTML=qrSvg(nxDash); + const cp=document.getElementById('copyShare'); + if(cp)cp.addEventListener('click',async()=>{try{await navigator.clipboard.writeText(nxDash);cp.textContent='Copied ✓';setTimeout(()=>cp.textContent=`Copy #${nx.id}'s page link`,1400)}catch(e){}}); + return; + } + el.innerHTML=`

★ Qualified This position has its 2 directs and everyone in your leg is qualified too — outstanding. Send new members through the team rotation — the current sponsor is always live on the start page.

Team QR code
Open the Team Sponsor Page →

This QR sends prospects to the team rotation — show it or print it.

`; return; } const need=2-d.directCount; diff --git a/server.js b/server.js index e14c0c3..38e7977 100644 --- a/server.js +++ b/server.js @@ -267,6 +267,7 @@ async function handleApi(req,res,pathname){ try{ const r=await Promise.race([chain.memberPublic(id),new Promise((_,rej)=>setTimeout(()=>rej(new Error('Blockchain lookup timed out — try again.')),20000))]); if(r.registered)r.referralUrl=`${getConfig().dappReferralBaseUrl}${encodeURIComponent(id)}`; + if(r.nextInLine)r.nextInLine.referralUrl=`${getConfig().dappReferralBaseUrl}${encodeURIComponent(r.nextInLine.id)}`; memberCache.set(id,{data:r,ts:Date.now()}); if(memberCache.size>500)memberCache.delete(memberCache.keys().next().value); return json(res,200,r,{'Cache-Control':'public, max-age=60'});