Wall ownership ladder: positions 2 and 3 become the member's own at 2 / 5 qualifying buyers
- accounts.wall_offers (JSON, up to 2 offers: label, https link, banner) set from Profile > Your wall; upload supported; locks show the buyer threshold. - /api/wall assembles: position 1 = own line banner; positions 2-3 = own offer when unlocked and set, else upline banners (only uplines with a live banner), else house ads. Response carries unlocked + buyerCount; wall labels show "this wall" / "their line" / "InstantAdPay". - Chatbot canned answer + facts, follow-up email 7 mention the ladder. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -1532,8 +1532,46 @@
|
||||
const a = await (await fetch('/api/me')).json();
|
||||
fillLineBanner(a);
|
||||
fillProfileDetails(a);
|
||||
// buyerCount + wallUnlocked live on the dashboard payload (chain read), not on /api/me
|
||||
let d = {}; try { d = await (await fetch('/api/my/dashboard')).json(); } catch (e) {}
|
||||
fillWallOffers(Object.assign({}, a, { buyerCount: d.buyerCount || 0, wallUnlocked: d.wallUnlocked || 1 }));
|
||||
} catch (e) {}
|
||||
}
|
||||
// ── wall positions 2 & 3: the member's own offers, unlocked by qualifying buyers ──
|
||||
function fillWallOffers(a) {
|
||||
if (!a || !$('wallOffersCard')) return;
|
||||
const unlocked = a.wallUnlocked || 1, bc = a.buyerCount || 0;
|
||||
const offers = Array.isArray(a.wallOffers) ? a.wallOffers : [];
|
||||
const NEED = [2, 5];
|
||||
for (let i = 0; i < 2; i++) {
|
||||
const o = offers[i] || {};
|
||||
const open = unlocked >= i + 2;
|
||||
$('woTitle' + i).value = o.title || ''; $('woTarget' + i).value = o.targetUrl || ''; $('woBanner' + i).value = o.bannerUrl || '';
|
||||
$('woPrev' + i).hidden = !o.bannerUrl; $('woPrev' + i).innerHTML = o.bannerUrl ? '<img src="' + o.bannerUrl + '" alt="">' : '';
|
||||
$('woLock' + i).textContent = open ? 'yours' : 'unlocks at ' + NEED[i] + ' qualifying buyers (' + bc + '/' + NEED[i] + ')';
|
||||
$('woSlot' + i).classList.toggle('locked', !open);
|
||||
}
|
||||
$('woStatus').textContent = unlocked >= 3 ? 'Fully qualified: all three wall positions are yours.'
|
||||
: unlocked === 2 ? 'Position 2 is yours. ' + (5 - bc) + ' more qualifying buyer' + (5 - bc === 1 ? '' : 's') + ' and position 3 is too.'
|
||||
: (2 - bc) + ' more qualifying buyer' + (2 - bc === 1 ? '' : 's') + ' ($20 or more) opens position 2. You can set your links now; they go live the moment a slot unlocks.';
|
||||
}
|
||||
document.querySelectorAll('.wo-upload').forEach(b => b.addEventListener('click', () => { const f = document.querySelector('.wo-file[data-slot="' + b.dataset.slot + '"]'); if (f) f.click(); }));
|
||||
document.querySelectorAll('.wo-file').forEach(inp => inp.addEventListener('change', async () => {
|
||||
const i = inp.dataset.slot, f = inp.files[0]; if (!f) return;
|
||||
$('woInfo' + i).textContent = 'Uploading…';
|
||||
try {
|
||||
const r = await (await fetch('/api/my/upload', { method: 'POST', headers: { 'Content-Type': f.type }, body: f })).json();
|
||||
if (r.error) { $('woInfo' + i).textContent = r.error; }
|
||||
else { $('woBanner' + i).value = r.url; $('woInfo' + i).textContent = 'Uploaded'; $('woPrev' + i).hidden = false; $('woPrev' + i).innerHTML = '<img src="' + r.url + '" alt="">'; }
|
||||
} catch (e) { $('woInfo' + i).textContent = 'Upload failed. Try again.'; }
|
||||
inp.value = '';
|
||||
}));
|
||||
if ($('woSaveBtn')) $('woSaveBtn').addEventListener('click', busy2($('woSaveBtn'), async () => {
|
||||
const offers = [0, 1].map(i => ({ title: $('woTitle' + i).value, targetUrl: $('woTarget' + i).value, bannerUrl: $('woBanner' + i).value }));
|
||||
const r = await api('/api/my/wall-offers', { offers });
|
||||
IAP.status('Wall positions saved.', 'ok');
|
||||
await loadLineBanner();
|
||||
}));
|
||||
const SOCIALS = ['facebook', 'twitter', 'youtube', 'instagram', 'tiktok', 'telegram', 'linkedin', 'website'];
|
||||
function fillProfileDetails(a) {
|
||||
if (!a) return;
|
||||
|
||||
Reference in New Issue
Block a user