Member dashboard: stat cards, next-move guidance, line roster, share kit
/api/my/dashboard aggregates credits, earned POL (from the chain index), qualification count, and the referral roster (privacy-masked emails, joined-free vs wallet-linked status, code+id referrer match). Members area leads with four stat cards, a next-move card with a qualification progress bar (2 and 5 buyer marks), the line roster, and a copy-ready share message beside the invite link. Assets v=20260904j. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -300,6 +300,42 @@ const server = http.createServer(async (req, res) => {
|
||||
return json(res, 200, out);
|
||||
}
|
||||
|
||||
if (p === '/api/my/dashboard' && req.method === 'GET') {
|
||||
const s = await auth.fromRequest(req);
|
||||
if (!s) return json(res, 401, { error: 'Sign in first.' });
|
||||
const memberId = await auth.refreshMemberId(s);
|
||||
const acct = (s.email && await accounts.byEmail(s.email)) || (s.address && await accounts.byAddress(s.address)) || null;
|
||||
const out = { memberId, email: s.email || (acct && acct.email) || null,
|
||||
address: s.address || (acct && acct.address) || null,
|
||||
refCode: (acct && acct.code) || null, credits: 0, buyerCount: 0,
|
||||
earnedWei: '0', earnCount: 0, referrals: [] };
|
||||
if (memberId) {
|
||||
try {
|
||||
const mm = await chain.member(memberId);
|
||||
out.buyerCount = mm.buyerCount;
|
||||
out.credits = await ads.availableCredits(memberId);
|
||||
} catch (e) { out.chainReadError = true; }
|
||||
let earned = 0n, n = 0;
|
||||
for (const ev of chain.recentEvents(600)) {
|
||||
if ((ev.type === 'TierPaid' && ev.recipientId === memberId) || (ev.type === 'AwardPaid' && ev.toId === memberId)) {
|
||||
earned += BigInt(ev.amountWei); n += 1;
|
||||
}
|
||||
}
|
||||
out.earnedWei = earned.toString();
|
||||
out.earnCount = n;
|
||||
}
|
||||
// who joined through this member (code and, once on-chain, numeric id)
|
||||
const refs = [];
|
||||
if (acct && acct.code) refs.push(acct.code);
|
||||
if (memberId) refs.push(String(memberId));
|
||||
const joined = await accounts.listByReferrer(refs);
|
||||
out.referrals = joined.map(r => ({
|
||||
email: r.email.replace(/^(.).*(@.*)$/, '$1***$2'), // privacy mask
|
||||
joined: r.created,
|
||||
status: r.address ? 'wallet linked' : 'joined free'
|
||||
}));
|
||||
return json(res, 200, out);
|
||||
}
|
||||
if (p === '/api/my/activity' && req.method === 'GET') {
|
||||
const s = await auth.fromRequest(req);
|
||||
if (!s) return json(res, 401, { error: 'Sign in first.' });
|
||||
|
||||
Reference in New Issue
Block a user