You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

chat-slice.js 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
  2. import roomService from "../services/roomService";
  3. import notificationService from "../services/notificationService";
  4. const initialState = {
  5. status: "idle",
  6. rooms: [],
  7. activeRoom: null,
  8. error: null,
  9. connection: null,
  10. messages: [],
  11. connections: [],
  12. notifications: [],
  13. typings: [],
  14. };
  15. export const fetchChatRoomsAsync = createAsyncThunk(
  16. "chat/fetchChatRoomsAsync",
  17. async (payload, thunkAPI) => {
  18. try {
  19. return await roomService.getRooms(payload);
  20. } catch (error) {
  21. return thunkAPI.rejectWithValue({ error });
  22. }
  23. }
  24. );
  25. export const fetchSupportRoomsAsync = createAsyncThunk(
  26. "chat/fetchSupportRooms",
  27. async (payload, thunkAPI) => {
  28. try {
  29. return await roomService.getSupportRooms(payload);
  30. } catch (error) {
  31. return thunkAPI.rejectWithValue({ error });
  32. }
  33. }
  34. );
  35. export const createChatRoomAsync = createAsyncThunk(
  36. "chat/createChatRoomAsync",
  37. async (payload, thunkAPI) => {
  38. try {
  39. return await roomService.createRoom(payload);
  40. } catch (error) {
  41. return thunkAPI.rejectWithValue({ error });
  42. }
  43. }
  44. );
  45. export const loadNotifications = createAsyncThunk(
  46. "chat/loadNotifications",
  47. async (payload, thunkAPI) => {
  48. try {
  49. return await notificationService.loadNotifications(payload);
  50. } catch (error) {
  51. return thunkAPI.rejectWithValue({ error });
  52. }
  53. }
  54. );
  55. export const readNotificationsAsync = createAsyncThunk(
  56. "chat/deleteNotificationsAsync",
  57. async (payload, thunkAPI) => {
  58. try {
  59. return await notificationService.readNotifications(payload);
  60. } catch (error) {
  61. return thunkAPI.rejectWithValue({ error });
  62. }
  63. }
  64. );
  65. const chatSlice = createSlice({
  66. name: "chat",
  67. initialState,
  68. reducers: {
  69. setAllChats: (state, action) => {
  70. state.rooms = action.payload;
  71. },
  72. setRoom: (state, action) => {
  73. state.activeRoom = action.payload;
  74. },
  75. deleteActiveRoom: (state, action) => {
  76. state.activeRoom = null;
  77. },
  78. // Set hub connection
  79. setConnection: (state, action) => {
  80. state.connection = action.payload;
  81. },
  82. // New message sent from user
  83. newMessage: (state, action) => {
  84. if (action.payload.changedRoom) {
  85. state.messages = [];
  86. } else {
  87. state.messages = [...state.messages, action.payload];
  88. }
  89. },
  90. saveContextId: (state, action) => {
  91. // Check is empty array
  92. // If array is not empty, check is connection for specific room and specific user already added
  93. if (state.connections.length > 0) {
  94. if (
  95. !state.connections.some(
  96. (e) => e.connId === action.payload && e.roomId === state.activeRoom
  97. )
  98. ) {
  99. state.connections.push({
  100. connId: action.payload.connId,
  101. roomId: state.activeRoom.id,
  102. userId: action.payload.userId,
  103. });
  104. }
  105. } else {
  106. // If array is empty, add connection
  107. state.connections.push({
  108. connId: action.payload.connId,
  109. roomId: state.activeRoom.id,
  110. userId: action.payload.userId,
  111. });
  112. }
  113. },
  114. // Set messages fetched from backend for specific room
  115. setMessages: (state, action) => {
  116. state.messages = action.payload;
  117. },
  118. addNotification: (state, action) => {
  119. console.log(1, action.payload);
  120. if (state.notifications.length !== 0) {
  121. console.log(2);
  122. const room = state.notifications.find(
  123. (notification) => notification.roomId === action.payload
  124. );
  125. if (room) {
  126. console.log(3);
  127. room.notificationCount++;
  128. } else {
  129. state.notifications.push({
  130. roomId: action.payload,
  131. notificationCount: 1,
  132. });
  133. }
  134. } else {
  135. console.log(4);
  136. state.notifications.push({
  137. roomId: action.payload,
  138. notificationCount: 1,
  139. });
  140. }
  141. },
  142. readNotifications: (state, action) => {
  143. state.notifications = state.notifications.filter(
  144. (notification) => notification.roomId !== action.payload
  145. );
  146. },
  147. leaveRoom: (state, action) => {
  148. state.activeRoom = null;
  149. const room = state.rooms.find(
  150. (room) => room.id === action.payload.roomId
  151. );
  152. room.customers = room.customers.filter(
  153. (customer) => customer.customerId !== action.payload.customerId
  154. );
  155. },
  156. addTyping: (state, action) => {
  157. if (
  158. !state.typings.some(
  159. (n) =>
  160. n.message === action.payload.message &&
  161. n.roomId === action.payload.roomId
  162. )
  163. )
  164. state.typings = [...state.typings, action.payload];
  165. else console.log("ima vec");
  166. },
  167. removeTyping: (state, action) => {
  168. if (state.typings.length >= 1) {
  169. let f = state.typings[0];
  170. state.typings = state.typings.filter((n) => n.message !== f.message);
  171. }
  172. },
  173. },
  174. extraReducers: (builder) => {
  175. // Fetch chat rooms
  176. builder.addCase(fetchChatRoomsAsync.pending, (state) => {
  177. state.status = "pendingFetchRooms";
  178. state.error = null;
  179. });
  180. builder.addCase(fetchChatRoomsAsync.fulfilled, (state, action) => {
  181. state.rooms = action.payload;
  182. state.status = "idle";
  183. state.error = null;
  184. });
  185. builder.addCase(fetchChatRoomsAsync.rejected, (state, action) => {
  186. state.status = "idle";
  187. state.error = "Fetch error" + action.payload;
  188. });
  189. // fetch rooms that support created
  190. builder.addCase(fetchSupportRoomsAsync.pending, (state) => {
  191. state.status = "pendingFetchRooms";
  192. state.error = null;
  193. });
  194. builder.addCase(fetchSupportRoomsAsync.fulfilled, (state, action) => {
  195. state.rooms = action.payload;
  196. state.status = "idle";
  197. state.error = null;
  198. });
  199. builder.addCase(fetchSupportRoomsAsync.rejected, (state, action) => {
  200. state.status = "idle";
  201. state.error = "Fetch error" + action.payload;
  202. });
  203. // Add chat room
  204. builder.addCase(createChatRoomAsync.pending, (state) => {
  205. state.status = "pendingAddRoom";
  206. state.error = null;
  207. });
  208. builder.addCase(createChatRoomAsync.fulfilled, (state, action) => {
  209. state.status = "idle";
  210. state.rooms = [...state.rooms, action.payload];
  211. state.error = null;
  212. });
  213. builder.addCase(createChatRoomAsync.rejected, (state, action) => {
  214. state.status = "idle";
  215. state.error = action.payload;
  216. });
  217. builder.addCase(loadNotifications.pending, (state) => {
  218. state.status = "pendingLoadingNotification";
  219. state.error = null;
  220. });
  221. builder.addCase(loadNotifications.fulfilled, (state, action) => {
  222. state.status = "idle";
  223. if (action.payload.length === 0) {
  224. state.notifications = [];
  225. } else {
  226. state.notifications = action.payload.map((n) => {
  227. return { roomId: n.roomId, notificationCount: n.count };
  228. });
  229. }
  230. state.error = null;
  231. });
  232. builder.addCase(loadNotifications.rejected, (state, action) => {
  233. state.status = "idle";
  234. state.error = action.payload;
  235. });
  236. // Read notifications
  237. builder.addCase(readNotificationsAsync.pending, (state) => {
  238. state.status = "pendingReadingNotifications";
  239. state.error = null;
  240. });
  241. builder.addCase(readNotificationsAsync.fulfilled, (state) => {
  242. state.status = "idle";
  243. state.error = null;
  244. });
  245. builder.addCase(readNotificationsAsync.rejected, (state, action) => {
  246. state.status = "idle";
  247. state.error = action.payload;
  248. });
  249. },
  250. });
  251. export const chatActions = chatSlice.actions;
  252. export const chatReducers = chatSlice.reducer;