chore: base form (#23101)
This commit is contained in:
@@ -11,6 +11,7 @@ import PureSelect from '@/app/components/base/select/pure'
|
|||||||
import type { FormSchema } from '@/app/components/base/form/types'
|
import type { FormSchema } from '@/app/components/base/form/types'
|
||||||
import { FormTypeEnum } from '@/app/components/base/form/types'
|
import { FormTypeEnum } from '@/app/components/base/form/types'
|
||||||
import { useRenderI18nObject } from '@/hooks/use-i18n'
|
import { useRenderI18nObject } from '@/hooks/use-i18n'
|
||||||
|
import RadioE from '@/app/components/base/radio/ui'
|
||||||
|
|
||||||
export type BaseFieldProps = {
|
export type BaseFieldProps = {
|
||||||
fieldClassName?: string
|
fieldClassName?: string
|
||||||
@@ -57,8 +58,27 @@ const BaseField = ({
|
|||||||
if (typeof placeholder === 'object' && placeholder !== null)
|
if (typeof placeholder === 'object' && placeholder !== null)
|
||||||
return renderI18nObject(placeholder as Record<string, string>)
|
return renderI18nObject(placeholder as Record<string, string>)
|
||||||
}, [placeholder, renderI18nObject])
|
}, [placeholder, renderI18nObject])
|
||||||
|
const optionValues = useStore(field.form.store, (s) => {
|
||||||
|
const result: Record<string, any> = {}
|
||||||
|
options?.forEach((option) => {
|
||||||
|
if (option.show_on?.length) {
|
||||||
|
option.show_on.forEach((condition) => {
|
||||||
|
result[condition.variable] = s.values[condition.variable]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
})
|
||||||
const memorizedOptions = useMemo(() => {
|
const memorizedOptions = useMemo(() => {
|
||||||
return options?.map((option) => {
|
return options?.filter((option) => {
|
||||||
|
if (!option.show_on?.length)
|
||||||
|
return true
|
||||||
|
|
||||||
|
return option.show_on.every((condition) => {
|
||||||
|
const conditionValue = optionValues[condition.variable]
|
||||||
|
return conditionValue === condition.value
|
||||||
|
})
|
||||||
|
}).map((option) => {
|
||||||
return {
|
return {
|
||||||
label: typeof option.label === 'string' ? option.label : renderI18nObject(option.label),
|
label: typeof option.label === 'string' ? option.label : renderI18nObject(option.label),
|
||||||
value: option.value,
|
value: option.value,
|
||||||
@@ -151,17 +171,28 @@ const BaseField = ({
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
formSchema.type === FormTypeEnum.radio && (
|
formSchema.type === FormTypeEnum.radio && (
|
||||||
<div className='flex items-center space-x-2'>
|
<div className={cn(
|
||||||
|
memorizedOptions.length < 3 ? 'flex items-center space-x-2' : 'space-y-2',
|
||||||
|
)}>
|
||||||
{
|
{
|
||||||
memorizedOptions.map(option => (
|
memorizedOptions.map(option => (
|
||||||
<div
|
<div
|
||||||
key={option.value}
|
key={option.value}
|
||||||
className={cn(
|
className={cn(
|
||||||
'system-sm-regular hover:bg-components-option-card-option-hover-bg hover:border-components-option-card-option-hover-border flex h-8 grow cursor-pointer items-center justify-center rounded-lg border border-components-option-card-option-border bg-components-option-card-option-bg p-2 text-text-secondary',
|
'system-sm-regular hover:bg-components-option-card-option-hover-bg hover:border-components-option-card-option-hover-border flex h-8 flex-[1] grow cursor-pointer items-center justify-center rounded-lg border border-components-option-card-option-border bg-components-option-card-option-bg p-2 text-text-secondary',
|
||||||
value === option.value && 'border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg text-text-primary shadow-xs',
|
value === option.value && 'border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg text-text-primary shadow-xs',
|
||||||
|
inputClassName,
|
||||||
)}
|
)}
|
||||||
onClick={() => field.handleChange(option.value)}
|
onClick={() => field.handleChange(option.value)}
|
||||||
>
|
>
|
||||||
|
{
|
||||||
|
formSchema.showRadioUI && (
|
||||||
|
<RadioE
|
||||||
|
className='mr-2'
|
||||||
|
isChecked={value === option.value}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
{option.label}
|
{option.label}
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
|
@@ -2,6 +2,7 @@ import {
|
|||||||
memo,
|
memo,
|
||||||
useCallback,
|
useCallback,
|
||||||
useImperativeHandle,
|
useImperativeHandle,
|
||||||
|
useMemo,
|
||||||
} from 'react'
|
} from 'react'
|
||||||
import type {
|
import type {
|
||||||
AnyFieldApi,
|
AnyFieldApi,
|
||||||
@@ -45,8 +46,18 @@ const BaseForm = ({
|
|||||||
disabled,
|
disabled,
|
||||||
formFromProps,
|
formFromProps,
|
||||||
}: BaseFormProps) => {
|
}: BaseFormProps) => {
|
||||||
|
const initialDefaultValues = useMemo(() => {
|
||||||
|
if (defaultValues)
|
||||||
|
return defaultValues
|
||||||
|
|
||||||
|
return formSchemas.reduce((acc, schema) => {
|
||||||
|
if (schema.default)
|
||||||
|
acc[schema.name] = schema.default
|
||||||
|
return acc
|
||||||
|
}, {} as Record<string, any>)
|
||||||
|
}, [defaultValues])
|
||||||
const formFromHook = useForm({
|
const formFromHook = useForm({
|
||||||
defaultValues,
|
defaultValues: initialDefaultValues,
|
||||||
})
|
})
|
||||||
const form: any = formFromProps || formFromHook
|
const form: any = formFromProps || formFromHook
|
||||||
const { getFormValues } = useGetFormValues(form, formSchemas)
|
const { getFormValues } = useGetFormValues(form, formSchemas)
|
||||||
|
@@ -7,6 +7,7 @@ const AuthForm = ({
|
|||||||
defaultValues,
|
defaultValues,
|
||||||
ref,
|
ref,
|
||||||
formFromProps,
|
formFromProps,
|
||||||
|
...rest
|
||||||
}: BaseFormProps) => {
|
}: BaseFormProps) => {
|
||||||
return (
|
return (
|
||||||
<BaseForm
|
<BaseForm
|
||||||
@@ -16,6 +17,7 @@ const AuthForm = ({
|
|||||||
formClassName='space-y-4'
|
formClassName='space-y-4'
|
||||||
labelClassName='h-6 flex items-center mb-1 system-sm-medium text-text-secondary'
|
labelClassName='h-6 flex items-center mb-1 system-sm-medium text-text-secondary'
|
||||||
formFromProps={formFromProps}
|
formFromProps={formFromProps}
|
||||||
|
{...rest}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -58,6 +58,7 @@ export type FormSchema = {
|
|||||||
options?: FormOption[]
|
options?: FormOption[]
|
||||||
labelClassName?: string
|
labelClassName?: string
|
||||||
validators?: AnyValidators
|
validators?: AnyValidators
|
||||||
|
showRadioUI?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FormValues = Record<string, any>
|
export type FormValues = Record<string, any>
|
||||||
|
@@ -5,13 +5,21 @@ import cn from '@/utils/classnames'
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isChecked: boolean
|
isChecked: boolean
|
||||||
|
className?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const RadioUI: FC<Props> = ({
|
const RadioUI: FC<Props> = ({
|
||||||
isChecked,
|
isChecked,
|
||||||
|
className,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className={cn(isChecked ? 'border-[5px] border-components-radio-border-checked' : 'border-[2px] border-components-radio-border', 'h-4 w-4 rounded-full')}>
|
<div
|
||||||
|
className={cn(
|
||||||
|
isChecked ? 'border-[5px] border-components-radio-border-checked' : 'border-[2px] border-components-radio-border',
|
||||||
|
'h-4 w-4 rounded-full',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user