@replyke/core
Version:
Replyke: Build interactive apps with social features like comments, votes, feeds, user lists, notifications, and more.
104 lines • 4.42 kB
JavaScript
import { createSlice } from "@reduxjs/toolkit";
// Initial state
const initialState = {
notifications: [],
unreadCount: 0,
loading: false,
hasMore: true,
page: 1,
limit: 10,
notificationTemplates: undefined,
currentProjectId: undefined,
};
// Create the slice
export const appNotificationsSlice = createSlice({
name: 'appNotifications',
initialState,
reducers: {
// Set the current project context
setProjectContext: (state, action) => {
state.currentProjectId = action.payload;
},
// Set pagination limit
setLimit: (state, action) => {
state.limit = action.payload;
},
// Set notification templates
setNotificationTemplates: (state, action) => {
state.notificationTemplates = action.payload;
},
// Reset notifications (clear all and restart pagination)
resetNotifications: (state) => {
state.notifications = [];
state.page = 1;
state.hasMore = true;
state.loading = false;
},
// Load more notifications (increment page)
loadMore: (state) => {
if (state.hasMore && !state.loading) {
state.page += 1;
}
},
// Set loading state
setLoading: (state, action) => {
state.loading = action.payload;
},
// Add new notifications (for pagination)
addNotifications: (state, action) => {
const { notifications, hasMore, isFirstPage = false } = action.payload;
if (isFirstPage) {
state.notifications = notifications;
}
else {
// Prevent duplicates when adding new pages
const existingIds = new Set(state.notifications.map(n => n.id));
const newNotifications = notifications.filter(n => !existingIds.has(n.id));
state.notifications.push(...newNotifications);
}
// Update hasMore from pagination metadata
state.hasMore = hasMore;
state.loading = false;
},
// Mark notification as read locally (optimistic update)
markAsReadLocally: (state, action) => {
const notificationId = action.payload;
const notification = state.notifications.find(n => n.id === notificationId);
if (notification && !notification.isRead) {
notification.isRead = true;
// Decrease unread count
state.unreadCount = Math.max(state.unreadCount - 1, 0);
}
},
// Mark all notifications as read locally (optimistic update)
markAllAsReadLocally: (state) => {
state.notifications.forEach(notification => {
notification.isRead = true;
});
// Set unread count to 0
state.unreadCount = 0;
},
// Set unread count
setUnreadCount: (state, action) => {
state.unreadCount = action.payload;
},
// Handle errors by stopping loading
handleError: (state) => {
state.loading = false;
},
},
});
// Export actions
export const { setProjectContext, setLimit, setNotificationTemplates, resetNotifications, loadMore, setLoading, addNotifications, markAsReadLocally, markAllAsReadLocally, setUnreadCount, handleError, } = appNotificationsSlice.actions;
// Export reducer
export default appNotificationsSlice.reducer;
// Selectors - use namespaced state for dual-mode support
export const selectAppNotifications = (state) => state.replyke.appNotifications.notifications;
export const selectUnreadCount = (state) => state.replyke.appNotifications.unreadCount;
export const selectAppNotificationsLoading = (state) => state.replyke.appNotifications.loading;
export const selectAppNotificationsHasMore = (state) => state.replyke.appNotifications.hasMore;
export const selectAppNotificationsPage = (state) => state.replyke.appNotifications.page;
export const selectAppNotificationsLimit = (state) => state.replyke.appNotifications.limit;
export const selectNotificationTemplates = (state) => state.replyke.appNotifications.notificationTemplates;
export const selectCurrentProjectId = (state) => state.replyke.appNotifications.currentProjectId;
//# sourceMappingURL=appNotificationsSlice.js.map