MembershipInfo.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import { FC, MouseEvent } from 'react'
  2. import { CSSTransition, SwitchTransition } from 'react-transition-group'
  3. import { absoluteRoutes } from '@/config/routes'
  4. import { useMediaMatch } from '@/hooks/useMediaMatch'
  5. import { cVar, transitions } from '@/styles'
  6. import { MembershipDetails, MembershipHeader, MembershipInfoContainer, StyledHandle } from './MembershipInfo.style'
  7. import { SvgActionEdit } from '../../assets/icons'
  8. import { Avatar } from '../Avatar'
  9. import { Button } from '../_buttons/Button'
  10. import { CopyAddressButton } from '../_buttons/CopyAddressButton/CopyAddressButton'
  11. import { SkeletonLoader } from '../_loaders/SkeletonLoader'
  12. export type MembershipInfoProps = {
  13. avatarUrl?: string | null
  14. avatarLoading?: boolean
  15. hasAvatarUploadFailed?: boolean
  16. onAvatarEditClick?: (event: MouseEvent<HTMLElement>) => void
  17. onImageValidation?: (validImage: boolean) => void
  18. handle?: string | null
  19. address?: string | null
  20. loading?: boolean
  21. isOwner?: boolean
  22. editable?: boolean
  23. className?: string
  24. }
  25. export const MembershipInfo: FC<MembershipInfoProps> = ({
  26. address,
  27. avatarUrl,
  28. avatarLoading,
  29. hasAvatarUploadFailed,
  30. onAvatarEditClick,
  31. onImageValidation,
  32. handle,
  33. loading,
  34. isOwner,
  35. editable,
  36. className,
  37. }) => {
  38. const smMatch = useMediaMatch('sm')
  39. return (
  40. <SwitchTransition>
  41. <CSSTransition
  42. key={String(loading)}
  43. timeout={parseInt(cVar('animationTimingFast', true))}
  44. classNames={transitions.names.fade}
  45. >
  46. <MembershipHeader className={className}>
  47. <MembershipInfoContainer>
  48. <Avatar
  49. size={smMatch ? 'preview' : 'channel-card'}
  50. editable={editable}
  51. onImageValidation={onImageValidation}
  52. onClick={onAvatarEditClick}
  53. assetUrl={avatarUrl}
  54. loading={avatarLoading}
  55. hasAvatarUploadFailed={hasAvatarUploadFailed}
  56. />
  57. <MembershipDetails>
  58. {loading ? (
  59. <SkeletonLoader width={200} height={smMatch ? 56 : 40} bottomSpace={8} />
  60. ) : (
  61. <StyledHandle as="h1" variant={smMatch ? 'h700' : 'h600'} margin={{ bottom: 2 }}>
  62. {handle || '\xa0'}
  63. </StyledHandle>
  64. )}
  65. {loading || !address ? (
  66. <SkeletonLoader width={140} height={24} />
  67. ) : (
  68. <CopyAddressButton address={address} />
  69. )}
  70. </MembershipDetails>
  71. </MembershipInfoContainer>
  72. {isOwner &&
  73. (loading ? (
  74. <SkeletonLoader width={smMatch ? 148 : '100%'} height={48} />
  75. ) : (
  76. <Button
  77. to={absoluteRoutes.viewer.editMembership()}
  78. icon={<SvgActionEdit />}
  79. size="large"
  80. variant="secondary"
  81. fullWidth={!smMatch}
  82. >
  83. Edit profile
  84. </Button>
  85. ))}
  86. </MembershipHeader>
  87. </CSSTransition>
  88. </SwitchTransition>
  89. )
  90. }