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:
+16
-1
@@ -82,6 +82,13 @@ const J = {
|
||||
async byEmail(e) { return pub(this.db.byEmail[e]); },
|
||||
async byAddress(a) { const e = this.db.byAddress[a]; return e ? pub(this.db.byEmail[e]) : null; },
|
||||
async byCode(c) { const e = this.db.byCode[c]; return e ? pub(this.db.byEmail[e]) : null; },
|
||||
async listByReferrer(refs) {
|
||||
const set = new Set(refs.filter(Boolean).map(String));
|
||||
return Object.values(this.db.byEmail)
|
||||
.filter(a => set.has(String(a.sponsorRef || '')))
|
||||
.sort((a, b) => b.created - a.created)
|
||||
.slice(0, 200).map(pub);
|
||||
},
|
||||
async linkWallet(e, a) {
|
||||
const acct = this.db.byEmail[e];
|
||||
if (!acct) return { error: 'No such account.' };
|
||||
@@ -133,6 +140,13 @@ const D = {
|
||||
async byEmail(e) { const r = await db.q('SELECT * FROM accounts WHERE email=?', [e]); return rowPub(r[0]); },
|
||||
async byAddress(a) { const r = await db.q('SELECT * FROM accounts WHERE address=?', [a]); return rowPub(r[0]); },
|
||||
async byCode(c) { const r = await db.q('SELECT * FROM accounts WHERE code=?', [c]); return rowPub(r[0]); },
|
||||
async listByReferrer(refs) {
|
||||
const clean = refs.filter(Boolean).map(String);
|
||||
if (!clean.length) return [];
|
||||
const rows = await db.q('SELECT * FROM accounts WHERE sponsor_ref IN (' + clean.map(() => '?').join(',')
|
||||
+ ') ORDER BY created DESC LIMIT 200', clean);
|
||||
return rows.map(rowPub);
|
||||
},
|
||||
async linkWallet(e, a) {
|
||||
const cur = await this.byEmail(e);
|
||||
if (!cur) return { error: 'No such account.' };
|
||||
@@ -166,6 +180,7 @@ async function ensure(email, sponsorRef) {
|
||||
async function byEmail(email) { return impl().byEmail(normEmail(email)); }
|
||||
async function byAddress(address) { return impl().byAddress(normAddr(address)); }
|
||||
async function byCode(code) { return impl().byCode(String(code || '').toLowerCase()); }
|
||||
async function listByReferrer(refs) { return impl().listByReferrer(refs || []); }
|
||||
async function linkWallet(email, address) {
|
||||
const a = normAddr(address);
|
||||
if (!/^0x[0-9a-f]{40}$/.test(a)) return { error: 'Bad wallet address.' };
|
||||
@@ -173,4 +188,4 @@ async function linkWallet(email, address) {
|
||||
}
|
||||
async function count() { return impl().count(); }
|
||||
|
||||
module.exports = { init, signup, login, ensure, byEmail, byAddress, byCode, linkWallet, count };
|
||||
module.exports = { init, signup, login, ensure, byEmail, byAddress, byCode, listByReferrer, linkWallet, count };
|
||||
|
||||
Reference in New Issue
Block a user