Qualified dashboards promote the next unqualified position in their leg
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 <noreply@anthropic.com>
This commit is contained in:
@@ -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);
|
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 = []; }
|
} catch (e) { out.income = []; }
|
||||||
out.subtree = getSubtree(id, 99); // full leg — the dashboard drills down client-side
|
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 chain = [];
|
||||||
const seen = new Set([id]);
|
const seen = new Set([id]);
|
||||||
let cur = m.uplineId;
|
let cur = m.uplineId;
|
||||||
|
|||||||
+10
-1
@@ -91,7 +91,16 @@
|
|||||||
if(!el)return;
|
if(!el)return;
|
||||||
const dashUrl=`https://rmcircle.saasy.top/my/${d.id}`;
|
const dashUrl=`https://rmcircle.saasy.top/my/${d.id}`;
|
||||||
if(d.directCount>=2){
|
if(d.directCount>=2){
|
||||||
el.innerHTML=`<p style="color:var(--muted);font-size:14px;line-height:1.6;margin:6px 0 14px"><span class="q-badge q-yes" style="margin-right:6px">★ Qualified</span> 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.</p><div style="display:flex;gap:16px;align-items:center;flex-wrap:wrap"><img src="/qr-start.svg" alt="Team QR code" class="qr-img"><div><a class="btn btn-primary" href="/start">Open the Team Sponsor Page →</a><p class="micro" style="margin:10px 0 0">This QR sends prospects to the team rotation — show it or print it.</p></div></div>`;
|
const nx=d.nextInLine;
|
||||||
|
if(nx){
|
||||||
|
const nxDash=`https://rmcircle.saasy.top/my/${nx.id}`;
|
||||||
|
el.innerHTML=`<p style="color:var(--muted);font-size:14px;line-height:1.6;margin:6px 0 14px"><span class="q-badge q-yes" style="margin-right:6px">★ Qualified</span> Your link is retired — now the effort moves down. <strong style="color:var(--text)">Next in line: #${nx.id}</strong> (${nx.directCount}/2 directs). Help them get their 2 — share their page or send prospects the join button, which carries <strong style="color:var(--gold)">#${nx.id}</strong> as sponsor.</p><div style="display:flex;gap:16px;align-items:center;flex-wrap:wrap"><span id="dQr" class="qr-img"></span><div style="min-width:220px"><div style="display:flex;gap:8px;flex-wrap:wrap"><button id="copyShare" class="btn btn-secondary btn-sm">Copy #${nx.id}'s page link</button><a class="btn btn-primary btn-sm" href="${esc(nx.referralUrl||'#')}" target="_blank" rel="noopener noreferrer">Join under #${nx.id} →</a></div><p class="micro" style="margin:10px 0 0;word-break:break-all">${esc(nxDash)}</p><p class="micro" style="margin:6px 0 0">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 <a href="/start" style="color:var(--teal)">team rotation</a>.</p></div></div>`;
|
||||||
|
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=`<p style="color:var(--muted);font-size:14px;line-height:1.6;margin:6px 0 14px"><span class="q-badge q-yes" style="margin-right:6px">★ Qualified</span> 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.</p><div style="display:flex;gap:16px;align-items:center;flex-wrap:wrap"><img src="/qr-start.svg" alt="Team QR code" class="qr-img"><div><a class="btn btn-primary" href="/start">Open the Team Sponsor Page →</a><p class="micro" style="margin:10px 0 0">This QR sends prospects to the team rotation — show it or print it.</p></div></div>`;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const need=2-d.directCount;
|
const need=2-d.directCount;
|
||||||
|
|||||||
@@ -267,6 +267,7 @@ async function handleApi(req,res,pathname){
|
|||||||
try{
|
try{
|
||||||
const r=await Promise.race([chain.memberPublic(id),new Promise((_,rej)=>setTimeout(()=>rej(new Error('Blockchain lookup timed out — try again.')),20000))]);
|
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.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()});
|
memberCache.set(id,{data:r,ts:Date.now()});
|
||||||
if(memberCache.size>500)memberCache.delete(memberCache.keys().next().value);
|
if(memberCache.size>500)memberCache.delete(memberCache.keys().next().value);
|
||||||
return json(res,200,r,{'Cache-Control':'public, max-age=60'});
|
return json(res,200,r,{'Cache-Control':'public, max-age=60'});
|
||||||
|
|||||||
Reference in New Issue
Block a user