import { useField } from 'formik' import React from 'react' import { Text } from 'react-native' import { Checkbox, DatePicker, DropdownMaterial, Input, PhoneInput, RadioGroup, } from '../../components' import { ICheckboxStyles } from '../../components/checkbox/types' import { IDatePickerStyles } from '../../components/datePicker/types' import { IDropdownMaterialStyles } from '../../components/dropdownMaterial/types' import { IInputStyles } from '../../components/input/types' import { IPhoneInputStyles } from '../../components/phoneInput/types' import { IRadioGroupStyles } from '../../components/radioGroup/types' import { FieldConfig } from './types' export interface FormikFieldComponentStyles { input?: IInputStyles select?: IDropdownMaterialStyles selectMulti?: IDropdownMaterialStyles phone?: IPhoneInputStyles checkbox?: ICheckboxStyles radio?: IRadioGroupStyles datePicker?: IDatePickerStyles } interface FormikFieldProps> { field: FieldConfig styles?: FormikFieldComponentStyles } export const FormikField = React.memo( >({ field, styles: componentStyles, }: FormikFieldProps) => { const [formikField, meta, helpers] = useField(field.name) const value = formikField.value const error = meta.touched ? meta.error : undefined if (field.hide) return null const handleChange = (val: string | number | boolean | string[]) => { field.onChange?.(val) helpers.setValue(val) } switch (field.type) { case 'input': return ( handleChange(val)} styles={componentStyles?.input} /> ) case 'textarea': return ( handleChange(val)} styles={componentStyles?.input} /> ) case 'select': { const options = field.options ?? [] return ( o.value === value) ?? { value: '', label: field.placeholder ?? `Select ${field.label}`, } } onSelectItem={(item) => handleChange(item.value)} materialInputProps={{ label: field.label ?? 'Select', error, }} styles={componentStyles?.select} /> ) } case 'select_multi': { const options = field.options ?? [] const selectedValues = (Array.isArray(value) ? value : []) as string[] const selectedOptions = options.filter((o) => selectedValues.includes(o.value)) const displayOption = { value: '', label: selectedOptions.length > 0 ? selectedOptions.map((o) => o.label).join(', ') : `Select ${field.label ?? 'items'}`, } return ( { let newValues = [...selectedValues] if (newValues.includes(String(item.value))) { newValues = newValues.filter((v) => v !== item.value) } else { newValues.push(String(item.value)) } handleChange(newValues) }} materialInputProps={{ label: field.label ?? 'Select Multiple', error, }} styles={componentStyles?.selectMulti ?? componentStyles?.select} /> ) } case 'phone': return ( handleChange(payload.input)} error={error} texts={{ label: field.label }} styles={componentStyles?.phone} /> ) case 'checkbox': return ( handleChange(!value)} styles={componentStyles?.checkbox} /> ) case 'radio': return ( handleChange(val)} label={field.label} error={error} styles={componentStyles?.radio} /> ) case 'datePicker': return ( handleChange(date.toISOString())} error={error} text={field.label || 'Select date'} placeholder={field.placeholder} styles={componentStyles?.datePicker} /> ) default: return {field.type} is not supported } } )