Repository URL to install this package:
|
Version:
0.9.5 ▾
|
/* eslint-disable brace-style */
import { Serializable } from 'exotic'
import { isObj, isFunction, isFalse } from 'exotic'
import { curry } from 'chain-able-boost'
import {
extendObservable,
action,
observable,
computed,
decorate,
} from 'xmobx/mobx'
import { isValid, errorMessage } from '../deps'
import { isAmexCard, isValidCreditCard } from '../deps/isValidCreditCard'
import { isValidYear } from '../deps/isValidExpiryDate'
import { InputState } from '../input/InputState'
import {
toSerialized,
fromInputToSpread,
fromInputToSerializable,
fromInputToSerializedKeyValue,
toInputState,
} from './deps'
import { GetInputValueType, ObserverFormProps } from './typings'
// const curriedDecorate = curry('_', decorate)
function curryDecorate(types: Object) {
return function(Klass: any) {
decorate(Klass, types)
return Klass
}
}
const decorations = {
setInputsList: action.bound,
setFormReference: action.bound,
setProps: action.bound,
}
// @todo + finish at the end removing validation duplication
// @curryDecorate(decorations)
class FormState {
inputsList: Array<InputState>
props: ObserverFormProps
form: Element
@observable hasAllValidInputs = false
@observable inputsList = []
static init(state: InputState) {
return new FormState(state)
}
/**
* @example [].map(FormState.toInputState)
*/
static toInputState = toInputState
constructor(stateData: Object = {}) {
// super(stateData)
// extendObservable(this, {
// // I think this has an issue - name
// // name: '',
// hasAllValidInputs: false,
// inputsList: [],
// })
/**
* @todo when setting inputs list, copy...
* ORIGINAL_INPUTS_LIST
*/
this.inputsList = observable([])
// no need to add another method, is an alias for specific usage
this.toSerialized = this.toJSON.bind(this)
}
/**
* @note added identifier check too
* @param {String} name name of the input for this form
* @return {InputState}
*/
get = (name): InputState => {
/**
* @todo convert this to a .find
*/
let result
const isSameName = (inputState: InputState) => {
console.info('[forms] input state get - recursing: ', inputState)
if (inputState.type === 'groupElements') {
inputState.elementList.forEach(isSameName)
} else if (inputState.name === name || inputState.identifier === name) {
result = inputState
}
}
this.inputsList.forEach(isSameName)
return result
}
@action
setInputsList(list: Array<InputState>) {
this.inputsList = list
return this
}
@action.bound
setFormReference(dom: HTMLFormElement) {
this.form = dom
}
@action.bound
setProps(props: ObserverFormProps) {
this.props = props
}
// ========= protected read =========
/**
* @type {Computed}
*/
toJSON(): Serializable {
const formData = {}
const getInputValue: GetInputValueType = input => {
// ignore labels
if (input.type === 'label') {
return
}
// title says it all
const { key, value } = fromInputToSerializedKeyValue(input, getInputValue)
// special place for radios
if (input.type === 'radio') {
if (value) {
formData['selectedItem'] = key
}
} else {
// otherwise, default
formData[key] = value
/**
* @todo @fixme bad serialization - fixed in ui-component-library
*/
if (formData['0'] === value) {
delete formData['0']
}
}
}
// this is using `getInputValue` as a longhand `.reduce`
this.inputsList.forEach(getInputValue)
return formData
}
// ========= @todo - remove this duplication =========
formValidation = () => {
const isValidInput = item => {
console.log('itemDetails', item)
const { type, isHidden, isEnabled, validationType } = item
if (isEnabled && type !== 'label' && validationType !== 'none') {
if (type === 'groupElements') {
return item.elementList.every(isValidInput)
} else {
return this.isValidElement(item)
}
} else {
return true
}
}
console.log('current input list', this.inputsList)
const hasAllValidInputs = this.inputsList.every(isValidInput)
console.log('hasAllValidInputs', hasAllValidInputs)
return hasAllValidInputs
}
/**
* @todo @gnanaprabhu why is this duplicated
*/
isValidElement = item => {
const { validationType, value } = item
if (validationType === 'creditcard' || validationType === 'securitycode') {
return this.validateCreditCard(item)
}
if (validationType === 'month' || validationType === 'year') {
return this.validateExpiryDate(item)
}
if (validationType === 'confirmPassword') {
if (this.validateConfirmPassword(item) === false) {
return false
}
} else {
const validationResult = isValid(value, validationType)
if (!validationResult) {
return false
}
}
return true
}
validateCreditCard = item => {
const creditCard = this.get('cardNumber')
const securityCode = this.get('SecurityCode')
if (creditCard && creditCard.getValue()) {
if (securityCode && securityCode.getValue()) {
const isamexCard = isAmexCard(creditCard.getValue())
if (isamexCard && securityCode.getValue().length !== 4) {
return false
} else if (!isamexCard && securityCode.getValue().length === 4) {
return false
}
}
return isValidCreditCard(creditCard.getValue())
}
return false
}
validateExpiryDate = item => {
const expiryMonth = this.get('expirationyear')
const expiryYear = this.get('expirationyear')
if (expiryMonth.getValue() && expiryYear.getValue()) {
if (isValidYear(expiryYear.getValue(), expiryMonth.getValue())) {
return true
} else {
return false
}
}
return false
}
@action.bound
validateConfirmPassword(item) {
// if (isObj(item) === false) {
// console.error('@ganesh - it is being passed a string')
// return false
// }
const password = this.get('password')
const passwordValue = password.getValue()
item.isValidInput = true
if (passwordValue === '' || passwordValue !== item.value) {
item.isValidInput = false
item.errorMessage = errorMessage(item.errorMessageFor)
return false
}
return true
}
// @todo remove userContainer logic and make it generic
// doesMatchesUserName = item => {
// const email = this.get('email')
// const userData = userContainer.username || userContainer.email
// const emailValue = userData ? userData : (email ? email.getValue() : '')
// if (item.value !== '' && emailValue === item.value) {
// item.isValidInput = false
// item.errorMessage = errorMessage('passwordSameAsEmail')
// return true
// }
// return false
// }
}
export { FormState }
export default FormState