index.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. import thunk from 'redux-thunk'
  2. import {
  3. actionAboutMe,
  4. actionAllPostsUser,
  5. actionAboutUser,
  6. actionPostsFeed,
  7. actionPostsFeedCount,
  8. actionOnePost,
  9. actionAddComment,
  10. actionAddLike,
  11. actionDeleteLike,
  12. actionPostsCount,
  13. actionAuthLogout,
  14. } from '../actions'
  15. import { createStore, combineReducers, applyMiddleware } from 'redux'
  16. import { history } from '../App'
  17. function promiseReducer(state = {}, { type, name, status, payload, error }) {
  18. if (type === 'PROMISE') {
  19. return {
  20. ...state,
  21. [name]: { status, payload, error },
  22. }
  23. }
  24. return state
  25. }
  26. const jwtDecode = (token) => {
  27. try {
  28. return JSON.parse(atob(token.split('.')[1]))
  29. } catch (e) {
  30. return null
  31. }
  32. }
  33. export const actionProfilePageDataTypeUser = (aboutUser, allPosts) => ({
  34. type: 'PROFILE-PAGE-USER',
  35. aboutUser,
  36. allPosts,
  37. })
  38. export const actionProfilePageData = (id) => ({ type: 'DATA_PROFILE', id })
  39. export const actionProfilePageDataType = (aboutMe) => ({
  40. type: 'PROFILE-PAGE',
  41. aboutMe,
  42. })
  43. export const actionAvatarUpdate = (aboutUser) => ({
  44. type: 'CHANGE-AVATAR-USER',
  45. aboutUser,
  46. })
  47. export const actionFullProfilePageUser = (_id) => async (dispatch) => {
  48. const aboutUser = await dispatch(actionAboutUser(_id))
  49. const allPosts = await dispatch(actionAllPostsUser(_id))
  50. await dispatch(actionPostsCount(_id))
  51. if (aboutUser && allPosts) {
  52. await dispatch(actionProfilePageDataTypeUser(aboutUser, allPosts))
  53. }
  54. }
  55. export const actionClearDataUserType = () => ({ type: 'CLEAR-DATA' })
  56. export const actionClearUserData = () => async (dispatch) => {
  57. const logOut = await dispatch(actionAuthLogout())
  58. if (logOut) {
  59. history.push('/input')
  60. await dispatch(actionClearDataUserType())
  61. }
  62. }
  63. export const actionFullProfilePage = (_id) => async (dispatch) => {
  64. const aboutMe = await dispatch(actionAboutMe(_id))
  65. if (aboutMe) {
  66. await dispatch(actionProfilePageDataType(aboutMe))
  67. }
  68. }
  69. export const actionRemoveDataUser = () => ({ type: 'REMOVE-DATA' })
  70. export const profileUserReducer = (
  71. state = {},
  72. { type, aboutUser, allPosts, newPosts },
  73. ) => {
  74. const types = {
  75. 'PROFILE-PAGE-USER': () => {
  76. return {
  77. ...state,
  78. aboutUser,
  79. allPosts,
  80. }
  81. },
  82. 'CLEAR-DATA': () => {
  83. return {
  84. ...(state = {}),
  85. aboutUser: {},
  86. allPosts: [],
  87. }
  88. },
  89. 'CHANGE-AVATAR-USER': () => {
  90. return {
  91. ...state,
  92. aboutUser,
  93. }
  94. },
  95. }
  96. if (type in types) {
  97. return types[type]()
  98. }
  99. return state
  100. }
  101. export const actionFeedType = (newPosts) => ({ type: 'ADD-POSTS', newPosts })
  102. export const actionAddCommentPostInTape = (postId, newResult) => ({
  103. type: 'ADD-COMMENT-POSTS',
  104. postId,
  105. newResult,
  106. })
  107. export const actionAddFullCommentFeed = (postId, newResult) => async (
  108. dispatch,
  109. getState,
  110. ) => {
  111. await dispatch(actionAddComment(postId, newResult))
  112. const {
  113. promise: {
  114. addComment: { status },
  115. },
  116. } = getState()
  117. if (status === 'FULFILLED') {
  118. const onePost = await dispatch(actionOnePost(postId))
  119. if (onePost) await dispatch(actionAddCommentPostInTape(postId, newResult))
  120. }
  121. // await dispatch(actionOnePost(postId));
  122. }
  123. const actionAddLikePostInTape = (postId) => ({ type: 'ADD-LIKE-POSTS', postId })
  124. export const actionAddFullLikeFeed = (postId) => async (dispatch, getState) => {
  125. await dispatch(actionAddLike(postId))
  126. const {
  127. promise: {
  128. addLike: { status },
  129. },
  130. } = getState()
  131. if (status === 'FULFILLED') {
  132. const onePost = await dispatch(actionOnePost(postId))
  133. if (onePost) await dispatch(actionAddLikePostInTape(postId))
  134. }
  135. }
  136. const actionDeleteLikePostInTape = (likeId, postId) => ({
  137. type: 'DELETE-LIKE-POSTS',
  138. likeId,
  139. postId,
  140. })
  141. export const actionDeleteFullLikeFeed = (likeId, postId) => async (
  142. dispatch,
  143. getState,
  144. ) => {
  145. await dispatch(actionDeleteLike(likeId, postId))
  146. const {
  147. promise: {
  148. deleteLike: { status },
  149. },
  150. } = getState()
  151. if (status === 'FULFILLED') {
  152. const onePost = await dispatch(actionOnePost(postId))
  153. if (onePost) await dispatch(actionDeleteLikePostInTape(likeId, postId))
  154. }
  155. }
  156. export const actionFullFeed = () => async (dispatch, getState) => {
  157. const postsFeed = await dispatch(actionPostsFeed(getState))
  158. const skip = postsFeed.length
  159. const postsFeedCount = await dispatch(actionPostsFeedCount(getState))
  160. if (skip < postsFeedCount) {
  161. const newPosts = await dispatch(actionPostsFeed(getState, skip))
  162. if (newPosts) {
  163. await dispatch(actionFeedType(newPosts))
  164. }
  165. }
  166. }
  167. export const actionOnePostType = (onePost) => ({ type: 'ONE-POST', onePost })
  168. export const actionClearFeedPosts = () => ({ type: 'DELETE-POSTS' })
  169. export const actionFullClearFeedPosts = () => (dispatch) => {
  170. return dispatch(actionClearFeedPosts())
  171. }
  172. export const actionFullOnePost = (_id) => async (dispatch) => {
  173. const onePost = await dispatch(actionOnePost(_id))
  174. if (onePost) {
  175. await dispatch(actionOnePostType(onePost))
  176. // await dispatch(actionClearDataUserType())
  177. }
  178. }
  179. export const feedReducer = (
  180. state = {},
  181. { skip, type, newPosts = [], postId, postsFeed, postsFeedCount, newResult },
  182. ) => {
  183. const types = {
  184. 'ADD-POSTS': () => {
  185. return {
  186. ...state,
  187. postsFeed: postsFeed ? [...postsFeed, ...newPosts] : [...newPosts],
  188. }
  189. },
  190. 'DELETE-POSTS': () => {
  191. return {
  192. ...state,
  193. postsFeed: [],
  194. }
  195. },
  196. 'ADD-LIKE-POSTS': () => ({
  197. ...state,
  198. postsFeed: postsFeed?.map((p) =>
  199. p._id === postId ? (p = { ...p, likes: [...newResult] }) : p,
  200. ),
  201. }),
  202. 'DELETE-LIKE-POSTS': () => ({
  203. ...state,
  204. postsFeed: postsFeed?.map((p) =>
  205. p._id === postId ? (p = { ...p, likes: [...newResult] }) : p,
  206. ),
  207. }),
  208. 'ADD-COMMENT-POSTS': () => ({
  209. ...state,
  210. postsFeed: postsFeed?.map((p) =>
  211. p._id === postId ? (p = { ...p, comments: [...newResult] }) : p,
  212. ),
  213. }),
  214. }
  215. if (type in types) {
  216. return types[type]()
  217. }
  218. return state
  219. }
  220. export const postReducer = (
  221. state = {},
  222. { skip, type, newPosts = [], onePost, postsFeed, postsFeedCount },
  223. ) => {
  224. const types = {
  225. 'ONE-POST': () => {
  226. return {
  227. ...state,
  228. onePost,
  229. }
  230. },
  231. 'CLEAR-POST-ONE': () => {
  232. return {
  233. ...state,
  234. onePost: {},
  235. }
  236. },
  237. }
  238. if (type in types) {
  239. return types[type]()
  240. }
  241. return state
  242. }
  243. export const profileReducer = (state = {}, { type, aboutMe, newResult }) => {
  244. const types = {
  245. 'PROFILE-PAGE': () => {
  246. return {
  247. ...state,
  248. aboutMe,
  249. }
  250. },
  251. 'REMOVE-DATA': () => {
  252. return {
  253. ...(state = {}),
  254. aboutMe: {},
  255. }
  256. },
  257. }
  258. if (type in types) {
  259. return types[type]()
  260. }
  261. return state
  262. }
  263. function authReducer(state, { type, token }) {
  264. if (state === undefined && localStorage.authToken) {
  265. token = localStorage.authToken
  266. type = 'AUTH_LOGIN'
  267. }
  268. if (type === 'AUTH_LOGIN') {
  269. if (jwtDecode(token)) {
  270. localStorage.authToken = token
  271. return { token, payload: jwtDecode(token) }
  272. }
  273. }
  274. if (type === 'AUTH_LOGOUT') {
  275. localStorage.authToken = ''
  276. return {}
  277. }
  278. return state || {}
  279. }
  280. export const actionClearPostsOne = () => ({ type: 'CLEAR-POST-ONE' })
  281. export const store = createStore(
  282. combineReducers({
  283. promise: promiseReducer,
  284. auth: authReducer,
  285. profileData: profileReducer,
  286. profilePage: profileUserReducer,
  287. feed: feedReducer,
  288. post: postReducer,
  289. }),
  290. applyMiddleware(thunk),
  291. )