diff --git a/ghost/admin/app/components/settings/tips-and-donations.hbs b/ghost/admin/app/components/settings/tips-and-donations.hbs index 7ecf08ba21..482755d3d4 100644 --- a/ghost/admin/app/components/settings/tips-and-donations.hbs +++ b/ghost/admin/app/components/settings/tips-and-donations.hbs @@ -73,7 +73,11 @@ @class="gh-btn gh-btn-black gh-btn-icon" /> + + {{#if this.tipsAndDonationsError}} +

{{this.tipsAndDonationsError}}

+ {{/if}} {{/liquid-if}} diff --git a/ghost/admin/app/components/settings/tips-and-donations.js b/ghost/admin/app/components/settings/tips-and-donations.js index d3d5979aa0..860b03e460 100644 --- a/ghost/admin/app/components/settings/tips-and-donations.js +++ b/ghost/admin/app/components/settings/tips-and-donations.js @@ -2,10 +2,11 @@ import Component from '@glimmer/component'; import copyTextToClipboard from 'ghost-admin/utils/copy-text-to-clipboard'; import envConfig from 'ghost-admin/config/environment'; import {action} from '@ember/object'; -import {currencies} from 'ghost-admin/utils/currency'; +import {currencies, getSymbol, minimumAmountForCurrency} from 'ghost-admin/utils/currency'; import {inject} from 'ghost-admin/decorators/inject'; import {inject as service} from '@ember/service'; import {task, timeout} from 'ember-concurrency'; +import {tracked} from '@glimmer/tracking'; const CURRENCIES = currencies.map((currency) => { return { @@ -20,6 +21,7 @@ export default class TipsAndDonations extends Component { @service membersUtils; @inject config; + @tracked tipsAndDonationsError = ''; get allCurrencies() { return CURRENCIES; @@ -58,7 +60,16 @@ export default class TipsAndDonations extends Component { setDonationsSuggestedAmount(event) { const amount = Math.abs(event.target.value); const amountInCents = Math.round(amount * 100); + const currency = this.settings.donationsCurrency; + const symbol = getSymbol(currency); + const minimumAmount = minimumAmountForCurrency(currency); + if (amountInCents !== 0 && amountInCents < minimumAmount) { + this.tipsAndDonationsError = `The suggested amount cannot be less than ${symbol}${minimumAmount / 100}.`; + return; + } + + this.tipsAndDonationsError = ''; this.settings.donationsSuggestedAmount = amountInCents; } diff --git a/ghost/admin/app/utils/currency.js b/ghost/admin/app/utils/currency.js index cbae980a30..0ea03f2870 100644 --- a/ghost/admin/app/utils/currency.js +++ b/ghost/admin/app/utils/currency.js @@ -162,3 +162,45 @@ export function getCurrencyOptions() { } ]; } + +/* +* Returns the minimum charge amount for a given currency, +* based on Stripe's requirements. Values here are double the Stripe limits, to take conversions to the settlement currency into account. +* @see https://stripe.com/docs/currencies#minimum-and-maximum-charge-amounts +* @param {String} currency — Currency in the 3-letter ISO format (e.g. "USD", "EUR") +* @retuns {Number} — Minimum amount in cents (e.g. 100 for $1.00) +*/ +export function minimumAmountForCurrency(currency) { + switch (currency) { + case 'AED': + return 400; + case 'BGN': + return 200; + case 'CZK': + return 3000; + case 'DKK': + return 500; + case 'HKD': + return 800; + case 'HUF': + return 25000; + case 'JPY': + return 10000; + case 'MXN': + return 2000; + case 'MYR': + return 400; + case 'NOK': + return 600; + case 'PLN': + return 400; + case 'RON': + return 400; + case 'SEK': + return 600; + case 'THB': + return 2000; + default: + return 100; + } +}