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:
+1
-1
@@ -6,7 +6,7 @@
|
||||
<title>Admin | InstantAdPay</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||
<link rel="icon" type="image/png" href="/logo-icon.png">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909c">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909d">
|
||||
<style>
|
||||
.adm-table th,.adm-table td{padding:8px 10px;text-align:left;vertical-align:top;border-bottom:1px solid var(--line);font-size:13.5px}
|
||||
.adm-table th{color:var(--muted);font-size:11.5px;text-transform:uppercase;letter-spacing:.08em}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -610,3 +610,8 @@ img{max-width:100%}
|
||||
|
||||
.lin-row .earn{font-family:var(--mono);font-size:12px;color:var(--muted);white-space:nowrap;font-variant-numeric:tabular-nums}
|
||||
.lin-row .earn.on{color:var(--mint);font-weight:700}
|
||||
|
||||
.wo-slot{border:1px solid var(--line);border-radius:12px;padding:12px 14px}
|
||||
.wo-slot.locked{opacity:.6}
|
||||
.wo-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:6px}
|
||||
.wo-slot img{max-width:100%;border-radius:8px}
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
const creative = m.bannerUrl
|
||||
? '<img src="' + m.bannerUrl + '" alt="' + safe + ' banner">'
|
||||
: '<b>' + safe + '</b><br><span class="muted small">' + (m.targetUrl ? 'visit their site' : 'banner slot open') + '</span>';
|
||||
d.innerHTML = '<div class="wall-pos">Position ' + (i + 1) + (i === 0 ? ' · this wall' : '') + '</div>'
|
||||
d.innerHTML = '<div class="wall-pos">Position ' + (i + 1) + (m.own ? ' · this wall' : m.admin ? ' · InstantAdPay' : ' · their line') + '</div>'
|
||||
+ '<div class="wc-creative">' + creative + '</div>'
|
||||
+ '<div class="wc-action"></div>'
|
||||
+ '<div class="small muted" style="margin-top:8px">' + safe + '</div>';
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<meta name="theme-color" content="#043b2f">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||
<link rel="icon" type="image/png" href="/logo-icon.png">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909c">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909d">
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<title>Disclaimer | InstantAdPay</title>
|
||||
<link rel="icon" type="image/png" href="/logo-icon.png">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909c">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909d">
|
||||
</head>
|
||||
<body>
|
||||
<div id="nav"></div>
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
<meta name="theme-color" content="#043b2f">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||
<link rel="icon" type="image/png" href="/logo-icon.png">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909c">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909d">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
<title>You're invited | InstantAdPay</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||
<link rel="icon" type="image/png" href="/logo-icon.png">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909c">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909d">
|
||||
<style>
|
||||
.jn-nav{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:16px 0}
|
||||
.jn-hero{padding:34px 0 10px;text-align:left}
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
<meta name="theme-color" content="#043b2f">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||
<link rel="icon" type="image/png" href="/logo-icon.png">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909c">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909d">
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
|
||||
+33
-2
@@ -5,7 +5,7 @@
|
||||
<title>Member area | InstantAdPay</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||
<link rel="icon" type="image/png" href="/logo-icon.png">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909c">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909d">
|
||||
</head>
|
||||
<body class="bo-body">
|
||||
|
||||
@@ -648,6 +648,37 @@
|
||||
<p><button class="btn" id="lbSaveBtn">Save line banner</button></p>
|
||||
<p class="muted small" id="lbCurrent"></p>
|
||||
</div>
|
||||
<div class="card" id="wallOffersCard">
|
||||
<h3>Your wall: positions 2 and 3</h3>
|
||||
<p class="muted small">Your public wall shows three ads. Position 1 is your line banner above. Positions 2 and 3
|
||||
start out showing your upline (or InstantAdPay). <b>Two qualifying buyers</b> make position 2 yours,
|
||||
<b>five</b> make position 3 yours: your own links, your own offers, nobody else's ad on your page.
|
||||
An unlocked slot you leave empty keeps showing your upline until you fill it.</p>
|
||||
<p class="small" id="woStatus" style="color:var(--mint)"></p>
|
||||
<div class="grid c2">
|
||||
<div class="wo-slot" id="woSlot0">
|
||||
<div class="wo-head"><b>Position 2</b> <span class="chip flat" id="woLock0"></span></div>
|
||||
<p><input id="woTitle0" maxlength="60" placeholder="Label shown under the ad (optional)" style="width:100%"></p>
|
||||
<p><input id="woTarget0" placeholder="Link (https://…)" style="width:100%"></p>
|
||||
<p><input id="woBanner0" placeholder="Banner image URL (optional, or upload)" style="width:100%"></p>
|
||||
<p><input type="file" class="wo-file" data-slot="0" accept="image/png,image/jpeg,image/webp,image/gif" hidden>
|
||||
<button class="btn small sec wo-upload" data-slot="0" type="button">Upload image</button>
|
||||
<span class="small muted" id="woInfo0"></span></p>
|
||||
<div id="woPrev0" hidden style="margin:6px 0"></div>
|
||||
</div>
|
||||
<div class="wo-slot" id="woSlot1">
|
||||
<div class="wo-head"><b>Position 3</b> <span class="chip flat" id="woLock1"></span></div>
|
||||
<p><input id="woTitle1" maxlength="60" placeholder="Label shown under the ad (optional)" style="width:100%"></p>
|
||||
<p><input id="woTarget1" placeholder="Link (https://…)" style="width:100%"></p>
|
||||
<p><input id="woBanner1" placeholder="Banner image URL (optional, or upload)" style="width:100%"></p>
|
||||
<p><input type="file" class="wo-file" data-slot="1" accept="image/png,image/jpeg,image/webp,image/gif" hidden>
|
||||
<button class="btn small sec wo-upload" data-slot="1" type="button">Upload image</button>
|
||||
<span class="small muted" id="woInfo1"></span></p>
|
||||
<div id="woPrev1" hidden style="margin:6px 0"></div>
|
||||
</div>
|
||||
</div>
|
||||
<p><button class="btn" id="woSaveBtn">Save wall positions</button></p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Sponsor chat</h3>
|
||||
<p class="muted small">Your line can message you one-to-one for help, and you can message anyone
|
||||
@@ -739,7 +770,7 @@
|
||||
<script src="/assets/common.js?v=20260909a"></script>
|
||||
<script src="/assets/wallet.js?v=20260909c"></script>
|
||||
<script src="/assets/promo.js?v=20260909b"></script>
|
||||
<script src="/assets/my.js?v=20260909h"></script>
|
||||
<script src="/assets/my.js?v=20260909i"></script>
|
||||
<script src="/assets/chat.js?v=20260907l"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<title>Privacy Policy | InstantAdPay</title>
|
||||
<link rel="icon" type="image/png" href="/logo-icon.png">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909c">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909d">
|
||||
</head>
|
||||
<body>
|
||||
<div id="nav"></div>
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<title>Shorts | InstantAdPay</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||
<link rel="icon" type="image/png" href="/logo-icon.png">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909c">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909d">
|
||||
<style>
|
||||
html,body{height:100%;margin:0;overflow:hidden;background:#000}
|
||||
.sh{position:fixed;inset:0;display:flex;flex-direction:column;background:#000;color:var(--ink,#e8fff7)}
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<title>Terms of Service | InstantAdPay</title>
|
||||
<link rel="icon" type="image/png" href="/logo-icon.png">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909c">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909d">
|
||||
</head>
|
||||
<body>
|
||||
<div id="nav"></div>
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<title>Transaction | InstantAdPay</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||
<link rel="icon" type="image/png" href="/logo-icon.png">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909c">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909d">
|
||||
</head>
|
||||
<body>
|
||||
<div id="nav"></div>
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Viewing ad — InstantAdPay</title>
|
||||
<link rel="icon" type="image/png" href="/logo-icon.png">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909c">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909d">
|
||||
<style>
|
||||
html,body{height:100%;margin:0;overflow:hidden}
|
||||
.vw{display:flex;flex-direction:column;height:100vh;height:100dvh;background:var(--bg,#04110c);color:var(--ink,#e8fff7)}
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@
|
||||
<!--OG-->
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||
<link rel="icon" type="image/png" href="/logo-icon.png">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909c">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909d">
|
||||
</head>
|
||||
<body>
|
||||
<div id="nav"></div>
|
||||
@@ -40,6 +40,6 @@
|
||||
</div>
|
||||
</section>
|
||||
<script src="/assets/common.js?v=20260909a"></script>
|
||||
<script src="/assets/wall.js?v=20260909a"></script>
|
||||
<script src="/assets/wall.js?v=20260909b"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user