import { useEffect, useState } from 'react' import type { Dispatch, FC, SetStateAction } from 'react' import { useContext } from 'use-context-selector' import type { Field, FormValue, ProviderConfigModal } from '../declarations' import { useValidate } from '../../key-validator/hooks' import { ValidatingTip } from '../../key-validator/ValidateStatus' import { validateModelProviderFn } from '../utils' import Input from './Input' import I18n from '@/context/i18n' import { SimpleSelect } from '@/app/components/base/select' type FormProps = { modelModal?: ProviderConfigModal initValue?: FormValue fields: Field[] onChange: (v: FormValue) => void onValidatedError: (v: string) => void mode: string cleared: boolean onClearedChange: Dispatch> onValidating: (validating: boolean) => void } const nameClassName = ` py-2 text-sm text-gray-900 ` const Form: FC = ({ modelModal, initValue = {}, fields, onChange, onValidatedError, mode, cleared, onClearedChange, onValidating, }) => { const { locale } = useContext(I18n) const [value, setValue] = useState(initValue) const [validate, validating, validatedStatusState] = useValidate(value) const [changeKey, setChangeKey] = useState('') useEffect(() => { onValidatedError(validatedStatusState.message || '') }, [validatedStatusState, onValidatedError]) useEffect(() => { onValidating(validating) }, [validating, onValidating]) const updateValue = (v: FormValue) => { setValue(v) onChange(v) } const handleMultiFormChange = (v: FormValue, newChangeKey: string) => { updateValue(v) setChangeKey(newChangeKey) const validateKeys = (typeof modelModal?.validateKeys === 'function' ? modelModal?.validateKeys(v) : modelModal?.validateKeys) || [] if (validateKeys.length) { validate({ before: () => { for (let i = 0; i < validateKeys.length; i++) { if (!v[validateKeys[i]]) return false } return true }, run: () => { return validateModelProviderFn(modelModal!.key, v) }, }) } } const handleClear = (saveValue?: FormValue) => { const needClearFields = modelModal?.fields.filter(field => field.type !== 'radio') const newValue: Record = {} needClearFields?.forEach((field) => { newValue[field.key] = '' }) updateValue({ ...value, ...newValue, ...saveValue }) onClearedChange(true) } const handleFormChange = (k: string, v: string) => { if (mode === 'edit' && !cleared) handleClear({ [k]: v }) else handleMultiFormChange({ ...value, [k]: v }, k) } const handleFocus = () => { if (mode === 'edit' && !cleared) handleClear() } const renderField = (field: Field) => { const hidden = typeof field.hidden === 'function' ? field.hidden(value) : field.hidden if (hidden) return null if (field.type === 'text') { return (
{field.label[locale]}
handleMultiFormChange(v, field.key)} onFocus={handleFocus} validatedStatusState={validatedStatusState} /> {validating && changeKey === field.key && }
) } if (field.type === 'radio') { const options = typeof field.options === 'function' ? field.options(value) : field.options return (
{field.label[locale]}
{ options?.map(option => (
handleFormChange(field.key, option.key)} key={`${field.key}-${option.key}`} >
{option.label[locale]}
)) }
{validating && changeKey === field.key && }
) } if (field.type === 'select') { const options = typeof field.options === 'function' ? field.options(value) : field.options return (
{field.label[locale]}
({ value: option.key, name: option.label[locale] }))} onSelect={item => handleFormChange(field.key, item.value as string)} /> {validating && changeKey === field.key && }
) } } return (
{ fields.map(field => renderField(field)) }
) } export default Form