AppCard.tsx 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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 from '@/context/app-context'
  15. export type AppCardProps = {
  16. app: App
  17. }
  18. const AppCard = ({
  19. app,
  20. }: AppCardProps) => {
  21. const { t } = useTranslation()
  22. const { notify } = useContext(ToastContext)
  23. const mutateApps = useContextSelector(AppsContext, state => state.mutateApps)
  24. const [showConfirmDelete, setShowConfirmDelete] = useState(false)
  25. const onDeleteClick: MouseEventHandler = useCallback((e) => {
  26. e.preventDefault()
  27. setShowConfirmDelete(true)
  28. }, [])
  29. const onConfirmDelete = useCallback(async () => {
  30. try {
  31. await deleteApp(app.id)
  32. notify({ type: 'success', message: t('app.appDeleted') })
  33. mutateApps()
  34. }
  35. catch (e: any) {
  36. notify({ type: 'error', message: `${t('app.appDeleteFailed')}${'message' in e ? `: ${e.message}` : ''}` })
  37. }
  38. setShowConfirmDelete(false)
  39. }, [app.id])
  40. return (
  41. <>
  42. <Link href={`/app/${app.id}/overview`} className={style.listItem}>
  43. <div className={style.listItemTitle}>
  44. <AppIcon size='small' />
  45. <div className={style.listItemHeading}>
  46. <div className={style.listItemHeadingContent}>{app.name}</div>
  47. </div>
  48. <span className={style.deleteAppIcon} onClick={onDeleteClick} />
  49. </div>
  50. <div className={style.listItemDescription}>{app.model_config?.pre_prompt}</div>
  51. <div className={style.listItemFooter}>
  52. <AppModeLabel mode={app.mode} />
  53. </div>
  54. {showConfirmDelete && (
  55. <Confirm
  56. title={t('app.deleteAppConfirmTitle')}
  57. content={t('app.deleteAppConfirmContent')}
  58. isShow={showConfirmDelete}
  59. onClose={() => setShowConfirmDelete(false)}
  60. onConfirm={onConfirmDelete}
  61. onCancel={() => setShowConfirmDelete(false)}
  62. />
  63. )}
  64. </Link>
  65. </>
  66. )
  67. }
  68. export default AppCard