Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

chat-slice.js 7.9KB

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