/* eslint-disable @typescript-eslint/no-explicit-any */ import { FormikErrors, FormikValues } from 'formik' import _flatMapDeep from 'lodash/flatMapDeep' import _forEach from 'lodash/forEach' import _get from 'lodash/get' import _isArray from 'lodash/isArray' import _isEmpty from 'lodash/isEmpty' import _map from 'lodash/map' import { nanoid } from 'nanoid' import React from 'react' import { AttributesConfig } from '../../api' import { IGroupItem } from '../../types' import { CONFIGS } from '../../utils' import { combineValidators, requiredValidator } from '../../validators' import { CheckboxField, CustomField, DatePickerField, PhoneNumberField, RadioGroupField, SelectField, } from '../common/index' export interface ILoggedInValues { emailLogged?: string; firstNameLogged?: string; lastNameLogged?: string; phoneLogged?: string; } export interface IValues { [key: string]: any; } export const getInitialValues = ( data: any = [], propsInitialValues: IValues = {}, userValues: any = {}, ticketHoldersFields: any = {}, ticketsQuantity: any = [] ): IValues => { const results = _flatMapDeep(data, ({ fields }) => _map(fields, ({ groupItems }) => _map(groupItems, ({ name, value }) => ({ name, value })) ) ) // Add Ticket Holder default values for custom fields const ticketHoldersCustomFields = ticketHoldersFields?.fields?.find((groupItem: any) => groupItem.customFields) ?.groupItems || [] const ticketHoldersCustomFieldsInitValues = {} as IValues const selectedTicketsCount = ticketsQuantity.length || localStorage.getItem('selectedTicketsQuantity') || 0 if (!_isEmpty(ticketHoldersCustomFields)) { for (const customField of ticketHoldersCustomFields) { for (let i = 0; i < selectedTicketsCount; i++) { const fieldName = `${customField.name}-${i}` const fieldValue = customField.value ticketHoldersCustomFieldsInitValues[fieldName] = fieldValue } } } const initialValues: IValues = {} _forEach(results, groupItem => { const { name, value } = groupItem initialValues[name] = value || propsInitialValues[name] || userValues[name] || '' }) // set logged in user as first ticket holder initialValues['holderFirstName-0'] = propsInitialValues.firstName || userValues.firstName || '' initialValues['holderLastName-0'] = propsInitialValues.lastName || userValues.lastName || '' initialValues['holderEmail-0'] = propsInitialValues.email || userValues.email || '' initialValues['holderPhone-0'] = propsInitialValues.phone || userValues.phone || '' return { ...initialValues, ...ticketHoldersCustomFieldsInitValues } } export const createRegisterFormData = ( values: IValues = {}, checkoutBody: { attributes: { [key: string]: any } }, flagFreeTicket = false ): FormData => { const bodyFormData = new FormData() bodyFormData.append('first_name', values.firstName) bodyFormData.append('last_name', values.lastName) bodyFormData.append('email', values.email) bodyFormData.append('password', values.password) bodyFormData.append('password_confirmation', values.confirmPassword) bodyFormData.append( 'client_id', CONFIGS.CLIENT_ID || 'e9d8f8922797b4621e562255afe90dbf' ) bodyFormData.append( 'client_secret', CONFIGS.CLIENT_SECRET || 'b89c191eff22fdcf84ac9bfd88d005355a151ec2c83b26b9' ) bodyFormData.append('check_cart_expiration', 'true') _forEach(checkoutBody.attributes, (item: any, key: string) => { if ( !(flagFreeTicket && ['country', 'state', 'city', 'street_address'].includes(key)) ) { bodyFormData.append(key, item) } }) return bodyFormData } export interface ICheckoutBody { attributes: { [key: string]: any; }; data_capture?: { [key: string]: any; }; } interface IticketHolder { first_name?: string; last_name?: string; phone?: string; email?: string; } export const createCheckoutDataBody = ( ticketsQuantity: number, values: IValues = {}, logedInValues: ILoggedInValues = {}, includeDob = false ): ICheckoutBody => { const { firstName, lastName, holderAge, confirmEmail, confirmPassword, ...restValues } = values const holders = [] let ticket_holders: IticketHolder[] = [] for (let i = 0; i <= ticketsQuantity; i++) { const individualHolder = Object.fromEntries( Object.entries(values).filter(([key, _val]) => key.includes(String(i))) ) holders.push(individualHolder) } const filteredHolders = holders.filter(holder => Object.entries(holder).length > 0) ticket_holders = filteredHolders.map((item, index) => ({ first_name: !index ? item[`holderFirstName-${index}`] || logedInValues.firstNameLogged || '' : item[`holderFirstName-${index}`] || '', last_name: !index ? item[`holderLastName-${index}`] || logedInValues.lastNameLogged || '' : item[`holderLastName-${index}`] || '', phone: !index ? item[`holderPhone-${index}`] || logedInValues.phoneLogged || '' : item[`holderPhone-${index}`] || '', email: !index ? item[`holderEmail-${index}`] || logedInValues.emailLogged || '' : item[`holderEmail-${index}`] || '', })) const filteredRestValue: { [key: string]: any } = {} _forEach(restValues, (value, key) => { if (!key.includes('holder')) { filteredRestValue[key] = value } }) const body: ICheckoutBody = { attributes: { ...filteredRestValue, email: restValues.email || logedInValues.emailLogged, confirm_email: restValues.email || logedInValues.emailLogged, first_name: firstName || logedInValues.firstNameLogged, last_name: lastName || logedInValues.lastNameLogged, ticket_holders, }, } if (includeDob) { const holderAgeDate = new Date(holderAge) body.attributes.dob_day = holderAgeDate.getDate() body.attributes.dob_month = holderAgeDate.getMonth() + 1 body.attributes.dob_year = holderAgeDate.getFullYear() } return body } export const getValidateFunctions = ( element: IGroupItem, states: Array<{ [key: string]: any }>, values: FormikValues, errors: FormikErrors ) => { const validationFunctions: any[] = [] if (element.required) { if (element.name !== 'state' || (element.name === 'state' && states.length)) { validationFunctions.push(requiredValidator) } } if (element.onValidate) { validationFunctions.push(element.onValidate) } if (element.name === 'phone') { const invalidPhone = () => errors.phone === 'Invalid phone number' ? 'Invalid phone number' : null validationFunctions.push(invalidPhone) } if (element.name === 'confirmEmail') { const isSameEmail = (confirmEmail?: string) => values.email !== confirmEmail ? 'Please confirm your email address correctly' : null validationFunctions.push(isSameEmail) } if (element.name === 'confirmPassword') { const isSame = (confirmPassword?: string) => values.password !== confirmPassword ? 'Password confirmation does not match' : null validationFunctions.push(isSame) } return combineValidators(...validationFunctions) } export const assingUniqueIds = (data: any): any => { if (_get(data[0], 'uniqueId')) { return data } return _map(data, (item: any) => { _forEach(item, (itemValue: string, key) => { if (_isArray(itemValue) && !itemValue.some(item => typeof item === 'string')) { item[key] = assingUniqueIds(itemValue) } }) return { ...item, uniqueId: nanoid() } }) } export const isRequiredField = ( element: IGroupItem, configs?: null | AttributesConfig ) => { const { name, required } = element const flagRequirePhone = _get(configs, 'phone_required', false) const collectMandatoryWalletAddress = _get( configs, 'collect_mandatory_wallet_address', false ) if ( required || (name === 'phone' && flagRequirePhone) || (name === 'data_capture[wallet_address]' && !collectMandatoryWalletAddress) ) { return true } return false } export const getFieldLabel = (element: IGroupItem, configs?: null | AttributesConfig) => { if (isRequiredField(element, configs) || React.isValidElement(element.label)) { return element.label } return `${element.label} (optional)` } export const getFieldComponent = (element: IGroupItem) => { const type = _get(element, 'type', 'text') const fieldComponentConfigs = { checkbox: CheckboxField, select: CustomField, // Temp change untill refactoring select_multi: SelectField, phone: PhoneNumberField, date: DatePickerField, radio: RadioGroupField, text: CustomField, } const fieldComponent = _get(fieldComponentConfigs, type, CustomField) return fieldComponent } /** * Renders a React component with the provided props * @param Component - The React component to render * @param props - The props to apply to the component * @returns JSX element with applied props */ export const renderComponentWithProps = >( Component: React.ComponentType, props: T ): React.ReactElement => export const filterBillingInfoFields = ( fields: IGroupItem[], options: { showDOB: boolean; hideTtfOptIn: boolean; hidePhoneField: boolean; flagRequirePhone: boolean; collectMandatoryWalletAddress: boolean; collectMandatoryJobTitle: boolean; collectMandatoryBusinessCategory: boolean; collectMandatoryCompany: boolean; collectMandatoryInstagram: boolean; flagFreeTicket: boolean; hideWalletAddressField: boolean; hideJobTitleField: boolean; hideBusinessCategoryField: boolean; hideCompanyField: boolean; hideInstagramField: boolean; } ) => { const { showDOB, hideTtfOptIn, hidePhoneField, flagRequirePhone, collectMandatoryWalletAddress, collectMandatoryJobTitle, collectMandatoryBusinessCategory, collectMandatoryCompany, collectMandatoryInstagram, flagFreeTicket, hideWalletAddressField, hideJobTitleField, hideBusinessCategoryField, hideCompanyField, hideInstagramField, } = options return fields.filter(el => { if (el.name === 'holderAge' && !showDOB) { return false } if (el.name === 'ttf_opt_in' && hideTtfOptIn) { return false } if (el.name === 'phone') { if (!hidePhoneField) { el.required = flagRequirePhone } else { return false } } if (el.name === 'data_capture[wallet_address]') { if (collectMandatoryWalletAddress) { el.required = true } } if (el.name === 'data_capture[jobTitle]') { if (collectMandatoryJobTitle) { el.required = true } } if (el.name === 'data_capture[businessCategory]') { if (collectMandatoryBusinessCategory) { el.required = true } } if (el.name === 'data_capture[company]') { if (collectMandatoryCompany) { el.required = true } } if (el.name === 'data_capture[instagram]') { if (collectMandatoryInstagram) { el.required = true } } if (['street_address', 'country', 'state', 'city'].includes(el.name)) { if (flagFreeTicket) { el.required = false return false } } if ( hideWalletAddressField && (el.name === 'wallet-address-info' || el.name === 'data_capture[wallet_address]') ) { return false } if (hideJobTitleField && el.name === 'data_capture[jobTitle]') { return false } if (hideBusinessCategoryField && el.name === 'data_capture[businessCategory]') { return false } if (hideCompanyField && el.name === 'data_capture[company]') { return false } if ( hideInstagramField && (el.name === 'data_capture[instagram]' || el.name === 'instagram-info') ) { return false } return true }) }