index.tsx 3.6 KB

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