houdini/client/js/nonprofits/donate/amount-step.js

199 lines
7.2 KiB
JavaScript

// License: LGPL-3.0-or-later
const h = require('snabbdom/h')
const R = require('ramda')
const flyd = require('flyd')
const format = require('../../common/format')
flyd.scanMerge = require('flyd/module/scanmerge')
function init(donationDefaults, params$) {
var state = {
params$: params$
, evolveDonation$: flyd.stream() // Stream of objects that can be used to R.evolve the initial donation object
, buttonAmountSelected$: flyd.stream(true) // Whether the button or input is selected
, currentStep$: flyd.stream()
}
// A stream of objects that an be used to modify the existing donation by using R.evolve
donationDefaults = R.merge(donationDefaults, {
amount: format.dollarsToCents(state.params$().single_amount || 0)
, designation: state.params$().designation
, recurring: state.params$().type === 'recurring'
, weekly: (typeof state.params$().weekly !== 'undefined')
})
// Apply R.evolve using every value on the evolveDonation$ stream, starting with the defaults
state.donation$ = flyd.scanMerge([
[state.params$ || flyd.stream(), setDonationFromParams]
, [state.evolveDonation$, R.flip(R.evolve)]
], donationDefaults)
return state
}
const setDonationFromParams = (donation, params) => {
if(params.single_amount) {
donation.amount = format.dollarsToCents(params.single_amount)
}
else
donation.amount = undefined
if(params.designation)
donation.designation = params.designation
else
donation.designation = undefined
if (params.type === 'recurring')
donation.recurring = true
else
donation.recurring = undefined
return donation
}
function view(state) {
const isRecurring = state.donation$().recurring
return h('div.wizard-step.amount-step', [
chooseDesignation(state)
, recurringCheckbox(isRecurring, state)
, recurringMessage(isRecurring, state)
, amountFields(state)
, showSingleAmount(isRecurring, state)
])
}
// Dropdown to choose among custom designations
function chooseDesignation(state) {
if(!state.params$().multiple_designations) return ''
var defaultDesigs = [
state.params$().designations_prompt || I18n.t('nonprofits.donate.amount.designation.choose')
, I18n.t('nonprofits.donate.amount.designation.most_needed')
]
return h('section.u-paddingX--5', {
class: {'u-hide': !state.params$().multiple_designations}
}, [
h('select.donate-designationDropdown.select.u-marginBottom--10', {
on: { change: ev => state.evolveDonation$({designation: R.always(ev.currentTarget.value)}) }
}, R.concat(
R.map(
d => h('option', {props: {value: ''}}, d)
, defaultDesigs
)
, R.map(
d => h('option', {props: {value: d}}, d)
, state.params$().multiple_designations
)
)
)
])
}
// Checkbox to make the donation monthly recurring
function recurringCheckbox(isRecurring, state) {
if(state.params$().type === 'recurring' || state.params$().type === 'one-time') return ''
return h('section.donate-recurringCheckbox.u-paddingX--5 u-marginBottom--10', [
h('div.u-padding--8.u-background--grey.u-centered', {
class: {highlight: isRecurring}
}, [
h('input.u-margin--0.donationWizard-amount-input', {
props: {type: 'checkbox', selected: isRecurring, id: 'checkbox-recurring'}
, on: {change: ev => state.evolveDonation$({recurring: t => !t})}
})
, h('label', {props: {htmlFor: 'checkbox-recurring'}}, composeTranslation(
I18n.t('nonprofits.donate.amount.sustaining')
, I18n.t('nonprofits.donate.amount.sustaining_bold')
)
)
])
])
}
// If recurring, an extra message to reinforce that it is in fact charged every month
function recurringMessage(isRecurring, state) {
if(!isRecurring) return ''
var label=I18n.t('nonprofits.donate.amount.sustaining_selected')
var bolded=I18n.t('nonprofits.donate.amount.sustaining_selected_bold');
if (state.donation$().weekly) {
label = label.replace(I18n.t('nonprofits.donate.amount.monthly'),I18n.t('nonprofits.donate.amount.weekly'));
bolded=I18n.t('nonprofits.donate.amount.weekly');
}
return h('section.donate-recurringMessage.group', [
h('p.u-paddingX--5.u-centered', {
class: {'u-hide': !isRecurring}
}, [
state.params$().single_amount ? '' : h('small.info', composeTranslation(label,bolded))
])
])
}
function prependCurrencyClassname() {
if (app.currency_symbol === '$') {
return 'prepend--dollar'
} else if (app.currency_symbol === '€') {
return 'prepend--euro'
}
}
function composeTranslation(full, bold) {
const texts = full.split(bold)
if(texts.length > 1) {
return [texts[0], h('strong', bold), texts[1]]
} else {
return full
}
}
// All the buttons and the custom input for the amounts to select
function amountFields(state) {
if(state.params$().single_amount) return ''
return h('div.u-inline.fieldsetLayout--three--evenPadding', [
h('span',
R.map(
amt => h('fieldset', [
h('button.button.u-width--full.white.amount', {
class: {'is-selected': state.buttonAmountSelected$() && state.donation$().amount === amt*100}
, on: {click: ev => {
state.evolveDonation$({amount: R.always(format.dollarsToCents(amt))})
state.buttonAmountSelected$(true)
state.currentStep$(1) // immediately advance steps when selecting an amount button
} }
}, [
h('span.dollar', app.currency_symbol)
, String(amt)
])
])
, state.params$().custom_amounts || [] )
)
, h('fieldset.' + prependCurrencyClassname(), [
h('input.amount.other', {
props: {name: 'amount', step: 'any', type: 'number', min: 1, placeholder: I18n.t('nonprofits.donate.amount.custom')}
, class: {'is-selected': !state.buttonAmountSelected$()}
, on: {
focus: ev => state.buttonAmountSelected$(false)
, change: ev => state.evolveDonation$({amount: R.always(format.dollarsToCents(ev.currentTarget.value))})
}
})
])
, h('fieldset', [
h('button.button.u-width--full.btn-next', {
props: {type: 'submit', disabled: !state.donation$().amount || state.donation$().amount <= 0}
, on: {click: [state.currentStep$, 1]}
}, I18n.t('nonprofits.donate.amount.next'))
])
])
}
// If the params have a single amount, show a large message saying how much it is
function showSingleAmount(isRecurring, state) {
if(!state.params$().single_amount) return ''
var gift = state.params$().gift_option || {}
if(state.params$().gift_option_name) gift.name = state.params$().gift_option_name
var desig = state.params$().designation
return h('section.u-centered', [
h('p.singleAmount-message', [
h('strong', app.currency_symbol + format.centsToDollars(format.dollarsToCents(state.params$().single_amount)))
, h('span.u-padding--0', { class: {'u-hide': !isRecurring} }, ' monthly')
, h('span', {class: {'u-hide': !state.params$().designation && !gift.id}}, [ ' for ' + (desig || gift.name) ])
])
, h('button.button.u-marginBottom--20', {on: {click: [state.currentStep$, 1]}}, I18n.t('nonprofits.donate.amount.next'))
])
}
module.exports = {view, init}