Teach spillover in the matrix views
Tree nodes now carry referrerId, so positions placed by spillover (their referrer differs from their matrix parent) get a teal "spillover · ref #N" tag on cards in both the member dashboard and admin matrix, plus a legend entry. When a member is unqualified but has spillover positions under them — the classic "why do I have 2 under me but no checkmark?" state — a callout explains that spillover grows the matrix but only members joining with their own ID count toward 2/2, and points them at their share link. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+15
-2
@@ -8,12 +8,14 @@
|
||||
|
||||
const treeUI={byId:{},parent:{},homeId:0,rootId:0,mode:'pyramid'};
|
||||
function indexTree(n,par){if(!n)return;treeUI.byId[n.id]=n;if(par)treeUI.parent[n.id]=par.id;indexTree(n.left,n);indexTree(n.right,n)}
|
||||
function isSpill(n){return !!(n&&treeUI.parent[n.id]&&n.referrerId&&n.referrerId!==treeUI.parent[n.id])}
|
||||
function card(n,focus){
|
||||
if(!n)return '<div class="mtp-card mtp-open">open<br>slot</div>';
|
||||
const badge=n.tier===2?'<span class="mt-badge mt-prem">P</span>':'<span class="mt-badge">S</span>';
|
||||
const qmark=n.directCount>=2?'<span class="mtp-qmark" title="Qualified — 2/2 directs">✓</span>':'';
|
||||
const spill=isSpill(n)?`<span class="mtp-spill" title="Placed here by spillover — referred by #${n.referrerId}">↧ spillover · ref #${n.referrerId}</span>`:'';
|
||||
const down=n.downCount?`<span class="mtp-down">⬇ ${n.downCount} below · ${fmt(n.downPol)} POL</span>`:'<span class="mtp-down mtp-down-none">no downline yet</span>';
|
||||
return `<button class="mtp-card${focus?' mtp-focus':''}" data-tid="${n.id}">${qmark}${badge} <span class="mt-id">#${n.id}</span><span class="mtp-lvl">${esc(n.levelName)}</span><span class="mtp-sub">${n.directCount}/2 · ${fmt(n.earnedPol)} POL</span>${down}</button>`;
|
||||
return `<button class="mtp-card${focus?' mtp-focus':''}" data-tid="${n.id}">${qmark}${badge} <span class="mt-id">#${n.id}</span><span class="mtp-lvl">${esc(n.levelName)}</span><span class="mtp-sub">${n.directCount}/2 · ${fmt(n.earnedPol)} POL</span>${spill}${down}</button>`;
|
||||
}
|
||||
function renderPyramid(){
|
||||
const out=document.getElementById('dTree'),nav=document.getElementById('dTreeNav');
|
||||
@@ -39,7 +41,7 @@
|
||||
const ch=[n.left,n.right].filter(Boolean);
|
||||
const qmark=n.directCount>=2?'<span class="mtp-qmark" style="position:static;display:inline-grid;width:16px;height:16px;font-size:10px;vertical-align:middle">✓</span> ':'';
|
||||
const badge=n.tier===2?'<span class="mt-badge mt-prem">P</span>':'<span class="mt-badge">S</span>';
|
||||
const label=`${qmark}${badge} <span class="mt-id">#${n.id}</span> <span class="mt-meta">${esc(n.levelName)} · ${n.directCount}/2 directs · ${fmt(n.earnedPol)} POL${n.downCount?` · ⬇ ${n.downCount} below (${fmt(n.downPol)} POL)`:''}</span>`;
|
||||
const label=`${qmark}${badge} <span class="mt-id">#${n.id}</span> <span class="mt-meta">${esc(n.levelName)} · ${n.directCount}/2 directs · ${fmt(n.earnedPol)} POL${n.downCount?` · ⬇ ${n.downCount} below (${fmt(n.downPol)} POL)`:''}${isSpill(n)?` · <span style="color:var(--teal)">↧ spillover (ref #${n.referrerId})</span>`:''}</span>`;
|
||||
const kids=ch.length?`<ul class="mt-kids">${ch.map(c=>node(c,depth+1)).join('')}</ul>`:'';
|
||||
return ch.length?`<li class="mt-node"><details${depth<3?' open':''}><summary>${label}</summary>${kids}</details></li>`:`<li class="mt-node mt-leaf">${label}</li>`;
|
||||
};
|
||||
@@ -71,6 +73,17 @@
|
||||
treeUI.byId={};treeUI.parent={};treeUI.homeId=d.id;treeUI.rootId=d.id;
|
||||
indexTree(d.subtree,null);
|
||||
renderTree();
|
||||
// spillover explainer — shown exactly when the confusing state exists:
|
||||
// positions sitting under you while you're not yet qualified
|
||||
const note=document.getElementById('dSpillNote');
|
||||
if(note){
|
||||
const kids=d.subtree?[d.subtree.left,d.subtree.right].filter(Boolean):[];
|
||||
const spills=kids.filter(k=>k.referrerId&&k.referrerId!==d.id).length;
|
||||
if(d.directCount<2&&kids.length&&spills){
|
||||
note.innerHTML=`<div class="callout" style="margin-top:14px"><strong>Why am I not qualified when people sit under me?</strong> ${spills===kids.length?'The positions':'Some positions'} under you arrived by <strong>spillover</strong> — when your upline recruits, the contract fills the next open slot downward, which can land members in your matrix. Spillover grows your team and your future level payments, but qualification only counts your <strong>directs</strong> — people who join using <em>your</em> ID. You have ${d.directCount}/2 directs; share your link above to get ${2-d.directCount===1?'your last one':'your 2'}.</div>`;
|
||||
note.classList.remove('hidden');
|
||||
}else{note.classList.add('hidden');note.innerHTML='';}
|
||||
}
|
||||
const inc=d.income||[];
|
||||
document.getElementById('dIncome').innerHTML=inc.length
|
||||
?`<div class="table-wrap"><table class="table" style="min-width:520px"><thead><tr><th>When</th><th>From member</th><th>For</th><th>Amount</th></tr></thead><tbody>${inc.map(p=>`<tr><td>${date(p.ts)}</td><td>#${p.fromId}</td><td>${esc(p.desc)}</td><td><strong>${fmt(p.pol)} POL</strong></td></tr>`).join('')}</tbody></table></div>`
|
||||
|
||||
Reference in New Issue
Block a user