import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"; import roomService from "../services/roomService"; import notificationService from "../services/notificationService"; const initialState = { status: "idle", rooms: [], activeRoom: null, error: null, connection: null, messages: [], connections: [], notifications: [], typings: [], }; export const fetchChatRoomsAsync = createAsyncThunk( "chat/fetchChatRoomsAsync", async (payload, thunkAPI) => { try { return await roomService.getRooms(payload); } catch (error) { return thunkAPI.rejectWithValue({ error }); } } ); export const fetchSupportRoomsAsync = createAsyncThunk( "chat/fetchSupportRooms", async (payload, thunkAPI) => { try { return await roomService.getSupportRooms(payload); } catch (error) { return thunkAPI.rejectWithValue({ error }); } } ); export const createChatRoomAsync = createAsyncThunk( "chat/createChatRoomAsync", async (payload, thunkAPI) => { try { return await roomService.createRoom(payload); } catch (error) { return thunkAPI.rejectWithValue({ error }); } } ); export const loadNotifications = createAsyncThunk( "chat/loadNotifications", async (payload, thunkAPI) => { try { return await notificationService.loadNotifications(payload); } catch (error) { return thunkAPI.rejectWithValue({ error }); } } ); export const readNotificationsAsync = createAsyncThunk( "chat/deleteNotificationsAsync", async (payload, thunkAPI) => { try { return await notificationService.readNotifications(payload); } catch (error) { return thunkAPI.rejectWithValue({ error }); } } ); const chatSlice = createSlice({ name: "chat", initialState, reducers: { setAllChats: (state, action) => { state.rooms = action.payload; }, setRoom: (state, action) => { state.activeRoom = action.payload; }, deleteActiveRoom: (state, action) => { state.activeRoom = null; }, // Set hub connection setConnection: (state, action) => { state.connection = action.payload; }, // New message sent from user newMessage: (state, action) => { if (action.payload.changedRoom) { state.messages = []; } else { state.messages = [...state.messages, action.payload]; } }, saveContextId: (state, action) => { // Check is empty array // If array is not empty, check is connection for specific room and specific user already added if (state.connections.length > 0) { if ( !state.connections.some( (e) => e.connId === action.payload && e.roomId === state.activeRoom ) ) { state.connections.push({ connId: action.payload.connId, roomId: state.activeRoom.id, userId: action.payload.userId, }); } } else { // If array is empty, add connection state.connections.push({ connId: action.payload.connId, roomId: state.activeRoom.id, userId: action.payload.userId, }); } }, // Set messages fetched from backend for specific room setMessages: (state, action) => { state.messages = action.payload; }, addNotification: (state, action) => { console.log(1, action.payload); if (state.notifications.length !== 0) { console.log(2); const room = state.notifications.find( (notification) => notification.roomId === action.payload ); if (room) { console.log(3); room.notificationCount++; } else { state.notifications.push({ roomId: action.payload, notificationCount: 1, }); } } else { console.log(4); state.notifications.push({ roomId: action.payload, notificationCount: 1, }); } }, readNotifications: (state, action) => { state.notifications = state.notifications.filter( (notification) => notification.roomId !== action.payload ); }, leaveRoom: (state, action) => { state.activeRoom = null; const room = state.rooms.find( (room) => room.id === action.payload.roomId ); room.customers = room.customers.filter( (customer) => customer.customerId !== action.payload.customerId ); }, addTyping: (state, action) => { if ( !state.typings.some( (n) => n.message === action.payload.message && n.roomId === action.payload.roomId ) ) state.typings = [...state.typings, action.payload]; else console.log("ima vec"); }, removeTyping: (state, action) => { if (state.typings.length >= 1) { let f = state.typings[0]; state.typings = state.typings.filter((n) => n.message !== f.message); } }, }, extraReducers: (builder) => { // Fetch chat rooms builder.addCase(fetchChatRoomsAsync.pending, (state) => { state.status = "pendingFetchRooms"; state.error = null; }); builder.addCase(fetchChatRoomsAsync.fulfilled, (state, action) => { state.rooms = action.payload; state.status = "idle"; state.error = null; }); builder.addCase(fetchChatRoomsAsync.rejected, (state, action) => { state.status = "idle"; state.error = "Fetch error" + action.payload; }); // fetch rooms that support created builder.addCase(fetchSupportRoomsAsync.pending, (state) => { state.status = "pendingFetchRooms"; state.error = null; }); builder.addCase(fetchSupportRoomsAsync.fulfilled, (state, action) => { state.rooms = action.payload; state.status = "idle"; state.error = null; }); builder.addCase(fetchSupportRoomsAsync.rejected, (state, action) => { state.status = "idle"; state.error = "Fetch error" + action.payload; }); // Add chat room builder.addCase(createChatRoomAsync.pending, (state) => { state.status = "pendingAddRoom"; state.error = null; }); builder.addCase(createChatRoomAsync.fulfilled, (state, action) => { state.status = "idle"; state.rooms = [...state.rooms, action.payload]; state.error = null; }); builder.addCase(createChatRoomAsync.rejected, (state, action) => { state.status = "idle"; state.error = action.payload; }); builder.addCase(loadNotifications.pending, (state) => { state.status = "pendingLoadingNotification"; state.error = null; }); builder.addCase(loadNotifications.fulfilled, (state, action) => { state.status = "idle"; if (action.payload.length === 0) { state.notifications = []; } else { state.notifications = action.payload.map((n) => { return { roomId: n.roomId, notificationCount: n.count }; }); } state.error = null; }); builder.addCase(loadNotifications.rejected, (state, action) => { state.status = "idle"; state.error = action.payload; }); // Read notifications builder.addCase(readNotificationsAsync.pending, (state) => { state.status = "pendingReadingNotifications"; state.error = null; }); builder.addCase(readNotificationsAsync.fulfilled, (state) => { state.status = "idle"; state.error = null; }); builder.addCase(readNotificationsAsync.rejected, (state, action) => { state.status = "idle"; state.error = action.payload; }); }, }); export const chatActions = chatSlice.actions; export const chatReducers = chatSlice.reducer;