File size: 4,970 Bytes
27fd333
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import type { FC } from 'react'
import { useTranslation } from 'react-i18next'
import type {
  ModelProvider,
  TypeWithI18N,
} from '../declarations'
import { ConfigurateMethodEnum } from '../declarations'
import {
  DEFAULT_BACKGROUND_COLOR,
  MODEL_PROVIDER_QUOTA_GET_FREE,
  modelTypeFormat,
} from '../utils'
import {
  useAnthropicBuyQuota,
  useFreeQuota,
  useLanguage,
  useUpdateModelProviders,
} from '../hooks'
import ModelBadge from '../model-badge'
import ProviderIcon from '../provider-icon'
import s from './index.module.css'
import { Plus, Settings01 } from '@/app/components/base/icons/src/vender/line/general'
import Button from '@/app/components/base/button'
import { IS_CE_EDITION } from '@/config'

type ProviderCardProps = {
  provider: ModelProvider
  onOpenModal: (configurateMethod: ConfigurateMethodEnum) => void
}

const TIP_MAP: { [k: string]: TypeWithI18N } = {
  minimax: {
    en_US: 'Earn 1 million tokens for free',
    zh_Hans: '免费获取 100 万个 token',
  },
  spark: {
    en_US: 'Earn 3 million tokens (v3.0) for free',
    zh_Hans: '免费获取 300 万个 token (v3.0)',
  },
  zhipuai: {
    en_US: 'Earn 10 million tokens for free',
    zh_Hans: '免费获取 1000 万个 token',
  },
}
const ProviderCard: FC<ProviderCardProps> = ({
  provider,
  onOpenModal,
}) => {
  const { t } = useTranslation()
  const language = useLanguage()
  const updateModelProviders = useUpdateModelProviders()
  const handlePay = useAnthropicBuyQuota()
  const handleFreeQuotaSuccess = () => {
    updateModelProviders()
  }
  const handleFreeQuota = useFreeQuota(handleFreeQuotaSuccess)
  const configurateMethods = provider.configurate_methods.filter(method => method !== ConfigurateMethodEnum.fetchFromRemote)
  const canGetFreeQuota = MODEL_PROVIDER_QUOTA_GET_FREE.includes(provider.provider) && !IS_CE_EDITION && provider.system_configuration.enabled

  return (
    <div
      className='group relative flex flex-col justify-between px-4 py-3 h-[148px] border-[0.5px] border-black/5 rounded-xl shadow-xs hover:shadow-lg'
      style={{ background: provider.background || DEFAULT_BACKGROUND_COLOR }}
    >
      <div>
        <div className='py-0.5'>
          <ProviderIcon provider={provider} />
        </div>
        {
          provider.description && (
            <div className='mt-1 leading-4 text-xs text-black/[48]'>{provider.description[language] || provider.description.en_US}</div>
          )
        }
      </div>
      <div>
        <div className={`flex flex-wrap group-hover:hidden gap-0.5 ${canGetFreeQuota && 'pb-[18px]'}`}>
          {
            provider.supported_model_types.map(modelType => (
              <ModelBadge key={modelType}>
                {modelTypeFormat(modelType)}
              </ModelBadge>
            ))
          }
          {
            canGetFreeQuota && (
              <div className='absolute left-0 right-0 bottom-0 flex items-center h-[26px] px-4 bg-white/50 rounded-b-xl'>
                📣&nbsp;
                <div
                  className={`${s.vender} text-xs font-medium text-transparent truncate`}
                  title={TIP_MAP[provider.provider][language]}
                >
                  {TIP_MAP[provider.provider][language]}
                </div>
              </div>
            )
          }
        </div>
        {
          canGetFreeQuota && (
            <div className='hidden group-hover:block'>
              <Button
                className='mb-1 w-full h-7 text-xs'
                type='primary'
                onClick={() => handleFreeQuota(provider.provider)}
              >
                {t('common.modelProvider.getFreeTokens')}
              </Button>
            </div>
          )
        }
        <div className={`hidden group-hover:grid grid-cols-${configurateMethods.length} gap-1`}>
          {
            configurateMethods.map((method) => {
              if (method === ConfigurateMethodEnum.predefinedModel) {
                return (
                  <Button
                    key={method}
                    className={'h-7 bg-white text-xs text-gray-700 shrink-0'}
                    onClick={() => onOpenModal(method)}
                  >
                    <Settings01 className={`mr-[5px] w-3.5 h-3.5 ${s.icon}`} />
                    <span className='text-xs inline-flex items-center justify-center overflow-ellipsis shrink-0'>{t('common.operation.setup')}</span>
                  </Button>
                )
              }
              return (
                <Button
                  key={method}
                  className='px-0 h-7 bg-white text-xs text-gray-700'
                  onClick={() => onOpenModal(method)}
                >
                  <Plus className='mr-[5px] w-3.5 h-3.5' />
                  {t('common.modelProvider.addModel')}
                </Button>
              )
            })
          }
        </div>
      </div>
    </div>
  )
}

export default ProviderCard