| import { useState } from 'react' |
| import Operate from './Operate' |
| import KeyInput from './KeyInput' |
| import { useValidate } from './hooks' |
| import type { Form, KeyFrom, Status, ValidateValue } from './declarations' |
| import { useEventEmitterContextContext } from '@/context/event-emitter' |
| import { LinkExternal02 } from '@/app/components/base/icons/src/vender/line/general' |
|
|
| export type KeyValidatorProps = { |
| type: string |
| title: React.ReactNode |
| status: Status |
| forms: Form[] |
| keyFrom: KeyFrom |
| onSave: (v: ValidateValue) => Promise<boolean | undefined> |
| disabled?: boolean |
| } |
|
|
| const KeyValidator = ({ |
| type, |
| title, |
| status, |
| forms, |
| keyFrom, |
| onSave, |
| disabled, |
| }: KeyValidatorProps) => { |
| const triggerKey = `plugins/${type}` |
| const { eventEmitter } = useEventEmitterContextContext() |
| const [isOpen, setIsOpen] = useState(false) |
| const prevValue = forms.reduce((prev: ValidateValue, next: Form) => { |
| prev[next.key] = next.value |
| return prev |
| }, {}) |
| const [value, setValue] = useState(prevValue) |
| const [validate, validating, validatedStatusState] = useValidate(value) |
|
|
| eventEmitter?.useSubscription((v) => { |
| if (v !== triggerKey) { |
| setIsOpen(false) |
| setValue(prevValue) |
| validate({ before: () => false }) |
| } |
| }) |
|
|
| const handleCancel = () => { |
| eventEmitter?.emit('') |
| } |
|
|
| const handleSave = async () => { |
| if (await onSave(value)) |
| eventEmitter?.emit('') |
| } |
|
|
| const handleAdd = () => { |
| setIsOpen(true) |
| eventEmitter?.emit(triggerKey) |
| } |
|
|
| const handleEdit = () => { |
| setIsOpen(true) |
| eventEmitter?.emit(triggerKey) |
| } |
|
|
| const handleChange = (form: Form, val: string) => { |
| setValue({ ...value, [form.key]: val }) |
|
|
| if (form.validate) |
| validate(form.validate) |
| } |
|
|
| const handleFocus = (form: Form) => { |
| if (form.handleFocus) |
| form.handleFocus(value, setValue) |
| } |
|
|
| return ( |
| <div className='mb-2 border-[0.5px] border-gray-200 bg-gray-50 rounded-md'> |
| <div className={ |
| `flex items-center justify-between px-4 h-[52px] cursor-pointer ${isOpen && 'border-b-[0.5px] border-b-gray-200'}` |
| }> |
| {title} |
| <Operate |
| isOpen={isOpen} |
| status={status} |
| onCancel={handleCancel} |
| onSave={handleSave} |
| onAdd={handleAdd} |
| onEdit={handleEdit} |
| disabled={disabled} |
| /> |
| </div> |
| { |
| isOpen && !disabled && ( |
| <div className='px-4 py-3'> |
| { |
| forms.map(form => ( |
| <KeyInput |
| key={form.key} |
| className='mb-4' |
| name={form.title} |
| placeholder={form.placeholder} |
| value={value[form.key] as string || ''} |
| onChange={v => handleChange(form, v)} |
| onFocus={() => handleFocus(form)} |
| validating={validating} |
| validatedStatusState={validatedStatusState} |
| /> |
| )) |
| } |
| <a className="flex items-center text-xs cursor-pointer text-primary-600" href={keyFrom.link} target='_blank' rel='noopener noreferrer'> |
| {keyFrom.text} |
| <LinkExternal02 className='w-3 h-3 ml-1 text-primary-600' /> |
| </a> |
| </div> |
| ) |
| } |
| </div> |
| ) |
| } |
|
|
| export default KeyValidator |
|
|