Your organization rooted at #${d.rootId} is ${d.orgMembers} of ${d.totalMembers} members in the whole contract (${d.orgBelow} below you + your position), and has earned ${fmt(d.orgPol)} of ${fmt(d.totalPol)} POL ever paid.
`+
+ `
Your org members${d.orgMembers}
Whole network${d.totalMembers}
Your org earned${fmt(d.orgPol)} POL
Network paid${fmt(d.totalPol)} POL
`;
+ }catch(x){out.innerHTML=`
${esc(x.message)}
`}
+}
+document.getElementById('orgShareForm').addEventListener('submit',e=>{e.preventDefault();loadOrgShare()});
let incomeAutoLoaded=false;
async function loadIncome(){
const ids=(document.getElementById('incomeIds').value||'').trim();
diff --git a/server.js b/server.js
index a6a406f..d92d3b5 100644
--- a/server.js
+++ b/server.js
@@ -419,6 +419,12 @@ async function handleApi(req,res,pathname){
if(req.method==='GET'&&pathname==='/api/admin/matrix-tree'){
return json(res,200,chain.getMatrixTree());
}
+ if(req.method==='GET'&&pathname==='/api/admin/org-share'){
+ const raw=new URL(req.url,'http://x').searchParams.get('root');
+ const root=Number(raw||parseOwnerIds()[0]||21);
+ if(!Number.isInteger(root)||root<1||root>281474976710655)return json(res,400,{error:'Enter a numeric root ID.'});
+ return json(res,200,chain.getOrgShare(root));
+ }
if(req.method==='GET'&&pathname==='/api/admin/income'){
const raw=new URL(req.url,'http://x').searchParams.get('ids')||'';
const ids=[...new Set(raw.split(',').map(s=>parseInt(String(s).trim(),10)).filter(n=>Number.isInteger(n)&&n>0&&n<=281474976710655))].slice(0,12);
@@ -470,7 +476,7 @@ async function handleApi(req,res,pathname){
const maxOrder=sponsors.reduce((m,s)=>Math.max(m,s.sortOrder||0),0);sponsors.push({id:String(id).trim(),name:String(name).trim(),parentId:String(parentId||'').trim(),directs:0,level,status:sponsors.some(s=>s.status==='active')?'waiting':'active',sortOrder:maxOrder+10,clicks:0,notes:String(notes||'').trim(),email:String(email||'').trim().slice(0,120)});sponsors=normalizeStatuses(sponsors);saveSponsors(sponsors);return json(res,201,{sponsors});
}
if(req.method==='PATCH'&&pathname==='/api/admin/config'){
- const b=await bodyJson(req),cur=getConfig(),next={...cur};for(const k of ['siteName','programName','bridgeHeadline','bridgeSubheadline','premiumEntryPol','dappReferralBaseUrl','telegramUrl','supportLabel','showSponsorName','showQueueProgress','bemobPostbackUrl','telegramBotToken','telegramChatId','telegramTopicId','teamRootId','emailFrom','teamAlertEmail','ownerIds','ownerAlertEmail'])if(Object.prototype.hasOwnProperty.call(b,k))next[k]=b[k];next.premiumEntryPol=Number(next.premiumEntryPol)||362;next.updatedAt=new Date().toISOString();writeJson(CONFIG_FILE,next);return json(res,200,{config:next});
+ const b=await bodyJson(req),cur=getConfig(),next={...cur};for(const k of ['siteName','programName','bridgeHeadline','bridgeSubheadline','premiumEntryPol','dappReferralBaseUrl','telegramUrl','supportLabel','showSponsorName','showQueueProgress','bemobPostbackUrl','telegramBotToken','telegramChatId','telegramTopicId','teamRootId','emailFrom','teamAlertEmail','ownerIds','ownerAlertEmail','orgRootId'])if(Object.prototype.hasOwnProperty.call(b,k))next[k]=b[k];next.premiumEntryPol=Number(next.premiumEntryPol)||362;next.updatedAt=new Date().toISOString();writeJson(CONFIG_FILE,next);return json(res,200,{config:next});
}
const m=pathname.match(/^\/api\/admin\/sponsors\/([^/]+)(?:\/(increment|activate|qualify|reset|move))?$/);
if(m){const id=decodeURIComponent(m[1]),action=m[2]||null;let sponsors=getSponsors(),idx=sponsors.findIndex(s=>s.id===id);if(idx<0)return json(res,404,{error:'Sponsor not found.'});