PersonalDropdown.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import type { JSX } from 'react';
  2. import Link from 'next/link';
  3. import { pagePathUtils } from '@growi/core/dist/utils';
  4. import { UserPicture } from '@growi/ui/dist/components';
  5. import { useAtomValue } from 'jotai';
  6. import { useTranslation } from 'next-i18next';
  7. import {
  8. DropdownItem,
  9. DropdownMenu,
  10. DropdownToggle,
  11. UncontrolledDropdown,
  12. } from 'reactstrap';
  13. import { apiv3Post } from '~/client/util/apiv3-client';
  14. import { toastError } from '~/client/util/toastr';
  15. import { useCurrentUser } from '~/states/global';
  16. import { disableUserPagesAtom } from '~/states/server-configurations';
  17. import { SkeletonItem } from './SkeletonItem';
  18. import styles from './PersonalDropdown.module.scss';
  19. export const PersonalDropdown = (): JSX.Element => {
  20. const { t } = useTranslation('commons');
  21. const currentUser = useCurrentUser();
  22. const disableUserPages = useAtomValue(disableUserPagesAtom);
  23. if (currentUser == null) {
  24. return <SkeletonItem />;
  25. }
  26. const logoutHandler = async () => {
  27. try {
  28. await apiv3Post('/logout');
  29. window.location.reload();
  30. } catch (err) {
  31. toastError(err);
  32. }
  33. };
  34. return (
  35. <UncontrolledDropdown direction="end">
  36. <DropdownToggle
  37. className={`btn btn-primary ${styles['btn-personal-dropdown']} opacity-100`}
  38. data-testid="personal-dropdown-button"
  39. >
  40. <UserPicture user={currentUser} noLink noTooltip />
  41. </DropdownToggle>
  42. <DropdownMenu
  43. container="body"
  44. data-testid="personal-dropdown-menu"
  45. className={styles['personal-dropdown-menu']}
  46. >
  47. <DropdownItem className={styles['personal-dropdown-header']} header>
  48. <div className="mt-2 mb-3">
  49. <UserPicture user={currentUser} size="lg" noLink noTooltip />
  50. </div>
  51. <div className="ms-1 fs-6">{currentUser.name}</div>
  52. <div className="d-flex align-items-center my-2">
  53. <small className="material-symbols-outlined me-1 pb-0 fs-6">
  54. person
  55. </small>
  56. <span>{currentUser.username}</span>
  57. </div>
  58. <div className="d-flex align-items-center">
  59. <span className="material-symbols-outlined me-1 pb-0 fs-6">
  60. mail
  61. </span>
  62. <span className="item-text-email">{currentUser.email}</span>
  63. </div>
  64. </DropdownItem>
  65. <DropdownItem className="my-3" divider />
  66. {!disableUserPages && (
  67. <Link
  68. href={pagePathUtils.userHomepagePath(currentUser)}
  69. data-testid="grw-personal-dropdown-menu-user-home"
  70. >
  71. <DropdownItem
  72. className={`my-1 ${styles['personal-dropdown-item']}`}
  73. >
  74. <span className="d-flex align-items-center">
  75. <span className="item-icon material-symbols-outlined me-2 pb-0 fs-6">
  76. home
  77. </span>
  78. <span className="item-text">{t('personal_dropdown.home')}</span>
  79. </span>
  80. </DropdownItem>
  81. </Link>
  82. )}
  83. <Link href="/me" data-testid="grw-personal-dropdown-menu-user-settings">
  84. <DropdownItem className={`my-1 ${styles['personal-dropdown-item']}`}>
  85. <span className="d-flex align-items-center">
  86. <span className="item-icon material-symbols-outlined me-2 pb-0 fs-6">
  87. discover_tune
  88. </span>
  89. <span className="item-text">
  90. {t('personal_dropdown.settings')}
  91. </span>
  92. </span>
  93. </DropdownItem>
  94. </Link>
  95. <DropdownItem
  96. data-testid="logout-button"
  97. onClick={logoutHandler}
  98. className={`my-1 ${styles['personal-dropdown-item']}`}
  99. >
  100. <span className="d-flex align-items-center">
  101. <span className="item-icon material-symbols-outlined me-2 pb-0 fs-6">
  102. logout
  103. </span>
  104. <span className="item-text">{t('Sign out')}</span>
  105. </span>
  106. </DropdownItem>
  107. </DropdownMenu>
  108. </UncontrolledDropdown>
  109. );
  110. };