import { createAsyncThunk, createSlice, createEntityAdapter, createSelector, } from '@reduxjs/toolkit' // import io from 'socket.io-client' import { request } from 'api' const notifyAdapter = createEntityAdapter({ selectId: notification => notification._id.toString(), sortComparer: (a, b) => b.created_at.localeCompare(a.created_at), }) // /* TODO move to its own file for general purpose */ // const socket = io('/auth', { // autoConnect: false, // /* // * As netlify doesn't support socket proxying // * resorting to just polling, instead of using JWT now // */ // transports: ['polling'] // }); // export const initSocket = createAsyncThunk( // 'notify/initSocket', // async (_, { dispatch }) => { // socket.on('connect', () => { // // console.log("Socket connected? ", socket.connected, ' id: ', socket.id); // true // }); // socket.on('disconnect', () => { // // console.log("Socket connected? ", socket.connected, ' id: ', socket.id); // false // }); // socket.on('error', err => { // // console.log('Socket error: ', err) // }) // socket.on('notification', notification => dispatch(notificationAdded(notification))) // socket.on('notifications', notifications => dispatch(notificationsAdded(notifications))) // socket.on('message', message => console.log('got message: ', message)) // // socket.open() // } // ) const interval = 15 * 1000 var notifsInterval export const fetchNotifs = () => async (dispatch, getState) => { const { auth: { isAuthenticated }, } = getState() if (isAuthenticated && !notifsInterval) { notifsInterval = setInterval(() => { dispatch(fetchNotifs()) }, interval) } else if (!isAuthenticated && notifsInterval) clearInterval(notifsInterval) const { notify: { status }, } = getState() if (status === 'loading') return dispatch(_fetchNotifs()) } export const _fetchNotifs = createAsyncThunk('notifs/fetchAll', async (_, { dispatch }) => { let { notifications } = await request('/api/notifications', { dispatch }) if (!notifications) throw Error('No notifications') return dispatch(notificationsAdded(notifications)) }) export const readNotif = createAsyncThunk( 'notifs/readNotif', async (notification, { dispatch }) => { dispatch(notifRead(notification)) return request(`/api/notification_read/${notification._id}`, { dispatch, body: {} }) } ) const initialState = notifyAdapter.getInitialState({ status: 'idle', // || 'loading' }) const notifySlice = createSlice({ name: 'notify', initialState, reducers: { notificationAdded: notifyAdapter.upsertOne, notificationsAdded: notifyAdapter.upsertMany, notifRead: (state, action) => { let notif = action.payload notifyAdapter.upsertOne(state, { ...notif, read: true, }) }, }, extraReducers: { [fetchNotifs.pending]: state => { state.status = 'loading' }, [fetchNotifs.rejected]: state => { state.status = 'idle' }, [fetchNotifs.fulfilled]: state => { state.status = 'idle' }, }, }) const { reducer, actions } = notifySlice export const { notificationAdded, notificationsAdded, notifRead } = actions export default reducer export const notifySelectors = notifyAdapter.getSelectors(state => state.notify) export const selectUnread = createSelector([notifySelectors.selectAll], all => all.filter(one => !one.read) )