1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-24 20:36:40 +07:00
vault-frontend/src/components/main/Notifications/index.tsx
2020-11-06 12:15:07 +07:00

86 lines
2.6 KiB
TypeScript

import React, { FC, useMemo, useState, useCallback, useEffect } from 'react';
import { Icon } from '~/components/input/Icon';
import styles from './styles.module.scss';
import { connect } from 'react-redux';
import { selectAuthUpdates, selectAuthUser } from '~/redux/auth/selectors';
import pick from 'ramda/es/pick';
import classNames from 'classnames';
import * as AUTH_ACTIONS from '~/redux/auth/actions';
import { NotificationBubble } from '../../notifications/NotificationBubble';
import { INotification, IMessageNotification } from '~/redux/types';
const mapStateToProps = state => ({
user: pick(['last_seen_messages'], selectAuthUser(state)),
updates: selectAuthUpdates(state),
});
const mapDispatchToProps = {
authSetLastSeenMessages: AUTH_ACTIONS.authSetLastSeenMessages,
authOpenProfile: AUTH_ACTIONS.authOpenProfile,
};
type IProps = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
const NotificationsUnconnected: FC<IProps> = ({
updates: { last, notifications },
user: { last_seen_messages },
authSetLastSeenMessages,
authOpenProfile,
}) => {
const [visible, setVisible] = useState(false);
const has_new = useMemo(
() =>
notifications.length &&
last &&
Date.parse(last) &&
(!last_seen_messages ||
(Date.parse(last_seen_messages) && Date.parse(last) > Date.parse(last_seen_messages))),
[last, last_seen_messages, notifications]
);
const onNotificationClick = useCallback(
(notification: INotification) => {
switch (notification.type) {
case 'message':
return authOpenProfile(
(notification as IMessageNotification).content.from.username,
'messages'
);
default:
return;
}
},
[authOpenProfile]
);
const showList = useCallback(() => setVisible(true), [setVisible]);
const hideList = useCallback(() => setVisible(false), [setVisible]);
useEffect(() => {
if (!visible || !has_new || !last) return;
authSetLastSeenMessages(last);
}, [visible, last]);
return (
<div
className={classNames(styles.wrap, {
[styles.is_new]: has_new,
[styles.active]: notifications.length > 0,
})}
>
<div className={styles.icon} onFocus={showList} onBlur={hideList} tabIndex={-1}>
{has_new ? <Icon icon="bell_ring" size={24} /> : <Icon icon="bell" size={24} />}
</div>
{visible && (
<NotificationBubble notifications={notifications} onClick={onNotificationClick} />
)}
</div>
);
};
const Notifications = connect(
mapStateToProps,
mapDispatchToProps
)(NotificationsUnconnected);
export { Notifications };