diff --git a/site/donate/donate.js b/site/donate/donate.js
index 1ed8010..4855af2 100644
--- a/site/donate/donate.js
+++ b/site/donate/donate.js
@@ -2,29 +2,36 @@
//
// Handles the interactive bits of the donation form:
// - Frequency + payment method picker (Monthly · DD / One-off · Card)
-// - Suggested-amount selection
-// - "Other" -> custom amount input
+// - Suggested-amount selection (presets only for Monthly; "Other" shown for One-off)
+// - "Other" -> custom amount input (One-off only — Stripe sets the amount there)
// - Dynamic CTA label ("Donate £5 a month" / "Donate £5")
-// - On submit: POST to the Cloudflare Worker that creates a Stripe
-// Checkout Session and redirects the donor there.
-//
-// The Stripe call itself is STUBBED below until the Worker is deployed
-// and the Stripe account exists. Search for TODO(stripe).
+// - On submit: redirect to the matching Stripe Payment Link
(function () {
'use strict';
// ── Config ─────────────────────────────────────────────
- // TODO(stripe): replace with the deployed Cloudflare Worker URL once we
- // have it (e.g. https://donate-api.pauseai-uk.workers.dev/checkout).
- const CHECKOUT_ENDPOINT = '/api/create-checkout-session';
+ // Stripe Payment Links. The one-off link is "customer chooses price" —
+ // the donor confirms the amount on Stripe's secure page. The monthly
+ // links are fixed-amount recurring, so each preset routes to its own.
+ const ONE_OFF_URL = 'https://donate.stripe.com/14AaEY7J69wKgTAaSlcbC02';
+ const MONTHLY_URLS = {
+ 3: 'https://donate.stripe.com/3cI3cwgfCgZc46O4tXcbC03',
+ 5: 'https://donate.stripe.com/3cIdRa7J610ebzg4tXcbC00',
+ 10: 'https://donate.stripe.com/cNi3cwd3q24i5aS1hLcbC01',
+ 25: 'https://donate.stripe.com/14AcN61kI7oCbzgaSlcbC04',
+ 50: 'https://donate.stripe.com/7sYeVebZmcIW8n41hLcbC05',
+ 100: 'https://donate.stripe.com/9B6bJ2d3qeR446O9OhcbC06',
+ 250: 'https://donate.stripe.com/dRmfZi1kIfV8bzg2lPcbC07',
+ 500: 'https://donate.stripe.com/cNi28s5AY5gucDkbWpcbC08',
+ };
const MIN_AMOUNT = 3; // pounds
// ── State ──────────────────────────────────────────────
const state = {
- frequency: 'monthly', // 'monthly' | 'oneoff'
+ frequency: 'monthly', // 'monthly' | 'oneoff'
paymentMethod: 'bacs_debit', // 'bacs_debit' | 'card'
- amount: 5, // pounds; null when "other" is picked with no value
+ amount: 5, // pounds; null when "other" is picked with no value
isCustom: false,
};
@@ -34,24 +41,47 @@
const freqOptions = form.querySelectorAll('.freq-option');
const amountOptions = form.querySelectorAll('.amount-option');
+ const amountSelector = form.querySelector('.amount-selector');
+ const otherBtn = form.querySelector('.amount-other');
const customWrap = form.querySelector('.amount-custom');
const customInput = form.querySelector('#custom-amount');
const submitBtn = form.querySelector('#donate-submit');
const ctaLabel = form.querySelector('#donate-cta-label');
const customSuffix = form.querySelector('.amount-input-wrap [data-freq-suffix]');
- // ── UI updates ─────────────────────────────────────────
+ // ── Helpers ────────────────────────────────────────────
function updateCtaLabel() {
- const amountText = state.amount && state.amount >= MIN_AMOUNT
- ? '£' + state.amount
- : '£…';
- const tail = state.frequency === 'monthly' ? ' a month' : '';
- if (ctaLabel) ctaLabel.textContent = 'Donate ' + amountText + tail;
+ if (!ctaLabel) return;
+ if (state.frequency === 'oneoff') {
+ ctaLabel.textContent = 'Donate one-off →';
+ } else {
+ const amountText = state.amount && state.amount >= MIN_AMOUNT
+ ? '£' + state.amount
+ : '£…';
+ ctaLabel.textContent = 'Donate ' + amountText + ' a month';
+ }
if (customSuffix) {
customSuffix.textContent = state.frequency === 'monthly' ? 'per month' : 'one-off';
}
}
+ function setAmountSelectorVisible(visible) {
+ if (amountSelector) amountSelector.hidden = !visible;
+ }
+
+ function setOtherVisible(visible) {
+ if (otherBtn) otherBtn.hidden = !visible;
+ }
+
+ function activatePreset(amount) {
+ const btn = form.querySelector('.amount-option[data-amount="' + amount + '"]');
+ if (!btn) return;
+ amountOptions.forEach((b) => b.classList.toggle('is-active', b === btn));
+ state.amount = amount;
+ state.isCustom = false;
+ customWrap.hidden = true;
+ }
+
// ── Frequency / method tabs ────────────────────────────
freqOptions.forEach((btn) => {
btn.addEventListener('click', () => {
@@ -65,6 +95,16 @@
b.classList.toggle('is-active', active);
b.setAttribute('aria-checked', active ? 'true' : 'false');
});
+ // Monthly: show preset grid (no custom recurring), hide Other.
+ // One-off: hide the grid entirely — the donor picks the amount on
+ // Stripe's "customer chooses price" page.
+ if (freq === 'monthly') {
+ setAmountSelectorVisible(true);
+ setOtherVisible(false);
+ if (state.isCustom) activatePreset(5);
+ } else {
+ setAmountSelectorVisible(false);
+ }
updateCtaLabel();
});
});
@@ -94,15 +134,22 @@
updateCtaLabel();
});
- // ── Submit ─────────────────────────────────────────────
+ // ── Submit → redirect to the matching Stripe Payment Link ─
function validate() {
+ // One-off: Stripe's "customer chooses price" page enforces the amount.
+ if (state.frequency === 'oneoff') return null;
if (!Number.isFinite(state.amount) || state.amount < MIN_AMOUNT) {
return `Please enter an amount of £${MIN_AMOUNT} or more.`;
}
return null;
}
- form.addEventListener('submit', async (event) => {
+ function targetUrl() {
+ if (state.frequency === 'oneoff') return ONE_OFF_URL;
+ return MONTHLY_URLS[state.amount] || null;
+ }
+
+ form.addEventListener('submit', (event) => {
event.preventDefault();
const err = validate();
if (err) {
@@ -110,50 +157,18 @@
if (state.isCustom) customInput.focus();
return;
}
-
+ const url = targetUrl();
+ if (!url) {
+ alert('Sorry — that amount is not available right now. Please pick a preset or email hello@pauseai.uk.');
+ return;
+ }
submitBtn.disabled = true;
- const previousLabel = submitBtn.innerHTML;
submitBtn.textContent = 'Redirecting…';
-
- try {
- // TODO(stripe): once the Cloudflare Worker is live, this fetch will
- // create a Checkout Session server-side and return { url } that we
- // redirect the donor to. Until then we just log what would be sent.
- const payload = {
- amount_pounds: state.amount,
- frequency: state.frequency, // 'monthly' | 'oneoff'
- payment_method: state.paymentMethod, // 'bacs_debit' | 'card'
- };
- console.log('[donate] would POST to', CHECKOUT_ENDPOINT, payload);
- alert(
- 'Stripe is not wired up yet. This would create a ' +
- state.frequency +
- ' £' +
- state.amount +
- ' donation via ' +
- (state.paymentMethod === 'bacs_debit' ? 'Direct Debit' : 'card / wallet') +
- '.'
- );
-
- // Real implementation (commented until Worker is deployed):
- //
- // const res = await fetch(CHECKOUT_ENDPOINT, {
- // method: 'POST',
- // headers: { 'Content-Type': 'application/json' },
- // body: JSON.stringify(payload),
- // });
- // if (!res.ok) throw new Error('Checkout session failed');
- // const { url } = await res.json();
- // window.location.href = url;
- } catch (e) {
- console.error(e);
- alert('Something went wrong. Please try again or email joseph@pauseai.info.');
- } finally {
- submitBtn.disabled = false;
- submitBtn.innerHTML = previousLabel;
- }
+ window.location.href = url;
});
- // Initial render
+ // Initial render — default is Monthly: show preset grid, hide Other.
+ setAmountSelectorVisible(true);
+ setOtherVisible(false);
updateCtaLabel();
})();
diff --git a/site/donate/index.html b/site/donate/index.html
index 0502aee..e545506 100644
--- a/site/donate/index.html
+++ b/site/donate/index.html
@@ -166,6 +166,8 @@
Let's press pause on unsafe AI together
+
+
@@ -214,16 +216,18 @@
Let's press pause on unsafe AI together
Other ways to give
Major gifts & bank transfer
- If you're considering a larger gift, prefer to give by bank
- transfer, or represent a foundation, please get in touch.
+ Prefer to give by bank transfer, making a large one-off gift, or
+ giving on behalf of a foundation? Get in touch and we'll help
+ directly — and say a proper thank-you.
-
Bank transfer & major donors
+
Bank transfer & major gifts
- For UK bank transfers (Faster Payments / BACS) and gifts
- above £500, please email us so we can share account
- details directly.
+ For UK bank transfers (Faster Payments / BACS) or larger
+ one-off donations, email us and we'll share account details
+ directly. (Regular gifts of any size are easy above — Direct
+ Debit keeps our fees low.)