(function(){
const esc=s=>String(s??'').replace(/[&<>'"]/g,c=>({'&':'&','<':'<','>':'>',"'":''','"':'"'}[c]));
const fmt=n=>Number(n||0).toLocaleString(undefined,{maximumFractionDigits:2});
const date=ts=>ts?new Date(ts*1000).toLocaleDateString(undefined,{year:'numeric',month:'short',day:'numeric'}):'—';
const prompt=document.getElementById('idPrompt'),dash=document.getElementById('dash');
function pathId(){const m=location.pathname.match(/^\/my\/(\d+)$/);if(m)return m[1];const q=new URLSearchParams(location.search).get('id');if(q&&/^\d+$/.test(q))return q;try{return localStorage.getItem('ctb.myId')||''}catch(e){return ''}}
function card(n,focus){
if(!n)return '
open
slot
';
const badge=n.tier===2?'P':'S';
const down=n.downCount?`⬇ ${n.downCount} below · ${fmt(n.downPol)} POL`:'no downline yet';
return `${badge} #${n.id}${esc(n.levelName)}${n.directCount}/2 · ${fmt(n.earnedPol)} POL${down}
`;
}
function renderTree(root){
if(!root){document.getElementById('dTree').innerHTML='Team view is still indexing — check back in a few minutes.
';return}
const rows=[[root]];
for(let g=1;g<4;g++)rows.push(rows[g-1].flatMap(n=>n?[n.left||null,n.right||null]:[null,null]));
if(!rows[3].some(Boolean))rows.pop();
document.getElementById('dTree').innerHTML=`${rows.map((r,i)=>`
${r.map(n=>card(n,i===0&&n&&true)).join('')}
`).join('')}
`;
}
function render(d){
prompt.classList.add('hidden');dash.classList.remove('hidden');
document.getElementById('dTitle').textContent='#'+d.id;
document.getElementById('dFacts').innerHTML=
`Tier${esc(d.tierName)}
`+
`Level${esc(d.levelName)}
`+
`Directs${d.directCount}/2${d.directCount>=2?' ✓ qualified':''}
`+
`Total received${fmt(d.totalEarnedPol)} POL
`+
`Team below you${d.subtree?`${d.subtree.downCount} member${d.subtree.downCount===1?'':'s'}`:'—'}
`+
`Member since${date(d.joinedAt)}
`;
renderTree(d.subtree);
const inc=d.income||[];
document.getElementById('dIncome').innerHTML=inc.length
?`| When | From member | For | Amount |
${inc.map(p=>`| ${date(p.ts)} | #${p.fromId} | ${esc(p.desc)} | ${fmt(p.pol)} POL |
`).join('')}
`
:'No payments yet — they appear here the moment they land on-chain.
';
document.getElementById('dLineage').innerHTML=d.uplineChain&&d.uplineChain.length
?`#${d.id} → ${d.uplineChain.map(i=>'#'+i).join(' → ')} (root)`
:'You are at the top of your line.';
}
async function load(id){
try{
const r=await fetch('/api/public/member?id='+id);
const d=await r.json();
if(!r.ok)throw new Error(d.error||'Lookup failed');
if(!d.registered)throw new Error(`ID ${id} isn't registered on the smart contract — double-check the number.`);
try{localStorage.setItem('ctb.myId',String(id))}catch(e){}
if(!/^\/my\/\d+$/.test(location.pathname))history.replaceState(null,'','/my/'+id);
render(d);
}catch(x){
prompt.classList.remove('hidden');dash.classList.add('hidden');
document.getElementById('idError').textContent=x.message;
}
}
document.getElementById('idForm').addEventListener('submit',e=>{
e.preventDefault();
const v=document.getElementById('memberId').value.trim();
if(!/^\d{1,15}$/.test(v)){document.getElementById('idError').textContent='Numbers only — the ID from the RM Circle dApp.';return}
load(v);
});
document.getElementById('switchId').addEventListener('click',()=>{
try{localStorage.removeItem('ctb.myId')}catch(e){}
history.replaceState(null,'','/my');
dash.classList.add('hidden');prompt.classList.remove('hidden');
document.getElementById('memberId').value='';
});
const id=pathId();
if(id)load(id);
})();