Leaderboard + referral contest: /leaderboard (week/month/all, read from chain, own positions excluded), Overview card with own rank, weekly and monthly winners recorded at rollover with credit ladders granted automatically and announced to Telegram
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -757,7 +757,7 @@
|
||||
}));
|
||||
|
||||
// site settings: key / value rows; booleans as checkboxes, numbers stay numbers
|
||||
const SITE_META = { siteName: 'Site name', tagline: 'Tagline', rehearsal: 'Testnet rehearsal banner', defaultSponsorId: 'Fallback sponsor (member #)', walletConnectProjectId: 'WalletConnect project id', moonpayPublicKey: 'MoonPay public key', telegramBotToken: 'Telegram proof feed: bot token', telegramChatId: 'Telegram proof feed: chat id', telegramTopicId: 'Telegram proof feed: topic id (optional)', telegramEvents: 'Telegram proof feed: events (payouts | payouts+purchases | all)', telegramCtaUrl: 'Telegram proof feed: join link under each post', telegramEchoChatId: 'Telegram echo (shared payments topic): chat id', telegramEchoTopicId: 'Telegram echo: topic id', telegramEchoEvents: 'Telegram echo: events (payouts | payouts+purchases | all)', legacyCreditsAdvertiser: 'Legacy welcome credits: former advertisers', legacyCreditsEarner: 'Legacy welcome credits: former earners', pnlFixedMonthlyUsd: 'P&L: fixed monthly cost (USD)' };
|
||||
const SITE_META = { siteName: 'Site name', tagline: 'Tagline', rehearsal: 'Testnet rehearsal banner', defaultSponsorId: 'Fallback sponsor (member #)', walletConnectProjectId: 'WalletConnect project id', moonpayPublicKey: 'MoonPay public key', telegramBotToken: 'Telegram proof feed: bot token', telegramChatId: 'Telegram proof feed: chat id', telegramTopicId: 'Telegram proof feed: topic id (optional)', telegramEvents: 'Telegram proof feed: events (payouts | payouts+purchases | all)', telegramCtaUrl: 'Telegram proof feed: join link under each post', leaderboardWeeklyPrize: 'Leaderboard: weekly prize text (optional; blank shows the credit ladder)', leaderboardMonthlyPrize: 'Leaderboard: monthly prize text (optional)', leaderboardWeeklyCredits: 'Leaderboard: weekly credits for 1st,2nd,3rd… (e.g. 1000,500,250; blank = none)', leaderboardMonthlyCredits: 'Leaderboard: monthly credits for 1st,2nd,3rd… (e.g. 5000,2500,1000)', leaderboardAnnounceGeneral: 'Leaderboard: announce winners in the main group too (1/0)', telegramEchoChatId: 'Telegram echo (shared payments topic): chat id', telegramEchoTopicId: 'Telegram echo: topic id', telegramEchoEvents: 'Telegram echo: events (payouts | payouts+purchases | all)', legacyCreditsAdvertiser: 'Legacy welcome credits: former advertisers', legacyCreditsEarner: 'Legacy welcome credits: former earners', pnlFixedMonthlyUsd: 'P&L: fixed monthly cost (USD)' };
|
||||
function drawSite() {
|
||||
const wrap = $('siteForm');
|
||||
wrap.innerHTML = Object.entries(siteObj).map(([k, v]) => '<div class="kv-row"><span class="k" title="' + esc(k) + '">' + esc(SITE_META[k] || humanize(k)) + '</span>'
|
||||
|
||||
@@ -53,7 +53,7 @@ window.IAP = (function () {
|
||||
f.style.cssText = 'border-top:1px solid var(--line);margin-top:48px;padding:26px 22px;text-align:center;color:var(--muted);font-size:13px';
|
||||
f.innerHTML = '<div>© ' + new Date().getFullYear() + ' InstantAdPay</div>'
|
||||
+ '<div style="margin-top:8px;display:flex;gap:16px;justify-content:center;flex-wrap:wrap">'
|
||||
+ '<a href="/">How it works</a><a href="/ledger">Live ledger</a><a href="/contract">The contract</a><a href="/blog">Blog</a><a href="/whats-new">What\'s new</a>'
|
||||
+ '<a href="/">How it works</a><a href="/ledger">Live ledger</a><a href="/contract">The contract</a><a href="/blog">Blog</a><a href="/leaderboard">Leaderboard</a><a href="/whats-new">What\'s new</a>'
|
||||
+ '<a href="/terms">Terms</a><a href="/privacy">Privacy</a><a href="/disclaimer">Disclaimer</a></div>';
|
||||
document.body.appendChild(f);
|
||||
}
|
||||
|
||||
+16
-1
@@ -363,6 +363,7 @@
|
||||
// site-wide activity (not about me): joins, tank, adoptions, purchases, payouts, qualifications
|
||||
if (ev.type === 'Joined') { communityToast('👋 ' + ev.name + ' just joined' + (ev.tank ? ' and is waiting for a sponsor in the holding tank' : '')); liveRefresh(); return; }
|
||||
if (ev.type === 'Adopted') { communityToast('🤝 ' + ev.sponsor + ' picked up ' + ev.member + ' from the holding tank'); liveRefresh(); return; }
|
||||
if (ev.type === 'Contest') { communityToast('🏆 ' + ev.winner + ' won the ' + (ev.kind === 'week' ? 'weekly' : 'monthly') + ' referral contest'); return; }
|
||||
if (ev.type === 'Badge') { communityToast('🏆 ' + ev.member + ' unlocked ' + ev.label); return; }
|
||||
if (ev.type === 'Released') { communityToast('🪣 ' + ev.sponsor + ' returned ' + ev.member + ' to the holding tank'); liveRefresh(); return; }
|
||||
const mine = MYID && (ev.recipientId === MYID || ev.toId === MYID || ev.sponsorId === MYID || ev.skippedId === MYID || ev.buyerId === MYID);
|
||||
@@ -457,9 +458,23 @@
|
||||
$('newsCard').addEventListener('click', () => { try { localStorage.setItem('iap.news.seen', r.latest || ''); } catch (e) {} $('newsList').querySelectorAll('span[style*="mint"]').forEach(s => { if (s.textContent === '●') s.remove(); }); }, { once: true });
|
||||
} catch (e) {}
|
||||
}
|
||||
// Leaderboard card: top 5 this week + your own rank + the prize (Marty, 2026-09-14)
|
||||
async function loadLeaderboard() {
|
||||
if (!$('lbCard')) return;
|
||||
try {
|
||||
const r = await (await fetch('/api/leaderboard?period=week')).json();
|
||||
const esc = t => String(t == null ? '' : t).replace(/[&<>"]/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"' }[c]));
|
||||
let h = r.prize ? '<p style="margin:0 0 8px"><b>Prize this week:</b> ' + esc(r.prize) + '</p>' : '';
|
||||
h += r.top.length ? '<table style="width:100%;border-collapse:collapse;font-variant-numeric:tabular-nums">' + r.top.slice(0, 5).map(x => '<tr><td style="padding:3px 0;width:26px;color:' + (x.rank === 1 ? '#ffd15c' : 'var(--muted)') + '">' + x.rank + '</td><td style="padding:3px 0"><b>' + esc(x.name) + '</b></td><td style="padding:3px 0;text-align:right">' + x.sales + ' sold · $' + x.usd + '</td></tr>').join('') + '</table>'
|
||||
: '<p class="muted" style="margin:0">No packages sold yet this week. First sale takes the top spot.</p>';
|
||||
h += r.me ? '<p style="margin:8px 0 0">You: <b>#' + r.me.rank + '</b> · ' + r.me.sales + ' sold · $' + r.me.usd + '</p>' : '<p class="muted" style="margin:8px 0 0">You: no sales yet this week. Sales are $20+ packages bought by people you sponsor.</p>';
|
||||
h += '<p style="margin:6px 0 0"><a href="/leaderboard" target="_blank" rel="noopener" style="color:var(--mint)">Full leaderboard: week, month, all time →</a></p>';
|
||||
$('lbList').innerHTML = h; $('lbCard').hidden = false;
|
||||
} catch (e) {}
|
||||
}
|
||||
async function loadDashboard() {
|
||||
try {
|
||||
loadNews();
|
||||
loadNews(); loadLeaderboard();
|
||||
const d = await (await fetch('/api/my/dashboard')).json();
|
||||
if (d.error) return;
|
||||
chatSync(d);
|
||||
|
||||
+3
-1
@@ -258,6 +258,8 @@
|
||||
</div>
|
||||
<div class="card"><h3>Earning levels</h3>
|
||||
<p id="qualLine" class="muted small">…</p></div>
|
||||
<div class="card" id="lbCard" hidden><div class="card-head"><h3>Leaderboard</h3><span class="sub"><a href="/leaderboard" target="_blank" rel="noopener" style="color:var(--mint);text-decoration:none">this week's contest</a></span></div>
|
||||
<div id="lbList" class="small"></div></div>
|
||||
<div class="card" id="newsCard" hidden><div class="card-head"><h3>What's new</h3><span class="sub"><a href="/whats-new" target="_blank" rel="noopener" style="color:var(--mint);text-decoration:none">release notes and roadmap</a></span></div>
|
||||
<div id="newsList" class="small"></div></div>
|
||||
<div class="card" id="promoCard"><h3>Have a promo code?</h3>
|
||||
@@ -917,7 +919,7 @@
|
||||
<script src="/assets/common.js?v=20260913a"></script>
|
||||
<script src="/assets/wallet.js?v=20260911a"></script>
|
||||
<script src="/assets/promo.js?v=20260911a"></script>
|
||||
<script src="/assets/my.js?v=20260914a"></script>
|
||||
<script src="/assets/my.js?v=20260914b"></script>
|
||||
<script src="/assets/chat.js?v=20260907l"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user