index.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. 'use client'
  2. import type { FC } from 'react'
  3. import React, { useState } from 'react'
  4. import { useTranslation } from 'react-i18next'
  5. import type { AnnotationItemBasic } from '../type'
  6. import EditItem, { EditItemType } from './edit-item'
  7. import Drawer from '@/app/components/base/drawer-plus'
  8. import Button from '@/app/components/base/button'
  9. import Toast from '@/app/components/base/toast'
  10. import { useProviderContext } from '@/context/provider-context'
  11. import AnnotationFull from '@/app/components/billing/annotation-full'
  12. type Props = {
  13. isShow: boolean
  14. onHide: () => void
  15. onAdd: (payload: AnnotationItemBasic) => void
  16. }
  17. const AddAnnotationModal: FC<Props> = ({
  18. isShow,
  19. onHide,
  20. onAdd,
  21. }) => {
  22. const { t } = useTranslation()
  23. const { plan, enableBilling } = useProviderContext()
  24. const isAnnotationFull = (enableBilling && plan.usage.annotatedResponse >= plan.total.annotatedResponse)
  25. const [question, setQuestion] = useState('')
  26. const [answer, setAnswer] = useState('')
  27. const [isCreateNext, setIsCreateNext] = useState(false)
  28. const [isSaving, setIsSaving] = useState(false)
  29. const isValid = (payload: AnnotationItemBasic) => {
  30. if (!payload.question)
  31. return t('appAnnotation.errorMessage.queryRequired')
  32. if (!payload.answer)
  33. return t('appAnnotation.errorMessage.answerRequired')
  34. return true
  35. }
  36. const handleSave = async () => {
  37. const payload = {
  38. question,
  39. answer,
  40. }
  41. if (isValid(payload) !== true) {
  42. Toast.notify({
  43. type: 'error',
  44. message: isValid(payload) as string,
  45. })
  46. return
  47. }
  48. setIsSaving(true)
  49. try {
  50. await onAdd(payload)
  51. }
  52. catch (e) {
  53. }
  54. setIsSaving(false)
  55. if (isCreateNext) {
  56. setQuestion('')
  57. setAnswer('')
  58. }
  59. else {
  60. onHide()
  61. }
  62. }
  63. return (
  64. <div>
  65. <Drawer
  66. isShow={isShow}
  67. onHide={onHide}
  68. maxWidthClassName='!max-w-[480px]'
  69. title={t('appAnnotation.addModal.title') as string}
  70. body={(
  71. <div className='p-6 pb-4 space-y-6'>
  72. <EditItem
  73. type={EditItemType.Query}
  74. content={question}
  75. onChange={setQuestion}
  76. />
  77. <EditItem
  78. type={EditItemType.Answer}
  79. content={answer}
  80. onChange={setAnswer}
  81. />
  82. </div>
  83. )}
  84. foot={
  85. (
  86. <div>
  87. {isAnnotationFull && (
  88. <div className='mt-6 mb-4 px-6'>
  89. <AnnotationFull />
  90. </div>
  91. )}
  92. <div className='px-6 flex h-16 items-center justify-between border-t border-black/5 bg-gray-50 rounded-bl-xl rounded-br-xl leading-[18px] text-[13px] font-medium text-gray-500'>
  93. <div
  94. className='flex items-center space-x-2'
  95. >
  96. <input type="checkbox" checked={isCreateNext} onChange={() => setIsCreateNext(!isCreateNext)} className="w-4 h-4 rounded border-gray-300 text-blue-700 focus:ring-blue-700" />
  97. <div>{t('appAnnotation.addModal.createNext')}</div>
  98. </div>
  99. <div className='mt-2 flex space-x-2'>
  100. <Button className='!h-7 !text-xs !font-medium' onClick={onHide}>{t('common.operation.cancel')}</Button>
  101. <Button className='!h-7 !text-xs !font-medium' variant='primary' onClick={handleSave} loading={isSaving} disabled={isAnnotationFull}>{t('common.operation.add')}</Button>
  102. </div>
  103. </div>
  104. </div>
  105. )
  106. }
  107. >
  108. </Drawer>
  109. </div>
  110. )
  111. }
  112. export default React.memo(AddAnnotationModal)