Repository URL to install this package:
|
Version:
3.0.10 ▾
|
/* eslint-disable brace-style */
import { Serializable } from '@skava/typings'
import { isArray } from 'exotic'
import { action, observable } from 'xmobx/mobx'
import { isValid, errorMessage, isValidPassword } from '../deps'
import { isAmexCard, isValidCreditCard } from '../deps/isValidCreditCard'
import { isValidExpiryDate } from '../deps/isValidExpiryDate'
import { InputState } from '../input/InputState'
import { InputType, InputStateType } from '../input/typings'
import { fromInputToSerializedKeyValue, toInputState } from './deps'
import { GetInputValueType, ObserverFormProps } from './typings'
class FormState {
props: ObserverFormProps
form: Element
@observable
hasAllValidInputs = false
@observable
inputsList: Array<InputState> = []
static init(state: InputState) {
return new FormState(state)
}
toSerialized: () => Serializable
constructor(stateData: Object = {}) {
/**
* @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 name name of the input for this form
*/
get = (name: string): InputState | undefined => {
/**
* @todo convert this to a .find
*/
let result
const isSameName = (inputState: InputState) => {
console.info('[forms] input state get - recursing: ', inputState)
/**
* @todo @james - this actually helps to loop through the elementsList inside groupElements,
* will calling it recursively "result" variable has the element state, though it doesn't return anything.
*/
if (inputState.type === 'groupElements') {
// console.error('[form state] MISSING serialized')
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 =========
toJSON(): Serializable {
const formData = {}
const assignInputValue = (
input: InputStateType,
index?: number
): Serializable => {
// ignore labels
if (input.type === 'label') {
return undefined
}
// title says it all
const { key, value } = fromInputToSerializedKeyValue(
input,
assignInputValue
)
// 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 `assignInputValue` as a longhand `.reduce`
this.inputsList.forEach(assignInputValue)
return formData
}
// ========= @todo - remove this duplication =========
formValidation = () => {
const isValidInput = (item: InputStateType, index?: number): boolean => {
console.log('itemDetails', item)
const { type, isHidden, isEnabled, validationType } = item
if (isEnabled && type !== 'label' && validationType !== 'none') {
if (type === 'groupElements' && isArray(item.elementList)) {
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
}
}
if (validationType === 'newPassword') {
if (this.validateNewPassword(item) === false) {
return false
}
} else {
const validationResult = isValid(value, validationType)
if (!validationResult) {
return false
}
}
return true
}
creditCardNumberNullCheck = (props?: any) => {
if (props && props.item && props.item.value && props.item.value.cardnumber) {
return props.item.value.cardnumber
}
return ''
}
securityCodeNullCheck = (item?: any) => {
if (item.validationType === 'securityCode') {
return item.value
}
return ''
}
validateCardType = (isamexCard: boolean, securityCodeValue, validateCard: boolean) => {
if (isamexCard && securityCodeValue.length !== 4) {
return false
} else if (!isamexCard && securityCodeValue.length !== 3) {
return false
}
if (validateCard) {
return true
}
}
validateCreditCard = (item?: any) => {
const validationType = item.validationType
const creditCard = this.get('cardNumber')
const creditCardValue = creditCard && creditCard.getValue()
const securityCode = this.get('SecurityCode')
const securityCodeValue = securityCode ? securityCode.getValue() : this.securityCodeNullCheck(item)
if (creditCardValue) {
if (securityCodeValue) {
const isamexCard = isAmexCard(creditCardValue)
this.validateCardType(isamexCard, securityCodeValue, false)
} else if (validationType === 'securityCode') {
return false
}
return isValidCreditCard(creditCardValue, securityCodeValue)
} else {
//@todo @component - Need to change the toAmexCard - to validate partially
const isamexCard = this.props.item.value.cardtype === 'AMERICAN_EXPRESS'
return this.validateCardType(isamexCard, securityCodeValue, true)
}
return false
}
validateExpiryDate = (item: any) => {
const expiryMonth = this.get('expirationMonth') as InputState
const expiryYear = this.get('expirationYear') as InputState
const objValid = {
validationType: item.validationType,
expiryYear,
expiryMonth,
expiryMonthParsed: expiryMonth.getValue(),
expiryYearParsed: expiryYear.getValue(),
}
return isValidExpiryDate(objValid)
}
@action.bound
validateForSamePassword(item, name, shouldBeSamePassword) {
// if (isObj(item) === false) {
// console.error('@ganesh - it is being passed a string')
// return false
// }
const { value } = item
if (!isValidPassword(value)) {
item.setIsValidInput(false)
item.errorMessage = errorMessage('password')
return false
}
const password = this.get(name) as InputState
const passwordValue = password.getValue()
item.setIsValidInput(true)
let isValid = passwordValue === ''
isValid = shouldBeSamePassword
? passwordValue !== item.value
: passwordValue === item.value
if (isValid) {
item.setIsValidInput(false)
item.errorMessage = errorMessage(item.errorMessageFor)
return false
}
return true
}
@action.bound
validateConfirmPassword(item) {
return this.validateForSamePassword(item, 'password', true)
}
@action.bound
validateNewPassword(item) {
return this.validateForSamePassword(item, 'oldPassword', false)
}
}
export { FormState }
export default FormState