file-image-item.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import { useState } from 'react'
  2. import {
  3. RiCloseLine,
  4. RiDownloadLine,
  5. } from '@remixicon/react'
  6. import FileImageRender from '../file-image-render'
  7. import type { FileEntity } from '../types'
  8. import {
  9. downloadFile,
  10. fileIsUploaded,
  11. } from '../utils'
  12. import Button from '@/app/components/base/button'
  13. import ProgressCircle from '@/app/components/base/progress-bar/progress-circle'
  14. import { ReplayLine } from '@/app/components/base/icons/src/vender/other'
  15. import ImagePreview from '@/app/components/base/image-uploader/image-preview'
  16. type FileImageItemProps = {
  17. file: FileEntity
  18. showDeleteAction?: boolean
  19. showDownloadAction?: boolean
  20. canPreview?: boolean
  21. onRemove?: (fileId: string) => void
  22. onReUpload?: (fileId: string) => void
  23. }
  24. const FileImageItem = ({
  25. file,
  26. showDeleteAction,
  27. showDownloadAction,
  28. canPreview,
  29. onRemove,
  30. onReUpload,
  31. }: FileImageItemProps) => {
  32. const { id, progress, base64Url, url, name } = file
  33. const [imagePreviewUrl, setImagePreviewUrl] = useState('')
  34. return (
  35. <>
  36. <div
  37. className='group/file-image relative cursor-pointer'
  38. onClick={() => canPreview && setImagePreviewUrl(url || '')}
  39. >
  40. {
  41. showDeleteAction && (
  42. <Button
  43. className='hidden group-hover/file-image:flex absolute -right-1.5 -top-1.5 p-0 w-5 h-5 rounded-full z-[11]'
  44. onClick={() => onRemove?.(id)}
  45. >
  46. <RiCloseLine className='w-4 h-4 text-components-button-secondary-text' />
  47. </Button>
  48. )
  49. }
  50. <FileImageRender
  51. className='w-[68px] h-[68px] shadow-md'
  52. imageUrl={base64Url || url || ''}
  53. showDownloadAction={showDownloadAction}
  54. />
  55. {
  56. progress >= 0 && !fileIsUploaded(file) && (
  57. <div className='absolute inset-0 flex items-center justify-center border-[2px] border-effects-image-frame bg-background-overlay-alt z-10'>
  58. <ProgressCircle
  59. percentage={progress}
  60. size={12}
  61. circleStrokeColor='stroke-components-progress-white-border'
  62. circleFillColor='fill-transparent'
  63. sectorFillColor='fill-components-progress-white-progress'
  64. />
  65. </div>
  66. )
  67. }
  68. {
  69. progress === -1 && (
  70. <div className='absolute inset-0 flex items-center justify-center border-[2px] border-state-destructive-border bg-background-overlay-destructive z-10'>
  71. <ReplayLine
  72. className='w-5 h-5'
  73. onClick={() => onReUpload?.(id)}
  74. />
  75. </div>
  76. )
  77. }
  78. {
  79. showDownloadAction && (
  80. <div className='hidden group-hover/file-image:block absolute inset-0.5 bg-background-overlay-alt bg-opacity-[0.3] z-10'>
  81. <div
  82. className='absolute bottom-0.5 right-0.5 flex items-center justify-center w-6 h-6 rounded-lg bg-components-actionbar-bg shadow-md'
  83. onClick={(e) => {
  84. e.stopPropagation()
  85. downloadFile(url || '', name)
  86. }}
  87. >
  88. <RiDownloadLine className='w-4 h-4 text-text-tertiary' />
  89. </div>
  90. </div>
  91. )
  92. }
  93. </div>
  94. {
  95. imagePreviewUrl && canPreview && (
  96. <ImagePreview
  97. title={name}
  98. url={imagePreviewUrl}
  99. onCancel={() => setImagePreviewUrl('')}
  100. />
  101. )
  102. }
  103. </>
  104. )
  105. }
  106. export default FileImageItem