UNPKG

@replyke/core

Version:

Replyke: Build interactive apps with social features like comments, votes, feeds, user lists, notifications, and more.

162 lines 6.52 kB
import { useCallback } from "react"; import { useReplykeDispatch, useReplykeSelector } from "../../store/hooks"; import { loadMore as loadMoreAction, resetNotifications, setLoading, addNotifications, markAsReadLocally, markAllAsReadLocally, setUnreadCount, selectCurrentProjectId, selectAppNotificationsPage, selectAppNotificationsLimit, } from "../../store/slices/appNotificationsSlice"; import { useLazyFetchAppNotificationsQuery, useMarkNotificationAsReadMutation, useMarkAllNotificationsAsReadMutation, useLazyCountUnreadNotificationsQuery, } from "../../store/api/appNotificationsApi"; import { handleError } from "../../utils/handleError"; import useProject from "../projects/useProject"; import { useUser } from "../user"; /** * Hook that provides Redux-powered actions for app notifications * Integrates RTK Query with Redux slice actions * * Note: Templates are applied at display time in useAppNotifications, not here. * This ensures templates are always fresh and avoids race conditions. */ export function useAppNotificationsActions() { const dispatch = useReplykeDispatch(); // Get current state for actions const projectIdFromSlice = useReplykeSelector(selectCurrentProjectId); const page = useReplykeSelector(selectAppNotificationsPage); const limit = useReplykeSelector(selectAppNotificationsLimit); // Get project and user context (fallback to current hooks) const { projectId: projectIdFromHook } = useProject(); const { user } = useUser(); // Use project ID from slice if available, otherwise from hook const projectId = projectIdFromSlice || projectIdFromHook; // RTK Query hooks const [triggerFetchNotifications] = useLazyFetchAppNotificationsQuery(); const [markNotificationAsReadMutation] = useMarkNotificationAsReadMutation(); const [markAllNotificationsAsReadMutation] = useMarkAllNotificationsAsReadMutation(); const [triggerCountUnread] = useLazyCountUnreadNotificationsQuery(); // Load more action const loadMore = useCallback(() => { dispatch(loadMoreAction()); }, [dispatch]); // Mark notification as read action const markNotificationAsRead = useCallback(async ({ notificationId }) => { if (!projectId || !user) { throw new Error("No project ID or authenticated user available"); } try { // Optimistic update dispatch(markAsReadLocally(notificationId)); // Make API call await markNotificationAsReadMutation({ projectId, notificationId, }).unwrap(); } catch (error) { handleError(error, "Failed to mark notification as read:"); throw error; } }, [dispatch, projectId, user, markNotificationAsReadMutation]); // Reset notifications action const resetAppNotifications = useCallback(async () => { if (!projectId || !user) { throw new Error("No project ID or authenticated user available"); } try { dispatch(setLoading(true)); dispatch(resetNotifications()); // Fetch first page const response = await triggerFetchNotifications({ projectId, page: 1, limit, }).unwrap(); if (response) { const { data: notifications, pagination } = response; // Store raw notifications - templates applied at display time dispatch(addNotifications({ notifications, hasMore: pagination.hasMore, isFirstPage: true, })); } } catch (error) { handleError(error, "Failed to refresh notifications:"); throw error; } }, [ dispatch, projectId, user, triggerFetchNotifications, limit, ]); // Fetch more notifications (internal action triggered by page changes) const fetchMoreNotifications = useCallback(async ({ pageToFetch }) => { if (!projectId || !user) return; try { dispatch(setLoading(true)); const response = await triggerFetchNotifications({ projectId, page: pageToFetch, limit, }).unwrap(); if (response) { const { data: notifications, pagination } = response; // Store raw notifications - templates applied at display time dispatch(addNotifications({ notifications, hasMore: pagination.hasMore, })); } } catch (error) { handleError(error, "Loading more app notifications failed:"); } finally { dispatch(setLoading(false)); } }, [ dispatch, projectId, user, triggerFetchNotifications, limit, ]); // Update unread count const updateUnreadCount = useCallback(async () => { if (!projectId || !user) return; try { const count = await triggerCountUnread({ projectId }).unwrap(); if (typeof count === "number") { dispatch(setUnreadCount(count)); } } catch (error) { handleError(error, "Failed to fetch unread count:"); } }, [dispatch, projectId, user, triggerCountUnread]); // Mark all notifications as read action const markAllNotificationsAsRead = useCallback(async () => { if (!projectId || !user) { throw new Error("No project ID or authenticated user available"); } try { // Optimistic update dispatch(markAllAsReadLocally()); // Make API call await markAllNotificationsAsReadMutation({ projectId }).unwrap(); } catch (error) { handleError(error, "Failed to mark all notifications as read:"); throw error; } }, [dispatch, projectId, user, markAllNotificationsAsReadMutation]); return { loadMore, markNotificationAsRead, markAllNotificationsAsRead, resetAppNotifications, fetchMoreNotifications, // Internal action updateUnreadCount, // Internal action }; } export default useAppNotificationsActions; //# sourceMappingURL=useAppNotificationsActions.js.map