// License: LGPL-3.0-or-later const h = require('snabbdom/h') const R = require('ramda') const validatedForm = require('ff-core/validated-form') const button = require('ff-core/button') const flyd = require('flyd') flyd.flatMap = require('flyd/module/flatmap') flyd.filter = require('flyd/module/filter') flyd.sampleOn = require('flyd/module/sampleon') const scanMerge = require('flyd/module/scanmerge') const IBAN = require('iban') const request = require('../common/request') // Form validation constraints, validator functions, and error messages: const constraints = { name: {required: true} , iban: {required: true, ibanFormat: /[a-zA-Z]{2}\d{14}/} , bic: {required: true} } const validators = { ibanFormat: IBAN.isValid } // You can pass in the .hideButton boolean if you want to control whether the submit button is shown/hidden // Pass in a .card object, which can have default objects for the card form (name, number, cvc, exp_month, etc) // Pass in .path to set the endpoint for saving the card // Pass in .payload for default data to send to the server for every card save request (such as a request token) const init = (state) => { state = state || {} var messages = { required: I18n.t('nonprofits.donate.payment.card.errors.field.presence') , ibanFormat: I18n.t('nonprofits.donate.payment.card.errors.field.format') } state.form = validatedForm.init({constraints, validators, messages}) state.supp$ = flyd.sampleOn(state.form.validData$, state.supporter) state.sepa$ = flyd.combine((supporter, sepaParams) => { return {sepa_params: sepaParams(), supporter_id: supporter()} }, [state.supp$, state.form.validData$]) const response$ = flyd.flatMap(saveTransferData, state.sepa$) state.reponseOk$ = flyd.filter(response => !response.error, response$) state.error$ = flyd.map(R.prop('error'), flyd.filter(response => response.error, state.reponseOk$)) state.saved$ = flyd.filter(response => !response.error, state.reponseOk$) state.loading$ = scanMerge([ [state.form.validSubmit$, R.always(true)] , [state.error$, R.always(false)] , [state.saved$, R.always(false)] ], false) return state } // Save transfer details to our own servers, and return a response stream function saveTransferData(params){ return flyd.map(R.prop('body'), request({ method: 'post' , path: '/sepa' , send: params }).load ) } // -- Virtual DOM const view = state => { var field = validatedForm.field(state.form) return validatedForm.form(state.form, h('form.sepaForm', [ h('div.u-background--grey.group.u-padding--8', [ nameInput(field) , ibanInput(field) , bicInput(field) ]) , h('div.u-centered', [ button({ error$: state.hideErrors ? flyd.stream() : state.error$ , buttonText: I18n.t('nonprofits.donate.payment.card.submit') , loadingText: ` ${I18n.t('nonprofits.donate.payment.card.loading')}` , loading$: state.loading$ }) ]) ]) ) } const nameInput = (field, name) => h('fieldset', [ field(h('input.u-margin--0', { props: { name: 'name' , value: name || '', placeholder: I18n.t('nonprofits.donate.payment.sepa.name') } } )) ]) const ibanInput = field => h('fieldset.col-12.u-margin--0', [ field(h('input.u-margin--0', {props: { type: 'text' , name: 'iban' , placeholder: I18n.t('nonprofits.donate.payment.sepa.iban') } } )) ]) const bicInput = field => h('fieldset.col-right-0.u-margin--0', [ field(h('input.u-margin--0.hidden', { props: { name: 'bic' , type: 'hidden', value:'NOTPROVIDED', placeholder: I18n.t('nonprofits.donate.payment.sepa.bic') } } )) ]) module.exports = {view, init}