Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

index.tsx 1.5KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. 'use client'
  2. import { useEffect, useState } from 'react'
  3. import cn from '@/utils/classnames'
  4. export type AvatarProps = {
  5. name: string
  6. avatar: string | null
  7. size?: number
  8. className?: string
  9. textClassName?: string
  10. onError?: (x: boolean) => void
  11. }
  12. const Avatar = ({
  13. name,
  14. avatar,
  15. size = 30,
  16. className,
  17. textClassName,
  18. onError,
  19. }: AvatarProps) => {
  20. const avatarClassName = 'shrink-0 flex items-center rounded-full bg-primary-600'
  21. const style = { width: `${size}px`, height: `${size}px`, fontSize: `${size}px`, lineHeight: `${size}px` }
  22. const [imgError, setImgError] = useState(false)
  23. const handleError = () => {
  24. setImgError(true)
  25. onError?.(true)
  26. }
  27. // after uploaded, api would first return error imgs url: '.../files//file-preview/...'. Then return the right url, Which caused not show the avatar
  28. useEffect(() => {
  29. if(avatar && imgError)
  30. setImgError(false)
  31. }, [avatar])
  32. if (avatar && !imgError) {
  33. return (
  34. <img
  35. className={cn(avatarClassName, className)}
  36. style={style}
  37. alt={name}
  38. src={avatar}
  39. onError={handleError}
  40. onLoad={() => onError?.(false)}
  41. />
  42. )
  43. }
  44. return (
  45. <div
  46. className={cn(avatarClassName, className)}
  47. style={style}
  48. >
  49. <div
  50. className={cn(textClassName, 'scale-[0.4] text-center text-white')}
  51. style={style}
  52. >
  53. {name && name[0].toLocaleUpperCase()}
  54. </div>
  55. </div>
  56. )
  57. }
  58. export default Avatar