import classNames from 'classnames'; import React, { useState, useEffect, useRef, createContext } from 'react'; import { ModalContextProvider, ModalTrigger, Modal } from '../../data-display/Modal'; import { Bell } from './Bell'; import ReactMarkdown from 'react-markdown'; import { UrlObject } from 'query-string'; /* individual items to be included in the dropdown */ export interface NotificationItem { className?: string; label?: string; href?: string; content?: string; header?: string; isRead?: boolean; id?: string; } export interface NotificationDropdownProps { className?: string; id?: string; notifyLevel?: string; hasUnread?: boolean; isHidden?: boolean; items: NotificationItem[]; isRight?: boolean; isModal?: boolean; link?: string; } export const NotificationDropdown: React.FC = (props) => { const [isActive, setIsActive] = useState(false); /* state for the dropdown menu */ /* add reference for closing dropdown, if clicked outside then close the dropdown */ const dropdownRef = useRef(null); const handleClickOutside = (e: MouseEvent) => { if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) { setIsActive(false); } }; useEffect(() => { document.addEventListener('mousedown', handleClickOutside); return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, []); /* map a list of messages with id name and isread state */ const [unreadMessages, setUnreadMessages] = useState( props.items.map((item, i) => ({ id: item.id && item.id, isRead: false })) ); /* state for displaying the red dot next to the bell */ const [hasUnreadMessages, setHasUnreadMessages] = useState( props.hasUnread ? props.hasUnread : false ); let handleItemClick; if (props.notifyLevel == 'Message') { /* handler for each menu item */ handleItemClick = async (e: any, messageId: string | undefined) => { /** prevent the dropwdown from closing */ e.stopPropagation(); /* when clicked, the corresponding message will update its isRead to true */ const updatedMessages = unreadMessages.map((message) => { if (message.id === messageId) { return { ...message, isRead: true }; } return message; }); setUnreadMessages(updatedMessages); setHasUnreadMessages(updatedMessages.some((message) => !message.isRead)); /* TODO: add post method to the api for each message */ }; } else { handleItemClick = (e: any) => { e.stopPropagation(); }; } if (props.isHidden) { return
; } else { return (
{ setIsActive(!isActive); if (props.notifyLevel !== 'message') { setHasUnreadMessages(false); } }} ref={dropdownRef} > {/** * Link content is populated by children prop * This is the only way a dash component can take a component as a prop */}
{props.items.map((item, i) => { return (
handleItemClick(e, item.id)}> {props.notifyLevel == 'message' ? ( !unreadMessages.find((message) => message.id === item.id)?.isRead && ( ) ) : ( )} {item.label}
{item.header}
{item.content ? item.content : ' '}
); })} More
); } }; NotificationDropdown.defaultProps = { items: [] }; export default NotificationDropdown;