You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
79 lines
2.5 KiB
79 lines
2.5 KiB
import React from 'react';
|
|
|
|
import { FiBell, FiX } from 'react-icons/fi';
|
|
|
|
import { shift, useFloating } from '@floating-ui/react-dom';
|
|
import { Popover } from '@headlessui/react';
|
|
import { useAppSelector } from '@hooks/useAppSelector';
|
|
import { Button, IconButton } from '@meshtastic/components';
|
|
|
|
export const Notifications = (): JSX.Element => {
|
|
const [unreadCount, setUnreadCount] = React.useState(0);
|
|
const notifications = useAppSelector((state) => state.app.notifications);
|
|
|
|
const { x, y, reference, floating, strategy } = useFloating({
|
|
placement: 'bottom',
|
|
middleware: [shift()],
|
|
});
|
|
|
|
React.useEffect(() => {
|
|
setUnreadCount(
|
|
notifications.filter((notification) => !notification.read).length,
|
|
);
|
|
}, [notifications]);
|
|
|
|
return (
|
|
<Popover>
|
|
<Popover.Button as="div" className="relative" ref={reference}>
|
|
<IconButton icon={<FiBell className="w-5 h-5" />} />
|
|
{unreadCount > 0 && (
|
|
<div className="absolute pointer-events-none top-1 right-1">
|
|
<div className="w-3 h-3 text-xs font-semibold leading-3 text-center text-white bg-orange-500 rounded-full">
|
|
{unreadCount}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</Popover.Button>
|
|
|
|
<Popover.Panel
|
|
ref={floating}
|
|
style={{
|
|
position: strategy,
|
|
top: y ?? '',
|
|
left: x ?? '',
|
|
}}
|
|
className="fixed z-50 border border-gray-300 rounded-md shadow-md w-72 bg-primaryDark dark:border-gray-600"
|
|
>
|
|
<div className="divide-y divide-gray-600">
|
|
{notifications.map((notification, index) => (
|
|
<div
|
|
key={index}
|
|
className={`p-1 flex text-sm justify-between ${
|
|
notification.read
|
|
? 'text-gray-600 dark:text-gray-300'
|
|
: 'text-gray-900 dark:text-white'
|
|
}`}
|
|
>
|
|
<div className="my-auto">{notification.icon}</div>
|
|
|
|
<div className="my-auto font-light">{notification.title}</div>
|
|
|
|
<div className="flex space-x-1">
|
|
{notification.action ? (
|
|
<div className="my-auto w-18">
|
|
<Button border onClick={notification.action.action}>
|
|
{notification.action.message}
|
|
</Button>
|
|
</div>
|
|
) : (
|
|
<div className="w-16" />
|
|
)}
|
|
<IconButton icon={<FiX />} />
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</Popover.Panel>
|
|
</Popover>
|
|
);
|
|
};
|
|
|