RecentActivity.tsx 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import React, {
  2. useState, useCallback, useEffect, type JSX,
  3. } from 'react';
  4. import { toastError } from '~/client/util/toastr';
  5. import type { IActivityHasId, ActivityHasUserId } from '~/interfaces/activity';
  6. import { useSWRxRecentActivity } from '~/stores/recent-activity';
  7. import loggerFactory from '~/utils/logger';
  8. import PaginationWrapper from '../PaginationWrapper';
  9. import { ActivityListItem } from './ActivityListItem';
  10. const logger = loggerFactory('growi:RecentActivity');
  11. type RecentActivityProps = {
  12. userId: string,
  13. }
  14. const hasUser = (activity: IActivityHasId): activity is ActivityHasUserId => {
  15. return activity.user != null
  16. && typeof activity.user === 'object';
  17. };
  18. export const RecentActivity = (props: RecentActivityProps): JSX.Element => {
  19. const { userId } = props;
  20. const [activities, setActivities] = useState<ActivityHasUserId[]>([]);
  21. const [activePage, setActivePage] = useState(1);
  22. const [limit] = useState(10);
  23. const [offset, setOffset] = useState(0);
  24. const { data: paginatedData, error } = useSWRxRecentActivity(limit, offset, userId);
  25. const handlePage = useCallback(async(selectedPage: number) => {
  26. const newOffset = (selectedPage - 1) * limit;
  27. setOffset(newOffset);
  28. setActivePage(selectedPage);
  29. }, [limit]);
  30. useEffect(() => {
  31. if (error) {
  32. logger.error('Failed to fetch recent activity data', error);
  33. toastError(error);
  34. return;
  35. }
  36. if (paginatedData) {
  37. const activitiesWithPages = paginatedData.docs
  38. .filter(hasUser);
  39. setActivities(activitiesWithPages);
  40. }
  41. }, [paginatedData, error]);
  42. const totalItemsCount = paginatedData?.totalDocs || 0;
  43. const needsPagination = totalItemsCount > limit;
  44. return (
  45. <div className="page-list-container-activity">
  46. <ul className="page-list-ul page-list-ul-flat mb-3">
  47. {activities.map(activity => (
  48. <li key={`recent-activity-view:${activity._id}`} className="mt-4">
  49. <ActivityListItem activity={activity} />
  50. </li>
  51. ))}
  52. </ul>
  53. {needsPagination && (
  54. <PaginationWrapper
  55. activePage={activePage}
  56. changePage={handlePage}
  57. totalItemsCount={totalItemsCount}
  58. pagingLimit={limit}
  59. align="center"
  60. size="sm"
  61. />
  62. )}
  63. </div>
  64. );
  65. };