Changeset c3d12a6 in Klonkt for src/views/pages


Ignore:
Timestamp:
07/21/2026 02:07:18 AM (7 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
9019a3e
Parents:
603d246
git-author:
Robin <roboburr@…> (07/21/2026 02:07:07 AM)
git-committer:
Robin <roboburr@…> (07/21/2026 02:07:18 AM)
Message:

Feature: a way to actually become a supporter, and a styled expired page

Bart's test surfaced two gaps in the visitor flow:

  • After "Allow" on Patreon, a non-supporter landed on "Nog geen supporter" with no way to actually pledge. The page now shows a primary "Word supporter op Patreon" button. The site owner sets their public Patreon page in Beheer -> Betaalde posts (new field); it's also linked from the gate itself ("Nog geen supporter? Word het op Patreon").
  • The invalid/expired callback replied with a raw res.send() plain-text line. It now renders the normal paid-result page (reason 'expired').

Changed files:
src/config/database.js

  • paid_patreon.patreon_url column (additive)

src/services/PaidPatreonService.js

  • patreonUrl in config/status/save (undefined keeps, empty clears) + patreonUrl(siteId) helper

src/routes/admin-paid.js

  • save patreon_url from the form

src/views/pages/admin-paid.ejs

  • "Openbare Patreon-pagina" field

src/routes/paid.js

  • expired callback renders paid-result; pass patronUrl to the result pages

src/routes/posts.js

  • pass pgPatronUrl to the gate

src/views/pages/paid-gate.ejs

  • "Word supporter" join line under the unlock button

src/views/pages/paid-result.ejs

  • "Word supporter op Patreon" primary button, 'expired' reason, ghost back button always has a label

test/paid-patron.test.js

  • patreonUrl set/keep/clear semantics

-robo
Co-Authored-By: Claude Opus 4.8 <noreply@…>

Location:
src/views/pages
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/views/pages/admin-paid.ejs

    r603d246 rc3d12a6  
    4747      <input type="text" name="campaign_id" value="<%= status.campaignId || '' %>" autocomplete="off" style="width:100%">
    4848    </label>
     49    <label>Openbare Patreon-pagina
     50      <input type="url" name="patreon_url" value="<%= status.patreonUrl || '' %>" placeholder="https://www.patreon.com/jouwnaam" autocomplete="off" style="width:100%">
     51      <small style="color:var(--ink-soft,#888)">De link waar bezoekers supporter kunnen worden. Getoond als "Word supporter" wanneer iemand nog niet doneert.</small>
     52    </label>
    4953    <label>Creator access token
    5054      <input type="password" name="access_token" placeholder="blijft ongewijzigd" autocomplete="off" style="width:100%">
  • src/views/pages/paid-gate.ejs

    r603d246 rc3d12a6  
    2020    <button type="button" id="pg-unlock" class="pg-btn">Ontgrendelen</button>
    2121    <p id="pg-status" class="pg-status" hidden></p>
     22    <% if (typeof pgPatronUrl !== 'undefined' && pgPatronUrl) { %>
     23      <p class="pg-join">Nog geen supporter? <a href="<%= pgPatronUrl %>" target="_blank" rel="noopener">Word het op Patreon</a> en ontgrendel daarna met je passkey.</p>
     24    <% } %>
    2225  </section>
    2326</article>
     
    8891  .pg-status { margin: 12px 0 0; opacity: .9; }
    8992  .pg-status.is-err { color: #c0392b; }
     93  .pg-join { margin: 14px 0 0; font-size: .92rem; opacity: .8; }
    9094</style>
  • src/views/pages/paid-result.ejs

    r603d246 rc3d12a6  
     1<%
     2  var _slug = (typeof postSlug !== 'undefined' && postSlug) ? postSlug : '';
     3  var _base = (typeof siteUrlBase !== 'undefined' && siteUrlBase) ? siteUrlBase : '';
     4  var _patron = (typeof patronUrl !== 'undefined' && patronUrl) ? patronUrl : '';
     5%>
    16<section class="pr">
    27  <div class="pr-card">
     
    49    <% if (reason === 'notpatron') { %>
    510      <h1 class="pr-h1">Nog geen supporter</h1>
    6       <p class="pr-sub">Je bent (nog) geen actieve supporter van deze site op Patreon. Word supporter en probeer het opnieuw.</p>
     11      <p class="pr-sub">Je bent (nog) geen actieve supporter van deze site op Patreon. Word supporter en probeer het daarna opnieuw vanaf de post.</p>
    712    <% } else if (reason === 'tier') { %>
    813      <h1 class="pr-h1">Een niveau hoger nodig</h1>
     
    1116        Jouw steun is nu &euro;<%= ((typeof haveCents !== 'undefined' ? haveCents : 0)/100).toFixed(2) %>. Verhoog je steun en probeer opnieuw.
    1217      </p>
     18    <% } else if (reason === 'expired') { %>
     19      <h1 class="pr-h1">Aanvraag verlopen</h1>
     20      <p class="pr-sub">Deze ontgrendel-link is verlopen of al gebruikt. Ga terug naar de post en probeer het opnieuw.</p>
    1321    <% } else { %>
    1422      <h1 class="pr-h1">Ontgrendelen afgebroken</h1>
    1523      <p class="pr-sub">Er is niets gekoppeld. Je kunt het opnieuw proberen vanaf de post.</p>
    1624    <% } %>
    17     <% if (typeof postSlug !== 'undefined' && postSlug) { %>
    18       <p><a class="pr-btn" href="<%= (typeof siteUrlBase !== 'undefined' && siteUrlBase ? siteUrlBase : '') %>/<%= postSlug %>">Terug naar de post</a></p>
    19     <% } %>
     25
     26    <div class="pr-actions">
     27      <% if ((reason === 'notpatron' || reason === 'tier') && _patron) { %>
     28        <a class="pr-btn" href="<%= _patron %>" target="_blank" rel="noopener">Word supporter op Patreon</a>
     29      <% } %>
     30      <% if (_slug) { %>
     31        <a class="pr-btn pr-btn-ghost" href="<%= _base %>/<%= _slug %>">Terug naar de post</a>
     32      <% } else { %>
     33        <a class="pr-btn pr-btn-ghost" href="<%= _base %>/">Terug naar de site</a>
     34      <% } %>
     35    </div>
    2036  </div>
    2137</section>
     
    2642  .pr-ic { font-size: 38px; margin-bottom: 6px; }
    2743  .pr-h1 { font-size: 23px; margin: 0 0 8px; }
    28   .pr-sub { opacity: .85; line-height: 1.6; margin: 0 0 18px; }
     44  .pr-sub { opacity: .85; line-height: 1.6; margin: 0 0 20px; }
     45  .pr-actions { display: flex; flex-direction: column; gap: 10px; align-items: stretch; }
    2946  .pr-btn { display: inline-block; padding: 11px 20px; border-radius: 10px; background: var(--accent,#6b8f71); color: #fff; text-decoration: none; font-weight: 600; }
     47  .pr-btn-ghost { background: transparent; color: var(--ink,#222); border: 1px solid color-mix(in srgb, var(--ink,#000) 22%, transparent); }
    3048</style>
Note: See TracChangeset for help on using the changeset viewer.