import { store } from "." import { useGetState } from 'react-redux'; import { useHistory } from "react-router-dom"; const url = 'http://hipstagram.node.ed.asmer.org.ua/graphql' // функция getGql function getGql(endpoint) { return async function gql(query, variables = {}) { let headers = { 'Content-Type': 'application/json;charset=utf-8', 'Accept': 'application/json', } if (('authToken' in localStorage)) { headers.Authorization = 'Bearer ' + localStorage.authToken } let result = await fetch(endpoint, { method: 'POST', headers, body: JSON.stringify({ query, variables }) }).then(res => res.json()) if (('errors' in result) && !('data' in result)) { throw new Error(JSON.stringify(result.errors)) } result = Object.values(result.data)[0] return result } } const gql = getGql(url) // акшоны для promiseReducer export const actionPending = (type, nameOfPromise) => ({ nameOfPromise, type, status: 'PENDING' }) export const actionFulfilled = (type, nameOfPromise, payload) => ({ nameOfPromise, type: type, status: 'FULFILLED', payload }) export const actionRejected = (type, nameOfPromise, error) => ({ nameOfPromise, type: type, status: 'REJECTED', error }) export const actionPromise = (type, nameOfPromise, promise) => async dispatch => { dispatch(actionPending(type, nameOfPromise)) //сигнализируем redux, что промис начался try { const payload = await promise //ожидаем промиса dispatch(actionFulfilled(type, nameOfPromise, payload)) //сигнализируем redux, что промис успешно выполнен return payload //в месте запуска store.dispatch с этим thunk можно так же получить результат промиса } catch (error) { dispatch(actionRejected(type, nameOfPromise, error)) //в случае ошибки - сигнализируем redux, что промис несложился } } // ============================================================= // Запросы на бек // Запрос на регистрацию пользователя export const actionRegistration = (login, password) => actionPromise('PROMISE', 'Registration', gql(`mutation Registration($login:String!, $password:String!) { createUser(login:$login, password:$password) { _id login } }`, { login, password }) ) // Запрос на логинизацию пользователя export const actionLogin = (login, password) => actionPromise('PROMISE', 'Login', gql(`query Login($login: String!, $password: String!) { login(login: $login, password: $password) }`, { login, password })) // акшон для логинизации в authReduser const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token }) // акшон для раззлогинивания export const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' }) // запрос на изменение пароля юзера export const actionPassChange = (loginChange, passwordChange, passwordNew) => actionPromise('PROMISE', 'PassChange', gql(`mutation PasswordChange($loginChange: String!, $passwordChange: String!, $passwordNew: String!) { changePassword( login: $loginChange, password: $passwordChange, newPassword: $passwordNew ) { _id login } }`, { loginChange, passwordChange, passwordNew })) // запрос на поиск конкретного поста export const actionFindPostOne = _id => actionPromise('PROMISE', 'PostFindOne', gql(`query OnePostFind ($postOne: String){ PostFindOne (query: $postOne) { _id createdAt title text likesCount images { url } comments { _id createdAt text answers { _id createdAt text likes { _id } likesCount owner { _id login nick avatar { _id url } } } likesCount } owner { _id login nick avatar { _id url } } } }`, { postOne: JSON.stringify([{ _id }]) })) // запрос на поиск конкретного юзера(folowwing - это те, на кого я подписан. followers - те, кто на меня подписан) // export const actionFindUserOne = (_id, promiseName = 'UserFindOne') => actionPromise('PROMISE', promiseName, gql(`query OneUserFind ($userOne: String) { // UserFindOne(query: $userOne) { // _id createdAt login nick // avatar { // _id url // } // followers { // _id login nick avatar {_id url} // } // following { // _id login nick avatar {_id url} // } // } // }`, { // userOne: JSON.stringify([{ _id }]) // })) export const actionFindUserOne = (_id, promiseName = 'UserFindOne') => actionPromise('PROMISE', promiseName, gql(`query OneUserFind ($userOne: String) { UserFindOne(query: $userOne) { _id createdAt login nick avatar { _id url } followers { _id login nick avatar {_id url} } following { _id } } }`, { userOne: JSON.stringify([{ _id }]) })) // запрос на поиск всех постов на беке (нигде не должен использоваться) export const actionfindPosts = () => actionPromise('PROMISE', 'PostsFind', gql(`query AllPostsFind ($allPosts: String){ PostFind(query: $allPosts){ _id createdAt title text likesCount images { url } owner { _id login nick } } }`, { allPosts: JSON.stringify([{}]) })) // Запрос на поиск ленты постов для юзера // export const actionFeedFindOne = (arr, sortOne, limitOne, promiseName = 'Feed') => actionPromise('PROMISE', promiseName, gql(`query FeedFindOne ($feedOne: String){ // PostFind(query: $feedOne){ // _id createdAt title text likesCount owner{ // _id login avatar{ // url // } // } // comments { // _id // } // images{ // url // } // } // }`, { // // вот тут прописал limit - количество постов, которые отображаются в ленте // feedOne: JSON.stringify([{ ___owner: { $in: arr } }, { sort: [{ _id: sortOne }], limit: [limitOne] }]) // })) //================= вот это тоже нужно будет удалить после тестов ===================== export const actionFeedFindOne = (arr, sortOne, limitOne, promiseName = 'Feed', skipOne = 0) => actionPromise('FEED', promiseName, gql(`query FeedFindOne ($feedOne: String){ PostFind(query: $feedOne){ _id createdAt title text likesCount owner{ _id login avatar{ url } } comments { _id } images{ url } } }`, { // вот тут прописал limit - количество постов, которые отображаются в ленте feedOne: JSON.stringify([{ ___owner: { $in: arr } }, { sort: [{ _id: sortOne }], limit: [limitOne], skip: [skipOne] }]) })) // запрос ленты с пропуском определенного количества постов.комментов // export const actionFeedFindOneSkip = (arr, sortOne, skipOne, limitOne, promiseName = 'Feed') => actionPromise('FEED', promiseName, gql(`query FeedFindOne ($feedOne: String){ // PostFind(query: $feedOne){ // _id createdAt title text likesCount owner{ // _id login avatar{ // url // } // } // comments { // _id // } // images{ // url // } // } // }`, { // // вот тут прописал limit - количество постов, которые отображаются в ленте // feedOne: JSON.stringify([{ ___owner: { $in: arr } }, { sort: [{ _id: sortOne }], skip: [skipOne], limit: [limitOne] }]) // })) // ====================== и это удалить после теста ==================== export const actionFeedFindOneSkip = (arr, sortOne, skipOne, limitOne, promiseName = 'Feed') => actionPromise('FEED', promiseName, gql(`query FeedFindOne ($feedOne: String){ PostFind(query: $feedOne){ _id createdAt title text likesCount owner{ _id login avatar{ url } } comments { _id } images{ url } } }`, { // вот тут прописал limit - количество постов, которые отображаются в ленте feedOne: JSON.stringify([{ ___owner: { $in: arr } }, { sort: [{ _id: sortOne }], skip: [skipOne], limit: [limitOne] }]) })) // запрос на подсчет количества постов юзера export const actionPostsCount = (id, promiseName) => actionPromise('PROMISE', promiseName, gql(`query PostsCount ($postsCount: String){ PostCount(query: $postsCount) }`, { postsCount: JSON.stringify([{ ___owner: id }]) }) ) // ========================================= // Thunk-и // Thunk логин и последующую логинизацию в authReduser export const actionFullLogin = (login, password) => async dispatch => { const token = await dispatch(actionLogin(login, password)) if (token !== null) { if (typeof (token) === 'string') { dispatch(actionAuthLogin(token)) localStorage.authToken = token } } return token } // Thunk на регистрацию и последующую логинизацию export const actionFullRegistration = (login, password) => async dispatch => { const token = await dispatch(actionRegistration(login, password)) if (token !== null) { dispatch(actionFullLogin(login, password)) } return token } // Thunk разлогина и последующей полной очистки localStorage export const actionFullLogout = () => async dispatch => { await dispatch(actionAuthLogout()) return {} } // Thunk для страницы юзера (диспатчим запрос на юзера и на ленту его постов) export const actionFullUserFindOne = _id => async dispatch => { // запрашиваем информацию о пользователе await dispatch(actionFindUserOne(_id, 'UserFindOne')) // парсим счетчик, сколько постов у юзера dispatch(actionPostsCount(_id, 'UserPostsCount')) // запрашиваем список постов для юзера dispatch(actionFeedFindOne([_id], -1, 100, 'UserFeed')) } // запрос AboutMe для главной страницы (лента моих постов и мои данные) export const actionAboutMe = () => async (dispatch, getState) => { const myId = getState()?.auth?.payload?.sub?.id // диспатчим запрос AboutMe (о себе) const userData = await dispatch(actionFindUserOne(myId, 'AboutMe')) // парсим счетчик, сколько постов у меня dispatch(actionPostsCount(myId, 'MyPostsCount')) let followingList = [] // проверяем, есть ли вообще подписчики и если да, парсим их if (userData?.following) { // получаем id всех подписок followingList = (userData.following).map(user => user?._id) } // запрашиваем формирование ленты моих постов (первый параметр - список id, второй - это сортировка постов от новых) dispatch(actionFeedFindOne(followingList, -1, 10, 'MyFeed')) } // ================= на удаление (начало)===================== export const actionDownloadFeed = (skip) => async (dispatch, getState) => { console.log('скипаем: ', skip) const followingList = (getState()?.promise?.AboutMe?.payload?.following).map(user => user._id) if (followingList) { const result = await dispatch(actionFeedFindOne(followingList, -1, 10, 'AddFeed', skip)) return result } } // ================= на удаление(конец) ===================== // запрос на загрузку картинок на бек function fileUpload(file) { const formData = new FormData() formData.append('photo', file) return ( fetch('http://hipstagram.node.ed.asmer.org.ua/upload', { method: 'POST', headers: { Authorization: 'Bearer ' + localStorage.authToken }, body: formData }).then(res => res.json()) ) } function filesUpload(files) { return Promise.all(files.map(fileUpload)) } export const actionFilesUpload = (files) => actionPromise('PROMISE', 'FilesUpload', filesUpload(files) ) // запрос на создание поста export const actionCreatePost = (params) => actionPromise('PROMISE', 'CreatePost', gql( `mutation CreatePost($createNewPost: PostInput){ PostUpsert(post: $createNewPost){ _id } }`, { createNewPost: params })) // санк для создания поста и последующего перехода на его страницу export const actionFullCreatePost = (params) => async dispatch => { const newPost = await dispatch(actionCreatePost(params)) // console.log('Тут нужный резульата: ', newPost) if (newPost) { dispatch(actionFindPostOne(newPost._id)) } }