Overview announcements: let a member put one away for the session

The PolHunter launch card, the Five Dollar Friday card and the "you came from
PolHunter" card repeat on a timer, so anyone who has read one had no way to
clear it. Each now carries a small close control in its heading: the card
stays hidden for the rest of that browser session and comes back at the next
sign-in, so a message nobody acted on is never lost for good.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-22 06:29:49 -05:00
parent 67fb8193bd
commit c47905d89a
4 changed files with 532 additions and 506 deletions
+21 -1
View File
@@ -1405,9 +1405,23 @@
}));
} catch (e) {}
}
// The announcement cards at the top of the Overview are repeated on a timer, so a member who has read
// one can put it away: dismissed for the rest of this browser session, back at the next sign-in
// (Marty, 2026-09-22) so a message nobody has acted on is never gone for good.
function cardHidden(key) { try { return sessionStorage.getItem('iap-hide-' + key) === '1'; } catch (e) { return false; } }
function cardDismiss(card, key) {
if (!card || card.querySelector('.card-x')) return;
const x = document.createElement('button');
x.type = 'button'; x.className = 'card-x'; x.innerHTML = '&times;';
x.title = 'Hide this until my next sign-in';
x.setAttribute('aria-label', 'Hide this message until my next sign-in');
x.addEventListener('click', () => { try { sessionStorage.setItem('iap-hide-' + key, '1'); } catch (e) {} card.hidden = true; });
(card.querySelector('.card-head') || card).appendChild(x);
}
// Five Dollar Friday card on the Overview: the live wave on Fridays, the date the rest of the week
async function loadFridayCard() {
const card = $('fdfCard'); if (!card) return;
if (cardHidden('fdf')) { card.hidden = true; return; }
try {
const f = await (await fetch('/api/friday')).json(); if (!f.on) { card.hidden = true; return; }
card.hidden = false;
@@ -1418,6 +1432,7 @@
+ '<p>Every Friday (Central time), any ad package from $5 up earns <b>+' + f.pct + '% bonus credits</b>, added the moment it settles. The whole network buys on the same day, so every line gets paid at once. Next one: <b>' + (f.nextLabel || 'soon') + '</b>.</p>'
+ '<button class="btn sec" type="button" id="fdfBuy">See the packages</button>';
const b = $('fdfBuy'); if (b) b.addEventListener('click', () => { const m = document.querySelector('.bo-menu [data-pane="buy"]'); if (m) m.click(); });
cardDismiss(card, 'fdf');
} catch (e) {}
}
loadFridayCard(); setInterval(loadFridayCard, 120000);
@@ -1429,17 +1444,21 @@
const nav = $('polhunterNav'); if (nav) nav.hidden = false; // listed in the menu from launch morning (Marty, 2026-09-21); the card below is the announcement and waits for launchAt
const cfg = await IAP.getConfig(); const at = cfg.launchAt ? new Date(cfg.launchAt).getTime() : 0;
if (!at || Date.now() < at) return;
const card = $('phLaunch'); if (!card || phShown) return; phShown = true; card.hidden = false;
const card = $('phLaunch'); if (!card || phShown) return;
if (cardHidden('phLaunch')) { card.hidden = true; return; }
phShown = true; card.hidden = false;
card.innerHTML = '<div class="card-head"><h3>\u{1F3AF} New today: PolHunter</h3><span class="sub">Launch-day surprise</span></div>'
+ '<p>Missions across our sites. Visit the site, find your personal code on the page, tap it to copy, paste it on your board, and a random drip of POL lands in the wallet on this account, on chain, with a link to prove it. Three missions a day, a leaderboard with weekly POL prizes, and badge cards you can share. Your PolHunter share link puts sign-ups on your InstantAdPay line.</p>'
+ '<a class="btn" href="/api/my/polhunter">Open my PolHunter board</a> <button class="btn sec" type="button" id="phTrain">Watch: how it feeds your line (70 s)</button> <a class="btn sec" href="https://polhunter.com/" target="_blank" rel="noopener">The teaser</a>';
const tb = $('phTrain'); if (tb) tb.addEventListener('click', () => { const m = document.querySelector('.bo-menu [data-pane="training"]'); if (m) m.click(); });
cardDismiss(card, 'phLaunch');
} catch (e) {}
}
launchReveal(); setInterval(launchReveal, 30000);
// came from PolHunter (iap.return cookie): one card at the top of the Overview that sends them back
async function loadReturnCard() {
const card = $('phReturn'); if (!card) return;
if (cardHidden('phReturn')) { card.hidden = true; return; }
try {
const me = await (await fetch('/api/me')).json();
if (me.returnTo !== 'polhunter') { card.hidden = true; return; }
@@ -1448,6 +1467,7 @@
? '<p>Your wallet is linked, so your board is ready.</p><a class="btn" href="/api/my/polhunter">Back to PolHunter</a>'
: '<p>One step left: link the wallet your POL drips will be paid to. The moment it is linked you go straight back.</p><button class="btn" type="button" id="phGoWallet">Link my wallet</button>');
const b = $('phGoWallet'); if (b) b.addEventListener('click', () => { const m = document.querySelector('.bo-menu [data-pane="wallet"]'); if (m) m.click(); });
cardDismiss(card, 'phReturn');
} catch (e) {}
}
async function loadCoach() {
+6
View File
@@ -388,6 +388,12 @@ textarea{resize:vertical;font:inherit}
.chip.warm{background:rgba(255,178,56,.12);color:var(--amber)}
.card-head{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.card-head .sub{font-size:12px;color:var(--muted)}
/* dismiss on the announcement cards at the top of the Overview (Marty, 2026-09-22):
hides the card for the rest of this browser session, back at the next sign-in */
.card-x{flex:none;align-self:center;margin:-4px -6px 0 2px;width:28px;height:28px;border-radius:50%;
border:1px solid var(--line);background:transparent;color:var(--muted);font-size:19px;line-height:1;
cursor:pointer;display:grid;place-items:center;padding:0}
.card-x:hover{border-color:var(--line-strong);color:var(--ink);background:rgba(139,166,156,.1)}
/* bar chart (divs, real data) */
.barchart{display:flex;align-items:flex-end;gap:6px;height:120px;margin-top:14px}
.barchart .bar{flex:1;min-width:6px;background:linear-gradient(180deg,var(--mint),rgba(67,232,195,.25));