provider-card.tsx 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. 'use client'
  2. import React from 'react'
  3. import type { FC } from 'react'
  4. import { useTranslation } from 'react-i18next'
  5. import { RiArrowRightUpLine } from '@remixicon/react'
  6. import Badge from '../base/badge'
  7. import type { Plugin } from './types'
  8. import Description from './card/base/description'
  9. import Icon from './card/base/card-icon'
  10. import Title from './card/base/title'
  11. import DownloadCount from './card/base/download-count'
  12. import Button from '@/app/components/base/button'
  13. import InstallFromMarketplace from '@/app/components/plugins/install-plugin/install-from-marketplace'
  14. import cn from '@/utils/classnames'
  15. import { useBoolean } from 'ahooks'
  16. import { getPluginLinkInMarketplace } from '@/app/components/plugins/marketplace/utils'
  17. import { useI18N } from '@/context/i18n'
  18. import { useRenderI18nObject } from '@/hooks/use-i18n'
  19. type Props = {
  20. className?: string
  21. payload: Plugin
  22. }
  23. const ProviderCard: FC<Props> = ({
  24. className,
  25. payload,
  26. }) => {
  27. const getValueFromI18nObject = useRenderI18nObject()
  28. const { t } = useTranslation()
  29. const [isShowInstallFromMarketplace, {
  30. setTrue: showInstallFromMarketplace,
  31. setFalse: hideInstallFromMarketplace,
  32. }] = useBoolean(false)
  33. const { org, label } = payload
  34. const { locale } = useI18N()
  35. return (
  36. <div className={cn('group relative rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg p-4 pb-3 shadow-xs hover:bg-components-panel-on-panel-item-bg', className)}>
  37. {/* Header */}
  38. <div className="flex">
  39. <Icon src={payload.icon} />
  40. <div className="ml-3 w-0 grow">
  41. <div className="flex h-5 items-center">
  42. <Title title={getValueFromI18nObject(label)} />
  43. {/* <RiVerifiedBadgeLine className="shrink-0 ml-0.5 w-4 h-4 text-text-accent" /> */}
  44. </div>
  45. <div className='mb-1 flex h-4 items-center justify-between'>
  46. <div className='flex items-center'>
  47. <div className='system-xs-regular text-text-tertiary'>{org}</div>
  48. <div className='system-xs-regular mx-2 text-text-quaternary'>·</div>
  49. <DownloadCount downloadCount={payload.install_count || 0} />
  50. </div>
  51. </div>
  52. </div>
  53. </div>
  54. <Description className='mt-3' text={getValueFromI18nObject(payload.brief)} descriptionLineRows={2}></Description>
  55. <div className='mt-3 flex space-x-0.5'>
  56. {payload.tags.map(tag => (
  57. <Badge key={tag.name} text={tag.name} />
  58. ))}
  59. </div>
  60. <div
  61. className='absolute bottom-0 left-0 right-0 hidden items-center gap-2 rounded-xl bg-gradient-to-tr from-components-panel-on-panel-item-bg to-background-gradient-mask-transparent p-4 pt-8 group-hover:flex'
  62. >
  63. <Button
  64. className='grow'
  65. variant='primary'
  66. onClick={showInstallFromMarketplace}
  67. >
  68. {t('plugin.detailPanel.operation.install')}
  69. </Button>
  70. <Button
  71. className='grow'
  72. variant='secondary'
  73. >
  74. <a href={`${getPluginLinkInMarketplace(payload)}?language=${locale}`} target='_blank' className='flex items-center gap-0.5'>
  75. {t('plugin.detailPanel.operation.detail')}
  76. <RiArrowRightUpLine className='h-4 w-4' />
  77. </a>
  78. </Button>
  79. </div>
  80. {
  81. isShowInstallFromMarketplace && (
  82. <InstallFromMarketplace
  83. manifest={payload as any}
  84. uniqueIdentifier={payload.latest_package_identifier}
  85. onClose={hideInstallFromMarketplace}
  86. onSuccess={() => hideInstallFromMarketplace()}
  87. />
  88. )
  89. }
  90. </div>
  91. )
  92. }
  93. export default ProviderCard