|
@@ -1,257 +1,67 @@
|
|
|
-import logo from './logo.svg';
|
|
|
+// import logo from './logo.svg';
|
|
|
import './App.css';
|
|
|
-import React, { useState, useEffect } from 'react';
|
|
|
-import { Router, Route, Link, Redirect, Switch, useParams } from 'react-router-dom';
|
|
|
-import { createStore, combineRedusers, applyMiddleware } from 'redux';
|
|
|
-import thunk from 'redux-thunk';
|
|
|
-import { Provider, connect, useDispatch, useSelector } from 'react-redux';
|
|
|
-import Feed from './components/feed';
|
|
|
-import User from './components/user';
|
|
|
-
|
|
|
-// импорт страниц
|
|
|
-import AsideMenu from './components/pages/structure/aside_menu';
|
|
|
-
|
|
|
+import React from 'react';
|
|
|
+import { Router, Route, Switch } from 'react-router-dom';
|
|
|
+import { Provider } from 'react-redux';
|
|
|
+import { store } from './components/redux/index';
|
|
|
import createHistory from "history/createBrowserHistory";
|
|
|
|
|
|
-// ==============================================================================
|
|
|
-// создание promiseReducer
|
|
|
-function promiseReducer(state = {}, { type, status, payload, error, nameOfPromise }) {
|
|
|
- if (type === 'PROMISE') {
|
|
|
- return {
|
|
|
- ...state,
|
|
|
- [nameOfPromise]: { status, payload, error }
|
|
|
- }
|
|
|
- }
|
|
|
- return state
|
|
|
-}
|
|
|
-
|
|
|
-// акшоны для promiseReducer
|
|
|
-const actionPending = nameOfPromise => ({ nameOfPromise, type: 'PROMISE', status: 'PENDING' })
|
|
|
-
|
|
|
-const actionFulfilled = (nameOfPromise, payload) => ({ nameOfPromise, type: 'PROMISE', status: 'FULFILLED', payload })
|
|
|
-
|
|
|
-const actionRejected = (nameOfPromise, error) => ({ nameOfPromise, type: 'PROMISE', status: 'REJECTED', error })
|
|
|
-
|
|
|
-const actionPromise = (nameOfPromise, promise) =>
|
|
|
- async dispatch => {
|
|
|
- dispatch(actionPending(nameOfPromise)) //сигнализируем redux, что промис начался
|
|
|
- try {
|
|
|
- const payload = await promise //ожидаем промиса
|
|
|
- dispatch(actionFulfilled(nameOfPromise, payload)) //сигнализируем redux, что промис успешно выполнен
|
|
|
- return payload //в месте запуска store.dispatch с этим thunk можно так же получить результат промиса
|
|
|
- }
|
|
|
- catch (error) {
|
|
|
- dispatch(actionRejected(nameOfPromise, error)) //в случае ошибки - сигнализируем redux, что промис несложился
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-// =============================================================
|
|
|
-// функция 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('http://hipstagram.node.ed.asmer.org.ua/graphql')
|
|
|
-
|
|
|
-// запрос на все посты (для ленты общей)
|
|
|
-const actionfindPosts = () => actionPromise('PostsFind', gql(`query AllPostsFind ($allPosts: String){
|
|
|
- PostFind(query: $allPosts){
|
|
|
- _id createdAt title text likesCount
|
|
|
- images {
|
|
|
- url
|
|
|
- }
|
|
|
- owner {
|
|
|
- _id login nick
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-}`, {
|
|
|
- allPosts: JSON.stringify([{}])
|
|
|
-}))
|
|
|
-
|
|
|
-// запрос на конкретный пост
|
|
|
-const actionFindPostOne = _id => actionPromise('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
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-}`, {
|
|
|
- postOne: JSON.stringify([{ _id }])
|
|
|
-}))
|
|
|
-
|
|
|
-// запрос на конкретного юзера
|
|
|
-const actionFindUserOne = _id => actionPromise('UserFindOne', 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 }])
|
|
|
-}))
|
|
|
-
|
|
|
-const store = createStore(promiseReducer, applyMiddleware(thunk))
|
|
|
-store.subscribe(() => console.log(store.getState()))
|
|
|
+// импорт страниц
|
|
|
+import { CUser } from './components/user';
|
|
|
+import { CFeed } from './components/feed';
|
|
|
+import { CComments } from './components/post';
|
|
|
+import { CreatePost } from './components/create_post';
|
|
|
+import Authorization from './components/auth_reg';
|
|
|
+// import Header from './components/structure/header';
|
|
|
+import { CHeader } from './components/structure/header';
|
|
|
+import Footer from './components/structure/footer';
|
|
|
|
|
|
-store.dispatch(actionfindPosts())
|
|
|
-// store.dispatch(actionCategoryFind())
|
|
|
-// store.dispatch(actionFindUserOne())
|
|
|
+// url проекта
|
|
|
+export const url = 'http://hipstagram.node.ed.asmer.org.ua/graphql'
|
|
|
|
|
|
|
|
|
const history = createHistory()
|
|
|
|
|
|
-const Autorization = () =>
|
|
|
- <div>
|
|
|
- Авторизация
|
|
|
- </div>
|
|
|
-
|
|
|
const Registration = () =>
|
|
|
<div>
|
|
|
Регистрация
|
|
|
</div>
|
|
|
|
|
|
-const Direct = () =>
|
|
|
- <div>
|
|
|
- Direct
|
|
|
- </div>
|
|
|
-
|
|
|
-const CreatePost = () =>
|
|
|
- <div>
|
|
|
- Страницв создания поста
|
|
|
- </div>
|
|
|
-
|
|
|
-const PageAbout = () =>
|
|
|
- <div>
|
|
|
- Страница "О нас"
|
|
|
- </div>
|
|
|
-
|
|
|
const Page404 = () =>
|
|
|
<div>
|
|
|
NOT FOUND
|
|
|
</div>
|
|
|
|
|
|
|
|
|
-// создаем компонент ленты на основе стандартного, который отслеживает все изменения state
|
|
|
-const ReduxFeed = connect(state => ({ posts: state.PostsFind.payload }))(Feed)
|
|
|
-
|
|
|
-// ==================================================
|
|
|
-// страница одного поста
|
|
|
-const CComments = connect(state => ({ post: state?.PostFindOne?.payload }), { loadPost: actionFindPostOne })(Comments)
|
|
|
-
|
|
|
-function Comments({ post = {}, loadPost }) {
|
|
|
-
|
|
|
- const { postId } = useParams() // отслеживаем изменения в урле
|
|
|
- // const post2 = useSelector(state => state?.CategoryGoodsAndSubCategoryGoods?.payload)
|
|
|
- console.log(66, postId)
|
|
|
-
|
|
|
- useEffect(() => { loadPost(postId) }, [postId]) // перезапускаем loadPost, если произошло изменение в урле
|
|
|
-
|
|
|
- // console.log(post)
|
|
|
-
|
|
|
- return (
|
|
|
- <div>
|
|
|
- {/* <div>{user} and {postId}</div> */}
|
|
|
- тут будут отображаться все комментарии под постом
|
|
|
- <h2>{post.createdAt}</h2>
|
|
|
- </div>
|
|
|
- )
|
|
|
-}
|
|
|
-
|
|
|
-// ==================================================
|
|
|
-// страница юзера
|
|
|
-const CUser = connect(state => ({ user: state?.UserFindOne?.payload }), { loadUser: actionFindUserOne })(User)
|
|
|
-
|
|
|
-// ====================================================
|
|
|
-
|
|
|
function App() {
|
|
|
return (
|
|
|
<Provider store={store}>
|
|
|
<Router history={history}>
|
|
|
- <div className="wrapper" style={{ display: 'flex', minHeight: '100hv' }}>
|
|
|
-
|
|
|
- <AsideMenu />
|
|
|
- <section style={{ width: '50%', margin: '0 auto', minHeight: '100hv', display: 'flex', flexDirection: 'column' }}>
|
|
|
- <header style={{ backgroundColor: '#dbffe7' }}>
|
|
|
- Тут будут какие-то заголовки или что-то вроде этого
|
|
|
- </header>
|
|
|
- <main style={{ backgroundColor: '#dcdbff', flex: '1 1 auto' }}>
|
|
|
- {/* прописывание редиректа */}
|
|
|
- {/* <Redirect from='/direct' to='/profile' /> */}
|
|
|
-
|
|
|
- <Switch>
|
|
|
- <Route path="/autorization" component={Autorization} />
|
|
|
- <Route path="/user/:userId" component={CUser} />
|
|
|
-
|
|
|
- <Route path="/registration" component={Registration} />
|
|
|
- <Route path="/" component={ReduxFeed} exact />
|
|
|
- <Route path="/createpost" component={CreatePost} />
|
|
|
- <Route path="/direct" component={Direct} />
|
|
|
- <Route path="/about" component={PageAbout} />
|
|
|
- <Route path="/post/:postId" component={CComments} />
|
|
|
-
|
|
|
-
|
|
|
- <Route path="*" component={Page404} />
|
|
|
- {/* <Page404 /> - это аналог записи выше */}
|
|
|
- </Switch>
|
|
|
- </main>
|
|
|
- <footer style={{ backgroundColor: '#dbffe7' }}>Hipstagram from Volddemar4ik</footer>
|
|
|
- </section>
|
|
|
+ <div className="wrapper">
|
|
|
+ {/* <Header /> */}
|
|
|
+ <CHeader />
|
|
|
+ <main style={{ flexGrow: '1' }}>
|
|
|
+ <Switch>
|
|
|
+ <Route path="/" component={CFeed} exact />
|
|
|
+ <Route path="/authorization" component={Authorization} />
|
|
|
+ <Route path="/registration" component={Registration} />
|
|
|
+ <Route path="/post/:postId" component={CComments} />
|
|
|
+ <Route path="/user/:userId" component={CUser} />
|
|
|
+ <Route path="/createpost" component={CreatePost} />
|
|
|
+ {/* <Route path="/about" component={PageAbout} /> */}
|
|
|
+ <Route path="*" component={Page404} />
|
|
|
+ {/* <Page404 /> - это аналог записи выше */}
|
|
|
+ </Switch>
|
|
|
+ </main>
|
|
|
+ <Footer />
|
|
|
</div>
|
|
|
</Router >
|
|
|
- </Provider>
|
|
|
+ </Provider >
|
|
|
);
|
|
|
}
|
|
|
|
|
|
export default App;
|
|
|
+
|
|
|
+
|
|
|
+//прописывание редиректа
|
|
|
+//<Redirect from='/direct' to='/profile' />
|