Quota.tsx 3.9 KB

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