hm
This commit is contained in:
199
static/js/donate.js
Normal file
199
static/js/donate.js
Normal file
@@ -0,0 +1,199 @@
|
||||
(async () => {
|
||||
const cfg = await fetch("/config").then(r => r.json());
|
||||
const stripe = Stripe(cfg.publishableKey);
|
||||
|
||||
const form = document.getElementById("donation-form");
|
||||
const result = document.getElementById("result");
|
||||
const amountInput = document.getElementById("amount");
|
||||
const currencyInput = document.getElementById("currency");
|
||||
|
||||
let elements, expressCheckoutElement, cardElement, paymentIntent;
|
||||
|
||||
// Initialize payment elements
|
||||
async function initializePayment() {
|
||||
const amount = parseFloat(amountInput.value) || 10;
|
||||
const currency = currencyInput.value;
|
||||
const supporterName = document.getElementById('supporter-name').value;
|
||||
|
||||
// Create payment intent
|
||||
const res = await fetch("/create-payment-intent", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ amount, currency, supporterName })
|
||||
});
|
||||
const { clientSecret } = await res.json();
|
||||
|
||||
// Create elements with appearance customization
|
||||
elements = stripe.elements({
|
||||
clientSecret,
|
||||
appearance: {
|
||||
theme: document.documentElement.getAttribute('data-theme') === 'dark' ? 'night' : 'stripe'
|
||||
}
|
||||
});
|
||||
|
||||
// Create and mount express checkout element (Google Pay, Apple Pay, etc.)
|
||||
expressCheckoutElement = elements.create("expressCheckout", {
|
||||
buttonType: {
|
||||
googlePay: "donate",
|
||||
applePay: "donate"
|
||||
},
|
||||
paymentMethods: {
|
||||
link: "never" // Disable Link payment method
|
||||
}
|
||||
});
|
||||
expressCheckoutElement.mount("#express-checkout-element");
|
||||
|
||||
// Listen for express checkout readiness
|
||||
expressCheckoutElement.on('ready', (event) => {
|
||||
const paymentDivider = document.querySelector('.payment-divider');
|
||||
if (event.availablePaymentMethods && Object.keys(event.availablePaymentMethods).length > 0) {
|
||||
// Express methods are available, show the divider
|
||||
paymentDivider.style.display = 'block';
|
||||
} else {
|
||||
// No express methods available, hide the divider on desktop but keep on mobile
|
||||
if (window.innerWidth <= 768) {
|
||||
paymentDivider.style.display = 'block';
|
||||
paymentDivider.querySelector('span').textContent = 'Pay with card';
|
||||
} else {
|
||||
paymentDivider.style.display = 'none';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Create and mount card element
|
||||
cardElement = elements.create("card", {
|
||||
style: {
|
||||
base: {
|
||||
fontSize: '16px',
|
||||
color: getComputedStyle(document.documentElement).getPropertyValue('--text-primary'),
|
||||
'::placeholder': {
|
||||
color: getComputedStyle(document.documentElement).getPropertyValue('--text-secondary'),
|
||||
},
|
||||
},
|
||||
}
|
||||
});
|
||||
cardElement.mount("#card-element");
|
||||
|
||||
return clientSecret;
|
||||
}
|
||||
|
||||
// Handle express checkout (Google Pay, Apple Pay, etc.)
|
||||
async function handleExpressPayment() {
|
||||
result.textContent = "Processing...";
|
||||
|
||||
try {
|
||||
const { error } = await stripe.confirmPayment({
|
||||
elements,
|
||||
confirmParams: {
|
||||
return_url: window.location.href,
|
||||
},
|
||||
redirect: "if_required"
|
||||
});
|
||||
|
||||
if (error) {
|
||||
result.textContent = "❌ " + error.message;
|
||||
} else {
|
||||
result.textContent = "✅ Thank you! Support received successfully.";
|
||||
showSuccessAnimation();
|
||||
addToSupporterWall();
|
||||
}
|
||||
} catch (err) {
|
||||
result.textContent = "❌ Payment failed. Please try again.";
|
||||
}
|
||||
}
|
||||
|
||||
// Handle card payment
|
||||
async function handleCardPayment(e) {
|
||||
e.preventDefault();
|
||||
result.textContent = "Processing...";
|
||||
|
||||
try {
|
||||
const { error } = await stripe.confirmPayment({
|
||||
elements,
|
||||
confirmParams: {
|
||||
return_url: window.location.href,
|
||||
},
|
||||
redirect: "if_required"
|
||||
});
|
||||
|
||||
if (error) {
|
||||
result.textContent = "❌ " + error.message;
|
||||
} else {
|
||||
result.textContent = "✅ Thank you! Support received successfully.";
|
||||
showSuccessAnimation();
|
||||
addToSupporterWall();
|
||||
}
|
||||
} catch (err) {
|
||||
result.textContent = "❌ Payment failed. Please try again.";
|
||||
}
|
||||
}
|
||||
|
||||
// Success animation
|
||||
function showSuccessAnimation() {
|
||||
result.style.background = 'linear-gradient(135deg, #28a745, #20c997)';
|
||||
result.style.color = 'white';
|
||||
result.style.padding = '12px';
|
||||
result.style.borderRadius = '8px';
|
||||
result.style.animation = 'bounce 0.6s ease-out';
|
||||
}
|
||||
|
||||
// Add to supporter wall
|
||||
async function addToSupporterWall() {
|
||||
const supporterName = document.getElementById('supporter-name').value.trim();
|
||||
const amount = parseFloat(amountInput.value) || 0;
|
||||
const currency = currencyInput.value;
|
||||
|
||||
if (supporterName && window.supporterWall) {
|
||||
await window.supporterWall.addSupporter(supporterName, amount * 100, currency);
|
||||
}
|
||||
}
|
||||
|
||||
// Reinitialize when amount or currency changes
|
||||
async function reinitialize() {
|
||||
if (elements) {
|
||||
elements.destroy();
|
||||
}
|
||||
|
||||
const amount = parseFloat(amountInput.value);
|
||||
if (amount && amount > 0) {
|
||||
await initializePayment();
|
||||
|
||||
// Set up event listeners
|
||||
if (expressCheckoutElement) {
|
||||
expressCheckoutElement.on('click', handleExpressPayment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Event listeners
|
||||
form.addEventListener("submit", handleCardPayment);
|
||||
amountInput.addEventListener("blur", reinitialize);
|
||||
currencyInput.addEventListener("change", reinitialize);
|
||||
|
||||
// Initialize on page load
|
||||
await initializePayment();
|
||||
|
||||
// Set up express checkout event listener
|
||||
if (expressCheckoutElement) {
|
||||
expressCheckoutElement.on('click', handleExpressPayment);
|
||||
}
|
||||
|
||||
// Handle responsive payment divider visibility
|
||||
window.addEventListener('resize', () => {
|
||||
const paymentDivider = document.querySelector('.payment-divider');
|
||||
if (window.innerWidth <= 768) {
|
||||
// Always show on mobile
|
||||
paymentDivider.style.display = 'block';
|
||||
}
|
||||
});
|
||||
|
||||
// Update elements theme when theme changes
|
||||
if (window.themeManager) {
|
||||
const originalSetTheme = window.themeManager.setTheme;
|
||||
window.themeManager.setTheme = function(theme) {
|
||||
originalSetTheme.call(this, theme);
|
||||
// Reinitialize elements with new theme
|
||||
setTimeout(reinitialize, 100);
|
||||
};
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user