import { createSelector } from '@reduxjs/toolkit' ; import { RootState } from '@store/store' ; export const cardNumberSelector = state => state . checkout . paymentInfo . card . number ; export const cardNameSelector = state => state . checkout . paymentInfo . card . name ; export const cardExpirySelector = state => state . checkout . paymentInfo . card . expiry ; export const cardCvcSelector = state => state . checkout . paymentInfo . card . cvc ; export const isValidCardNumberSelector = createSelector ( cardNumberSelector , cardNumber => { const containsOnlyNumbers = Array . from ( cardNumber ) . every ( number => number . match ( /[0-9]/ ) ) ; const expectedLength = 16 ; const hasCorrectLength = cardNumber . length === expectedLength ; return containsOnlyNumbers && hasCorrectLength ; } ) ; export const isValidCardNameSelector = createSelector ( cardNameSelector , cardName => { const containsValidChars = Array . from ( cardName ) . every ( letter => letter . match ( /[a-z A-Z]/ ) ) ; const maxLength = 60 ; const isLessThanMaxLength = cardName . length > 0 && cardName . length <= maxLength ; return containsValidChars && isLessThanMaxLength ; } ) ; export const isValidCardExpirySelector = createSelector ( cardExpirySelector , expiry => { const expectedLength = 4 ; const monthIndexStart = 0 ; const monthIndexEnd = 2 ; const yearIndexStart = 2 ; const yearIndexEnd = 4 ; const lastTwoDigits = - 2 ; const monthField = Number ( expiry . substring ( monthIndexStart , monthIndexEnd ) ) ; const monthsInYear = 12 ; const isCorrectMonthField = monthField > 0 && monthField <= monthsInYear ; const yearField = Number ( expiry . substring ( yearIndexStart , yearIndexEnd ) ) ; const isCorrectYearField = yearField >= Number ( new Date ( ) . getFullYear ( ) . toString ( ) . substr ( lastTwoDigits ) ) ; const hasCorrectLength = expiry . length === expectedLength ; return hasCorrectLength && isCorrectMonthField && isCorrectYearField ; } ) ; export const isValidCardCvcSelector = createSelector ( cardCvcSelector , cvc => { const expectedLength = 3 ; const containsOnlyNumbers = Array . from ( cvc ) . every ( number => number . match ( /[0-9]/ ) ) ; const hasCorrectLength = cvc . length === expectedLength ; return containsOnlyNumbers && hasCorrectLength ; } ) ; export const isValidCardPaymentFormSelector = createSelector ( isValidCardNumberSelector , isValidCardNameSelector , isValidCardExpirySelector , isValidCardCvcSelector , ( isValidCardNumber , isValidCardName , isValidExpiry , isValidCvc ) => isValidCardNumber && isValidCardName && isValidExpiry && isValidCvc ) ; export const billingFullNameSelector = state => state . checkout . billingInfo . fullName ; export const billingAddressSelector = state => state . checkout . billingInfo . address ; export const isValidBillingFullNameSelector = createSelector ( billingFullNameSelector , name => { const containsValidChars = Array . from ( name ) . every ( char => char . match ( /[a-z A-Z]/ ) ) ; const maxLength = 60 ; const hasCorrectLength = name . length > 0 && name . length <= maxLength ; return containsValidChars && hasCorrectLength ; } ) ; export const isValidBillingAddressSelector = createSelector ( billingAddressSelector , address => { const maxLength = 30 ; const hasCorrectLength = address . length > 0 && address . length <= maxLength ; return hasCorrectLength ; } ) ; export const isValidBillingInfoForm = createSelector ( isValidBillingFullNameSelector , isValidBillingAddressSelector , ( isValidBillingFullName , isValidBillingAddress ) => isValidBillingFullName && isValidBillingAddress ) ;