File size: 3,356 Bytes
a8b3f00
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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