feat: showing un-read notification count

This commit is contained in:
Dakshesh Jain 2023-07-17 13:59:26 +05:30
parent 82d03b4882
commit cc2146a404
6 changed files with 116 additions and 41 deletions

View File

@ -39,8 +39,6 @@ export const NotificationCard: React.FC<NotificationCardProps> = (props) => {
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
if (notification.data.issue_activity.field === "None") return null;
return ( return (
<div <div
key={notification.id} key={notification.id}
@ -88,30 +86,39 @@ export const NotificationCard: React.FC<NotificationCardProps> = (props) => {
</span> </span>
{notification.data.issue_activity.field !== "comment" && {notification.data.issue_activity.field !== "comment" &&
notification.data.issue_activity.verb}{" "} notification.data.issue_activity.verb}{" "}
{notification.data.issue_activity.field !== "comment" {notification.data.issue_activity.field === "comment"
? replaceUnderscoreIfSnakeCase(notification.data.issue_activity.field) ? "commented"
: "commented"}{" "} : notification.data.issue_activity.field === "None"
{notification.data.issue_activity.field !== "comment" ? "to" : ""} ? null
: replaceUnderscoreIfSnakeCase(notification.data.issue_activity.field)}{" "}
{notification.data.issue_activity.field !== "comment" &&
notification.data.issue_activity.field !== "None"
? "to"
: ""}
<span className="font-semibold text-custom-text-200"> <span className="font-semibold text-custom-text-200">
{" "} {" "}
{notification.data.issue_activity.field !== "comment" ? ( {notification.data.issue_activity.field !== "None" ? (
notification.data.issue_activity.field === "target_date" ? ( notification.data.issue_activity.field !== "comment" ? (
renderShortDateWithYearFormat(notification.data.issue_activity.new_value) notification.data.issue_activity.field === "target_date" ? (
) : notification.data.issue_activity.field === "attachment" ? ( renderShortDateWithYearFormat(notification.data.issue_activity.new_value)
"the issue" ) : notification.data.issue_activity.field === "attachment" ? (
) : stripHTML(notification.data.issue_activity.new_value).length > 55 ? ( "the issue"
stripHTML(notification.data.issue_activity.new_value).slice(0, 50) + "..." ) : stripHTML(notification.data.issue_activity.new_value).length > 55 ? (
stripHTML(notification.data.issue_activity.new_value).slice(0, 50) + "..."
) : (
stripHTML(notification.data.issue_activity.new_value)
)
) : ( ) : (
stripHTML(notification.data.issue_activity.new_value) <span>
{`"`}
{notification.data.issue_activity.new_value.length > 55
? notification?.data?.issue_activity?.issue_comment?.slice(0, 50) + "..."
: notification.data.issue_activity.issue_comment}
{`"`}
</span>
) )
) : ( ) : (
<span> "the issue and assigned it to you."
{`"`}
{notification.data.issue_activity.new_value.length > 55
? notification?.data?.issue_activity?.issue_comment?.slice(0, 50) + "..."
: notification.data.issue_activity.issue_comment}
{`"`}
</span>
)} )}
</span> </span>
</p> </p>

View File

@ -5,7 +5,7 @@ import Image from "next/image";
// hooks // hooks
import useTheme from "hooks/use-theme"; import useTheme from "hooks/use-theme";
import { Popover, Transition, Menu } from "@headlessui/react"; import { Popover, Transition } from "@headlessui/react";
// hooks // hooks
import useUserNotification from "hooks/use-user-notifications"; import useUserNotification from "hooks/use-user-notifications";
@ -14,27 +14,12 @@ import useUserNotification from "hooks/use-user-notifications";
import { Spinner, Icon } from "components/ui"; import { Spinner, Icon } from "components/ui";
import { SnoozeNotificationModal, NotificationCard } from "components/notifications"; import { SnoozeNotificationModal, NotificationCard } from "components/notifications";
// helpers
import { getNumberCount } from "helpers/string.helper";
// type // type
import type { NotificationType } from "types"; import type { NotificationType } from "types";
const notificationTabs: Array<{
label: string;
value: NotificationType;
}> = [
{
label: "My Issues",
value: "assigned",
},
{
label: "Created by me",
value: "created",
},
{
label: "Subscribed",
value: "watching",
},
];
export const NotificationPopover = () => { export const NotificationPopover = () => {
const { const {
notifications, notifications,
@ -52,11 +37,35 @@ export const NotificationPopover = () => {
markNotificationArchivedStatus, markNotificationArchivedStatus,
markNotificationReadStatus, markNotificationReadStatus,
markSnoozeNotification, markSnoozeNotification,
notificationCount,
totalNotificationCount,
} = useUserNotification(); } = useUserNotification();
// theme context // theme context
const { collapsed: sidebarCollapse } = useTheme(); const { collapsed: sidebarCollapse } = useTheme();
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_notifications,
},
];
return ( return (
<> <>
<SnoozeNotificationModal <SnoozeNotificationModal
@ -85,6 +94,11 @@ export const NotificationPopover = () => {
> >
<Icon iconName="notifications" /> <Icon iconName="notifications" />
{sidebarCollapse ? null : <span>Notifications</span>} {sidebarCollapse ? null : <span>Notifications</span>}
{totalNotificationCount && totalNotificationCount > 0 ? (
<span className="ml-auto bg-custom-primary-300 rounded-full text-xs text-white px-1.5">
{getNumberCount(totalNotificationCount)}
</span>
) : null}
</Popover.Button> </Popover.Button>
<Transition <Transition
as={Fragment} as={Fragment}
@ -190,6 +204,11 @@ export const NotificationPopover = () => {
}`} }`}
> >
{tab.label} {tab.label}
{tab.unreadCount && tab.unreadCount > 0 ? (
<span className="ml-3 bg-custom-background-1000/5 rounded-full text-custom-text-100 text-xs px-1.5">
{getNumberCount(tab.unreadCount)}
</span>
) : null}
</button> </button>
))} ))}
</nav> </nav>

View File

@ -241,3 +241,6 @@ export const USER_WORKSPACE_NOTIFICATIONS_DETAILS = (
notificationId: string notificationId: string
) => ) =>
`USER_WORKSPACE_NOTIFICATIONS_DETAILS_${workspaceSlug.toUpperCase()}_${notificationId.toUpperCase()}`; `USER_WORKSPACE_NOTIFICATIONS_DETAILS_${workspaceSlug.toUpperCase()}_${notificationId.toUpperCase()}`;
export const UNREAD_NOTIFICATIONS_COUNT = (workspaceSlug: string) =>
`UNREAD_NOTIFICATIONS_COUNT_${workspaceSlug.toUpperCase()}`;

View File

@ -134,3 +134,20 @@ export const stripHTML = (html: string) => {
tmp.innerHTML = html; tmp.innerHTML = html;
return tmp.textContent || tmp.innerText || ""; return tmp.textContent || tmp.innerText || "";
}; };
/**
* @description: This function return number count in string if number is more than 100 then it will return 99+
* @param {number} number
* @return {string}
* @example:
* const number = 100;
* const text = getNumberCount(number);
* console.log(text); // 99+
*/
export const getNumberCount = (number: number): string => {
if (number > 99) {
return "99+";
}
return number.toString();
};

View File

@ -9,7 +9,7 @@ import useSWR from "swr";
import userNotificationServices from "services/notifications.service"; import userNotificationServices from "services/notifications.service";
// fetch-keys // fetch-keys
import { USER_WORKSPACE_NOTIFICATIONS } from "constants/fetch-keys"; import { UNREAD_NOTIFICATIONS_COUNT, USER_WORKSPACE_NOTIFICATIONS } from "constants/fetch-keys";
// type // type
import type { NotificationType } from "types"; import type { NotificationType } from "types";
@ -46,6 +46,14 @@ const useUserNotification = () => {
: null : null
); );
const { data: notificationCount, mutate: mutateNotificationCount } = useSWR(
workspaceSlug ? UNREAD_NOTIFICATIONS_COUNT(workspaceSlug.toString()) : null,
() =>
workspaceSlug
? userNotificationServices.getUnreadNotificationsCount(workspaceSlug.toString())
: null
);
const markNotificationReadStatus = async (notificationId: string) => { const markNotificationReadStatus = async (notificationId: string) => {
if (!workspaceSlug) return; if (!workspaceSlug) return;
const isRead = const isRead =
@ -66,6 +74,7 @@ const useUserNotification = () => {
return prevNotification; return prevNotification;
}) })
); );
mutateNotificationCount();
}) })
.catch(() => { .catch(() => {
throw new Error("Something went wrong"); throw new Error("Something went wrong");
@ -85,6 +94,7 @@ const useUserNotification = () => {
return prevNotification; return prevNotification;
}) })
); );
mutateNotificationCount();
}) })
.catch(() => { .catch(() => {
throw new Error("Something went wrong"); throw new Error("Something went wrong");
@ -164,6 +174,13 @@ const useUserNotification = () => {
setSelectedNotificationForSnooze, setSelectedNotificationForSnooze,
selectedTab, selectedTab,
setSelectedTab, setSelectedTab,
totalNotificationCount: notificationCount
? notificationCount.created_issues +
notificationCount.watching_notifications +
notificationCount.my_issues
: null,
notificationCount,
mutateNotificationCount,
}; };
}; };

View File

@ -155,6 +155,18 @@ class UserNotificationsServices extends APIService {
throw error?.response?.data; throw error?.response?.data;
}); });
} }
async getUnreadNotificationsCount(workspaceSlug: string): Promise<{
created_issues: number;
my_issues: number;
watching_notifications: number;
}> {
return this.get(`/api/workspaces/${workspaceSlug}/users/notifications/unread/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
} }
const userNotificationServices = new UserNotificationsServices(); const userNotificationServices = new UserNotificationsServices();