Quota.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import { useState } from 'react'
  2. import type { FC } from 'react'
  3. import { useTranslation } from 'react-i18next'
  4. import type { Provider, ProviderWithQuota } from '../declarations'
  5. import Tooltip from '@/app/components/base/tooltip'
  6. import { InfoCircle } from '@/app/components/base/icons/src/vender/line/general'
  7. import { getPayUrl } from '@/service/common'
  8. import Button from '@/app/components/base/button'
  9. type QuotaProps = {
  10. currentProvider: Provider
  11. }
  12. const Quota: FC<QuotaProps> = ({
  13. currentProvider,
  14. }) => {
  15. const { t } = useTranslation()
  16. const [loading, setLoading] = useState(false)
  17. const systemTrial = currentProvider.providers.find(p => p.provider_type === 'system' && (p as ProviderWithQuota)?.quota_type === 'trial') as ProviderWithQuota
  18. const systemPaid = currentProvider.providers.find(p => p.provider_type === 'system' && (p as ProviderWithQuota)?.quota_type === 'paid') as ProviderWithQuota
  19. const QUOTA_UNIT_MAP: Record<string, string> = {
  20. times: t('common.modelProvider.card.callTimes'),
  21. tokens: 'Tokens',
  22. }
  23. const renderStatus = () => {
  24. const totalQuota = (systemPaid?.is_valid ? systemPaid.quota_limit : 0) + systemTrial.quota_limit
  25. const totalUsed = (systemPaid?.is_valid ? systemPaid.quota_used : 0) + systemTrial.quota_used
  26. if (totalQuota === totalUsed) {
  27. return (
  28. <div className='px-1.5 bg-[#FEF3F2] rounded-md text-xs font-semibold text-[#D92D20]'>
  29. {t('common.modelProvider.card.quotaExhausted')}
  30. </div>
  31. )
  32. }
  33. if (systemPaid?.is_valid) {
  34. return (
  35. <div className='px-1.5 bg-[#FFF6ED] rounded-md text-xs font-semibold text-[#EC4A0A]'>
  36. {t('common.modelProvider.card.paid')}
  37. </div>
  38. )
  39. }
  40. return (
  41. <div className='px-1.5 bg-primary-50 rounded-md text-xs font-semibold text-primary-600'>
  42. {t('common.modelProvider.card.onTrial')}
  43. </div>
  44. )
  45. }
  46. const renderQuota = () => {
  47. if (systemPaid?.is_valid)
  48. return systemPaid.quota_limit - systemPaid.quota_used
  49. if (systemTrial.is_valid)
  50. return systemTrial.quota_limit - systemTrial.quota_used
  51. }
  52. const renderUnit = () => {
  53. if (systemPaid?.is_valid)
  54. return QUOTA_UNIT_MAP[systemPaid.quota_unit]
  55. if (systemTrial.is_valid)
  56. return QUOTA_UNIT_MAP[systemTrial.quota_unit]
  57. }
  58. const handleGetPayUrl = async () => {
  59. setLoading(true)
  60. try {
  61. const res = await getPayUrl(`/workspaces/current/model-providers/${systemPaid.provider_name}/checkout-url`)
  62. window.location.href = res.url
  63. }
  64. finally {
  65. setLoading(false)
  66. }
  67. }
  68. return (
  69. <div className='flex justify-between px-4 py-3 border-b-[0.5px] border-b-[rgba(0, 0, 0, 0.5)]'>
  70. <div>
  71. <div className='flex items-center mb-1 h-5'>
  72. <div className='mr-1 text-xs font-medium text-gray-500'>
  73. {t('common.modelProvider.card.quota')}
  74. </div>
  75. {renderStatus()}
  76. </div>
  77. <div className='flex items-center text-gray-700'>
  78. <div className='mr-1 text-sm font-medium'>{renderQuota()}</div>
  79. <div className='mr-1 text-sm'>
  80. {renderUnit()}
  81. </div>
  82. <Tooltip
  83. selector='setting-model-card'
  84. htmlContent={
  85. <div className='w-[261px] text-gray-500'>{t('common.modelProvider.card.tip')}</div>
  86. }
  87. >
  88. <InfoCircle className='w-3 h-3 text-gray-400 hover:text-gray-700' />
  89. </Tooltip>
  90. </div>
  91. </div>
  92. {
  93. systemPaid && (
  94. <Button
  95. type='primary'
  96. className='mt-1.5 !px-3 !h-8 !text-[13px] font-medium !rounded-lg'
  97. onClick={handleGetPayUrl}
  98. disabled={loading}
  99. >
  100. {t('common.modelProvider.card.buyQuota')}
  101. </Button>
  102. )
  103. }
  104. </div>
  105. )
  106. }
  107. export default Quota