diff --git a/assets/javascripts/discourse/components/donation-form.js.es6 b/assets/javascripts/discourse/components/donation-form.js.es6 new file mode 100644 index 0000000..6999995 --- /dev/null +++ b/assets/javascripts/discourse/components/donation-form.js.es6 @@ -0,0 +1,42 @@ +import { default as computed } from "ember-addons/ember-computed-decorators"; + +export default Ember.Component.extend({ + @computed("confirmation.card.last4") + last4() { + return this.get("confirmation.card.last4"); + }, + + init() { + this._super(...arguments); + + const settings = Discourse.SiteSettings; + + this.setProperties({ + confirmation: false, + currency: settings.discourse_donations_currency, + }); + }, + + actions: { + closeModal() { + this.set('paymentError', false); + this.set('confirmation', false); + }, + + handleConfirmStripeCard(paymentMethod) { + this.set('confirmation', paymentMethod); + }, + + confirmStripeCard() { + const paymentMethodId = this.confirmation.id; + this.stripePaymentHandler(paymentMethodId, this.amount).then((paymentIntent) => { + if (paymentIntent.error) { + this.set('paymentError', paymentIntent.error); + } + else { + console.log('ok done'); + } + }); + }, + }, +}); diff --git a/assets/javascripts/discourse/components/donation-list.js.es6 b/assets/javascripts/discourse/components/donation-list.js.es6 new file mode 100644 index 0000000..b9fcea7 --- /dev/null +++ b/assets/javascripts/discourse/components/donation-list.js.es6 @@ -0,0 +1,5 @@ +export default Ember.Component.extend({ + classNames: "donation-list", + hasSubscriptions: Ember.computed.notEmpty("subscriptions"), + hasCharges: Ember.computed.notEmpty("charges") +}); diff --git a/assets/javascripts/discourse/components/donation-row.js.es6 b/assets/javascripts/discourse/components/donation-row.js.es6 new file mode 100644 index 0000000..fb2ab1a --- /dev/null +++ b/assets/javascripts/discourse/components/donation-row.js.es6 @@ -0,0 +1,99 @@ +import { ajax } from "discourse/lib/ajax"; +import { popupAjaxError } from "discourse/lib/ajax-error"; +import { formatAnchor, formatAmount } from "../lib/donation-utilities"; +import { default as computed } from "ember-addons/ember-computed-decorators"; +import showModal from "discourse/lib/show-modal"; + +export default Ember.Component.extend({ + classNameBindings: [":donation-row", "canceled", "updating"], + includePrefix: Ember.computed.or("invoice", "charge"), + canceled: Ember.computed.equal("subscription.status", "canceled"), + + @computed("subscription", "invoice", "charge", "customer") + data(subscription, invoice, charge, customer) { + if (subscription) { + return $.extend({}, subscription.plan, { + anchor: subscription.billing_cycle_anchor + }); + } else if (invoice) { + let receiptSent = false; + + if (invoice.receipt_number && customer.email) { + receiptSent = true; + } + + return $.extend({}, invoice.lines.data[0], { + anchor: invoice.date, + invoiceLink: invoice.invoice_pdf, + receiptSent + }); + } else if (charge) { + let receiptSent = false; + + if (charge.receipt_number && charge.receipt_email) { + receiptSent = true; + } + + return $.extend({}, charge, { + anchor: charge.created, + receiptSent + }); + } + }, + + @computed("data.currency") + currency(currency) { + return currency ? currency.toUpperCase() : null; + }, + + @computed("data.amount", "currency") + amount(amount, currency) { + return formatAmount(amount, currency); + }, + + @computed("data.interval") + interval(interval) { + return interval || "once"; + }, + + @computed("data.anchor", "interval") + period(anchor, interval) { + return I18n.t(`discourse_donations.period.${interval}`, { + anchor: formatAnchor(interval, moment.unix(anchor)) + }); + }, + + cancelSubscription() { + const subscriptionId = this.get("subscription.id"); + this.set("updating", true); + + ajax("/donate/charges/cancel-subscription", { + data: { + subscription_id: subscriptionId + }, + method: "put" + }) + .then(result => { + if (result.success) { + this.set("subscription", result.subscription); + } + }) + .catch(popupAjaxError) + .finally(() => { + this.set("updating", false); + }); + }, + + actions: { + cancelSubscription() { + showModal("cancel-subscription", { + model: { + currency: this.get("currency"), + amount: this.get("amount"), + period: this.get("period"), + confirm: () => this.cancelSubscription() + } + }); + } + } +}); diff --git a/assets/javascripts/discourse/components/stripe-card.js.es6 b/assets/javascripts/discourse/components/stripe-card.js.es6 new file mode 100644 index 0000000..1eab3f1 --- /dev/null +++ b/assets/javascripts/discourse/components/stripe-card.js.es6 @@ -0,0 +1,59 @@ + +export default Ember.Component.extend({ + init() { + this._super(...arguments); + + const settings = Discourse.SiteSettings; + + this.setProperties({ + cardError: false, + color: jQuery("body").css("color"), + backgroundColor: jQuery("body").css("background-color"), + stripe: Stripe(settings.discourse_patrons_public_key), + }); + }, + + didInsertElement() { + this._super(...arguments); + + const color = this.get('color'); + + const style = { + base: { + color, + iconColor: color, + "::placeholder": { color } + } + }; + + const elements = this.stripe.elements(); + const card = elements.create("card", { style, hidePostalCode: true }); + + card.mount('#card-element'); + + this.set("card", card); + + card.on("change", (result) => { + this.set('cardError', false); + + if(result.error) { + this.set('cardError', result.error.message); + } + }); + }, + + actions: { + submitStripeCard() { + this.stripe.createPaymentMethod('card', this.card).then((result) => { + if (result.error) { + this.set('cardError', result.error.message); + } + else { + this.handleConfirmStripeCard(result.paymentMethod); + } + }, () => { + this.set('cardError', 'Unknown error.'); + }); + }, + }, +}); diff --git a/assets/javascripts/discourse/templates/components/donation-form.hbs b/assets/javascripts/discourse/templates/components/donation-form.hbs new file mode 100644 index 0000000..641cfb1 --- /dev/null +++ b/assets/javascripts/discourse/templates/components/donation-form.hbs @@ -0,0 +1,57 @@ + +{{#if confirmation}} + {{#d-modal closeModal=(action "closeModal") modalStyle="inline-modal" title=(i18n "discourse_donations.confirm")}} + {{#d-modal-body}} +
Amount | +{{amount}} | +
Card | +.... .... .... {{last4}} | +