plane/web/components/notifications/notification-header.tsx

222 lines
7.1 KiB
TypeScript
Raw Normal View History

import React from "react";
import { ArrowLeft, CheckCheck, Clock, ListFilter, MoreVertical, RefreshCw, X } from "lucide-react";
// components
import { ArchiveIcon, CustomMenu, Tooltip } from "@plane/ui";
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
// ui
// hooks
import {
ARCHIVED_NOTIFICATIONS,
NOTIFICATIONS_READ,
SNOOZED_NOTIFICATIONS,
UNREAD_NOTIFICATIONS,
} from "constants/event-tracker";
import { getNumberCount } from "helpers/string.helper";
import { useEventTracker } from "hooks/store";
import { usePlatformOS } from "hooks/use-platform-os";
// helpers
// type
import type { NotificationType, NotificationCount } from "@plane/types";
// constants
type NotificationHeaderProps = {
notificationCount?: NotificationCount | null;
notificationMutate: () => void;
closePopover: () => void;
isRefreshing?: boolean;
snoozed: boolean;
archived: boolean;
readNotification: boolean;
selectedTab: NotificationType;
setSnoozed: React.Dispatch<React.SetStateAction<boolean>>;
setArchived: React.Dispatch<React.SetStateAction<boolean>>;
setReadNotification: React.Dispatch<React.SetStateAction<boolean>>;
setSelectedTab: React.Dispatch<React.SetStateAction<NotificationType>>;
2023-08-28 07:56:38 +00:00
markAllNotificationsAsRead: () => Promise<void>;
};
export const NotificationHeader: React.FC<NotificationHeaderProps> = (props) => {
const {
notificationCount,
notificationMutate,
closePopover,
isRefreshing,
snoozed,
archived,
readNotification,
selectedTab,
setSnoozed,
setArchived,
setReadNotification,
setSelectedTab,
2023-08-28 07:56:38 +00:00
markAllNotificationsAsRead,
} = props;
// store hooks
const { captureEvent } = useEventTracker();
// hooks
const { isMobile } = usePlatformOS();
const notificationTabs: Array<{
label: string;
value: NotificationType;
unreadCount?: number;
}> = [
{
label: "My Issues",
value: "assigned",
unreadCount: notificationCount?.my_issues,
},
{
label: "Created by me",
value: "created",
unreadCount: notificationCount?.created_issues,
},
{
label: "Subscribed",
value: "watching",
unreadCount: notificationCount?.watching_issues,
},
];
return (
<>
<div className="flex items-center justify-between px-5 pt-5">
<div className="flex items-center gap-x-2 ">
<SidebarHamburgerToggle />
<h2 className="md:text-xl md:font-semibold">Notifications</h2>
</div>
<div className="flex items-center justify-center gap-x-4 text-custom-text-200">
<Tooltip tooltipContent="Refresh" isMobile={isMobile}>
<button
type="button"
onClick={() => {
notificationMutate();
}}
>
<RefreshCw className={`h-3.5 w-3.5 ${isRefreshing ? "animate-spin" : ""}`} />
</button>
</Tooltip>
<Tooltip tooltipContent="Unread notifications" isMobile={isMobile}>
<button
type="button"
onClick={() => {
setSnoozed(false);
setArchived(false);
setReadNotification((prev) => !prev);
captureEvent(UNREAD_NOTIFICATIONS);
}}
>
<ListFilter className="h-3.5 w-3.5" />
</button>
</Tooltip>
2023-08-28 07:56:38 +00:00
<CustomMenu
customButton={
<div className="grid place-items-center ">
<MoreVertical className="h-3.5 w-3.5" />
2023-08-28 07:56:38 +00:00
</div>
}
closeOnSelect
2023-08-28 07:56:38 +00:00
>
<CustomMenu.MenuItem
onClick={() => {
markAllNotificationsAsRead();
captureEvent(NOTIFICATIONS_READ);
}}
>
2023-08-28 07:56:38 +00:00
<div className="flex items-center gap-2">
<CheckCheck className="h-3.5 w-3.5" />
2023-08-28 07:56:38 +00:00
Mark all as read
</div>
</CustomMenu.MenuItem>
<CustomMenu.MenuItem
onClick={() => {
setArchived(false);
setReadNotification(false);
setSnoozed((prev) => !prev);
captureEvent(SNOOZED_NOTIFICATIONS);
}}
>
2023-08-28 07:56:38 +00:00
<div className="flex items-center gap-2">
<Clock className="h-3.5 w-3.5" />
2023-08-28 07:56:38 +00:00
Show snoozed
</div>
</CustomMenu.MenuItem>
<CustomMenu.MenuItem
onClick={() => {
setSnoozed(false);
setReadNotification(false);
setArchived((prev) => !prev);
captureEvent(ARCHIVED_NOTIFICATIONS);
}}
>
2023-08-28 07:56:38 +00:00
<div className="flex items-center gap-2">
<ArchiveIcon className="h-3.5 w-3.5" />
2023-08-28 07:56:38 +00:00
Show archived
</div>
</CustomMenu.MenuItem>
</CustomMenu>
<div className="hidden md:block">
<Tooltip tooltipContent="Close" isMobile={isMobile}>
<button type="button" onClick={() => closePopover()}>
<X className="h-3.5 w-3.5" />
</button>
</Tooltip>
</div>
</div>
</div>
<div className="mt-5 w-full border-b border-custom-border-300 px-5">
{snoozed || archived || readNotification ? (
<button
type="button"
onClick={() => {
setSnoozed(false);
setArchived(false);
setReadNotification(false);
}}
>
<h4 className="flex items-center gap-2 pb-4">
<ArrowLeft className="h-3.5 w-3.5" />
<span className="ml-2 font-medium">
{snoozed
? "Snoozed Notifications"
: readNotification
? "Unread Notifications"
: "Archived Notifications"}
</span>
</h4>
</button>
) : (
<nav className="flex space-x-5 overflow-x-auto" aria-label="Tabs">
{notificationTabs.map((tab) => (
<button
type="button"
key={tab.value}
onClick={() => setSelectedTab(tab.value)}
className={`whitespace-nowrap border-b-2 px-1 pb-4 text-sm font-medium outline-none ${
tab.value === selectedTab
? "border-custom-primary-100 text-custom-primary-100"
: "border-transparent text-custom-text-200"
}`}
>
{tab.label}
{tab.unreadCount && tab.unreadCount > 0 ? (
<span
className={`ml-2 rounded-full px-2 py-0.5 text-xs ${
tab.value === selectedTab
? "bg-custom-primary-100 text-white"
: "bg-custom-background-80 text-custom-text-200"
}`}
>
{getNumberCount(tab.unreadCount)}
</span>
) : null}
</button>
))}
</nav>
)}
</div>
</>
);
};