199 lines
		
	
	
	
		
			7.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			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}
 | |
| 
 | 
