AppCard.tsx 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. 'use client'
  2. import { useContext, useContextSelector } from 'use-context-selector'
  3. import Link from 'next/link'
  4. import type { MouseEventHandler } from 'react'
  5. import { useCallback, useState } from 'react'
  6. import { useTranslation } from 'react-i18next'
  7. import style from '../list.module.css'
  8. import AppModeLabel from './AppModeLabel'
  9. import type { App } from '@/types/app'
  10. import Confirm from '@/app/components/base/confirm'
  11. import { ToastContext } from '@/app/components/base/toast'
  12. import { deleteApp } from '@/service/apps'
  13. import AppIcon from '@/app/components/base/app-icon'
  14. import AppsContext, { useAppContext } from '@/context/app-context'
  15. export type AppCardProps = {
  16. app: App
  17. onDelete?: () => void
  18. }
  19. const AppCard = ({
  20. app,
  21. onDelete,
  22. }: AppCardProps) => {
  23. const { t } = useTranslation()
  24. const { notify } = useContext(ToastContext)
  25. const { isCurrentWorkspaceManager } = useAppContext()
  26. const mutateApps = useContextSelector(AppsContext, state => state.mutateApps)
  27. const [showConfirmDelete, setShowConfirmDelete] = useState(false)
  28. const onDeleteClick: MouseEventHandler = useCallback((e) => {
  29. e.preventDefault()
  30. setShowConfirmDelete(true)
  31. }, [])
  32. const onConfirmDelete = useCallback(async () => {
  33. try {
  34. await deleteApp(app.id)
  35. notify({ type: 'success', message: t('app.appDeleted') })
  36. if (onDelete)
  37. onDelete()
  38. mutateApps()
  39. }
  40. catch (e: any) {
  41. notify({ type: 'error', message: `${t('app.appDeleteFailed')}${'message' in e ? `: ${e.message}` : ''}` })
  42. }
  43. setShowConfirmDelete(false)
  44. }, [app.id])
  45. return (
  46. <>
  47. <Link href={`/app/${app.id}/overview`} className={style.listItem}>
  48. <div className={style.listItemTitle}>
  49. <AppIcon size='small' icon={app.icon} background={app.icon_background} />
  50. <div className={style.listItemHeading}>
  51. <div className={style.listItemHeadingContent}>{app.name}</div>
  52. </div>
  53. { isCurrentWorkspaceManager
  54. && <span className={style.deleteAppIcon} onClick={onDeleteClick} />}
  55. </div>
  56. <div className={style.listItemDescription}>{app.model_config?.pre_prompt}</div>
  57. <div className={style.listItemFooter}>
  58. <AppModeLabel mode={app.mode} />
  59. </div>
  60. {showConfirmDelete && (
  61. <Confirm
  62. title={t('app.deleteAppConfirmTitle')}
  63. content={t('app.deleteAppConfirmContent')}
  64. isShow={showConfirmDelete}
  65. onClose={() => setShowConfirmDelete(false)}
  66. onConfirm={onConfirmDelete}
  67. onCancel={() => setShowConfirmDelete(false)}
  68. />
  69. )}
  70. </Link>
  71. </>
  72. )
  73. }
  74. export default AppCard