InAppNotificationElm.tsx 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import type { FC } from 'react';
  2. import React from 'react';
  3. import type { HasObjectId } from '@growi/core';
  4. import { UserPicture } from '@growi/ui/dist/components';
  5. import { apiv3Post } from '~/client/util/apiv3-client';
  6. import type { IInAppNotification } from '~/interfaces/in-app-notification';
  7. import { InAppNotificationStatuses } from '~/interfaces/in-app-notification';
  8. import { useSWRxInAppNotificationStatus } from '~/stores/in-app-notification';
  9. import { useModelNotification } from './ModelNotification';
  10. interface Props {
  11. notification: IInAppNotification & HasObjectId
  12. onUnopenedNotificationOpend?: () => void,
  13. }
  14. const InAppNotificationElm: FC<Props> = (props: Props) => {
  15. const { notification, onUnopenedNotificationOpend } = props;
  16. const modelNotificationUtils = useModelNotification(notification);
  17. const Notification = modelNotificationUtils?.Notification;
  18. const publishOpen = modelNotificationUtils?.publishOpen;
  19. const clickLink = modelNotificationUtils?.clickLink;
  20. const isDisabled = modelNotificationUtils?.isDisabled;
  21. const { mutate: mutateNotificationCount } = useSWRxInAppNotificationStatus();
  22. if (Notification == null) {
  23. return <></>;
  24. }
  25. const clickHandler = async(notification: IInAppNotification & HasObjectId): Promise<void> => {
  26. if (notification.status === InAppNotificationStatuses.STATUS_UNOPENED) {
  27. // set notification status "OPEND"
  28. await apiv3Post('/in-app-notification/open', { id: notification._id });
  29. onUnopenedNotificationOpend?.();
  30. mutateNotificationCount();
  31. }
  32. if (isDisabled) return;
  33. publishOpen?.();
  34. };
  35. const renderActionUserPictures = (): JSX.Element => {
  36. const actionUsers = notification.actionUsers;
  37. if (actionUsers.length < 1) {
  38. return <></>;
  39. }
  40. if (actionUsers.length === 1) {
  41. return <UserPicture user={actionUsers[0]} size="md" noTooltip />;
  42. }
  43. return (
  44. <div className="position-relative">
  45. <UserPicture user={actionUsers[0]} size="md" noTooltip />
  46. <div className="position-absolute" style={{ top: 10, left: 10 }}>
  47. <UserPicture user={actionUsers[1]} size="md" noTooltip />
  48. </div>
  49. </div>
  50. );
  51. };
  52. return (
  53. <div className="list-group-item list-group-item-action" style={{ cursor: 'pointer' }}>
  54. <a
  55. href={isDisabled ? undefined : clickLink}
  56. onClick={() => clickHandler(notification)}
  57. >
  58. <div className="d-flex align-items-center">
  59. <span
  60. className={`${notification.status === InAppNotificationStatuses.STATUS_UNOPENED
  61. ? 'grw-unopend-notification'
  62. : 'ms-2'
  63. } rounded-circle me-3`}
  64. >
  65. </span>
  66. {renderActionUserPictures()}
  67. <Notification />
  68. </div>
  69. </a>
  70. </div>
  71. );
  72. };
  73. export default InAppNotificationElm;