Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

expire-notice-modal.tsx 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. 'use client'
  2. import React from 'react'
  3. import Button from '@/app/components/base/button'
  4. import Modal from '@/app/components/base/modal'
  5. import { useDocLink } from '@/context/i18n'
  6. import Link from 'next/link'
  7. import { useTranslation } from 'react-i18next'
  8. import { RiExternalLinkLine } from '@remixicon/react'
  9. import { SparklesSoftAccent } from '../components/base/icons/src/public/common'
  10. import useTimestamp from '@/hooks/use-timestamp'
  11. import { useModalContextSelector } from '@/context/modal-context'
  12. import { useEducationVerify } from '@/service/use-education'
  13. import { useRouter } from 'next/navigation'
  14. export type ExpireNoticeModalPayloadProps = {
  15. expireAt: number
  16. expired: boolean
  17. }
  18. export type Props = {
  19. onClose: () => void
  20. } & ExpireNoticeModalPayloadProps
  21. const i18nPrefix = 'education.notice'
  22. const ExpireNoticeModal: React.FC<Props> = ({ expireAt, expired, onClose }) => {
  23. const { t } = useTranslation()
  24. const docLink = useDocLink()
  25. const eduDocLink = docLink('/getting-started/dify-for-education')
  26. const { formatTime } = useTimestamp()
  27. const setShowPricingModal = useModalContextSelector(s => s.setShowPricingModal)
  28. const { mutateAsync } = useEducationVerify()
  29. const router = useRouter()
  30. const handleVerify = async () => {
  31. const { token } = await mutateAsync()
  32. if (token)
  33. router.push(`/education-apply?token=${token}`)
  34. }
  35. const handleConfirm = async () => {
  36. await handleVerify()
  37. onClose()
  38. }
  39. return (
  40. <Modal
  41. isShow
  42. onClose={onClose}
  43. title={expired ? t(`${i18nPrefix}.expired.title`) : t(`${i18nPrefix}.isAboutToExpire.title`, { date: formatTime(expireAt, t(`${i18nPrefix}.dateFormat`) as string), interpolation: { escapeValue: false } })}
  44. closable
  45. className='max-w-[600px]'
  46. >
  47. <div className='body-md-regular mt-5 space-y-5 text-text-secondary'>
  48. <div>
  49. {expired ? (<>
  50. <div>{t(`${i18nPrefix}.expired.summary.line1`)}</div>
  51. <div>{t(`${i18nPrefix}.expired.summary.line2`)}</div>
  52. </>
  53. ) : t(`${i18nPrefix}.isAboutToExpire.summary`)}
  54. </div>
  55. <div>
  56. <strong className='title-md-semi-bold block'>{t(`${i18nPrefix}.stillInEducation.title`)}</strong>
  57. {t(`${i18nPrefix}.stillInEducation.${expired ? 'expired' : 'isAboutToExpire'}`)}
  58. </div>
  59. <div>
  60. <strong className='title-md-semi-bold block'>{t(`${i18nPrefix}.alreadyGraduated.title`)}</strong>
  61. {t(`${i18nPrefix}.alreadyGraduated.${expired ? 'expired' : 'isAboutToExpire'}`)}
  62. </div>
  63. </div>
  64. <div className="mt-7 flex items-center justify-between space-x-2">
  65. <Link className='system-xs-regular flex items-center space-x-1 text-text-accent' href={eduDocLink} target="_blank" rel="noopener noreferrer">
  66. <div>{t('education.learn')}</div>
  67. <RiExternalLinkLine className='size-3' />
  68. </Link>
  69. <div className='flex space-x-2'>
  70. {expired ? (
  71. <Button onClick={() => {
  72. onClose()
  73. setShowPricingModal()
  74. }} className='flex items-center space-x-1'>
  75. <SparklesSoftAccent className='size-4' />
  76. <div className='text-components-button-secondary-accent-text'>{t(`${i18nPrefix}.action.upgrade`)}</div>
  77. </Button>
  78. ) : (
  79. <Button onClick={onClose}>
  80. {t(`${i18nPrefix}.action.dismiss`)}
  81. </Button>
  82. )}
  83. <Button variant='primary' onClick={handleConfirm}>
  84. {t(`${i18nPrefix}.action.reVerify`)}
  85. </Button>
  86. </div>
  87. </div>
  88. </Modal>
  89. )
  90. }
  91. export default React.memo(ExpireNoticeModal)