source: Klonkt/src/views/pages/download.ejs@ 0d7acdf

main
Last change on this file since 0d7acdf was 91094a4, checked in by roboburr <roboburr@…>, 3 months ago

Download-for-email (premium feature #2)

Fan leaves their email -> receives the file; address is added to the mailing list
(source 'download', single opt-in so the download is not behind a confirm barrier).
Reuses SubscriberService (#1).

  • DB: audio_tracks.downloadable (default 0).
  • admin-audio: per-track no-JS toggle (POST /admin/audio/:id/downloadable) + ⬇ button in the admin list (premium-gated); downloadable also in the /api/:id whitelist.
  • routes/download.js (premium-gated): GET /downloads (list), GET /download/:id (capture page), POST /download/:id (save email + session grant), GET /download/:id/bestand (serves attachment from storage/audio, 15-min session window, path-traversal guards).
  • views: pages/downloads.ejs + pages/download.ejs (form/ready, auto-start download).
  • admin dashboard: ⬇ Downloads link (premium, non-hub).

node --check passed. Nothing else reuses this; #8 notify reuses subscribers.

Co-Authored-By: Claude <noreply@…>

  • Property mode set to 100644
File size: 2.9 KB
Line 
1<%
2 var t = (typeof dlTrack !== 'undefined') ? dlTrack : {};
3 var st = (typeof dlState !== 'undefined') ? dlState : 'form';
4 var fileUrl = siteUrlBase + '/download/' + t.id + '/bestand';
5%>
6<section class="dl">
7 <div class="dl-card">
8 <div class="dl-head">
9 <% if (t.cover_url) { %><span class="dl-cover" style="background-image:url('<%= t.cover_url %>')"></span><% } else { %><span class="dl-cover dl-cover-empty">♪</span><% } %>
10 <div>
11 <div class="dl-title"><%= t.title %></div>
12 <% if (t.artist) { %><div class="dl-artist"><%= t.artist %></div><% } %>
13 </div>
14 </div>
15
16 <% if (st === 'ready') { %>
17 <h1 class="dl-h1">Bedankt! ⬇</h1>
18 <p class="dl-sub">Je download zou nu moeten starten. Gebeurt er niets?</p>
19 <p><a class="dl-go" href="<%= fileUrl %>">Download handmatig starten</a></p>
20 <script>
21 // Auto-start de download (zelfde-origin attachment-link).
22 setTimeout(function(){ try { window.location.href = <%- JSON.stringify(fileUrl) %>; } catch(e){} }, 600);
23 </script>
24 <% } else { %>
25 <h1 class="dl-h1">Download <%= t.title %></h1>
26 <p class="dl-sub">Laat je e-mailadres achter en je krijgt het bestand. Je komt dan ook op de nieuwsbrieflijst — uitschrijven kan altijd.</p>
27 <% if (typeof dlError !== 'undefined' && dlError) { %><p class="dl-err"><%= dlError %></p><% } %>
28 <form method="POST" action="<%= siteUrlBase %>/download/<%= t.id %>" class="dl-form">
29 <input type="email" name="email" required placeholder="jouw@email.nl" value="<%= (typeof dlPrefill!=='undefined')?dlPrefill:'' %>" autocomplete="email">
30 <button type="submit" class="dl-go">⬇ Download</button>
31 </form>
32 <% } %>
33 </div>
34</section>
35
36<style>
37 .dl { max-width: 520px; margin: 0 auto; padding: 48px 18px; }
38 .dl-card { border: 1px solid rgba(128,128,128,.2); border-radius: 18px; padding: 28px; }
39 .dl-head { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; }
40 .dl-cover { width: 56px; height: 56px; border-radius: 10px; background-size: cover; background-position: center; display: grid; place-items: center; flex: 0 0 auto; }
41 .dl-cover-empty { background: var(--accent,#6b8f71); color: #fff; opacity: .85; }
42 .dl-title { font-weight: 700; font-size: 17px; }
43 .dl-artist { opacity: .65; font-size: 13px; }
44 .dl-h1 { font-size: clamp(22px,4.5vw,30px); margin: 0 0 8px; }
45 .dl-sub { opacity: .85; line-height: 1.55; margin: 0 0 18px; }
46 .dl-err { color: #c43c3c; margin: 0 0 12px; }
47 .dl-form { display: flex; gap: 10px; flex-wrap: wrap; }
48 .dl-form input { flex: 1 1 200px; padding: 12px 14px; border-radius: 10px; border: 1px solid rgba(128,128,128,.4); background: transparent; color: inherit; font-size: 15px; }
49 .dl-go { padding: 12px 20px; border-radius: 10px; border: none; background: var(--accent,#6b8f71); color: #fff; font-weight: 600; font-size: 15px; cursor: pointer; text-decoration: none; display: inline-block; }
50</style>
Note: See TracBrowser for help on using the repository browser.