index.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import { useState } from 'react'
  2. import Operate from './Operate'
  3. import KeyInput from './KeyInput'
  4. import { useValidate } from './hooks'
  5. import type { Form, KeyFrom, Status, ValidateValue } from './declarations'
  6. import { useEventEmitterContextContext } from '@/context/event-emitter'
  7. import { LinkExternal02 } from '@/app/components/base/icons/src/vender/line/general'
  8. export type KeyValidatorProps = {
  9. type: string
  10. title: React.ReactNode
  11. status: Status
  12. forms: Form[]
  13. keyFrom: KeyFrom
  14. onSave: (v: ValidateValue) => Promise<boolean | undefined>
  15. }
  16. const KeyValidator = ({
  17. type,
  18. title,
  19. status,
  20. forms,
  21. keyFrom,
  22. onSave,
  23. }: KeyValidatorProps) => {
  24. const triggerKey = `plugins/${type}`
  25. const { eventEmitter } = useEventEmitterContextContext()
  26. const [isOpen, setIsOpen] = useState(false)
  27. const prevValue = forms.reduce((prev: ValidateValue, next: Form) => {
  28. prev[next.key] = next.value
  29. return prev
  30. }, {})
  31. const [value, setValue] = useState(prevValue)
  32. const [validate, validating, validatedStatusState] = useValidate(value)
  33. eventEmitter?.useSubscription((v) => {
  34. if (v !== triggerKey) {
  35. setIsOpen(false)
  36. setValue(prevValue)
  37. validate({ before: () => false })
  38. }
  39. })
  40. const handleCancel = () => {
  41. eventEmitter?.emit('')
  42. }
  43. const handleSave = async () => {
  44. if (await onSave(value))
  45. eventEmitter?.emit('')
  46. }
  47. const handleAdd = () => {
  48. setIsOpen(true)
  49. eventEmitter?.emit(triggerKey)
  50. }
  51. const handleEdit = () => {
  52. setIsOpen(true)
  53. eventEmitter?.emit(triggerKey)
  54. }
  55. const handleChange = (form: Form, val: string) => {
  56. setValue({ ...value, [form.key]: val })
  57. if (form.validate)
  58. validate(form.validate)
  59. }
  60. const handleFocus = (form: Form) => {
  61. if (form.handleFocus)
  62. form.handleFocus(value, setValue)
  63. }
  64. return (
  65. <div className='mb-2 border-[0.5px] border-gray-200 bg-gray-50 rounded-md'>
  66. <div className={
  67. `flex items-center justify-between px-4 h-[52px] cursor-pointer ${isOpen && 'border-b-[0.5px] border-b-gray-200'}`
  68. }>
  69. {title}
  70. <Operate
  71. isOpen={isOpen}
  72. status={status}
  73. onCancel={handleCancel}
  74. onSave={handleSave}
  75. onAdd={handleAdd}
  76. onEdit={handleEdit}
  77. />
  78. </div>
  79. {
  80. isOpen && (
  81. <div className='px-4 py-3'>
  82. {
  83. forms.map(form => (
  84. <KeyInput
  85. key={form.key}
  86. className='mb-4'
  87. name={form.title}
  88. placeholder={form.placeholder}
  89. value={value[form.key] || ''}
  90. onChange={v => handleChange(form, v)}
  91. onFocus={() => handleFocus(form)}
  92. validating={validating}
  93. validatedStatusState={validatedStatusState}
  94. />
  95. ))
  96. }
  97. <a className="flex items-center text-xs cursor-pointer text-primary-600" href={keyFrom.link} target={'_blank'}>
  98. {keyFrom.text}
  99. <LinkExternal02 className='w-3 h-3 ml-1 text-primary-600' />
  100. </a>
  101. </div>
  102. )
  103. }
  104. </div>
  105. )
  106. }
  107. export default KeyValidator