InAppNotificationPage.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import type { FC } from 'react';
  2. import React, { useState } from 'react';
  3. import { LoadingSpinner } from '@growi/ui/dist/components';
  4. import { useAtomValue } from 'jotai';
  5. import { useTranslation } from 'next-i18next';
  6. import { apiv3Put } from '~/client/util/apiv3-client';
  7. import { InAppNotificationStatuses } from '~/interfaces/in-app-notification';
  8. import { showPageLimitationXLAtom } from '~/states/server-configurations';
  9. import { useSWRxInAppNotifications, useSWRxInAppNotificationStatus } from '~/stores/in-app-notification';
  10. import CustomNavAndContents from '../CustomNavigation/CustomNavAndContents';
  11. import PaginationWrapper from '../PaginationWrapper';
  12. import InAppNotificationList from './InAppNotificationList';
  13. export const InAppNotificationPage: FC = () => {
  14. const { t } = useTranslation('commons');
  15. const showPageLimitationXL = useAtomValue(showPageLimitationXLAtom);
  16. const limit = showPageLimitationXL != null ? showPageLimitationXL : 20;
  17. const InAppNotificationCategoryByStatus = (status?: InAppNotificationStatuses) => {
  18. const [activePage, setActivePage] = useState(1);
  19. const offset = (activePage - 1) * limit;
  20. let categoryStatus;
  21. switch (status) {
  22. case InAppNotificationStatuses.STATUS_UNOPENED:
  23. categoryStatus = InAppNotificationStatuses.STATUS_UNOPENED;
  24. break;
  25. default:
  26. }
  27. const { data: notificationData, mutate: mutateNotificationData } = useSWRxInAppNotifications(limit, offset, categoryStatus);
  28. const { mutate: mutateAllNotificationData } = useSWRxInAppNotifications(limit, offset, undefined);
  29. const { mutate: mutateNotificationCount } = useSWRxInAppNotificationStatus();
  30. const setAllNotificationPageNumber = (selectedPageNumber): void => {
  31. setActivePage(selectedPageNumber);
  32. };
  33. if (notificationData == null) {
  34. return (
  35. <div className="wiki" data-testid="grw-in-app-notification-page-spinner">
  36. <div className="text-muted text-center">
  37. <LoadingSpinner className="me-1 fs-3" />
  38. </div>
  39. </div>
  40. );
  41. }
  42. const updateUnopendNotificationStatusesToOpened = async() => {
  43. await apiv3Put('/in-app-notification/all-statuses-open');
  44. // mutate notification statuses in 'UNREAD' Category
  45. mutateNotificationData();
  46. // mutate notification statuses in 'ALL' Category
  47. mutateAllNotificationData();
  48. mutateNotificationCount();
  49. };
  50. return (
  51. <>
  52. {(status === InAppNotificationStatuses.STATUS_UNOPENED && notificationData.totalDocs > 0)
  53. && (
  54. <div className="mb-2 d-flex justify-content-end">
  55. <button
  56. type="button"
  57. className="btn btn-outline-primary"
  58. onClick={updateUnopendNotificationStatusesToOpened}
  59. >
  60. {t('in_app_notification.mark_all_as_read')}
  61. </button>
  62. </div>
  63. )}
  64. { notificationData != null && notificationData.docs.length === 0
  65. // no items
  66. ? t('in_app_notification.no_unread_messages')
  67. // render list-group
  68. : (
  69. <InAppNotificationList inAppNotificationData={notificationData} />
  70. )
  71. }
  72. {notificationData.totalDocs > 0 && (
  73. <div className="mt-4">
  74. <PaginationWrapper
  75. activePage={activePage}
  76. changePage={setAllNotificationPageNumber}
  77. totalItemsCount={notificationData.totalDocs}
  78. pagingLimit={notificationData.limit}
  79. align="center"
  80. size="sm"
  81. />
  82. </div>
  83. ) }
  84. </>
  85. );
  86. };
  87. const navTabMapping = {
  88. user_infomation: {
  89. Icon: () => <></>,
  90. Content: () => InAppNotificationCategoryByStatus(),
  91. i18n: t('in_app_notification.all'),
  92. },
  93. external_accounts: {
  94. Icon: () => <></>,
  95. Content: () => InAppNotificationCategoryByStatus(InAppNotificationStatuses.STATUS_UNOPENED),
  96. i18n: t('in_app_notification.unopend'),
  97. },
  98. };
  99. return (
  100. <div data-testid="grw-in-app-notification-page">
  101. <CustomNavAndContents navTabMapping={navTabMapping} tabContentClasses={['mt-4']} />
  102. </div>
  103. );
  104. };
  105. InAppNotificationPage.displayName = 'InAppNotificationPage';