feat: user issue notifications (#1523)
* feat: added new issue subscriber table * dev: notification model * feat: added CRUD operation for issue subscriber * Revert "feat: added CRUD operation for issue subscriber" This reverts commit b22e0625768f0b096b5898936ace76d6882b0736. * feat: added CRUD operation for issue subscriber * dev: notification models and operations * dev: remove delete endpoint response data * dev: notification endpoints and fix bg worker for saving notifications * feat: added list and unsubscribe function in issue subscriber * dev: filter by snoozed and response update for list and permissions * dev: update issue notifications * dev: notification segregation * dev: update notifications * dev: notification filtering * dev: add issue name in notifications * dev: notification new endpoints * fix: pushing local settings * feat: notification workflow setup and made basic UI * style: improved UX with toast alerts and other interactions refactor: changed classnames according to new theme structure, changed all icons to material icons * feat: showing un-read notification count * feat: not showing 'subscribe' button on issue created by user & assigned to user not showing 'Create by you' for view & guest of the workspace --------- Co-authored-by: NarayanBavisetti <narayan3119@gmail.com> Co-authored-by: pablohashescobar <nikhilschacko@gmail.com>
This commit is contained in:
parent
6e9f3971a5
commit
16a7bd3bda
23 changed files with 4665 additions and 32 deletions
187
apps/app/hooks/use-user-notifications.tsx
Normal file
187
apps/app/hooks/use-user-notifications.tsx
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
import { useState } from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
// swr
|
||||
import useSWR from "swr";
|
||||
|
||||
// services
|
||||
import userNotificationServices from "services/notifications.service";
|
||||
|
||||
// fetch-keys
|
||||
import { UNREAD_NOTIFICATIONS_COUNT, USER_WORKSPACE_NOTIFICATIONS } from "constants/fetch-keys";
|
||||
|
||||
// type
|
||||
import type { NotificationType } from "types";
|
||||
|
||||
const useUserNotification = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
const [snoozed, setSnoozed] = useState<boolean>(false);
|
||||
const [archived, setArchived] = useState<boolean>(false);
|
||||
const [readNotification, setReadNotification] = useState<boolean>(false);
|
||||
const [selectedNotificationForSnooze, setSelectedNotificationForSnooze] = useState<string | null>(
|
||||
null
|
||||
);
|
||||
const [selectedTab, setSelectedTab] = useState<NotificationType>("assigned");
|
||||
|
||||
const { data: notifications, mutate: notificationsMutate } = useSWR(
|
||||
workspaceSlug
|
||||
? USER_WORKSPACE_NOTIFICATIONS(workspaceSlug.toString(), {
|
||||
type: selectedTab,
|
||||
snoozed,
|
||||
archived,
|
||||
read: selectedTab === null ? !readNotification : undefined,
|
||||
})
|
||||
: null,
|
||||
workspaceSlug
|
||||
? () =>
|
||||
userNotificationServices.getUserNotifications(workspaceSlug.toString(), {
|
||||
type: selectedTab,
|
||||
snoozed,
|
||||
archived,
|
||||
read: selectedTab === null ? !readNotification : undefined,
|
||||
})
|
||||
: 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) => {
|
||||
if (!workspaceSlug) return;
|
||||
const isRead =
|
||||
notifications?.find((notification) => notification.id === notificationId)?.read_at !== null;
|
||||
|
||||
if (isRead) {
|
||||
await userNotificationServices
|
||||
.markUserNotificationAsUnread(workspaceSlug.toString(), notificationId)
|
||||
.then(() => {
|
||||
notificationsMutate((prev) =>
|
||||
prev?.map((prevNotification) => {
|
||||
if (prevNotification.id === notificationId) {
|
||||
return {
|
||||
...prevNotification,
|
||||
read_at: null,
|
||||
};
|
||||
}
|
||||
return prevNotification;
|
||||
})
|
||||
);
|
||||
mutateNotificationCount();
|
||||
})
|
||||
.catch(() => {
|
||||
throw new Error("Something went wrong");
|
||||
});
|
||||
} else {
|
||||
await userNotificationServices
|
||||
.markUserNotificationAsRead(workspaceSlug.toString(), notificationId)
|
||||
.then(() => {
|
||||
notificationsMutate((prev) =>
|
||||
prev?.map((prevNotification) => {
|
||||
if (prevNotification.id === notificationId) {
|
||||
return {
|
||||
...prevNotification,
|
||||
read_at: new Date(),
|
||||
};
|
||||
}
|
||||
return prevNotification;
|
||||
})
|
||||
);
|
||||
mutateNotificationCount();
|
||||
})
|
||||
.catch(() => {
|
||||
throw new Error("Something went wrong");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const markNotificationArchivedStatus = async (notificationId: string) => {
|
||||
if (!workspaceSlug) return;
|
||||
const isArchived =
|
||||
notifications?.find((notification) => notification.id === notificationId)?.archived_at !==
|
||||
null;
|
||||
|
||||
if (isArchived) {
|
||||
await userNotificationServices
|
||||
.markUserNotificationAsUnarchived(workspaceSlug.toString(), notificationId)
|
||||
.then(() => {
|
||||
notificationsMutate();
|
||||
})
|
||||
.catch(() => {
|
||||
throw new Error("Something went wrong");
|
||||
});
|
||||
} else {
|
||||
await userNotificationServices
|
||||
.markUserNotificationAsArchived(workspaceSlug.toString(), notificationId)
|
||||
.then(() => {
|
||||
notificationsMutate((prev) =>
|
||||
prev?.filter((prevNotification) => prevNotification.id !== notificationId)
|
||||
);
|
||||
})
|
||||
.catch(() => {
|
||||
throw new Error("Something went wrong");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const markSnoozeNotification = async (notificationId: string, dateTime?: Date) => {
|
||||
if (!workspaceSlug) return;
|
||||
|
||||
const isSnoozed =
|
||||
notifications?.find((notification) => notification.id === notificationId)?.snoozed_till !==
|
||||
null;
|
||||
|
||||
if (isSnoozed) {
|
||||
await userNotificationServices
|
||||
.patchUserNotification(workspaceSlug.toString(), notificationId, {
|
||||
snoozed_till: null,
|
||||
})
|
||||
.then(() => {
|
||||
notificationsMutate();
|
||||
});
|
||||
} else
|
||||
await userNotificationServices
|
||||
.patchUserNotification(workspaceSlug.toString(), notificationId, {
|
||||
snoozed_till: dateTime,
|
||||
})
|
||||
.then(() => {
|
||||
notificationsMutate(
|
||||
(prevData) => prevData?.filter((prev) => prev.id !== notificationId) || []
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
notifications,
|
||||
notificationsMutate,
|
||||
markNotificationReadStatus,
|
||||
markNotificationArchivedStatus,
|
||||
markSnoozeNotification,
|
||||
snoozed,
|
||||
setSnoozed,
|
||||
archived,
|
||||
setArchived,
|
||||
readNotification,
|
||||
setReadNotification,
|
||||
selectedNotificationForSnooze,
|
||||
setSelectedNotificationForSnooze,
|
||||
selectedTab,
|
||||
setSelectedTab,
|
||||
totalNotificationCount: notificationCount
|
||||
? notificationCount.created_issues +
|
||||
notificationCount.watching_notifications +
|
||||
notificationCount.my_issues
|
||||
: null,
|
||||
notificationCount,
|
||||
mutateNotificationCount,
|
||||
};
|
||||
};
|
||||
|
||||
export default useUserNotification;
|
||||
Loading…
Add table
Add a link
Reference in a new issue