Browse Source

03.04.2023 12:30

Volddemar4ik 1 year ago
parent
commit
68fe2fc9b8
39 changed files with 1313 additions and 2915 deletions
  1. 0 67
      js/Project/project/src/App(my).js
  2. 3 15
      js/Project/project/src/App.css
  3. 20 9
      js/Project/project/src/App.js
  4. 0 67
      js/Project/project/src/App_test.js
  5. 11 15
      js/Project/project/src/components/404/index.js
  6. 4 0
      js/Project/project/src/components/404/style.scss
  7. 18 46
      js/Project/project/src/components/auth_reg/index.js
  8. 210 230
      js/Project/project/src/components/auth_reg/login_form.js
  9. 44 0
      js/Project/project/src/components/auth_reg/style.scss
  10. 13 4
      js/Project/project/src/components/create_post/dnd.js
  11. 6 1
      js/Project/project/src/components/create_post/dropzone.js
  12. 53 58
      js/Project/project/src/components/create_post/index.js
  13. 26 15
      js/Project/project/src/components/create_post/uploaded_files.js
  14. 25 41
      js/Project/project/src/components/feed/aboutMe.js
  15. 92 40
      js/Project/project/src/components/feed/card.js
  16. 24 15
      js/Project/project/src/components/feed/carousel_feed.js
  17. 42 137
      js/Project/project/src/components/feed/index.js
  18. 13 13
      js/Project/project/src/components/feed/recommended.js
  19. 0 4
      js/Project/project/src/components/feed/test.js
  20. 36 41
      js/Project/project/src/components/post/carousel.js
  21. 57 43
      js/Project/project/src/components/post/comments.js
  22. 24 29
      js/Project/project/src/components/post/comments_add_field.js
  23. 12 9
      js/Project/project/src/components/post/comments_feed.js
  24. 40 46
      js/Project/project/src/components/post/comments_feed_card.js
  25. 43 24
      js/Project/project/src/components/post/index.js
  26. 50 37
      js/Project/project/src/components/search/index.js
  27. 1 0
      js/Project/project/src/components/structure/footer.js
  28. 115 49
      js/Project/project/src/components/structure/header.js
  29. 70 49
      js/Project/project/src/components/structure/modal.js
  30. 0 9
      js/Project/project/src/components/update_profile/index.js
  31. 93 1058
      js/Project/project/src/components/user/change_data.js
  32. 31 176
      js/Project/project/src/components/user/gallery.js
  33. 18 17
      js/Project/project/src/components/user/index.js
  34. 0 0
      js/Project/project/src/components/user/style.scss
  35. 64 428
      js/Project/project/src/components/user/userData.js
  36. 30 0
      js/Project/project/src/index.css
  37. 11 43
      js/Project/project/src/redux/action.js
  38. 1 3
      js/Project/project/src/redux/reducers.js
  39. 13 77
      js/Project/project/src/redux/thunks.js

+ 0 - 67
js/Project/project/src/App(my).js

@@ -1,67 +0,0 @@
-// import logo from './logo.svg';
-import './App.css';
-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";
-
-// импорт страниц
-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';
-
-// url проекта
-export const url = 'http://hipstagram.node.ed.asmer.org.ua/graphql'
-
-
-const history = createHistory()
-
-const Registration = () =>
-    <div>
-        Регистрация
-    </div>
-
-const Page404 = () =>
-    <div>
-        NOT FOUND
-    </div>
-
-
-function App() {
-    return (
-        <Provider store={store}>
-            <Router history={history}>
-                <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="/upsertpost" component={CreatePost} />
-                            {/* <Route path="/about" component={PageAbout} /> */}
-                            <Route path="*" component={Page404} />
-                            {/* <Page404 /> - это аналог записи выше */}
-                        </Switch>
-                    </main>
-                    <Footer />
-                </div>
-            </Router >
-        </Provider >
-    );
-}
-
-export default App;
-
-
-//прописывание редиректа
-//<Redirect from='/direct' to='/profile' />

+ 3 - 15
js/Project/project/src/App.css

@@ -43,20 +43,8 @@ a {
   color: inherit
 }
 
-/* анимация генерации пароля */
-.rotate {
-  animation-name: rotate;
-  animation-duration: 0.8s;
-  animation-timing-function: linear;
-  animation-iteration-count: 1;
-}
+/* ========== мои настройки =========== */
+
+
 
-@keyframes rotate {
-  from {
-    transform: rotate(0deg);
-  }
 
-  to {
-    transform: rotate(360deg);
-  }
-}

+ 20 - 9
js/Project/project/src/App.js

@@ -1,7 +1,22 @@
-import React, { createContext, useEffect, useState } from 'react'
-import { Router, Route, Redirect, withRouter, Switch } from 'react-router-dom';
-import { Provider, useSelector } from 'react-redux';
+import React, {
+    createContext,
+    useEffect,
+    useState
+} from 'react'
+
+import {
+    Provider,
+    useSelector
+} from 'react-redux';
+
+import {
+    Router,
+    Route,
+    Switch
+} from 'react-router-dom';
+
 import { store } from './redux/index';
+
 import createHistory from "history/createBrowserHistory";
 
 import './App.css';
@@ -15,13 +30,13 @@ import { CHeader } from './components/structure/header';
 import Footer from './components/structure/footer';
 import Search from './components/search';
 import Page404 from './components/404';
-// import UpsertProfile from './components/update_profile';
 
 // url проекта
 export const url = 'http://hipstagram.node.ed.asmer.org.ua/'
 
 const history = createHistory()
 
+// контексты модального окна для счетчиков и обновления профиля
 export const ModalForCountsContext = createContext()
 export const UpdateProfile = createContext()
 
@@ -33,7 +48,6 @@ const MyRoutes = () => {
             <Route path="/post/:postId" component={CComments} />
             <Route path="/user/:userId" component={CUser} />
             <Route path="/upsert/:postId" component={CreatePost} />
-            {/* <Route path="/updateprofile" component={UpsertProfile} /> */}
             <Route path='/search' component={Search} />
             <Route path="*" component={Page404} />
         </Switch>
@@ -60,9 +74,9 @@ const MainRoutes = () => {
     const handleCloseModal = () => {
         setOpenModal(false)
         setModalArray(false)
-        // console.log('modalArray: ', modalArray)
     }
 
+
     // функция управления моими данными для обновления профиля
     const aboutMe = useSelector(state => state?.promise?.AboutMe?.payload)
 
@@ -90,8 +104,6 @@ const MainRoutes = () => {
     }, [aboutMe])
 
 
-
-
     return (
         <main style={{ flexGrow: '1' }}>
             {currentState
@@ -110,7 +122,6 @@ const MainRoutes = () => {
     )
 }
 
-
 export default function App() {
     return (
         <Provider store={store}>

+ 0 - 67
js/Project/project/src/App_test.js

@@ -1,67 +0,0 @@
-// import logo from './logo.svg';
-import './App.css';
-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";
-
-// импорт страниц
-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';
-
-// url проекта
-export const url = 'http://hipstagram.node.ed.asmer.org.ua/graphql'
-
-
-const history = createHistory()
-
-const Registration = () =>
-  <div>
-    Регистрация
-  </div>
-
-const Page404 = () =>
-  <div>
-    NOT FOUND
-  </div>
-
-
-function App() {
-  return (
-    <Provider store={store}>
-      <Router history={history}>
-        <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="/upsertpost" component={CreatePost} />
-              {/* <Route path="/about" component={PageAbout} /> */}
-              <Route path="*" component={Page404} />
-              {/* <Page404 /> - это аналог записи выше */}
-            </Switch>
-          </main>
-          <Footer />
-        </div>
-      </Router >
-    </Provider >
-  );
-}
-
-export default App;
-
-
-//прописывание редиректа
-//<Redirect from='/direct' to='/profile' />

+ 11 - 15
js/Project/project/src/components/404/index.js

@@ -1,9 +1,13 @@
 import { useHistory } from 'react-router-dom'
 
-import { Typography, Box } from '@mui/material'
+import {
+    Typography,
+    Box
+} from '@mui/material'
 
-function Page404() {
+import './style.scss'
 
+function Page404() {
     const history = useHistory()
 
     function toMain() {
@@ -11,39 +15,32 @@ function Page404() {
     }
 
     return (
-        <Box
-            sx={{
-                marginTop: '20px',
-                padding: '16px'
-            }}
-        >
+        <Box className='container-404'>
             <Typography
                 variant="h6"
-                gutterBottom
                 color='text.primary'
                 align='center'
+                gutterBottom
             >
                 К сожалению, эта страница недоступна.
             </Typography>
 
             <Typography
                 variant="subtitle1"
-                gutterBottom
                 color='text.primary'
                 align='center'
+                gutterBottom
             >
                 Возможно, вы воспользовались недействительной ссылкой или страница была удалена.
             </Typography>
 
             <Typography
+                className='cursor-pointer'
                 variant="subtitle1"
-                gutterBottom
                 color='text.primary'
                 align='center'
+                gutterBottom
                 onClick={toMain}
-                sx={{
-                    cursor: 'pointer'
-                }}
             >
                 Назад в Instagram.
             </Typography>
@@ -51,5 +48,4 @@ function Page404() {
     )
 }
 
-
 export default Page404

+ 4 - 0
js/Project/project/src/components/404/style.scss

@@ -0,0 +1,4 @@
+.container-404 {
+    margin-top: 20px;
+    padding: 16px;
+}

+ 18 - 46
js/Project/project/src/components/auth_reg/index.js

@@ -1,20 +1,23 @@
 import * as React from 'react';
+
 import {
     useHistory,
     useLocation
 } from "react-router-dom";
 
-import LoginForm from './login_form';
-
 import {
     Paper,
     Box,
-    Typography
+    Typography,
+    Container
 } from "@mui/material";
 
+import LoginForm from './login_form';
+
+import './style.scss'
 
 
-// ссылка на страницу регистрации
+// ссылка на страницу регистрации/авторизации
 function RegistrationLink() {
     const history = useHistory()
     let location = useLocation().pathname === '/'
@@ -25,21 +28,14 @@ function RegistrationLink() {
 
     return (
         <Typography
+            className='registration-link'
             variant="subtitle1"
-            align='center'
-            sx={{
-                alignSelf: 'end',
-            }}
         >
             {location ? 'Нет аккаунта?' : 'Уже зарегистрированы? '}
             <Typography
+                className='cursor-pointer'
                 variant="body1"
-                align='center'
                 color='primary.main'
-                sx={{
-                    cursor: 'pointer'
-                }
-                }
                 onClick={regLogLink}
             >
                 {location ? 'Зарегистрироваться' : `Войти`}
@@ -52,49 +48,25 @@ function RegistrationLink() {
 // Основное окно регистрации (без полей ввода и кнопок)
 function AuthReg() {
     return (
-        <Box sx={{
-            display: 'grid',
-            height: '80vh',
-            justifyContent: 'center',
-            alignItems: 'center'
-        }}>
-            <Paper elevation={3}
-                sx={{
-                    padding: '5px',
-                    width: '400px',
-                    height: '500px',
-                    display: 'grid',
-                    justifyContent: 'center',
-                    alignItems: 'center'
-                }}>
+        <Container>
+            <Paper
+                className='block-auth-reg'
+                elevation={4}
+            >
                 <Typography
+                    className='logo'
                     variant="h4"
-                    noWrap
-                    sx={{
-                        display: 'grid',
-                        fontFamily: 'monospace',
-                        fontWeight: 700,
-                        letterSpacing: '.3rem',
-                        color: 'inherit',
-                        textDecoration: 'none',
-                        flexGrow: '1',
-                        marginTop: '20px',
-                        justifyContent: 'center'
-                    }} >
+                >
                     Hipstagram
                 </Typography>
 
-                <Box
-                    sx={{
-                        display: 'grid',
-                        alignSelf: 'start'
-                    }}>
+                <Box className="login-form" >
                     <LoginForm />
                 </Box>
 
                 <RegistrationLink />
             </Paper>
-        </Box >
+        </Container >
     )
 }
 

+ 210 - 230
js/Project/project/src/components/auth_reg/login_form.js

@@ -1,14 +1,14 @@
 import React, {
     forwardRef,
-    useEffect,
     useState
 } from 'react';
-import { store } from '../../redux';
+
+import { useDispatch } from 'react-redux';
+
 import {
     useHistory,
     useLocation
 } from "react-router-dom";
-import { actionFullLogin, actionFullRegistration } from "../../redux/thunks";
 
 import {
     Dialog,
@@ -36,6 +36,11 @@ import {
     Person
 } from '@mui/icons-material';
 
+import {
+    actionFullLogin,
+    actionFullRegistration
+} from "../../redux/thunks";
+
 
 // анимация появление модального окна
 const Transition = forwardRef(function Transition(props, ref) {
@@ -45,11 +50,17 @@ const Transition = forwardRef(function Transition(props, ref) {
 // поля ввода и кнопки
 function LoginForm() {
     const location = useLocation().pathname === '/';
+    const dispatch = useDispatch()
     const history = useHistory();
 
     // отслеживаем введение данных в полях логин/пароль
     const [data, setData] = useState({ login: '', pass: '', confirmPass: '' })
-    // console.log('data: ', data)
+
+    // проверяем данные на валидность, чтобы активировать кнопку
+    const [isDataValid, setIsDataValid] = useState(false)
+
+    // проверяем данные только после ухода с фокуса(чтобы при открытии страницы сразу не горело красным все)
+    const [passwordInFocus, setPassworInFocus] = useState(false)
 
     //  модальное окно ошибки при реге открытие/закрытие
     const [open, setOpen] = useState(false);
@@ -60,72 +71,13 @@ function LoginForm() {
         setOpen(false);
     }
 
-    // проверяем данные на валидность, чтобы активировать кнопку
-    const [isDataValid, setIsDataValid] = useState(false)
-    // проверяем данные только после ухода с фокуса(чтобы при открытии страницы сразу не горело красным все)
-    const [passwordInFocus, setPassworInFocus] = useState(false)
-
-
-
-
-
-    // const [onFocus, setOnFocus] = useState(false)
-    // console.log('onFosuc: ', onFocus)
-    // function isOnFocus() {
-    //     setOnFocus(true)
-    //     // setIsLoginValid(true)
-    //     // setIsPasswordValid(true)
-    //     // setIsPasswordConfirmValid(true)
-    // }
-
-    // const [isFullDataValid, setIsFullDataValid] = useState(true)
-    // console.log('MAIN: ', isFullDataValid)
-
-    // const [isLoginValid, setIsLoginValid] = useState(false)
-    // console.log('isLoginValid: ', isLoginValid)
-
-    // const [isPasswordValid, setIsPasswordValid] = useState(false)
-    // console.log('isPasswordValid: ', isPasswordValid)
-
-    // const [isPasswordConfirmValid, setIsPasswordConfirmValid] = useState(false)
-    // console.log('isPasswordConfirmValid: ', isPasswordConfirmValid)
-
-    // // регулярка для проверка пароля
-    // const patternPassword = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
-    // // регулярка для проверки логина на латинские символы и цифры
-    // const patternLogin = /^[a-zA-Z0-9]+$/
-
-    // // функция проверки пароля, которая запускается, когда уходит фокус с поля пароля
-    // useEffect(() => {
-    //     if (onFocus) {
-    //         // провекар логина на валид
-    //         setIsLoginValid(patternLogin.test(data?.login))
-
-    //         // провекар пароль на валид
-    //         setIsPasswordValid(patternPassword.test(data?.pass))
-
-    //         // провекар подтверждение пароля на валид
-    //         setIsPasswordConfirmValid(data?.pass === data?.confirmPass)
-
-    //         // //  общая проверка
-    //         // setIsFullDataValid(onFocus && isLoginValid && isPasswordValid && isPasswordConfirmValid)
-    //         setIsFullDataValid(!(true && !(isLoginValid && isPasswordValid && isPasswordConfirmValid)))
-    //     }
-
-    //     //  общая проверка
-
-    // }, [data])
-
-
-
-
-
     // функция проверки пароля, которая запускается, когда уходит фокус с поля пароля
     function isPasswordValid() {
         setPassworInFocus(true)
 
         // регулярка для проверка пароля
         const patternPassword = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
+
         // регулярка для проверки логина на латинские символы и цифры
         const patternLogin = /^[a-zA-Z0-9]+$/
 
@@ -193,155 +145,176 @@ function LoginForm() {
     };
 
     // Регистрация
-    async function fullRegistration() {
-        const token = await store.dispatch(actionFullRegistration(data.login, data.confirmPass))
-
-        if (token !== null) {
-            history.push('/')
-        } else {
-            openModalAlertWindow()
-        }
+    function fullRegistration() {
+        dispatch(actionFullRegistration(data.login, data.confirmPass))
+            .then(token => {
+                if (token === null) {
+                    openModalAlertWindow()
+                } else {
+                    history.push('/')
+                }
+            })
     }
 
     // Авторизация
-    async function fullLogin() {
-        const token = await store.dispatch(actionFullLogin(data.login, data.pass))
-
-        if (token == null) {
-            openModalAlertWindow()
-        }
+    function fullLogin() {
+        dispatch(actionFullLogin(data.login, data.pass))
+            .then(token => {
+                if (token === null) {
+                    openModalAlertWindow()
+                }
+            })
     }
 
 
     return (
-        <Box sx={{ width: '100%' }}>
-            <form>
-                <Stack spacing={2}>
-                    <ClickAwayListener onClickAway={handleTooltipCloseLogin}>
-                        <div>
-                            <Tooltip
-                                PopperProps={{
-                                    disablePortal: true,
-                                }}
-                                onClose={handleTooltipClose}
-                                open={openToolTipsLogin}
-                                disableFocusListener
-                                disableHoverListener
-                                disableTouchListener
-                                title={!location && 'Сгенерируйте или введите пароль (только латинские буквы и цифры)'}
-                                arrow
+        <React.Fragment>
+            <Stack spacing={2}>
+                <ClickAwayListener onClickAway={handleTooltipCloseLogin}>
+                    <Tooltip
+                        PopperProps={{
+                            disablePortal: true,
+                        }}
+                        onClose={handleTooltipClose}
+                        open={openToolTipsLogin}
+                        disableFocusListener
+                        disableHoverListener
+                        disableTouchListener
+                        title={!location &&
+                            'Сгенерируйте или введите пароль (только латинские буквы и цифры)'
+                        }
+                        arrow
+                    >
+                        <FormControl
+                            variant="outlined"
+                            onClick={handleTooltipOpenLogin}
+                            error={!location && passwordInFocus && !isDataValid}
+                        >
+                            <InputLabel
+                                htmlFor="outlined-adornment-password"
                             >
-                                <FormControl
-                                    variant="outlined"
-                                    onClick={handleTooltipOpenLogin}
-                                    error={!location && passwordInFocus && !isDataValid}
-                                // error={!location && isLoginValid}
-                                >
-                                    <InputLabel htmlFor="outlined-adornment-password">Логин</InputLabel>
-                                    <OutlinedInput
-                                        fullWidth
-                                        id="login"
-                                        label="Логин"
-                                        size="normal"
-                                        type='text'
-                                        value={data.login}
-                                        onChange={e => setData({ ...data, login: e.target.value })}
-                                        onBlur={isPasswordValid}
-                                        // onFocus={isOnFocus}
-
-                                        endAdornment={
-                                            <InputAdornment position="end">
-                                                {!location && <IconButton
-                                                    aria-label="login"
-                                                    onClick={generateLogin}
-                                                    edge="end"
-                                                    title='Сгенерировать логин'
-                                                >
-                                                    <Refresh id='loginUpdate' />
-                                                </IconButton>}
-                                                {location && <IconButton
-                                                    aria-label="login"
-                                                    edge="end"
-                                                    title='Логин'
-                                                >
-                                                    <Person />
-                                                </IconButton>}
-                                            </InputAdornment>
-                                        }
-                                    />
-                                </FormControl>
-                            </Tooltip>
-                        </div>
-                    </ClickAwayListener>
-
-                    <ClickAwayListener onClickAway={handleTooltipClose}>
-                        <div>
-                            <Tooltip
-                                PopperProps={{
-                                    disablePortal: true,
-                                }}
-                                onClose={handleTooltipClose}
-                                open={openToolTipsPass}
-                                disableFocusListener
-                                disableHoverListener
-                                disableTouchListener
-                                title={!location && 'Минимум 8 символов (большие и маленькие латинские буквы, цифры и спецсимволы)'}
-                                arrow
+                                Логин
+                            </InputLabel>
+
+                            <OutlinedInput
+                                fullWidth
+                                id="login"
+                                label="Логин"
+                                size="normal"
+                                type='text'
+                                value={data.login}
+                                onChange={e => setData({ ...data, login: e.target.value })}
+                                onBlur={isPasswordValid}
+                                endAdornment={
+                                    <InputAdornment
+                                        position="end"
+                                    >
+                                        {!location &&
+                                            <IconButton
+                                                aria-label="login"
+                                                onClick={generateLogin}
+                                                edge="end"
+                                                title='Сгенерировать логин'
+                                            >
+                                                <Refresh id='loginUpdate' />
+                                            </IconButton>}
+
+                                        {location &&
+                                            <IconButton
+                                                aria-label="login"
+                                                edge="end"
+                                                title='Логин'
+                                            >
+                                                <Person />
+                                            </IconButton>}
+                                    </InputAdornment>
+                                }
+                            />
+                        </FormControl>
+                    </Tooltip>
+                </ClickAwayListener>
+
+                <ClickAwayListener onClickAway={handleTooltipClose}>
+                    <Tooltip
+                        PopperProps={{
+                            disablePortal: true,
+                        }}
+                        onClose={handleTooltipClose}
+                        open={openToolTipsPass}
+                        disableFocusListener
+                        disableHoverListener
+                        disableTouchListener
+                        title={!location &&
+                            'Минимум 8 символов (большие и маленькие латинские буквы, цифры и спецсимволы)'
+                        }
+                        arrow
+                    >
+                        <FormControl
+                            variant="outlined"
+                            onClick={handleTooltipOpen}
+                            error={!location && passwordInFocus && !isDataValid}
+                        >
+                            <InputLabel
+                                htmlFor="outlined-adornment-password"
                             >
-                                <FormControl
-                                    variant="outlined"
-                                    onClick={handleTooltipOpen}
-                                    error={!location && passwordInFocus && !isDataValid}
-                                // error={!location && isPasswordValid}
-                                >
-                                    <InputLabel htmlFor="outlined-adornment-password">Пароль</InputLabel>
-                                    <OutlinedInput
-                                        fullWidth
-                                        id="password"
-                                        label="Пароль"
-                                        size="normal"
-                                        type={showPassword ? 'text' : 'password'}
-                                        value={data.pass}
-                                        onChange={e => setData({ ...data, pass: e.target.value })}
-                                        onBlur={isPasswordValid}
-                                        // onFocus={isOnFocus}
-
-                                        endAdornment={
-                                            <InputAdornment position="end">
-                                                <IconButton
-                                                    aria-label="visibility"
-                                                    onClick={handleClickShowPassword}
-                                                    onMouseDown={handleMouseDownPassword}
-                                                    edge="end"
-                                                    title={showPassword ? 'Скрыть пароль' : 'Показать пароль'}
-                                                >
-                                                    {showPassword ? <VisibilityOff /> : <Visibility />}
-                                                </IconButton>
-                                            </InputAdornment>
-                                        }
-                                    />
-                                </FormControl>
-                            </Tooltip>
-                        </div>
-                    </ClickAwayListener>
-
-                    {!location && <FormControl
+                                Пароль
+                            </InputLabel>
+
+                            <OutlinedInput
+                                fullWidth
+                                id="password"
+                                label="Пароль"
+                                size="normal"
+                                type={showPassword
+                                    ? 'text'
+                                    : 'password'}
+                                value={data.pass}
+                                onChange={e => setData({ ...data, pass: e.target.value })}
+                                onBlur={isPasswordValid}
+                                endAdornment={
+                                    <InputAdornment
+                                        position="end"
+                                    >
+                                        <IconButton
+                                            aria-label="visibility"
+                                            onClick={handleClickShowPassword}
+                                            onMouseDown={handleMouseDownPassword}
+                                            edge="end"
+                                            title={showPassword
+                                                ? 'Скрыть пароль'
+                                                : 'Показать пароль'}
+                                        >
+                                            {showPassword ? <VisibilityOff /> : <Visibility />}
+                                        </IconButton>
+                                    </InputAdornment>
+                                }
+                            />
+                        </FormControl>
+                    </Tooltip>
+                </ClickAwayListener>
+
+                {!location &&
+                    <FormControl
                         variant="outlined"
                         error={passwordInFocus && !isDataValid}
-                    // error={isPasswordConfirmValid}
                     >
-                        <InputLabel htmlFor="outlined-adornment-password">Подтвердите пароль</InputLabel>
+                        <InputLabel
+                            htmlFor="outlined-adornment-password"
+                        >
+                            Подтвердите пароль
+                        </InputLabel>
+
                         <OutlinedInput
                             fullWidth
                             id="confirmPassword"
                             label="Подтвердите пароль"
                             size="normal"
-                            type={showPasswordConfirm ? 'text' : 'password'}
+                            type={showPasswordConfirm
+                                ? 'text'
+                                : 'password'}
                             value={data.confirmPass}
                             onChange={e => setData({ ...data, confirmPass: e.target.value })}
                             onBlur={isPasswordValid}
-                            // onFocus={isOnFocus}
-
                             endAdornment={
                                 <InputAdornment position="end">
                                     <IconButton
@@ -349,7 +322,9 @@ function LoginForm() {
                                         onClick={handleClickShowPasswordConfirm}
                                         onMouseDown={handleMouseDownPasswordConfirm}
                                         edge="end"
-                                        title={showPasswordConfirm ? 'Скрыть пароль' : 'Показать пароль'}
+                                        title={showPasswordConfirm
+                                            ? 'Скрыть пароль'
+                                            : 'Показать пароль'}
                                     >
                                         {showPasswordConfirm ? <VisibilityOff /> : <Visibility />}
                                     </IconButton>
@@ -358,45 +333,50 @@ function LoginForm() {
                         />
                     </FormControl>}
 
+                <Button
+                    size="large"
+                    variant="contained"
+                    disabled={location
+                        ? (isDataValid || false)
+                        : !isDataValid}
+                    onClick={location
+                        ? fullLogin
+                        : fullRegistration}
+                >
+                    {location
+                        ? 'Войти'
+                        : 'Регистрация'}
+                </Button>
+            </Stack>
+
+            <Dialog
+                open={open}
+                onClose={closeModalAlertWindow}
+                TransitionComponent={Transition}
+            >
+                <DialogTitle>
+                    Что-то пошло не так!
+                </DialogTitle>
+
+                <DialogContent>
+                    <DialogContentText>
+                        {
+                            location
+                                ? 'Вы ввели неправильный логин или пароль. Повторите попытку.'
+                                : 'Этот логин уже зарегистрирован. Используйте другой логин или войдите в свою учетную запись.'
+                        }
+                    </DialogContentText>
+                </DialogContent>
+
+                <DialogActions>
                     <Button
-                        size="large"
-                        variant="contained"
-                        disabled={location
-                            ? (isDataValid || false)
-                            : !isDataValid}
-                        // ? (isFullDataValid || false)
-                        // : isFullDataValid}
-                        onClick={location ? fullLogin : fullRegistration}
+                        onClick={closeModalAlertWindow}
                     >
-                        {location
-                            ? 'Войти' : 'Регистрация'}
+                        Ок
                     </Button>
-                </Stack>
-            </form>
-
-            <div>
-                <Dialog
-                    open={open}
-                    onClose={closeModalAlertWindow}
-                    TransitionComponent={Transition}
-                // keepMounted // всегда держит компонент смонтированным в DOM
-                >
-                    <DialogTitle>Что-то пошло не так!</DialogTitle>
-                    <DialogContent>
-                        <DialogContentText>
-                            {
-                                location
-                                    ? 'Вы ввели неправильный логин или пароль. Повторите попытку.'
-                                    : 'Этот логин уже зарегистрирован. Используйте другой логин или войдите в свою учетную запись.'
-                            }
-                        </DialogContentText>
-                    </DialogContent>
-                    <DialogActions>
-                        <Button onClick={closeModalAlertWindow}>Ок</Button>
-                    </DialogActions>
-                </Dialog>
-            </div>
-        </Box>
+                </DialogActions>
+            </Dialog>
+        </React.Fragment>
     )
 }
 

+ 44 - 0
js/Project/project/src/components/auth_reg/style.scss

@@ -0,0 +1,44 @@
+main .css-1oqqzyl-MuiContainer-root {
+    display: grid;
+    height: 80vh;
+    justify-content: center;
+    align-items: center;
+
+    .block-auth-reg {
+        display: grid;
+        padding: 5px;
+        width: 400px;
+        height: 500px;
+        justify-content: center;
+        align-items: center;
+
+        .logo {
+            display: grid;
+            flex-wrap: nowrap;
+            font-family: 'monospace', sans-serif;
+            font-weight: 700;
+            letter-spacing: 0.3rem;
+            color: inherit;
+            text-decoration: none;
+            flex-grow: 1;
+            margin-top: 20px;
+            justify-content: center;
+        }
+
+        .login-form {
+            align-self: flex-start;
+
+            .rotate {
+                animation-name: rotate;
+                animation-duration: 0.8s;
+                animation-timing-function: linear;
+                animation-iteration-count: 1;
+            }
+        }
+
+        .registration-link {
+            align-self: flex-end;
+            text-align: center;
+        }
+    }
+}

+ 13 - 4
js/Project/project/src/components/create_post/dnd.js

@@ -1,5 +1,7 @@
-import * as React from 'react';
-import { useState, useEffect } from 'react';
+import React, {
+    useState,
+    useEffect
+} from 'react';
 
 import {
     DndContext,
@@ -8,8 +10,16 @@ import {
     useSensor,
     useSensors, useDroppable
 } from "@dnd-kit/core";
-import { sortableKeyboardCoordinates, rectSortingStrategy, SortableContext, useSortable, horizontalListSortingStrategy } from "@dnd-kit/sortable";
+
+import {
+    sortableKeyboardCoordinates,
+    rectSortingStrategy,
+    SortableContext,
+    useSortable
+} from "@dnd-kit/sortable";
+
 import { CSS } from "@dnd-kit/utilities";
+
 import { arrayMoveImmutable } from 'array-move';
 
 
@@ -39,7 +49,6 @@ const SortableItem = (props) => {
 
 
 const Droppable = ({ id, items, itemProp, keyField, render }) => {
-
     return (
         <SortableContext id={id} items={items} strategy={rectSortingStrategy}>
             {items?.map((item) => (

+ 6 - 1
js/Project/project/src/components/create_post/dropzone.js

@@ -1,5 +1,10 @@
-import React, { useCallback, useMemo } from 'react'
+import React, {
+    useCallback,
+    useMemo
+} from 'react'
+
 import { useDropzone } from 'react-dropzone'
+
 import { Box, Stack } from '@mui/system';
 
 const baseStyle = {

+ 53 - 58
js/Project/project/src/components/create_post/index.js

@@ -1,38 +1,50 @@
-import * as React from 'react';
-import { useState, useEffect } from 'react';
-import { connect, useDispatch, useSelector } from 'react-redux';
-import { useHistory, useParams } from "react-router-dom";
-import { store } from '../../redux';
-
-import Box from '@mui/material/Box';
-import TextField from '@mui/material/TextField';
-import Stack from '@mui/material/Stack';
-// import Button from '@mui/material/Button';
-import Container from '@mui/material/Container';
-import SendRoundedIcon from '@mui/icons-material/SendRounded';
+import React, {
+    useState,
+    useEffect
+} from 'react';
+
+import {
+    connect,
+    useDispatch,
+    useSelector
+} from 'react-redux';
+
+import {
+    useHistory,
+    useParams
+} from "react-router-dom";
+
+import {
+    Box,
+    TextField,
+    Container,
+} from '@mui/material'
+
 import Button from '@mui/material-next/Button';
 
+import SendRoundedIcon from '@mui/icons-material/SendRounded';
+
 import { StyledDropzone } from './dropzone';
-import { actionFilesUpload, actionFullCreatePost } from '../../redux/thunks';
-import { actionCreatePost } from '../../redux/action';
-import HighlightOffRoundedIcon from '@mui/icons-material/HighlightOffRounded';
 import { Dnd } from './dnd';
 import { UploadedFiles } from './uploaded_files';
+
+import {
+    actionFilesUpload,
+    actionFullCreatePost
+} from '../../redux/thunks';
 import { actionFindPostOne } from '../../redux/action';
 
 
 export const CreatePost = () => {
-
-    // отслеживаем url поста. если create - создаем новый
+    const history = useHistory()
     const { postId } = useParams()
-    // console.log('params', postId)
+    const dispatch = useDispatch()
 
-    // редактирование поста
+    // запускается, если открылась страница редактирования поста
     useEffect(() => {
         if (postId !== 'create') {
             const getPost = async (id) => {
                 const res = await dispatch(actionFindPostOne(id))
-                console.log('res', res)
 
                 if (res) {
                     post._id = postId
@@ -49,17 +61,13 @@ export const CreatePost = () => {
     }, [postId])
 
 
-    // параметры для поста
+    // параметры поста для отправки на бек
     const [post, setPost] = useState({ title: '', text: '', images: [] })
-    console.log('post', post)
 
-    // создаем объект с данными из форм для отправки на бек
+    // создаем объект с данными из всех форм для отправки на бек
     const newPostData = ({ ...post, images: ((post.images)?.map(item => ({ _id: item._id }))) })
-    console.log('newPostData', newPostData)
 
-    const dispatch = useDispatch()
-
-    // вот эту часть нужно будет сделать через connect???
+    // отслеживаем, когда картинки загрузятся на сервак и отработает промис
     const images = useSelector(state => state.promise?.FilesUpload?.payload)
 
     useEffect((() => {
@@ -68,20 +76,17 @@ export const CreatePost = () => {
         }
     }), [images])
 
-
+    // удаление картинки
     const deleteImage = image => setPost({ ...post, images: post.images.filter(i => i !== image) })
 
-    const localPostImage = ({ image }) => <UploadedFiles image={image}
-        onDelete={imgToDelete => deleteImage(imgToDelete)} />
-
-
-    // создаем новый пост и переходим на его страницу
-    const history = useHistory()
-
-    const newPost = useSelector(state => state.promise?.CreatePost?.payload?._id)
-    // console.log('newPost', newPost)
+    const localPostImage = ({ image }) => <UploadedFiles
+        image={image}
+        onDelete={imgToDelete => deleteImage(imgToDelete)}
+    />
 
+    // const newPost = useSelector(state => state.promise?.CreatePost?.payload?._id)
 
+    // запрос на бек на создание.редактирование поста
     async function onSend() {
         const res = await dispatch(actionFullCreatePost(newPostData));
 
@@ -93,12 +98,18 @@ export const CreatePost = () => {
 
     return (
         <Container maxWidth="90%">
-            <Container>
-                <StyledDropzone onFiles={files => dispatch(actionFilesUpload(files))} onPost={post} />
-            </Container>
-
+            <Box>
+                <StyledDropzone
+                    onFiles={files => dispatch(actionFilesUpload(files))}
+                    onPost={post}
+                />
+            </Box>
 
-            <Dnd items={post.images} render={localPostImage} itemProp="image" keyField="_id"
+            <Dnd
+                items={post.images}
+                render={localPostImage}
+                itemProp="image"
+                keyField="_id"
                 onChange={images => setPost({ ...post, images })}
                 horizontal
             />
@@ -134,20 +145,6 @@ export const CreatePost = () => {
                 />
             </Box>
 
-            {/* <Container spacing={2} direction="row" > */}
-            {/* <Button
-                    variant="outlined"
-                    startIcon={
-                        <SendRoundedIcon
-                            style={{ transform: 'translate(3px, -4px) rotate(-30deg)' }}
-                        />}
-
-                    onClick={onSend}
-                >
-                    Опубликовать пост
-                </Button> */}
-
-
             <Container
                 onClick={onSend}
                 sx={{
@@ -166,8 +163,6 @@ export const CreatePost = () => {
                     Опубликовать пост
                 </Button>
             </Container>
-
-            {/* </Container > */}
         </Container >
     )
 }

+ 26 - 15
js/Project/project/src/components/create_post/uploaded_files.js

@@ -1,27 +1,38 @@
 import { url } from "../../App";
 
 import { Box } from "@mui/system"
-import HighlightOffRoundedIcon from '@mui/icons-material/HighlightOffRounded';
+
+import { HighlightOffRounded } from '@mui/icons-material';
 
 
 export function UploadedFiles({ image, onDelete }) {
     return (
-        <Box className='imgBlock' sx={{
-            position: 'relative'
-        }}>
+        <Box
+            className='imgBlock'
+            sx={{
+                position: 'relative'
+            }}
+        >
             <img
-                style={{ maxWidth: '200px', margin: '5px' }}
-                src={url + image.url} key={image._id}
+                src={url + image.url}
+                key={image._id}
+                style={{
+                    maxWidth: '200px',
+                    margin: '5px'
+                }}
+            />
+
+            <HighlightOffRounded
+                style={{
+                    position: 'absolute',
+                    top: '7px',
+                    right: '7px',
+                    color: 'rgba(238, 238, 238, 0.8)',
+                    fontSize: '25px',
+                    cursor: 'default'
+                }}
+                onClick={() => onDelete(image)}
             />
-            <HighlightOffRoundedIcon style={{
-                position: 'absolute',
-                top: '7px',
-                right: '7px',
-                color: 'rgba(238, 238, 238, 0.8)',
-                fontSize: '25px',
-                cursor: 'default'
-            }}
-                onClick={() => onDelete(image)} />
         </Box>
     )
 } 

+ 25 - 41
js/Project/project/src/components/feed/aboutMe.js

@@ -1,32 +1,23 @@
+import { url } from "../../App"
+
 import React, { useContext } from 'react';
-import { Avatar, Typography, Box, Stack, CardHeader, Backdrop, Modal, Fade, Divider, IconButton } from '@mui/material'
-import { Close } from '@mui/icons-material'
-import { useSelector, connect } from 'react-redux'
-import { useHistory } from 'react-router-dom'
 
-import { RecommendedCard } from './recommended';
-import ModalWindow from '../structure/modal';
-import { ModalForCountsContext, UpdateProfile } from "../../App";
+import { useSelector, connect } from 'react-redux'
 
-import './style.scss'
+import { useHistory } from 'react-router-dom'
 
-import { url } from "../../App"
+import {
+    Avatar,
+    Typography,
+    Stack,
+    CardHeader,
+} from '@mui/material'
 
+import ModalWindow from '../structure/modal';
 
-const style = {
-    position: 'absolute',
-    top: '50%',
-    left: '50%',
-    transform: 'translate(-50%, -50%)',
-    width: 400,
-    height: 'fit-content',
-    bgcolor: 'background.paper',
-    boxShadow: 24,
-    outline: 0,
-    borderRadius: 3,
-    padding: '5px 0'
-};
+import { ModalForCountsContext } from "../../App";
 
+import './style.scss'
 
 
 function AboutMe({ aboutMe = {} }) {
@@ -34,10 +25,6 @@ function AboutMe({ aboutMe = {} }) {
 
     const myPostsCount = useSelector(state => state?.promise?.MyPostsCount?.payload)
 
-    function toMyAccount() {
-        history.push(`/user/${aboutMe?._id}`)
-    }
-
     // контекст модального окна
     const [modalName, setModalName, modalArray, setModalArray, openModal, setOpenModal, handleOpenModal, handleCloseModal] = useContext(ModalForCountsContext)
 
@@ -49,8 +36,13 @@ function AboutMe({ aboutMe = {} }) {
         handleOpenModal({ arr: aboutMe?.following, name: 'Ваши подписки' })
     }
 
+    function toMyAccount() {
+        history.push(`/user/${aboutMe?._id}`)
+    }
+
+
     return (
-        <Box>
+        <React.Fragment>
             <CardHeader
                 avatar={
                     <Avatar
@@ -65,9 +57,7 @@ function AboutMe({ aboutMe = {} }) {
 
                 title={
                     <Typography
-                        sx={{
-                            cursor: 'pointer'
-                        }}
+                        className='cursor-pointer'
                         variant='h6'
                         onClick={toMyAccount}
                     >
@@ -84,40 +74,34 @@ function AboutMe({ aboutMe = {} }) {
                     </Typography>
                 }
             />
+
             <Stack
                 direction="row"
                 spacing={1}
                 padding={2}
                 sx={{
                     paddingTop: 0,
-                    // flexWrap: 'wrap'
                 }}
             >
                 <Typography
+                    className='cursor-pointer'
                     variant='body2'
-                    sx={{
-                        cursor: 'pointer'
-                    }}
                     onClick={toMyAccount}
                 >
                     {myPostsCount || '0'} публикаций
                 </Typography>
 
                 <Typography
+                    className='cursor-pointer'
                     variant='body2'
-                    sx={{
-                        cursor: 'pointer'
-                    }}
                     onClick={myFollower}
                 >
                     {aboutMe?.followers?.length || '0'} подписчиков
                 </Typography>
 
                 <Typography
+                    className='cursor-pointer'
                     variant='body2'
-                    sx={{
-                        cursor: 'pointer'
-                    }}
                     onClick={myFollowings}
                 >
                     {aboutMe?.following?.length || '0'} подписок
@@ -125,7 +109,7 @@ function AboutMe({ aboutMe = {} }) {
             </Stack>
 
             {modalArray && <ModalWindow />}
-        </Box>
+        </React.Fragment>
     )
 }
 

+ 92 - 40
js/Project/project/src/components/feed/card.js

@@ -1,34 +1,68 @@
 import { url } from '../../App';
 
-import { useState, useEffect, useContext } from 'react';
-import { useDispatch, useSelector } from "react-redux";
+import React, {
+    useState,
+    useEffect,
+    useContext
+} from 'react';
+
+import {
+    useDispatch,
+    useSelector
+} from "react-redux";
 import { useHistory } from 'react-router-dom';
 
-import { Card, CardHeader, CardMedia, CardContent, CardActions, Avatar, IconButton, Typography, Box, Divider, Popover, Tooltip, Checkbox } from '@mui/material'
-import PopupState, { bindTrigger, bindPopover } from 'material-ui-popup-state';
-import { FavoriteBorderRounded, FavoriteRounded, ChatBubbleOutline, TurnedInNot, SendRounded } from '@mui/icons-material/'
+import {
+    Card,
+    CardHeader,
+    CardMedia,
+    CardContent,
+    CardActions,
+    Avatar,
+    IconButton,
+    Typography,
+    Box,
+    Divider,
+    Popover,
+    Tooltip,
+    Checkbox
+} from '@mui/material'
+
 import Grid from '@mui/material/Unstable_Grid2';
 
-import { actionFullAddLike, actionFullDeleteLike } from "../../redux/thunks";
+import PopupState, {
+    bindTrigger,
+    bindPopover
+} from 'material-ui-popup-state';
+
+import {
+    FavoriteBorderRounded,
+    FavoriteRounded,
+    ChatBubbleOutline,
+    TurnedInNot,
+    SendRounded
+} from '@mui/icons-material/'
+
+import {
+    actionFullAddLike,
+    actionFullDeleteLike
+} from "../../redux/thunks";
 
 import { MyCarousel } from './carousel_feed';
 import { createDate } from '../functions';
-import ModalWindow from '../structure/modal';
 import { ModalForCountsContext } from '../../App';
 
 
 export function CardFeed({ postData }) {
-    // console.log('postData: ', postData)
-
     const history = useHistory()
     const dispatch = useDispatch()
 
-
     // создание ссылки "поделиться"
     const [toolTipText, setToolTipText] = useState(true)
     let text = toolTipText ? 'Нажмите для копирования' : 'Ссылка скопирована в буфер обмена'
 
     function copyShareLink() {
+        // копируем текущий урл сайта и добавляем ид поста
         navigator.clipboard.writeText(window.location.href + `post/${postData?._id}`)
 
         // меняем текст тултипа и через 2сек возрващаем на место
@@ -36,8 +70,7 @@ export function CardFeed({ postData }) {
         setTimeout(() => setToolTipText(toolTipText), 2000)
     }
 
-
-    // функция управления лайками
+    // определяем мой ид
     const myId = useSelector(state => state?.auth?.payload?.sub?.id)
 
     // картинка лайка включить/отключить
@@ -67,26 +100,23 @@ export function CardFeed({ postData }) {
             : dispatch(actionFullAddLike({ post: { _id: postData?._id } }))
     }
 
-
     // контекст модального окна
     const [modalName, setModalName, modalArray, setModalArray, openModal, setOpenModal, handleOpenModal, handleCloseModal] = useContext(ModalForCountsContext)
 
-
     function toUser() {
         history.push(`/user/${postData?.owner?._id}`)
     }
 
-
     function toPost() {
         history.push(`/post/${postData?._id}`)
     }
 
 
-
     return (
-        <Card sx={{
-            width: 550
-        }}>
+        <Card
+            sx={{
+                width: 550
+            }}>
             <CardHeader
                 sx={{
                     padding: '8px'
@@ -112,11 +142,12 @@ export function CardFeed({ postData }) {
 
                 title={
                     <Typography
+                        className='cursor-pointer'
                         variant='subtitle1'
+                        onClick={toUser}
                         sx={{
-                            cursor: 'pointer'
+                            width: 'fit-content'
                         }}
-                        onClick={toUser}
                     >
                         {postData?.owner?.login}
                     </Typography>
@@ -128,7 +159,9 @@ export function CardFeed({ postData }) {
             />
 
             <CardMedia>
-                <MyCarousel images={postData?.images} />
+                <MyCarousel
+                    images={postData?.images}
+                />
             </CardMedia>
 
             <CardActions
@@ -137,10 +170,15 @@ export function CardFeed({ postData }) {
                     padding: '0 8px'
                 }}
             >
-                <Box sx={{
-                    flexGrow: 1,
-                }}>
-                    <Grid container spacing={2}>
+                <Box
+                    sx={{
+                        flexGrow: 1,
+                    }}
+                >
+                    <Grid
+                        container
+                        spacing={2}
+                    >
                         <Grid
                             xs={12}
                             container
@@ -157,6 +195,9 @@ export function CardFeed({ postData }) {
                             <Grid
                                 container
                                 columnSpacing={1}
+                                sx={{
+                                    marginLeft: '-21px'
+                                }}
                             >
                                 {/* Лайк */}
                                 <Grid>
@@ -188,9 +229,12 @@ export function CardFeed({ postData }) {
 
                                 {/* Расшаривание */}
                                 <Grid>
-                                    <PopupState variant="popover" popupId="demo-popup-popover">
+                                    <PopupState
+                                        variant="popover"
+                                        popupId="demo-popup-popover"
+                                    >
                                         {(popupState) => (
-                                            <div>
+                                            <React.Fragment>
                                                 <IconButton
                                                     aria-label="share"
                                                     {...bindTrigger(popupState)}
@@ -199,6 +243,7 @@ export function CardFeed({ postData }) {
                                                         sx={{ transform: 'translate(3px, -4px) rotate(-30deg)' }}
                                                     />
                                                 </IconButton>
+
                                                 <Popover
                                                     {...bindPopover(popupState)}
                                                     anchorOrigin={{
@@ -210,7 +255,10 @@ export function CardFeed({ postData }) {
                                                         horizontal: 'left',
                                                     }}
                                                 >
-                                                    <Tooltip title={text} placement='bottom-start'>
+                                                    <Tooltip
+                                                        title={text}
+                                                        placement='bottom-start'
+                                                    >
                                                         <Typography
                                                             sx={{ p: 2 }}
                                                             onClick={copyShareLink}
@@ -219,19 +267,18 @@ export function CardFeed({ postData }) {
                                                         </Typography>
                                                     </Tooltip>
                                                 </Popover>
-                                            </div>
+                                            </React.Fragment>
                                         )}
                                     </PopupState>
                                 </Grid>
                             </Grid>
 
-
                             {/* Добавление в изобранное */}
-                            <Grid>
+                            {/* <Grid>
                                 <IconButton>
                                     <TurnedInNot />
                                 </IconButton>
-                            </Grid>
+                            </Grid> */}
                         </Grid>
                     </Grid>
                 </Box>
@@ -244,10 +291,10 @@ export function CardFeed({ postData }) {
                 }}
             >
                 <Typography
+                    className='cursor-pointer'
                     variant='subtitle2'
                     onClick={() => handleOpenModal({ arr: postData?.likes, name: 'Отметки "Нравится"' })}
                     sx={{
-                        cursor: 'pointer',
                         width: 'fit-content'
                     }}
                 >
@@ -256,6 +303,7 @@ export function CardFeed({ postData }) {
             </CardContent>
 
             <CardContent
+                className='tytyty'
                 sx={{
                     padding: '8px',
                     paddingTop: '0'
@@ -271,8 +319,16 @@ export function CardFeed({ postData }) {
                 <Typography
                     variant='body2'
                     color='text.secondary'
+                    sx={{
+                        display: 'block',
+                        textOverflow: 'ellipsis',
+                        overflow: 'hidden',
+                        whiteSpace: 'nowrap',
+                        width: '400px'
+                    }}
                 >
                     {postData?.text}
+
                 </Typography>
             </CardContent>
 
@@ -283,18 +339,14 @@ export function CardFeed({ postData }) {
                 }}
             >
                 <Typography
+                    className='cursor-pointer'
                     variant='subtitle2'
                     color='text.secondary'
-                    sx={{
-                        cursor: 'pointer'
-                    }}
                     onClick={toPost}
                 >
-                    Посмотреть все комментарии ({postData?.comments?.length || '0'})
+                    Посмотреть пост и комментарии к нему ({postData?.comments?.length || '0'})
                 </Typography>
-
             </CardActions>
-
             <Divider />
         </Card >
     )

+ 24 - 15
js/Project/project/src/components/feed/carousel_feed.js

@@ -1,13 +1,15 @@
 import { url } from '../../App'
 
-import Carousel from 'react-material-ui-carousel'
+import React from 'react'
+
 import { Box } from '@mui/material'
 
-import './style.scss'
+import Carousel from 'react-material-ui-carousel'
 
+import './style.scss'
 
+// контейнер для карусели
 function DynamicItem({ item }) {
-
     return (
         <Box
             className={`slider-container-${item?._id}`}
@@ -18,8 +20,8 @@ function DynamicItem({ item }) {
                 justifyContent: 'center',
                 alignItems: 'center',
                 backgroundColor: '#000'
-            }}>
-
+            }}
+        >
             <img
                 alt='image'
                 src={item?.url && (url + item?.url)}
@@ -32,7 +34,6 @@ function DynamicItem({ item }) {
     )
 }
 
-
 // контейнер для одной картинки
 function StaticItem({ item }) {
     return (
@@ -43,8 +44,8 @@ function StaticItem({ item }) {
                 justifyContent: 'center',
                 alignItems: 'center',
                 backgroundColor: '#000'
-            }}>
-
+            }}
+        >
             <img
                 alt='image'
                 src={item?.url && (url + item?.url)}
@@ -56,14 +57,13 @@ function StaticItem({ item }) {
                     maxWidth: '550px',
                 }}
             />
-        </Box >
+        </Box>
     )
 }
 
-
 export function MyCarousel({ images }) {
     return (
-        <Box>
+        <React.Fragment>
             {images?.length > 1
                 ? <Carousel
                     autoPlay={false}
@@ -77,11 +77,20 @@ export function MyCarousel({ images }) {
                         }
                     }}
                 >
-                    {images && images?.map((item) => <DynamicItem key={item?._id} item={item} />)}
-                </Carousel >
-                : images && images?.map((item) => <StaticItem key={item?._id} item={item} />)
+                    {images &&
+                        images?.map((item) => <DynamicItem
+                            key={item?._id}
+                            item={item}
+                        />)
+                    }
+                </Carousel>
+                : images &&
+                images?.map((item) => <StaticItem
+                    key={item?._id}
+                    item={item}
+                />)
             }
-        </Box>
+        </React.Fragment>
     )
 }
 

+ 42 - 137
js/Project/project/src/components/feed/index.js

@@ -1,130 +1,29 @@
-// import React, { useEffect, useState } from 'react';
-// import { connect, useDispatch, useSelector } from 'react-redux';
+import React, { useEffect } from 'react';
 
-// import { Box, Divider, Paper } from '@mui/material';
-// import { styled } from '@mui/material/styles';
-// import { Container } from '@mui/system';
-// import Grid2 from '@mui/material/Unstable_Grid2/Grid2';
+import {
+    connect,
+    useDispatch,
+    useSelector
+} from 'react-redux';
 
-// // import { actionAboutMe, actionDownloadFeed } from '../redux/action';
-// import { actionAboutMe, actionDownloadFeed } from '../../redux/thunks';
-// import { CardFeed } from './card';
-// import { CAboutMe } from './aboutMe';
-// import Recommended from './recommended';
+import {
+    Box,
+    Paper
+} from '@mui/material';
 
-
-// const Item = styled(Paper)(() => ({
-//     padding: '0 10px',
-//     marginBottom: 10,
-//     borderRadius: 0,
-//     boxShadow: 'none',
-// }))
-
-
-// function Feed({ feed, loadFeed }) {
-//     const dispatch = useDispatch()
-
-//     const [posts, setPosts] = useState(feed)
-
-//     const newPosts = useSelector(state => state.feed?.AddFeed?.payload)
-
-//     // useEffect((() => {
-//     //     if (newPosts) {
-//     //         setPosts([...posts, ...newPosts])
-//     //     }
-//     // }), [newPosts])
-
-//     // чекер дна страницы
-//     window.onscroll = async function feedScroll() {
-//         if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
-//             const downloadedPosts = await dispatch(actionDownloadFeed(feed.length))
-
-//             // добавляем новые посты в общй массив постов
-//             downloadedPosts.map(post => feed.push(post))
-//         }
-//     }
-
-
-//     // console.log('feed: ', feed)
-//     // console.log('posts: ', posts)
-
-//     // первая загрузка страницы
-//     useEffect(() => { loadFeed() }, [])
-
-//     return (
-//         <Container sx={{
-//             width: '90%',
-//             mt: 1
-//         }}>
-//             <Box sx={{
-//                 flexGrow: 1
-//             }}>
-//                 <Grid2 container spacing={2}>
-//                     <Grid2
-//                         xs={7}
-//                         sx={{
-//                             display: 'flex',
-//                             justifyContent: 'center'
-//                         }}
-//                     >
-//                         <Item>
-//                             {feed && feed?.map(post => <Item key={post._id}><CardFeed postData={post} /></Item>)}
-//                         </Item>
-//                     </Grid2>
-//                     <Grid2 xs={5}
-//                         sx={{
-//                             display: 'flex',
-//                             justifyContent: 'center'
-//                         }}
-//                     >
-//                         <Item sx={{
-//                             position: 'fixed'
-//                         }}>
-//                             <CAboutMe />
-
-//                             <Recommended />
-//                         </Item>
-//                     </Grid2>
-//                 </Grid2>
-//             </Box>
-//         </Container>
-//     )
-// }
-
-// export const CFeed = connect(state => ({ feed: state.feed?.MyFeed?.payload }), { loadFeed: actionAboutMe })(Feed)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-import React, { useEffect, useState } from 'react';
-import { connect, useDispatch, useSelector } from 'react-redux';
-
-import { Box, Divider, Paper } from '@mui/material';
 import { styled } from '@mui/material/styles';
 import { Container } from '@mui/system';
 import Grid2 from '@mui/material/Unstable_Grid2/Grid2';
 
-// import { actionAboutMe, actionDownloadFeed } from '../redux/action';
-import { actionAboutMe, actionDownloadFeed } from '../../redux/thunks';
+import {
+    actionAboutMe,
+    actionDownloadFeed
+} from '../../redux/thunks';
+
 import { CardFeed } from './card';
 import { CAboutMe } from './aboutMe';
 import Recommended from './recommended';
 
-
 const Item = styled(Paper)(() => ({
     padding: '0 10px',
     marginBottom: 10,
@@ -132,13 +31,18 @@ const Item = styled(Paper)(() => ({
     boxShadow: 'none',
 }))
 
-
 function Feed({ feed, loadFeed }) {
     const dispatch = useDispatch()
 
+    // функция отслеживания дна
+    function handleScroll() {
+        if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
+            dispatch(actionDownloadFeed())
+        }
+    }
+
     // отслеживаем дозагрузку новых постов
     const newPosts = useSelector(state => state?.feed?.AddFeed?.payload)
-    console.log('newPosts: ', newPosts)
 
     // когда пришли посты, делаем проверку на дубли и пушим в основную ленту
     if (newPosts) {
@@ -150,13 +54,6 @@ function Feed({ feed, loadFeed }) {
         });
     }
 
-    // функция отслеживания дна
-    function handleScroll() {
-        if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
-            dispatch(actionDownloadFeed())
-        }
-    };
-
     // первая загрузка страницы и монтирование прослушки
     useEffect(() => {
         loadFeed()
@@ -169,14 +66,19 @@ function Feed({ feed, loadFeed }) {
 
 
     return (
-        <Container sx={{
-            width: '90%',
-            mt: 1
-        }}>
-            <Box sx={{
-                flexGrow: 1
+        <Container
+            sx={{
+                width: '90%',
+                mt: 1
             }}>
-                <Grid2 container spacing={2}>
+            <Box
+                sx={{
+                    flexGrow: 1
+                }}>
+                <Grid2
+                    container
+                    spacing={2}
+                >
                     <Grid2
                         xs={7}
                         sx={{
@@ -185,19 +87,22 @@ function Feed({ feed, loadFeed }) {
                         }}
                     >
                         <Item>
-                            {/* {posts && posts?.map(post => <Item key={post._id}><CardFeed postData={post} /></Item>)} */}
                             {feed && feed?.map(post => <Item key={post._id}><CardFeed postData={post} /></Item>)}
                         </Item>
                     </Grid2>
-                    <Grid2 xs={5}
+
+                    <Grid2
+                        xs={5}
                         sx={{
                             display: 'flex',
                             justifyContent: 'center'
                         }}
                     >
-                        <Item sx={{
-                            position: 'fixed'
-                        }}>
+                        <Item
+                            sx={{
+                                position: 'fixed'
+                            }}
+                        >
                             <CAboutMe />
 
                             <Recommended />

+ 13 - 13
js/Project/project/src/components/feed/recommended.js

@@ -1,13 +1,14 @@
-import { url } from '../../App';
+import React from 'react';
+import { useSelector } from "react-redux"
 
-import React, { useContext } from 'react';
-import { useDispatch, useSelector } from "react-redux"
-import { useHistory } from 'react-router-dom';
+import {
+    Typography,
+    Box
+} from '@mui/material';
 
-import { CardHeader, Avatar, Typography, Button, Box, Divider } from '@mui/material';
+import { RecommendedCard } from '../structure/modal';
 
 import './style.scss'
-import { RecommendedCard } from '../structure/modal';
 
 
 // Блок с рекомендациями
@@ -28,7 +29,6 @@ function Recommended() {
             )
         ].filter((item) =>
             !myFollowings.some((current) => current._id === item._id)
-            // ))
         )).filter(currentItem => currentItem._id !== myId)
 
 
@@ -52,11 +52,13 @@ function Recommended() {
                 <Box
                     sx={{
                         marginTop: '10px'
-                    }}>
+                    }}
+                >
                     <Box
                         sx={{
                             padding: '0 24px'
-                        }}>
+                        }}
+                    >
                         <Typography
                             variant="subtitle1"
                             color='text.secondary'
@@ -73,15 +75,13 @@ function Recommended() {
                             width: '95%',
                             height: '400px',
                             overflowY: 'auto'
-                        }}>
+                        }}
+                    >
                         {recommendedList?.map(item => <RecommendedCard key={item._id} data={item} />)}
-                        {/* {recommendedList?.length != 0 && recommendedList?.map(item => <RecommendedCard key={item?._id} data={item} />)} */}
                     </Box>
                 </Box>}
         </React.Fragment>
-
     )
 }
 
-
 export default Recommended

+ 0 - 4
js/Project/project/src/components/feed/test.js

@@ -1,4 +0,0 @@
-const [isFullDataValid, setIsFullDataValid] = useState(false)
-const [isLoginValid, setIsLoginValid] = useState(false)
-const [isPasswordValid, setIsPasswordValid] = useState(false)
-const [isPasswordConfirmValid, setIsPasswordConfirmValid] = useState(false)

+ 36 - 41
js/Project/project/src/components/post/carousel.js

@@ -1,15 +1,15 @@
-import Carousel from 'react-material-ui-carousel'
-import { Box } from '@mui/system';
-
 import { url } from '../../App';
 
+import React from 'react';
+
+import Carousel from 'react-material-ui-carousel'
+import { Box } from '@mui/system';
 
 // карусель
 export function MyCarouselPost({ postImages }) {
-    // console.log('postImages: ', postImages)
 
     return (
-        <>
+        <React.Fragment>
             {postImages?.length > 1
                 ? <Carousel
                     autoPlay={false}
@@ -23,54 +23,51 @@ export function MyCarouselPost({ postImages }) {
                         }
                     }}
                     className='myCarousel'
-
                     sx={{
                         width: '100%',
-                        height: '100%',
-
+                        height: '100%'
                     }}
-
                 >
-                    {postImages && postImages?.map(item =>
-                        <Box
-                            sx={{
-                                width: '100%',
-                                height: '743px',
-                                overflow: 'hidden',
-                                position: 'relative'
-                            }}
-
-                            key={item?.url}
-                        >
-                            <img
-                                style={{
-                                    position: 'absolute',
-                                    top: '50%',
-                                    left: '50%',
-                                    transform: 'translate(-50%, -50%)',
+                    {postImages &&
+                        postImages?.map(item =>
+                            <Box
+                                key={item?.url}
+                                sx={{
                                     width: '100%',
-                                    height: '100%',
-                                    objectFit: 'contain',
-                                    objectPosition: 'center'
+                                    height: '743px',
+                                    overflow: 'hidden',
+                                    position: 'relative'
                                 }}
-
-                                src={url + item.url}
-                            />
-                        </Box>
-                    )}
-                </Carousel >
-                : postImages && postImages?.map(item =>
+                            >
+                                <img
+                                    src={url + item.url}
+                                    style={{
+                                        position: 'absolute',
+                                        top: '50%',
+                                        left: '50%',
+                                        transform: 'translate(-50%, -50%)',
+                                        width: '100%',
+                                        height: '100%',
+                                        objectFit: 'contain',
+                                        objectPosition: 'center'
+                                    }}
+                                />
+                            </Box>
+                        )}
+                </Carousel>
+                : postImages &&
+                postImages?.map(item =>
                     <Box
+                        key={item?.url}
                         sx={{
                             width: '100%',
                             height: '743px',
                             overflow: 'hidden',
                             position: 'relative'
                         }}
-
-                        key={item?.url}
                     >
                         <img
+                            src={url + item.url}
                             style={{
                                 position: 'absolute',
                                 top: '50%',
@@ -81,12 +78,10 @@ export function MyCarouselPost({ postImages }) {
                                 objectFit: 'contain',
                                 objectPosition: 'center'
                             }}
-
-                            src={url + item.url}
                         />
                     </Box>
                 )}
-        </>
+        </React.Fragment>
     )
 }
 

+ 57 - 43
js/Project/project/src/components/post/comments.js

@@ -1,6 +1,13 @@
 import { url } from "../../App";
-import { useHistory, useParams } from "react-router-dom";
-import { createContext, useState, useContext, useEffect } from "react";
+
+import React, { createContext, useState, useContext, useEffect } from "react";
+
+import { useDispatch, useSelector } from "react-redux";
+
+import {
+    useHistory,
+    useParams
+} from "react-router-dom";
 
 import './style.scss'
 
@@ -26,48 +33,43 @@ import {
     ChatBubbleOutline,
     TurnedInNot,
 } from '@mui/icons-material/'
+import Grid from '@mui/material/Unstable_Grid2';
 
 import PopupState, { bindTrigger, bindPopover } from 'material-ui-popup-state';
 
-import { actionFullAddLike, actionFullDeleteLike } from "../../redux/thunks";
-
-import Grid from '@mui/material/Unstable_Grid2';
-
-import { ModalForCountsContext, UpdateProfile } from "../../App";
+import {
+    actionFullAddLike,
+    actionFullDeleteLike
+} from "../../redux/thunks";
 
-import { createDate } from "../functions";
+import {
+    ModalForCountsContext,
+    UpdateProfile
+} from "../../App";
 
 import CCommentsFeed from "./comments_feed";
 import CommentField from "./comments_add_field";
 import ModalWindow from "../structure/modal";
-import { useDispatch, useSelector } from "react-redux";
+
+import { createDate } from "../functions";
 
 // контекст для управления состоянием данных для отправки комментов
 export const CommentContext = createContext()
 
 
 export function CardPost({ postData }) {
-    // console.log('postData: ', postData)
-
-    const dispatch = useDispatch()
-
     const history = useHistory()
     const { postId } = useParams()
+    const dispatch = useDispatch()
 
     // отслеживаем состояние поля ввода комментария для поста
     const [comment, setComment] = useState({ text: '', post: { _id: postId } })
 
     // контекст модального окна
     const [modalName, setModalName, modalArray, setModalArray, openModal, setOpenModal, handleOpenModal, handleCloseModal] = useContext(ModalForCountsContext)
-    // console.log('modalArray: ', modalArray)
 
     // контекст обновления профиля
-    const [updateProfile, setUpdateProfile] = useContext(UpdateProfile)
-
-    // Переход на профиль пользователя
-    function toAccount() {
-        history.push(`/user/${postData?.owner?._id}`)
-    }
+    // const [updateProfile, setUpdateProfile] = useContext(UpdateProfile)
 
     // перевод фокуса на строку добавления комментария при клике на иконку комментария
     function addCommentFocus() {
@@ -91,7 +93,7 @@ export function CardPost({ postData }) {
     }
 
 
-    // ============= функция отображения лайка (старт) =========================
+    // функция отображения лайка
     // чекаем мой ид
     const myId = useSelector(state => state?.auth?.payload?.sub?.id)
 
@@ -116,19 +118,21 @@ export function CardPost({ postData }) {
 
     useEffect(() => setChecked(isLike), [isLike])
 
-
     function likeAction() {
         checked
             ? dispatch(actionFullDeleteLike({ _id: likeId }))
             : dispatch(actionFullAddLike({ post: { _id: postData?._id } }))
     }
-    // ============= функция отображения лайка (финиш) =========================
-
 
+    // функция отображения людей, которым понравился пост
     function showLikesOwner() {
         handleOpenModal({ arr: postData?.likes, name: 'Отметки "Нравится"' })
     }
 
+    // Переход на профиль пользователя
+    function toAccount() {
+        history.push(`/user/${postData?.owner?._id}`)
+    }
 
     return (
         <CommentContext.Provider value={[comment, setComment]}>
@@ -156,9 +160,7 @@ export function CardPost({ postData }) {
 
                     title={
                         <Typography
-                            sx={{
-                                cursor: 'pointer'
-                            }}
+                            className="cursor-pointer"
                             onClick={toAccount}
                         >
                             {postData?.owner?.login}
@@ -205,13 +207,13 @@ export function CardPost({ postData }) {
                             xs={10}
                         >
                             <Typography
+                                className="cursor-pointer"
                                 variant="subtitle2"
                                 color="text.secondary"
+                                onClick={toAccount}
                                 sx={{
-                                    cursor: 'pointer',
                                     width: 'fit-content'
                                 }}
-                                onClick={toAccount}
                             >
                                 {postData?.owner?.login}
                             </Typography>
@@ -239,8 +241,10 @@ export function CardPost({ postData }) {
 
                 <Divider />
 
-                <Box>
-                    <CardActions disableSpacing className='qrrr'>
+                <React.Fragment>
+                    <CardActions
+                        disableSpacing
+                    >
                         <Box
                             sx={{
                                 flexGrow: 1
@@ -254,7 +258,9 @@ export function CardPost({ postData }) {
                                     fontSize: '12px'
                                 }}
                             >
-                                <Grid container>
+                                <Grid
+                                    container
+                                >
                                     <Grid>
                                         <Checkbox
                                             checked={checked}
@@ -263,7 +269,6 @@ export function CardPost({ postData }) {
                                             icon={<FavoriteBorderRounded />}
                                             checkedIcon={<FavoriteRounded />}
                                             onClick={likeAction}
-
                                             sx={{
                                                 '&.Mui-checked': {
                                                     color: 'red',
@@ -281,9 +286,12 @@ export function CardPost({ postData }) {
                                     </Grid>
 
                                     <Grid>
-                                        <PopupState variant="popover" popupId="demo-popup-popover">
+                                        <PopupState
+                                            variant="popover"
+                                            popupId="demo-popup-popover"
+                                        >
                                             {(popupState) => (
-                                                <div>
+                                                <React.Fragment>
                                                     <IconButton
                                                         aria-label="share"
                                                         {...bindTrigger(popupState)}
@@ -292,6 +300,7 @@ export function CardPost({ postData }) {
                                                             sx={{ transform: 'translate(3px, -4px) rotate(-30deg)' }}
                                                         />
                                                     </IconButton>
+
                                                     <Popover
                                                         {...bindPopover(popupState)}
                                                         anchorOrigin={{
@@ -303,7 +312,10 @@ export function CardPost({ postData }) {
                                                             horizontal: 'left',
                                                         }}
                                                     >
-                                                        <Tooltip title={text} placement='bottom-start'>
+                                                        <Tooltip
+                                                            title={text}
+                                                            placement='bottom-start'
+                                                        >
                                                             <Typography
                                                                 sx={{ p: 2 }}
                                                                 onClick={copyShareLink}
@@ -312,28 +324,30 @@ export function CardPost({ postData }) {
                                                             </Typography>
                                                         </Tooltip>
                                                     </Popover>
-                                                </div>
+                                                </React.Fragment>
                                             )}
                                         </PopupState>
                                     </Grid>
                                 </Grid>
 
-                                <Grid>
+                                {/* <Grid>
                                     <IconButton>
                                         <TurnedInNot />
                                     </IconButton>
-                                </Grid>
+                                </Grid> */}
                             </Grid>
 
-                            <Grid container>
+                            <Grid
+                                container
+                            >
                                 <Typography
+                                    className="cursor-pointer"
                                     variant="subtitle1"
                                     color="text.secondary"
+                                    onClick={showLikesOwner}
                                     sx={{
                                         padding: 1,
-                                        cursor: 'pointer'
                                     }}
-                                    onClick={showLikesOwner}
                                 >
                                     Нравится: {postData?.likes?.length || '0'}
                                 </Typography>
@@ -348,7 +362,7 @@ export function CardPost({ postData }) {
                     <CardActions>
                         <CommentField />
                     </CardActions>
-                </Box>
+                </React.Fragment>
             </Card>
         </CommentContext.Provider >
     )

+ 24 - 29
js/Project/project/src/components/post/comments_add_field.js

@@ -1,37 +1,29 @@
-import { url } from "../../App";
+import React, { useState, useContext } from "react";
 
-import './style.scss'
+import { useDispatch, useSelector } from "react-redux";
+
+import { useParams } from "react-router-dom";
 
 import {
     IconButton,
-    Typography,
     Box,
     TextField,
     Popover
 } from '@mui/material'
-
 import Button from '@mui/material-next/Button';
 
-import {
-    SentimentSatisfiedAlt
-} from '@mui/icons-material/'
+import { SentimentSatisfiedAlt } from '@mui/icons-material/'
 
 import EmojiPicker from 'emoji-picker-react';
 
-import { useState } from "react";
-import { useDispatch, useSelector } from "react-redux";
-
 import { actionFullAddComment } from "../../redux/thunks";
-import { useParams } from "react-router-dom";
-
 
 import { CommentContext } from "./comments";
-import { useContext } from "react";
 
+import './style.scss'
 
-function CommentField() {
-    // console.log('id: ', id)
 
+function CommentField() {
     const { postId } = useParams()
     const dispatch = useDispatch()
 
@@ -49,7 +41,7 @@ function CommentField() {
     const open = Boolean(openPopover);
     const emojiField = open ? 'simple-popover' : undefined;
 
-    // отслеживаем все комментарии в реальном времени для проверки имени пользователя в поле комментария при ответе на комментарий
+    // отслеживаем все комментарии для проверки имени пользователя в поле комментария при ответе на комментарий
     const allComments = useSelector(state => state?.promise?.FindComments?.payload)
 
     // запрос на создание комментария
@@ -93,16 +85,15 @@ function CommentField() {
                 placeholder='Комментировать...'
                 size="small"
                 color="info"
+                value={comment.text}
+                onChange={e => setComment({ ...comment, text: e.target.value })}
                 sx={{
                     margin: 1,
                     width: '100%',
                 }}
-                value={comment.text}
-                onChange={e => setComment({ ...comment, text: e.target.value })}
-
                 InputProps={{
                     startAdornment:
-                        <Box>
+                        <React.Fragment>
                             <IconButton
                                 aria-describedby={emojiField}
                                 onClick={openEmoji}
@@ -136,24 +127,28 @@ function CommentField() {
                                     }
                                 />
                             </Popover>
-                        </Box>,
-
+                        </React.Fragment>,
                     endAdornment:
                         <Box
                             onClick={uploadComment}
                         >
                             {comment.text !== '' &&
-                                <Button size="medium" align='center' sx={{
-                                    alignSelf: 'center',
-                                    cursor: 'pointer',
-                                    marginLeft: '8px',
-                                    padding: '2px 5px'
-                                }}>отправить</Button>
+                                <Button
+                                    className="cursor-pointer"
+                                    size="medium"
+                                    align='center' sx={{
+                                        alignSelf: 'center',
+                                        marginLeft: '8px',
+                                        padding: '2px 5px'
+                                    }}
+                                >
+                                    отправить
+                                </Button>
                             }
                         </Box>
                 }}
             />
-        </Box >
+        </Box>
     )
 }
 

+ 12 - 9
js/Project/project/src/components/post/comments_feed.js

@@ -1,8 +1,9 @@
-import { url } from "../../App";
-import { useParams } from "react-router-dom";
-import { useEffect } from "react";
+import React, { useEffect } from "react";
+
 import { connect, useSelector } from "react-redux";
 
+import { useParams } from "react-router-dom";
+
 import { actionFullFindCommentsPostOne } from "../../redux/thunks";
 
 import CommentCard from "./comments_feed_card";
@@ -11,16 +12,18 @@ import './style.scss';
 
 
 function CommentsFeed({ comments = [], loadComments }) {
-    // console.log('comments: ', comments)
-
     const { postId } = useParams()
+
     const addNewComment = useSelector(state => state?.promise?.CreateComment?.payload)
+
     const addNewCommentTo = useSelector(state => state?.promise?.CreateCommentTo?.payload)
 
     // перезагрузка ленты комментариев на посте, если только зашли на сраницу или отправили новый коммент
-    useEffect(() => { loadComments(postId) }, [postId, addNewComment, addNewCommentTo])
+    useEffect(() => {
+        loadComments(postId)
+    }, [postId, addNewComment, addNewCommentTo])
 
-    // фуyкция построения дерева комментариев
+    // функция построения дерева комментариев
     function commentsTreeConstructor(arr, answerToId = null) {
         const result = []
 
@@ -44,13 +47,13 @@ function CommentsFeed({ comments = [], loadComments }) {
 
 
     return (
-        <>
+        <React.Fragment>
             {data && data?.map(item => <CommentCard
                 data={item}
                 key={item._id}
             />
             )}
-        </>
+        </React.Fragment>
     )
 }
 

+ 40 - 46
js/Project/project/src/components/post/comments_feed_card.js

@@ -1,32 +1,46 @@
 import { url } from "../../App";
+
+import {
+    useState,
+    useEffect,
+    useContext
+} from "react";
+
+import {
+    useDispatch,
+    useSelector
+} from "react-redux";
+
 import { useHistory } from "react-router-dom";
-import { useState, useEffect } from "react";
 
 import {
     Avatar,
-    IconButton,
     Typography,
     Divider,
     Checkbox
 } from '@mui/material'
-
 import Grid from '@mui/material/Unstable_Grid2';
 
-import { FavoriteBorderRounded, FavoriteRounded } from '@mui/icons-material/'
-import { ModalForCountsContext } from "../../App";
+import {
+    FavoriteBorderRounded,
+    FavoriteRounded
+} from '@mui/icons-material/'
 
-import './style.scss'
+import { ModalForCountsContext } from "../../App";
 
-import { actionFullAddLike, actionFullDeleteLike } from "../../redux/thunks";
+import {
+    actionFullAddLike,
+    actionFullDeleteLike
+} from "../../redux/thunks";
 
 import { CommentContext } from "./comments";
-import { useContext } from "react";
-import { useDispatch, useSelector } from "react-redux";
 
+import { createDate } from "../functions";
 
-function CommentCard({ data }) {
-    // console.log('data: ', data)
+import './style.scss'
 
+
+function CommentCard({ data }) {
     const history = useHistory()
     const dispatch = useDispatch()
 
@@ -36,16 +50,9 @@ function CommentCard({ data }) {
     // контекст модального окна
     const [modalName, setModalName, modalArray, setModalArray, openModal, setOpenModal, handleOpenModal, handleCloseModal] = useContext(ModalForCountsContext)
 
-    // дата поста
-    const dateofPost = new Date(+data?.createdAt)
-    const months = ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря']
-    const dateofPostParse = `${dateofPost.getDate() < 10 ? '0' + dateofPost.getDate() : dateofPost.getDate()} 
-    ${months[dateofPost.getMonth()]} 
-    ${dateofPost.getFullYear()}
-    ${dateofPost.getHours() < 10 ? '0' + dateofPost.getHours() : dateofPost.getHours()}:${dateofPost.getMinutes() < 10 ? '0' + dateofPost.getMinutes() : dateofPost.getMinutes()}`
-
-    // скрываем/открываем вложенные комментарии
+    // отслеживаем скрываем/открываем вложенные комментарии
     const [openComments, setOpenComments] = useState(`Показать ответы (${data?.answers.length})`)
+
     // скрываем/открываем блок с ответами на комментарии
     const [toggleAnswerToBlock, setToggleAnswerToBlock] = useState(false)
 
@@ -54,14 +61,12 @@ function CommentCard({ data }) {
         setToggleAnswerToBlock(!toggleAnswerToBlock)
 
         return (openComments === (`Показать ответы (${data?.answers.length})`)
-            // ? setOpenComments('Скрыть ответы')
             ? setOpenComments(`Скрыть ответы (${data?.answers.length})`)
             : setOpenComments(`Показать ответы (${data?.answers.length})`)
         )
     }
 
-
-    // ============= функция отображения лайка (старт) =========================
+    // функция отображения лайка
     // чекаем мой ид
     const myId = useSelector(state => state?.auth?.payload?.sub?.id)
 
@@ -86,20 +91,13 @@ function CommentCard({ data }) {
 
     useEffect(() => setChecked(isLike), [isLike])
 
-
     function likeAction() {
         checked
             ? dispatch(actionFullDeleteLike({ _id: likeId }))
             : dispatch(actionFullAddLike({ comment: { _id: data?._id } }))
     }
-    // ============= функция отображения лайка (финиш) =========================
 
 
-    // функция перехода на страницу профиля
-    function toAccount(id) {
-        history.push(`/user/${id}`)
-    }
-
     // функция перевода фокуса в поле комментария при ответе на комментарий
     function addCommentFocus() {
         const inputField = document.getElementById('addCommentField')
@@ -111,6 +109,11 @@ function CommentCard({ data }) {
         setComment({ ...comment, text: `@${data?.owner?.login} `, answerTo: { _id: data._id } })
     }
 
+    // функция перехода на страницу профиля
+    function toAccount(id) {
+        history.push(`/user/${id}`)
+    }
+
 
     return (
         <Grid
@@ -147,11 +150,9 @@ function CommentCard({ data }) {
                     }}
                 >
                     <Typography
+                        className="cursor-pointer"
                         variant="subtitle2"
                         color="text.secondary"
-                        sx={{
-                            cursor: 'pointer'
-                        }}
                         onClick={() => toAccount(data?.owner?._id)}
                     >
                         {data?.owner?.login}
@@ -178,7 +179,6 @@ function CommentCard({ data }) {
                         icon={<FavoriteBorderRounded />}
                         checkedIcon={<FavoriteRounded />}
                         onClick={likeAction}
-
                         sx={{
                             '&.Mui-checked': {
                                 color: 'red',
@@ -192,7 +192,6 @@ function CommentCard({ data }) {
                     sx={{
                         padding: 0,
                         paddingLeft: 1
-
                     }}
                 >
                     <Typography
@@ -200,7 +199,7 @@ function CommentCard({ data }) {
                         color="text.disabled"
                         align='left'
                     >
-                        {dateofPostParse}
+                        {createDate(+data?.createdAt)}
                     </Typography>
                 </Grid>
 
@@ -211,9 +210,7 @@ function CommentCard({ data }) {
                     }}
                 >
                     <Typography
-                        sx={{
-                            cursor: 'pointer'
-                        }}
+                        className="cursor-pointer"
                         variant="caption"
                         color="text.disabled"
                         align='left'
@@ -231,12 +228,10 @@ function CommentCard({ data }) {
                     }}
                 >
                     <Typography
+                        className="cursor-pointer"
                         variant="caption"
                         color="text.disabled"
                         align='left'
-                        sx={{
-                            cursor: 'pointer'
-                        }}
                         onClick={addCommentFocus}
                     >
                         Ответить
@@ -252,11 +247,9 @@ function CommentCard({ data }) {
                     {(data?.answers.length !== 0) &&
                         <Divider>
                             <Typography
+                                className="cursor-pointer"
                                 variant="caption"
                                 color="text.disabled"
-                                sx={{
-                                    cursor: 'pointer'
-                                }}
                                 onClick={() => toggleBlock(data?._id)}
                             >
                                 {openComments}
@@ -268,7 +261,8 @@ function CommentCard({ data }) {
                     <Grid xs={12}
                         sx={{
                             padding: '0 8px'
-                        }}>
+                        }}
+                    >
                         {data?.answers && (data?.answers)?.map(item => <CommentCard
                             data={item}
                             key={item._id}

+ 43 - 24
js/Project/project/src/components/post/index.js

@@ -1,16 +1,19 @@
-import { useEffect } from 'react';
-import { useParams } from 'react-router-dom';
+import React, { useEffect } from 'react';
+
 import { connect } from 'react-redux';
 
+import { useParams } from 'react-router-dom';
+
+import { Box, Paper } from '@mui/material';
 import Grid2 from '@mui/material/Unstable_Grid2/Grid2';
-import { Paper, Box } from '@mui/material';
+
 import { styled } from '@mui/material/styles';
 
 import { actionFindPostOne } from '../../redux/action';
+
 import { MyCarouselPost } from './carousel';
 import { CardPost } from './comments';
 
-
 const Item = styled(Paper)(() => ({
     borderRadius: 0,
     boxShadow: 'none',
@@ -18,36 +21,52 @@ const Item = styled(Paper)(() => ({
 
 
 function Comments({ post = {}, loadPost }) {
-    // console.log('post: ', post)
-
     const { postId } = useParams()
     useEffect(() => { loadPost(postId) }, [postId])
 
     return (
-        <Box>
-            <Grid2 container sx={{
-                height: '80vh',
-            }}>
-                <Grid2 xs={7.5}>
-                    <Item sx={{
-                        backgroundColor: "black",
-                        width: '100%',
-                        height: '100%',
-                        display: 'flex',
-                        alignItems: 'center'
-                    }}>
-                        <MyCarouselPost postImages={post?.images} />
+        <React.Fragment>
+            <Grid2
+                container
+                sx={{
+                    height: '80vh',
+                }}
+            >
+                <Grid2
+                    xs={7.5}
+                >
+                    <Item
+                        sx={{
+                            backgroundColor: "black",
+                            width: '100%',
+                            height: '100%',
+                            display: 'flex',
+                            alignItems: 'center'
+                        }}
+                    >
+                        <MyCarouselPost
+                            postImages={post?.images}
+                        />
                     </Item>
                 </Grid2>
-                <Grid2 xs={4.5}>
+
+                <Grid2
+                    xs={4.5}
+                >
                     <Item >
-                        <div style={{ backgroundColor: "yellow" }}>
-                            <CardPost postData={post} />
-                        </div>
+                        <Box
+                            style={{
+                                backgroundColor: "yellow"
+                            }}
+                        >
+                            <CardPost
+                                postData={post}
+                            />
+                        </Box>
                     </Item>
                 </Grid2>
             </Grid2>
-        </Box>
+        </React.Fragment>
     )
 }
 

+ 50 - 37
js/Project/project/src/components/search/index.js

@@ -1,18 +1,34 @@
 import { url } from "../../App";
 
 import React, { useEffect, useState } from "react"
-import { Box, Typography, Avatar, Stack, InputBase, List, ListItem, ListItemAvatar, ListItemText, Paper, CircularProgress } from '@mui/material';
-import Button from '@mui/material-next/Button';
-import { SearchRounded, TouchAppRounded } from '@mui/icons-material';
+
 import { useDispatch, useSelector } from "react-redux";
 
-import { actionFullSearch } from "../../redux/thunks";
 import { useHistory } from "react-router-dom";
 
+import {
+    Box,
+    Typography,
+    Avatar,
+    Stack,
+    InputBase,
+    List,
+    ListItem,
+    ListItemAvatar,
+    ListItemText,
+    Paper,
+    CircularProgress
+} from '@mui/material';
+import Button from '@mui/material-next/Button';
+
+import {
+    SearchRounded,
+    TouchAppRounded
+} from '@mui/icons-material';
 
+import { actionFullSearch } from "../../redux/thunks";
 
 export default function Search() {
-
     const dispatch = useDispatch()
 
     const searchUserLogin = useSelector(state => state?.search?.userLogin?.payload)
@@ -29,7 +45,6 @@ export default function Search() {
 
     // отслеживаем статус загрузки всех промисов
     const [downloadStatus, setDownloadStatus] = useState(true)
-    console.log('downloadStatus: ', downloadStatus)
 
     useEffect(() => {
         setDownloadStatus(
@@ -42,18 +57,15 @@ export default function Search() {
     },
         [searchUserLoginStatus, searchUserNickStatus, searchPostTitleStatus, searchPostTextStatus, searchCommenttextStatus])
 
-
     // собираем все в один массив после завершения поиска
     const [fullSearchData, setFullSearchData] = useState([])
-    // console.log('fullSearchData; ', fullSearchData?.length)
 
     useEffect(() => {
         setFullSearchData((searchUserLogin && searchUserNick && searchPostTitle && searchPostText && searchCommenttext) && [...new Map([...searchUserLogin, ...searchUserNick, ...searchPostTitle, ...searchPostText, ...searchCommenttext]?.map(item => [item?._id, item])).values()])
     },
         [searchUserLogin, searchUserNick, searchPostTitle, searchPostText, searchCommenttext])
 
-
-    // отслеживание текста в поле ввода
+    // отслеживание текста в поле ввода поиска
     const [inputText, setInputText] = useState('')
 
     // отслеживаем, запустили поиск или нет
@@ -84,15 +96,17 @@ export default function Search() {
                 margin: '0 auto',
             }}
         >
-            <Stack spacing={2}>
-                <Box sx={{
-                    border: '1px solid #E8E8E8',
-                    borderRadius: '8px',
-                    padding: '8px'
-                }}
+            <Stack
+                spacing={2}
+            >
+                <Box
+                    sx={{
+                        border: '1px solid #E8E8E8',
+                        borderRadius: '8px',
+                        padding: '8px'
+                    }}
                 >
                     <InputBase
-
                         fullWidth={true}
                         placeholder="Найти..."
                         value={inputText}
@@ -112,21 +126,20 @@ export default function Search() {
                         startAdornment={
                             <SearchRounded position="start" />
                         }
-
                         endAdornment={
                             <Typography
+                                className="cursor-pointer"
                                 variant='subtitle2'
                                 align='right'
                                 color='primary.main'
                                 sx={{
                                     alignSelf: 'center',
-                                    cursor: 'pointer',
                                     margin: '0 8px',
                                     fontWeight: '700'
-                                }}>
+                                }}
+                            >
                                 {inputText !== '' &&
                                     <Box
-                                        // onClick={onSearching}
                                         onClick={onSearch}
                                     >
                                         <Button
@@ -155,18 +168,20 @@ export default function Search() {
                         height="20vh"
                     >
                         <CircularProgress />
-                    </Box>}
+                    </Box>
+                }
 
-                <Box>
+                <React.Fragment>
                     <List
                         sx={{
                             bgcolor: 'background.paper',
                             width: '90%',
                             margin: '0 auto'
-                        }}>
+                        }}
+                    >
                         {fullSearchData && fullSearchData?.map(item => <SearchCard data={item} key={item?._id} />)}
                     </List>
-                </Box>
+                </React.Fragment>
             </Stack >
 
             {fullSearchData && fullSearchData?.length === 0 &&
@@ -182,13 +197,10 @@ export default function Search() {
     )
 }
 
-
 function SearchCard({ data }) {
     const history = useHistory()
 
     function toPost() {
-        // if (data?.title) history.push(`/post/${data?._id}`)
-
         if (data?.post) {
             history.push(`/post/${data?.post?._id}`)
         } else {
@@ -209,15 +221,14 @@ function SearchCard({ data }) {
                 marginTop: '10px'
             }}
         >
-
             <ListItem
+                className="cursor-pointer"
                 alignItems="flex-start"
+                onClick={toUser}
                 sx={{
-                    cursor: 'pointer',
                     width: '100%',
                     padding: '0 16px'
                 }}
-                onClick={toUser}
             >
                 <ListItemAvatar>
                     <Avatar
@@ -229,27 +240,28 @@ function SearchCard({ data }) {
                     primary={data?.owner ? data?.owner?.login : data?.login}
                     secondary={
                         <Typography
-                            sx={{ display: 'inline' }}
                             component="span"
                             variant="body2"
                             color="text.primary"
+                            sx={{
+                                display: 'inline'
+                            }}
                         >
                             {data?.owner ? data?.owner?.nick : data?.nick}
                         </Typography>
                     }
                 />
-
             </ListItem>
 
             {data?.owner &&
                 <ListItem
+                    className="cursor-pointer"
+                    onClick={toPost}
                     sx={{
                         border: '1px solid #E8E8E8',
                         borderRadius: '8px',
                         marginTop: '8px',
-                        cursor: 'pointer'
                     }}
-                    onClick={toPost}
                 >
                     <ListItemText
                         primary={data?.title && data?.title}
@@ -266,10 +278,12 @@ function SearchCard({ data }) {
                                 }
 
                                 <Typography
-                                    sx={{ display: 'inline' }}
                                     component="span"
                                     variant="body2"
                                     color="text.primary"
+                                    sx={{
+                                        display: 'inline'
+                                    }}
                                 >
                                     {data?.text}
                                 </Typography>
@@ -277,7 +291,6 @@ function SearchCard({ data }) {
                         }
                     />
                 </ListItem>}
-
         </Paper>
     )
 }

+ 1 - 0
js/Project/project/src/components/structure/footer.js

@@ -1,4 +1,5 @@
 import { Typography } from "@mui/material"
+
 import { Container } from "@mui/system"
 
 function Footer() {

+ 115 - 49
js/Project/project/src/components/structure/header.js

@@ -1,14 +1,45 @@
-import React, { useState, cloneElement, useContext } from 'react';
-import { useHistory, useLocation } from 'react-router-dom';
+import { url } from '../../App';
+
+import React, {
+    useState,
+    cloneElement
+} from 'react';
+
 import { connect, useDispatch, useSelector } from 'react-redux';
 
-import { AppBar, Box, Toolbar, Typography, Menu, Container, Avatar, Tooltip, MenuItem, IconButton, Stack, useScrollTrigger, TextField } from '@mui/material'
+import { useHistory, useLocation } from 'react-router-dom';
+
+import {
+    AppBar,
+    Box,
+    Toolbar,
+    Typography,
+    Menu,
+    Container,
+    Avatar,
+    Tooltip,
+    MenuItem,
+    IconButton,
+    Stack,
+    useScrollTrigger,
+    TextField
+} from '@mui/material'
 import Button from '@mui/material-next/Button';
+
+import {
+    AddAPhotoRounded,
+    SearchRounded,
+    LogoutRounded,
+    ManageAccountsRounded,
+    TouchAppRounded
+} from '@mui/icons-material';
+
 import { styled } from '@mui/material/styles';
-import { AddAPhotoRounded, SearchRounded, LogoutRounded, ManageAccountsRounded, TouchAppRounded } from '@mui/icons-material';
-import { actionFullLogout, actionFullSearch } from '../../redux/thunks';
 
-import { url } from '../../App';
+import {
+    actionFullLogout,
+    actionFullSearch
+} from '../../redux/thunks';
 
 // Стилизация иконки поиска
 const StyledInputBase = styled(TextField)(({ theme }) => ({
@@ -43,16 +74,14 @@ function ElevationScroll(props) {
 }
 
 
-
 function UserMenu({ user }) {
     const history = useHistory()
     const dispatch = useDispatch()
-    const location = useLocation().pathname === '/'
 
     // потому что запрос на логин не отдает аватар, а только id и login
     const userData = useSelector(state => state?.promise?.AboutMe?.payload)
 
-    // открытие,закрытие меню на лого
+    // открытие/закрытие меню на лого справа
     const [anchorElUser, setAnchorElUser] = useState(null)
     const handleOpenUserMenu = (event) => {
         setAnchorElUser(event.currentTarget);
@@ -61,27 +90,33 @@ function UserMenu({ user }) {
         setAnchorElUser(null);
     }
 
-    // Thunk для разлогина и редирект на главную, потому что остальные запросы не работают, если нет токена
+    // Запрос на разлогин
     async function onLogout() {
         dispatch(actionFullLogout())
     }
 
+    // ссылка на создание поста
     function toCreatepost() {
         history.push('/upsert/create')
     }
 
+    // Запрос на переход на мой аккаунт
     function toMyAccount() {
         history.push(`/user/${user?.id}`)
     }
 
 
     return (
-        <Box sx={{ flexGrow: 0 }}>
+        <Box
+            sx={{ flexGrow: 0 }}
+        >
             <Tooltip
                 title='Меню пользователя'
                 placement="bottom-end"
             >
-                <IconButton onClick={handleOpenUserMenu}>
+                <IconButton
+                    onClick={handleOpenUserMenu}
+                >
                     <Avatar
                         alt={user?.login}
                         src={url + userData?.avatar?.url}
@@ -90,27 +125,36 @@ function UserMenu({ user }) {
             </Tooltip>
 
             <Menu
-                sx={{ mt: '45px' }}
                 id="menu-appbar"
                 anchorEl={anchorElUser}
                 anchorOrigin={{
                     vertical: 'top',
                     horizontal: 'right',
                 }}
-                keepMounted
+                // keepMounted
                 transformOrigin={{
                     vertical: 'top',
                     horizontal: 'right',
                 }}
                 open={Boolean(anchorElUser)}
                 onClose={handleCloseUserMenu}
+                sx={{
+                    mt: '45px'
+                }}
             >
                 <MenuItem
-                    onClick={toMyAccount}>
-                    <Stack direction="row" spacing={1}>
-                        <ManageAccountsRounded fontSize="small" />
+                    onClick={toMyAccount}
+                >
+                    <Stack
+                        direction="row"
+                        spacing={1}
+                    >
+                        <ManageAccountsRounded
+                            fontSize="small"
+                        />
                         <Typography
-                            textAlign="center">
+                            textAlign="center"
+                        >
                             <span>
                                 {user?.login}
                             </span>
@@ -119,9 +163,15 @@ function UserMenu({ user }) {
                 </MenuItem>
 
                 <MenuItem
-                    onClick={toCreatepost}>
-                    <Stack direction="row" spacing={1}>
-                        <AddAPhotoRounded fontSize="small" />
+                    onClick={toCreatepost}
+                >
+                    <Stack
+                        direction="row"
+                        spacing={1}
+                    >
+                        <AddAPhotoRounded
+                            fontSize="small"
+                        />
                         <Typography
                             textAlign="center">
                             <span>
@@ -134,8 +184,13 @@ function UserMenu({ user }) {
                 <MenuItem
                     onClick={onLogout}
                 >
-                    <Stack direction="row" spacing={1}>
-                        <LogoutRounded fontSize="small" />
+                    <Stack
+                        direction="row"
+                        spacing={1}
+                    >
+                        <LogoutRounded
+                            fontSize="small"
+                        />
                         <Typography
                             textAlign="center">
                             <span>
@@ -149,11 +204,10 @@ function UserMenu({ user }) {
     )
 }
 
-
 function Header({ login }) {
-    let history = useHistory()
-    const dispatch = useDispatch()
+    const history = useHistory()
     const location = useLocation().pathname === ('/search')
+    const dispatch = useDispatch()
 
     // отслеживание введенного текста в поиске
     const [searchText, setSearchText] = useState('')
@@ -179,7 +233,6 @@ function Header({ login }) {
         history.push('/search')
     }
 
-
     function toMain() {
         history.push('/')
     }
@@ -191,22 +244,31 @@ function Header({ login }) {
                 <AppBar
                     color='inherit'
                     position='sticky'
-                    sx={{ borderBottom: '1px solid #E8E8E8' }}>
-                    <Container maxWidth="xl">
-                        <Toolbar disableGutters>
+                    sx={{
+                        borderBottom: '1px solid #E8E8E8'
+                    }}
+                >
+                    <Container
+                        maxWidth="xl"
+                    >
+                        <Toolbar
+                            disableGutters
+                        >
                             <Stack
                                 direction='row'
                                 sx={{
                                     display: 'flex',
                                     flexGrow: '1'
-                                }}>
+                                }}
+                            >
                                 <Box
+                                    className="cursor-pointer"
                                     onClick={toMain}
-                                    sx={{
-                                        cursor: 'pointer'
-                                    }}
                                 >
-                                    <img src='/images/logo3.png' style={{ width: '28px' }} />
+                                    <img
+                                        src='/images/logo3.png'
+                                        style={{ width: '28px' }}
+                                    />
                                 </Box>
 
                                 <Typography
@@ -227,19 +289,23 @@ function Header({ login }) {
                             </Stack>
 
                             {login && !location &&
-                                <Box sx={{
-                                    position: 'relative',
-                                    marginLeft: 0
-                                }}>
-                                    <Box sx={{
-                                        padding: '0 16px',
-                                        height: '100%',
-                                        position: 'absolute',
-                                        pointerEvents: 'none',
-                                        display: 'flex',
-                                        alignItems: 'center',
-                                        justifyContent: 'center',
-                                    }}>
+                                <Box
+                                    sx={{
+                                        position: 'relative',
+                                        marginLeft: 0
+                                    }}
+                                >
+                                    <Box
+                                        sx={{
+                                            padding: '0 16px',
+                                            height: '100%',
+                                            position: 'absolute',
+                                            pointerEvents: 'none',
+                                            display: 'flex',
+                                            alignItems: 'center',
+                                            justifyContent: 'center',
+                                        }}
+                                    >
                                         <SearchRounded />
                                     </Box>
 
@@ -262,12 +328,12 @@ function Header({ login }) {
                                             'aria-label': 'search',
                                             endAdornment:
                                                 <Typography
+                                                    className="cursor-pointer"
                                                     variant='subtitle2'
                                                     align='right'
                                                     color='primary.main'
                                                     sx={{
                                                         alignSelf: 'center',
-                                                        cursor: 'pointer',
                                                         margin: '0 8px',
                                                         fontWeight: '700'
                                                     }}>

+ 70 - 49
js/Project/project/src/components/structure/modal.js

@@ -1,18 +1,36 @@
-import { useContext } from "react";
+import { url } from "../../App"
+
+import React, { useContext } from "react";
+
 import { useDispatch, useSelector } from "react-redux";
+
 import { useHistory, useLocation, useParams } from "react-router-dom";
 
-import { Typography, Box, Stack, Backdrop, Modal, Fade, Divider, IconButton, Avatar, CardHeader } from '@mui/material'
+import {
+    Typography,
+    Box,
+    Stack,
+    Backdrop,
+    Modal,
+    Fade,
+    Divider,
+    IconButton,
+    Avatar,
+    CardHeader
+} from '@mui/material'
 import Button from '@mui/material-next/Button';
+
 import { Close } from '@mui/icons-material'
 
-import { ModalForCountsContext, UpdateProfile } from "../../App";
+import {
+    ModalForCountsContext,
+    UpdateProfile
+} from "../../App";
+
 import { actionFullUpdateProfile } from "../../redux/thunks";
-import { url } from "../../App"
 
 import './style.scss'
 
-
 const style = {
     position: 'absolute',
     top: '50%',
@@ -31,14 +49,11 @@ const style = {
 
 // Компонент карточка юзера с кнопкой подписки/отписки (нужно делать всегда двойную проверку data.owner.id || data.id (идет вызов модалки на комменте || посте), потому что у нас разные сущности на лайках и на подписчиках)
 export function RecommendedCard({ data }) {
-    // console.log('data MODAL: ', data)
-
     const history = useHistory()
     const dispatch = useDispatch()
 
     // контекст обновления профиля
     const [updateProfile, setUpdateProfile] = useContext(UpdateProfile)
-    // console.log('updateProfile: ', updateProfile)
 
     // контекст модального окна
     const [modalName, setModalName, modalArray, setModalArray, openModal, setOpenModal, handleOpenModal, handleCloseModal] = useContext(ModalForCountsContext)
@@ -48,22 +63,13 @@ export function RecommendedCard({ data }) {
     const isFollowing = myData?.following && (myData?.following).some(item => item._id === (data?.owner?._id || data?._id))
 
     // проверка текущего id страницы
-    const currentId = useLocation().pathname.split('/')[useLocation().pathname.split('/').length - 1] // test
-    // console.log('currentId: ', currentId) // test
+    const currentId = useLocation().pathname.split('/')[useLocation().pathname.split('/').length - 1]
 
     // мой id
     const myid = myData?._id
 
-    // переход на аккаунт
-    function toAccount() {
-        history.push(data?.owner?._id ? `/user/${data?.owner?._id}` : `/user/${data?._id}`)
-        setModalArray(false)
-    }
-
     // функция подписки/отписки
     function isSubscribing() {
-        // console.log('old data: ', updateProfile)
-
         // при клике на посте
         const newData = {
             ...updateProfile, following: (isFollowing
@@ -72,51 +78,63 @@ export function RecommendedCard({ data }) {
             )
         }
 
-        // console.log('new data: ', newData)
         dispatch(actionFullUpdateProfile(newData, currentId))
     }
 
+    // переход на аккаунт
+    function toAccount() {
+        history.push(data?.owner?._id ? `/user/${data?.owner?._id}` : `/user/${data?._id}`)
+        setModalArray(false)
+    }
+
+
     return (
         <CardHeader
             avatar={
                 <Avatar
                     src={url + (data?.owner?.avatar?.url || data?.avatar?.url)}
                     aria-label="recipe"
-                    sx={{ width: 36, height: 36 }}
+                    sx={{
+                        width: 36,
+                        height: 36
+                    }}
                 />
             }
-
             title={
-                < Typography
+                <Typography
+                    className="cursor-pointer"
+                    variant="subtitle2"
+                    color='text.secondary'
+                    onClick={toAccount}
                     sx={{
-                        cursor: 'pointer',
                         width: 'fit-content',
                         maxWidth: '155px',
-                        whiteSpace: 'nowrap', /* запрещает перенос текста на новую строку */
-                        overflowX: 'hidden', /* скрывает текст, который выходит за пределы контейнера */
-                        textOverflow: 'ellipsis',
+                        whiteSpace: 'nowrap', // запрещает перенос текста на новую строку
+                        overflowX: 'hidden', // скрывает текст, который выходит за пределы контейнера
+                        textOverflow: 'ellipsis' // троеточие при выходе за пределы контейнера
                     }}
-                    variant="subtitle2"
-                    color='text.secondary'
-                    onClick={toAccount}
                 >
                     {data?.owner?.login || data?.login || 'anon user'}
                 </Typography >
             }
-
-            action={//сначала проверка на меня. если не я, рисуем кнопку
-                ((myData?.following && (data?.owner?._id || data?._id) != myid)) && <Box
+            action={//сначала проверка на меня - если не я, рисуем кнопку
+                ((myData?.following && (data?.owner?._id || data?._id) != myid)) &&
+                <Box
                     onClick={isSubscribing}
                 >
                     <Button
-                        variant={isFollowing ? "elevated" : "filledTonal"}
+                        variant={isFollowing
+                            ? "elevated"
+                            : "filledTonal"}
                         size="small"
                         sx={{
                             minWidth: '140px',
                             padding: '5px 10px'
                         }}
                     >
-                        {(isFollowing ? 'Отписаться' : 'Подписаться')}
+                        {(isFollowing
+                            ? 'Отписаться'
+                            : 'Подписаться')}
                     </Button>
                 </ Box>
             }
@@ -126,17 +144,11 @@ export function RecommendedCard({ data }) {
 
 
 function ModalWindow() {
-
     // контекст модального окна
     const [modalName, setModalName, modalArray, setModalArray, openModal, setOpenModal, handleOpenModal, handleCloseModal] = useContext(ModalForCountsContext)
 
-    // контекст обновления профиля
-    // const [updateProfile, setUpdateProfile] = useContext(UpdateProfile)
-    // console.log('test context: ', updateProfile)
-
-
     return (
-        <div>
+        <React.Fragment>
             <Modal
                 aria-labelledby="transition-modal-title"
                 aria-describedby="transition-modal-description"
@@ -151,15 +163,20 @@ function ModalWindow() {
                     },
                 }}
             >
-                <Fade in={openModal}>
-                    <Box sx={style}>
+                <Fade
+                    in={openModal}
+                >
+                    <Box
+                        sx={style}
+                    >
                         <Stack
                             direction="row"
                             justifyContent="space-between"
                             alignItems="center"
                             sx={{
                                 padding: '0 24px'
-                            }}>
+                            }}
+                        >
                             <Typography
                                 variant="subtitle1"
                                 color='text.primary'
@@ -169,15 +186,15 @@ function ModalWindow() {
                             </Typography>
 
                             <IconButton
-                                onClick={handleCloseModal}
                                 title='Закрыть'
+                                onClick={handleCloseModal}
                             >
                                 <Close
+                                    fontSize='medium'
                                     sx={{
                                         position: 'absolute',
                                         color: 'black'
                                     }}
-                                    fontSize='medium'
                                 />
                             </IconButton>
                         </Stack>
@@ -193,9 +210,13 @@ function ModalWindow() {
                                 maxHeight: 350,
                                 overflowY: 'auto',
                                 overflowX: 'hidden'
-                            }}>
+                            }}
+                        >
                             {modalArray.length != 0
-                                ? modalArray?.map(item => <RecommendedCard key={item._id} data={item} />)
+                                ? modalArray?.map(item => <RecommendedCard
+                                    key={item._id}
+                                    data={item}
+                                />)
                                 : <Typography
                                     variant="subtitle1"
                                     align='center'
@@ -208,7 +229,7 @@ function ModalWindow() {
                     </Box>
                 </Fade>
             </Modal >
-        </div>
+        </React.Fragment>
     )
 }
 

+ 0 - 9
js/Project/project/src/components/update_profile/index.js

@@ -1,9 +0,0 @@
-function UpsertProfile() {
-    return (
-        <div>
-            редактируем профиль здесь
-        </div>
-    )
-}
-
-export default UpsertProfile

File diff suppressed because it is too large
+ 93 - 1058
js/Project/project/src/components/user/change_data.js


+ 31 - 176
js/Project/project/src/components/user/gallery.js

@@ -1,161 +1,24 @@
-// import { url } from '../../App';
-
-// import React, { useContext, useEffect, useState } from 'react';
-// import { connect, useDispatch, useSelector } from 'react-redux';
-// import { useHistory } from 'react-router-dom';
-
-// import { Box } from '@mui/system';
-// import { IconButton, ImageList, ImageListItem, Typography } from '@mui/material';
-
-// import { AutoAwesomeMotionRounded, ReplyRounded, BorderColorRounded, DriveFileRenameOutlineRounded } from '@mui/icons-material';
-
-// import { actionDownloadUserFeed } from '../../redux/thunks';
-
-// import './style.scss'
-
-// import { EditProfile } from '.';
-
-
-// export default function StandardImageList({ images }) {
-//     const history = useHistory()
-//     const dispatch = useDispatch()
-
-//     // отслеживание старыых постов
-//     const [currentPosts, setCurrentPosts] = useState(images)
-//     console.log('currentPosts: ', currentPosts)
-
-
-
-
-
-//     // отслеживание нажатия кнопки редактирования профиля
-//     const [isEditProfile, setIsEditProfile] = useContext(EditProfile)
-
-//     // отслеживаем дозагрузку новых постов
-//     const newPosts = useSelector(state => state?.feed?.AddUserFeed?.payload)
-//     console.log('newPosts: ', newPosts)
-
-//     // когда пришли посты, делаем проверку на дубли и пушим в основную ленту
-//     if (newPosts) {
-//         newPosts.forEach((obj2) => {
-//             const obj1Exists = currentPosts?.some((obj1) => obj1?._id === obj2?._id);
-//             if (!obj1Exists) {
-//                 currentPosts?.push(obj2);
-//             }
-//         });
-//     }
-
-
-//     // функция отслеживания дна
-//     function handleScroll() {
-//         if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
-//             dispatch(actionDownloadUserFeed())
-//         }
-//     };
-
-
-//     // первая загрузка страницы и монтирование прослушки
-//     useEffect(() => {
-
-//         window.addEventListener('scroll', handleScroll);
-
-//         return () => window.removeEventListener('scroll', handleScroll);
-//     }, [])
-
-
-//     // стиль иконки на посте
-//     const iconStyle = {
-//         color: '#e8def8',
-//         // transform: 'scale(-1, 1)',
-//         position: 'absolute',
-//         right: '10px',
-//         top: '10px',
-//         fontSize: '32px'
-//     }
-
-//     // переход на пост при клике на его картинку
-//     function toPost(id) {
-//         if (isEditProfile) {
-//             history.push(`/upsertpost/${id}`)
-//         } else {
-//             history.push(`/post/${id}`)
-//         }
-
-//         setIsEditProfile(false)
-//     }
-
-//     return (currentPosts &&
-//         <ImageList
-//             sx={{
-//                 width: "100%",
-//                 minHeight: "100%"
-//             }}
-//             cols={3}
-//             rowHeight={'auto'}
-//         >
-//             {currentPosts?.map(item => (
-
-//                 <ImageListItem
-//                     key={item?._id}
-//                 >
-//                     {/* иконка галереи на посте в ленте */}
-//                     {(isEditProfile && <BorderColorRounded
-//                         sx={iconStyle}
-//                     />) ||
-//                         (item?.images?.length > 1) &&
-//                         <AutoAwesomeMotionRounded
-//                             sx={iconStyle}
-//                         />}
-
-//                     {/* пост в ленте */}
-//                     <Box
-//                         sx={{
-//                             width: '100%',
-//                             paddingTop: '100%',
-//                             backgroundSize: 'cover',
-//                             backgroundColor: 'black',
-//                             backgroundImage: `url(/images/noPhoto.png)`,
-//                             backgroundRepeat: 'no-repeat',
-//                             cursor: 'pointer',
-//                         }}
-
-//                         style={item?.images && (
-//                             item?.images[0]?.url &&
-//                             { backgroundImage: `url(${url + item?.images[0]?.url})` }
-//                         )}
-
-//                         onClick={() => {
-//                             toPost(item._id)
-//                         }}
-//                     />
-//                 </ImageListItem>
-//             ))
-//             }
-//         </ImageList >
-//     )
-// }
-
-// export const СStandardImageList = connect(state => ({ images: state?.feed?.UserFeed?.payload }))(StandardImageList)
-
-
-
-
-
 import { url } from '../../App';
 
 import React, { useContext, useEffect, useState } from 'react';
+
 import { connect, useDispatch, useSelector } from 'react-redux';
+
 import { useHistory } from 'react-router-dom';
 
 import { Box } from '@mui/system';
-import { IconButton, ImageList, ImageListItem, Typography } from '@mui/material';
+import {
+    ImageList,
+    ImageListItem,
+} from '@mui/material';
 
-import { AutoAwesomeMotionRounded, ReplyRounded, BorderColorRounded, DriveFileRenameOutlineRounded } from '@mui/icons-material';
+import {
+    AutoAwesomeMotionRounded,
+    BorderColorRounded
+} from '@mui/icons-material';
 
 import { actionDownloadUserFeed } from '../../redux/thunks';
 
-import './style.scss'
-
 import { EditProfile } from '.';
 
 
@@ -163,22 +26,26 @@ export default function StandardImageList({ images }) {
     const history = useHistory()
     const dispatch = useDispatch()
 
-    // отслеживание старыых постов
+    // отслеживание старых постов
     const [currentPosts, setCurrentPosts] = useState(images)
-    console.log('currentPosts: ', currentPosts)
-
 
+    // без useEffect не срабатывает изменение аватара при переходе между профилями
     useEffect(() => {
         setCurrentPosts(images)
     }, [images])
 
-
     // отслеживание нажатия кнопки редактирования профиля
     const [isEditProfile, setIsEditProfile] = useContext(EditProfile)
 
+    // функция отслеживания дна
+    function handleScroll() {
+        if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
+            dispatch(actionDownloadUserFeed())
+        }
+    };
+
     // отслеживаем дозагрузку новых постов
     const newPosts = useSelector(state => state?.feed?.AddUserFeed?.payload)
-    console.log('newPosts: ', newPosts)
 
     // когда пришли посты, делаем проверку на дубли и пушим в основную ленту
     if (newPosts) {
@@ -190,18 +57,8 @@ export default function StandardImageList({ images }) {
         });
     }
 
-
-    // функция отслеживания дна
-    function handleScroll() {
-        if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
-            dispatch(actionDownloadUserFeed())
-        }
-    };
-
-
-    // первая загрузка страницы и монтирование прослушки
+    // первая загрузка страницы и монтирование/размонтирование прослушки
     useEffect(() => {
-
         window.addEventListener('scroll', handleScroll);
 
         return () => window.removeEventListener('scroll', handleScroll);
@@ -211,7 +68,6 @@ export default function StandardImageList({ images }) {
     // стиль иконки на посте
     const iconStyle = {
         color: '#e8def8',
-        // transform: 'scale(-1, 1)',
         position: 'absolute',
         right: '10px',
         top: '10px',
@@ -229,24 +85,25 @@ export default function StandardImageList({ images }) {
         setIsEditProfile(false)
     }
 
+
     return (currentPosts &&
         <ImageList
+            cols={3}
+            rowHeight={'auto'}
             sx={{
                 width: "100%",
                 minHeight: "100%"
             }}
-            cols={3}
-            rowHeight={'auto'}
         >
             {currentPosts?.map(item => (
-
                 <ImageListItem
                     key={item?._id}
                 >
                     {/* иконка галереи на посте в ленте */}
-                    {(isEditProfile && <BorderColorRounded
-                        sx={iconStyle}
-                    />) ||
+                    {(isEditProfile &&
+                        <BorderColorRounded
+                            sx={iconStyle}
+                        />) ||
                         (item?.images?.length > 1) &&
                         <AutoAwesomeMotionRounded
                             sx={iconStyle}
@@ -254,6 +111,10 @@ export default function StandardImageList({ images }) {
 
                     {/* пост в ленте */}
                     <Box
+                        className="cursor-pointer"
+                        onClick={() => {
+                            toPost(item._id)
+                        }}
                         sx={{
                             width: '100%',
                             paddingTop: '100%',
@@ -261,17 +122,11 @@ export default function StandardImageList({ images }) {
                             backgroundColor: 'black',
                             backgroundImage: `url(/images/noPhoto.png)`,
                             backgroundRepeat: 'no-repeat',
-                            cursor: 'pointer',
                         }}
-
                         style={item?.images && (
                             item?.images[0]?.url &&
                             { backgroundImage: `url(${url + item?.images[0]?.url})` }
                         )}
-
-                        onClick={() => {
-                            toPost(item._id)
-                        }}
                     />
                 </ImageListItem>
             ))

+ 18 - 17
js/Project/project/src/components/user/index.js

@@ -1,45 +1,46 @@
 import React, { createContext, useEffect, useState } from 'react';
-// import { useEffect } from 'react';
-import { useParams } from 'react-router-dom';
+
 import { connect } from 'react-redux';
-// import { store } from '../../redux';
-// import { useState } from 'react';
 
-import { Box, Container, Divider } from '@mui/material';
+import { useParams } from 'react-router-dom';
+
+import {
+    Box,
+    Divider
+} from '@mui/material';
+
+import { actionFullUserFindOne } from '../../redux/thunks';
 
 import BasicCard from './userData';
-import { actionFindUserOne, actionFullUserFindOne } from '../../redux/thunks';
 
-import { StandardImageList, СStandardImageList } from './gallery';
+import { СStandardImageList } from './gallery';
 
 export const EditProfile = createContext()
 
-function User({ user = {}, loadUser }) {
-    // console.log('user: ', user)
-
-    const [isEditProfile, setIsEditProfile] = useState(false)
-    // console.log('isEditProfile: ', isEditProfile)
 
+function User({ user = {}, loadUser }) {
     const { userId } = useParams()
     useEffect(() => { loadUser(userId) }, [userId])
 
+    const [isEditProfile, setIsEditProfile] = useState(false)
+
     return (
-        // <React.Fragment>
         <EditProfile.Provider value={[isEditProfile, setIsEditProfile]}>
             <Box
                 sx={{
                     margin: "20px 50px"
                 }}
             >
-                <BasicCard userData={user} />
+                <BasicCard
+                    userData={user}
+                />
             </Box>
 
             <Divider />
 
-            <Box>
+            <React.Fragment>
                 <СStandardImageList />
-            </Box>
-            {/* </React.Fragment > */}
+            </React.Fragment>
         </EditProfile.Provider >
     );
 }

+ 0 - 0
js/Project/project/src/components/user/style.scss


+ 64 - 428
js/Project/project/src/components/user/userData.js

@@ -1,355 +1,58 @@
-// import { url } from "../../App"
-
-// import React, { useContext, useState } from 'react';
-// import { useHistory, useParams } from 'react-router-dom';
-// import { useDispatch, useSelector } from 'react-redux';
-
-// import { CardContent, Typography, Stack, Avatar, Box, Container, Badge, TextField, InputAdornment, IconButton } from '@mui/material';
-// import Button from '@mui/material-next/Button';
-// import { PersonRemoveRounded, PersonAddRounded, ManageAccountsRounded, BorderColorRounded, ImageSearchRounded, AccountCircle, HttpsRounded } from '@mui/icons-material';
-// import { actionUserPageSubscribing } from "../../redux/thunks";
-
-// import ModalWindow from '../structure/modal';
-// import ChangeData from "./change_data";
-// import { ModalForCountsContext, UpdateProfile } from "../../App";
-
-// import { EditProfile } from ".";
-
-
-
-// // Функция отображения кнопки редактирования своего профиля/отписки или подписки на другого юзера
-// function UptadeProfileButton({ data }) {
-//     // console.log('UserData: ', data)
-
-//     const history = useHistory()
-//     const { userId } = useParams()
-//     const dispatch = useDispatch()
-
-//     // отслеживание нажатия кнопки редактирования профиля
-//     const [isEditProfile, setIsEditProfile] = useContext(EditProfile)
-
-//     // контекст обновления профиля
-//     const [updateProfile, setUpdateProfile] = useContext(UpdateProfile)
-//     // console.log('updateProfile: ', updateProfile)
-
-//     // определяем мой id
-//     const myId = updateProfile?._id
-
-//     // определяем всех моих подписчиков
-//     const myFollowingList = updateProfile?.following?.map(user => user?._id)
-
-//     // проверка, является ли пользователь моим подписчиком
-//     const isFollowing = myFollowingList && (myFollowingList)?.some(item => item === (data?.owner?._id || data?._id))
-
-
-//     // функция подписки/отписки - это чисто кнопка
-//     function isSubscribing() {
-
-//         // при клике на посте
-//         const newData = {
-//             ...updateProfile, following: (isFollowing
-//                 ? updateProfile?.following?.filter(item => item?._id !== (data?.owner?._id || data?._id)) // отписка
-//                 // : [...updateProfile?.following, { _id: (data?.owner?._id || data?._id) }] // подписка
-//                 : updateProfile?.following
-//                     ? [...updateProfile?.following, { _id: (data?.owner?._id || data?._id) }] // подписка если уже есть кто-то в подписках
-//                     : [{ _id: (data?.owner?._id || data?._id) }] // подписка, если это первая подписка
-//             )
-//         }
-
-//         dispatch(actionUserPageSubscribing(newData, userId))
-//     }
-
-//     // функция перехода на редактирование профиля
-//     function upsertProfile() {
-//         // history.push('/updateprofile')
-//         setIsEditProfile(true)
-//     }
-
-
-//     return (
-//         <Box
-//             onClick={
-//                 (userId === myId && upsertProfile) ||
-//                 (myFollowingList?.includes(userId) && isSubscribing) ||
-//                 ((userId !== myId && !myFollowingList?.includes(userId)) && isSubscribing)}
-//         >
-//             <Button
-//                 size="large"
-//                 // variant="elevated"
-//                 variant={
-//                     ((userId === myId) && 'elevated') ||
-//                     ((myFollowingList?.includes(userId)) && 'elevated') ||
-//                     ((userId !== myId && !myFollowingList?.includes(userId)) && 'filledTonal')
-//                 }
-//                 sx={{
-//                     minWidth: '300px'
-//                 }}
-//                 startIcon={
-//                     ((userId === myId) && <ManageAccountsRounded />) ||
-//                     ((myFollowingList?.includes(userId)) && <PersonRemoveRounded />) ||
-//                     ((userId !== myId && !myFollowingList?.includes(userId)) && <PersonAddRounded />)
-//                 }
-//                 disableRipple
-//             >
-//                 <Typography
-//                     variant='button'
-//                     display='block'
-//                 >
-//                     {(userId === myId) && 'Редактировать аккаунт' ||
-//                         (myFollowingList?.includes(userId)) && 'Отписаться' ||
-//                         (userId !== myId && !myFollowingList?.includes(userId)) && 'Подписаться'
-//                     }
-//                 </Typography>
-//             </Button>
-//         </Box>
-//     )
-// }
-
-
-
-// // блок пользовательских данных
-// export default function BasicCard({ userData }) {
-//     // console.log('userData: ', userData)
-
-//     // определяем количество постов пользоваеля
-//     const userPostsCount = useSelector(state => state?.promise?.UserPostsCount?.payload)
-
-//     // контекст обновления профиля
-//     const [updateProfile, setUpdateProfile] = useContext(UpdateProfile)
-//     // console.log('updateProfile: ', updateProfile)
-
-//     // отслеживание нажатия кнопки редактирования профиля
-//     const [isEditProfile, setIsEditProfile] = useContext(EditProfile)
-
-//     // контекст модального окна
-//     const [modalName, setModalName, modalArray, setModalArray, openModal, setOpenModal, handleOpenModal, handleCloseModal] = useContext(ModalForCountsContext)
-
-//     // отслеживание статуса изменения пароля
-//     const [changePassword, setChangePassword] = useState(false)
-
-//     // открытие поля редактирвоания пароля
-//     function changePasswordButton() {
-//         setChangePassword(true)
-//     }
-
-
-//     function userFollowers() {
-//         handleOpenModal({
-//             arr: userData?.followers, name: `Подписчики ${userData?.login}`
-//         })
-//     }
-
-//     function userFollowing() {
-//         handleOpenModal({
-//             arr: userData?.following, name: `Подписки ${userData?.login}`
-//         })
-//     }
-
-
-//     return (
-//         <Container sx={{
-//             display: 'flex',
-//             alignItems: 'center'
-//         }}
-//         >
-//             <Box
-//                 sx={{
-//                     position: 'relative',
-//                     display: 'inline-block'
-//                 }}>
-//                 <Avatar
-//                     alt={userData?.login}
-//                     src={url + userData?.avatar?.url}
-//                     sx={{
-//                         width: 130,
-//                         height: 130
-//                     }}
-//                 />
-//                 {isEditProfile &&
-//                     <Box
-//                         sx={{
-//                             position: 'absolute',
-//                             top: 0,
-//                             left: 0,
-//                             width: '100%',
-//                             height: '100%',
-//                             display: 'flex',
-//                             justifyContent: 'center',
-//                             alignItems: 'center',
-//                             zIndex: 1,
-//                             '&:before': {
-//                                 content: '""',
-//                                 position: 'absolute',
-//                                 top: 0,
-//                                 left: 0,
-//                                 width: '100%',
-//                                 height: '100%',
-//                                 backgroundColor: 'rgba(0,0,0,0.5)',
-//                                 zIndex: -1,
-//                                 borderRadius: '50%',
-//                             }
-//                         }}
-//                     >
-//                         <IconButton
-//                             color="primary"
-//                             aria-label="upload avatar"
-//                             component="label"
-//                         >
-//                             <input hidden accept="image/*" type="file" />
-//                             <ImageSearchRounded
-//                                 sx={{
-//                                     color: '#FFF',
-//                                     fontSize: '40px'
-//                                 }}
-//                             />
-//                         </IconButton>
-
-//                     </Box>}
-//             </Box>
-
-
-
-//             {!isEditProfile &&
-//                 <Box
-//                     sx={{
-//                         display: 'flex',
-//                         flexDirection: 'column',
-//                         marginLeft: '50px '
-//                     }}
-//                 >
-//                     <CardContent sx={{
-//                         flex: '1 0 auto'
-//                     }}
-//                     >
-//                         <Stack
-//                             sx={{
-//                                 justifyContent: 'space-between'
-//                             }}
-//                             direction="row"
-//                             spacing={2}
-//                         >
-//                             <Typography
-//                                 component="div"
-//                                 variant="h4"
-//                             >
-//                                 {userData?.login}
-//                             </Typography>
-
-//                             <UptadeProfileButton data={userData} />
-//                         </Stack>
-
-//                         <Typography
-//                             variant="subtitle1"
-//                             color="text.secondary"
-//                             component="div"
-//                         >
-//                             {userData?.nick || ''}
-//                         </Typography>
-//                     </CardContent>
-
-//                     <Stack
-//                         direction="row"
-//                         spacing={5}
-//                         padding={2}
-//                         paddingTop={1}
-//                     >
-//                         <Typography
-//                             variant="subtitle1"
-//                         >
-//                             {userPostsCount || '0'} публикаций
-//                         </Typography>
-
-//                         <Typography
-//                             sx={{
-//                                 cursor: 'pointer'
-//                             }}
-//                             variant="subtitle1"
-//                             onClick={userFollowers}
-//                         >
-//                             {userData?.followers?.length || '0'} подписчиков
-//                         </Typography>
-
-//                         <Typography
-//                             sx={{
-//                                 cursor: 'pointer'
-//                             }}
-//                             variant="subtitle1"
-//                             onClick={userFollowing}
-//                         >
-//                             {userData?.following?.length || '0'} подписок
-//                         </Typography>
-//                     </Stack>
-//                 </Box>}
-
-//             {isEditProfile && <ChangeData />
-//             }
-
-//             {modalArray && <ModalWindow />}
-//         </Container>
-//     )
-// }
-
-
-
-
-
-
-
+import { url } from "../../App"
 
+import React, {
+    useContext,
+    useState,
+    useEffect
+} from 'react';
 
-import { url } from "../../App"
+import { useDispatch, useSelector } from 'react-redux';
 
-import React, { useContext, useState, useEffect } from 'react';
 import { useHistory, useParams } from 'react-router-dom';
-import { useDispatch, useSelector } from 'react-redux';
 
-import { CardContent, Typography, Stack, Avatar, Box, Container, Badge, TextField, InputAdornment, IconButton } from '@mui/material';
+import {
+    CardContent,
+    Typography,
+    Stack,
+    Avatar,
+    Box,
+    Container,
+    IconButton
+} from '@mui/material';
 import Button from '@mui/material-next/Button';
-import { PersonRemoveRounded, PersonAddRounded, ManageAccountsRounded, BorderColorRounded, ImageSearchRounded, AccountCircle, HttpsRounded } from '@mui/icons-material';
-import { actionUserPageSubscribing } from "../../redux/thunks";
 
-import ModalWindow from '../structure/modal';
-import ChangeData from "./change_data";
+import {
+    PersonRemoveRounded,
+    PersonAddRounded,
+    ManageAccountsRounded,
+    ImageSearchRounded
+} from '@mui/icons-material';
+
+import {
+    actionUserPageSubscribing,
+    actionFilesUpload
+} from "../../redux/thunks";
+
 import { ModalForCountsContext, UpdateProfile } from "../../App";
-import { UploadedFiles } from "../create_post/uploaded_files";
-import { actionFilesUpload } from "../../redux/thunks";
 
 import { EditProfile } from ".";
 
+import ModalWindow from '../structure/modal';
 
+import ChangeData from "./change_data";
 
 // Функция отображения кнопки редактирования своего профиля/отписки или подписки на другого юзера
 function UptadeProfileButton({ data }) {
-    // console.log('UserData: ', data)
-
     const history = useHistory()
     const { userId } = useParams()
     const dispatch = useDispatch()
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+    // контекст обновления профиля
+    const [updateProfile, setUpdateProfile] = useContext(UpdateProfile)
 
     // отслеживание нажатия кнопки редактирования профиля
     const [isEditProfile, setIsEditProfile] = useContext(EditProfile)
 
-    // контекст обновления профиля
-    const [updateProfile, setUpdateProfile] = useContext(UpdateProfile)
-    // console.log('updateProfile: ', updateProfile)
 
     // определяем мой id
     const myId = updateProfile?._id
@@ -360,17 +63,14 @@ function UptadeProfileButton({ data }) {
     // проверка, является ли пользователь моим подписчиком
     const isFollowing = myFollowingList && (myFollowingList)?.some(item => item === (data?.owner?._id || data?._id))
 
-
     // функция подписки/отписки - это чисто кнопка
     function isSubscribing() {
-
         // при клике на посте
         const newData = {
             ...updateProfile, following: (isFollowing
                 ? updateProfile?.following?.filter(item => item?._id !== (data?.owner?._id || data?._id)) // отписка
-                // : [...updateProfile?.following, { _id: (data?.owner?._id || data?._id) }] // подписка
                 : updateProfile?.following
-                    ? [...updateProfile?.following, { _id: (data?.owner?._id || data?._id) }] // подписка если уже есть кто-то в подписках
+                    ? [...updateProfile?.following, { _id: (data?.owner?._id || data?._id) }] // подписка, если уже есть кто-то в подписках
                     : [{ _id: (data?.owner?._id || data?._id) }] // подписка, если это первая подписка
             )
         }
@@ -380,7 +80,6 @@ function UptadeProfileButton({ data }) {
 
     // функция перехода на редактирование профиля
     function upsertProfile() {
-        // history.push('/updateprofile')
         setIsEditProfile(true)
     }
 
@@ -393,22 +92,21 @@ function UptadeProfileButton({ data }) {
                 ((userId !== myId && !myFollowingList?.includes(userId)) && isSubscribing)}
         >
             <Button
-                size="large"
-                // variant="elevated"
+                size="small"
                 variant={
                     ((userId === myId) && 'elevated') ||
                     ((myFollowingList?.includes(userId)) && 'elevated') ||
                     ((userId !== myId && !myFollowingList?.includes(userId)) && 'filledTonal')
                 }
-                sx={{
-                    minWidth: '300px'
-                }}
                 startIcon={
                     ((userId === myId) && <ManageAccountsRounded />) ||
                     ((myFollowingList?.includes(userId)) && <PersonRemoveRounded />) ||
                     ((userId !== myId && !myFollowingList?.includes(userId)) && <PersonAddRounded />)
                 }
                 disableRipple
+                sx={{
+                    minWidth: '250px'
+                }}
             >
                 <Typography
                     variant='button'
@@ -424,11 +122,8 @@ function UptadeProfileButton({ data }) {
     )
 }
 
-
-
 // блок пользовательских данных
 export default function BasicCard({ userData }) {
-    // console.log('userData: ', userData)
     const dispatch = useDispatch()
 
     // определяем количество постов пользоваеля
@@ -436,11 +131,9 @@ export default function BasicCard({ userData }) {
 
     // контекст обновления профиля
     const [updateProfile, setUpdateProfile] = useContext(UpdateProfile)
-    // console.log('updateProfile AVATAR: ', updateProfile)
 
     // отслеживание нажатия кнопки редактирования профиля
     const [isEditProfile, setIsEditProfile] = useContext(EditProfile)
-    console.log('isEditProfile: ', isEditProfile)
 
     // контекст модального окна
     const [modalName, setModalName, modalArray, setModalArray, openModal, setOpenModal, handleOpenModal, handleCloseModal] = useContext(ModalForCountsContext)
@@ -448,83 +141,49 @@ export default function BasicCard({ userData }) {
     // отслеживание статуса изменения пароля
     const [changePassword, setChangePassword] = useState(false)
 
-
-
-
-
-
-
-
     // отслеживаем добавление файлов
     const [selectedFile, setSelectedFile] = useState(null)
-    // console.log('selectedFile: ', selectedFile)
 
     // установка урла аватара
     const [userAvatarUrl, setUserAvatarUrl] = useState(url + userData?.avatar?.url);
-    // console.log('userAvatarUrl: ', userAvatarUrl)
 
     // функция загрузки файлов с компа
     const handleFileSelect = (event) => {
         const file = event.target.files[0];
         setSelectedFile(file);
-    };
+    }
 
-    // отправляем все на бек когда добавили с компа
+    // отправляем все на бек когда добавили картинки с компа
     useEffect(() => {
         if (selectedFile) {
-            // const res = await dispatch(actionFilesUpload(selectedFile))
             dispatch(actionFilesUpload(selectedFile)).then((res) => {
-
-                // console.log('res: ', res)
-
                 // ставим на аватар после загрузки
                 const newAvatarUrl = url + res?.url;
                 setUserAvatarUrl(newAvatarUrl)
 
                 setUpdateProfile({ ...updateProfile, avatar: { _id: res?._id } })
-
             })
         }
     }, [selectedFile])
 
-
     // меняем аватарку, если переходим между пользователями или отменяем изменения
     useEffect(() => {
         setUserAvatarUrl(url + userData?.avatar?.url)
     }, [userData, isEditProfile])
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 
     // открытие поля редактирвоания пароля
-    function changePasswordButton() {
-        setChangePassword(true)
-    }
-
+    // function changePasswordButton() {
+    //     setChangePassword(true)
+    // }
 
+    // открытие модального окна с подписчиками
     function userFollowers() {
         handleOpenModal({
             arr: userData?.followers, name: `Подписчики ${userData?.login}`
         })
     }
 
+    // открытие модального окна с подписками
     function userFollowing() {
         handleOpenModal({
             arr: userData?.following, name: `Подписки ${userData?.login}`
@@ -533,19 +192,20 @@ export default function BasicCard({ userData }) {
 
 
     return (
-        <Container sx={{
-            display: 'flex',
-            alignItems: 'center'
-        }}
+        <Container
+            sx={{
+                display: 'flex',
+                alignItems: 'center'
+            }}
         >
             <Box
                 sx={{
                     position: 'relative',
                     display: 'inline-block'
-                }}>
+                }}
+            >
                 <Avatar
                     alt={userData?.login}
-                    // src={url + userData?.avatar?.url}
                     src={userAvatarUrl}
                     sx={{
                         width: 130,
@@ -577,30 +237,10 @@ export default function BasicCard({ userData }) {
                             }
                         }}
                     >
-                        {/* <IconButton
-                            color="primary"
-                            aria-label="upload avatar"
-                            component="label"
-                        >
-                            <input
-                                hidden
-                                accept="image/*"
-                                type="file"
-                                className='getphoto'
-                                onFiles={files => dispatch(actionFilesUpload(files))}
-                            />
-                            <ImageSearchRounded
-                                sx={{
-                                    color: '#FFF',
-                                    fontSize: '40px'
-                                }}
-                            />
-                        </IconButton> */}
                         <IconButton
                             color="primary"
                             aria-label="upload avatar"
                             component="label"
-                        // onClick={handleFileUpload}
                         >
                             <input
                                 hidden
@@ -609,6 +249,7 @@ export default function BasicCard({ userData }) {
                                 className='getphoto'
                                 onChange={handleFileSelect}
                             />
+
                             <ImageSearchRounded
                                 sx={{
                                     color: '#FFF',
@@ -616,12 +257,9 @@ export default function BasicCard({ userData }) {
                                 }}
                             />
                         </IconButton>
-
                     </Box>}
             </Box>
 
-
-
             {!isEditProfile &&
                 <Box
                     sx={{
@@ -630,16 +268,17 @@ export default function BasicCard({ userData }) {
                         marginLeft: '50px '
                     }}
                 >
-                    <CardContent sx={{
-                        flex: '1 0 auto'
-                    }}
+                    <CardContent
+                        sx={{
+                            flex: '1 0 auto'
+                        }}
                     >
                         <Stack
+                            direction="row"
+                            spacing={2}
                             sx={{
                                 justifyContent: 'space-between'
                             }}
-                            direction="row"
-                            spacing={2}
                         >
                             <Typography
                                 component="div"
@@ -648,7 +287,9 @@ export default function BasicCard({ userData }) {
                                 {userData?.login}
                             </Typography>
 
-                            <UptadeProfileButton data={userData} />
+                            <UptadeProfileButton
+                                data={userData}
+                            />
                         </Stack>
 
                         <Typography
@@ -673,9 +314,7 @@ export default function BasicCard({ userData }) {
                         </Typography>
 
                         <Typography
-                            sx={{
-                                cursor: 'pointer'
-                            }}
+                            className="cursor-pointer"
                             variant="subtitle1"
                             onClick={userFollowers}
                         >
@@ -683,9 +322,7 @@ export default function BasicCard({ userData }) {
                         </Typography>
 
                         <Typography
-                            sx={{
-                                cursor: 'pointer'
-                            }}
+                            className="cursor-pointer"
                             variant="subtitle1"
                             onClick={userFollowing}
                         >
@@ -694,8 +331,7 @@ export default function BasicCard({ userData }) {
                     </Stack>
                 </Box>}
 
-            {isEditProfile && <ChangeData />
-            }
+            {isEditProfile && <ChangeData />}
 
             {modalArray && <ModalWindow />}
         </Container>

+ 30 - 0
js/Project/project/src/index.css

@@ -1,3 +1,9 @@
+*,
+*:before,
+*:after {
+  box-sizing: inherit;
+}
+
 body {
   margin: 0;
   font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
@@ -8,9 +14,17 @@ body {
 
   /* мои стили */
   height: 100%;
+  font-family: 'Roboto', sans-serif;
+  font-size: 16px;
+  line-height: 1.65em;
+  font-style: normal;
+  font-weight: 400;
+  vertical-align: text-top;
 }
 
 .wrapper {
+  overflow: hidden;
+  position: relative;
   max-width: 60%;
   margin: 0 auto;
   display: flex;
@@ -21,4 +35,20 @@ body {
 code {
   font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
     monospace;
+}
+
+
+
+@keyframes rotate {
+  from {
+    transform: rotate(0deg);
+  }
+
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+.cursor-pointer {
+  cursor: pointer;
 }

+ 11 - 43
js/Project/project/src/redux/action.js

@@ -55,12 +55,12 @@ export const actionPromise = (type, nameOfPromise, promise) =>
 // ================================================================================================== 
 
 
-// акшон для логинизации в authReduser
+// акшон логинизации
 export const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token })
 
-// акшон для раззлогинивания в authReduser
-export const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' })
 
+// акшон разлогинивания
+export const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' })
 
 
 // Запрос на регистрацию юзера
@@ -74,7 +74,6 @@ export const actionRegistration = (login, password) => actionPromise('PROMISE',
 }))
 
 
-
 // Запрос на логинизацию юзера
 export const actionLogin = (login, password) => actionPromise('PROMISE', 'Login', gql(`query Login($login: String!, $password: String!) {
 login(login: $login, password: $password)
@@ -84,7 +83,6 @@ login(login: $login, password: $password)
 }))
 
 
-
 // Запрос на изменение пароля юзера
 export const actionPassChange = (loginChange, passwordChange, passwordNew) => actionPromise('PROMISE', 'PassChange', gql(`mutation PasswordChange($loginChange: String!, $passwordChange: String!, $passwordNew: String!) {
   changePassword(
@@ -100,7 +98,6 @@ export const actionPassChange = (loginChange, passwordChange, passwordNew) => ac
 }))
 
 
-
 // Запрос на поиск конкретного поста
 export const actionFindPostOne = _id => actionPromise('PROMISE', 'PostFindOne', gql(`query OnePostFind ($postOne: String){
   PostFindOne (query: $postOne) {
@@ -145,7 +142,6 @@ export const actionFindPostOne = _id => actionPromise('PROMISE', 'PostFindOne',
 }))
 
 
-
 // запрос на поиск конкретного юзера(folowwing - это те, на кого я подписан. followers - те, кто на меня подписан)
 export const actionFindUserOne = (_id, promiseName = 'UserFindOne') => actionPromise('PROMISE', promiseName, gql(`query OneUserFind ($userOne: String) {
     UserFindOne(query: $userOne) {
@@ -165,8 +161,7 @@ export const actionFindUserOne = (_id, promiseName = 'UserFindOne') => actionPro
 }))
 
 
-
-// Запрос на поиск всех постов на беке (нигде не должен использоваться)
+// Запрос на поиск всех постов на беке (нигде не должен использоваться, но пусть будет)
 export const actionfindPosts = () => actionPromise('PROMISE', 'PostsFind', gql(`query AllPostsFind ($allPosts: String){
   PostFind(query: $allPosts){
     _id createdAt title text likesCount
@@ -183,9 +178,7 @@ export const actionfindPosts = () => actionPromise('PROMISE', 'PostsFind', gql(`
 }))
 
 
-
 // Запрос на поиск ленты постов для юзера
-//================= вот это тоже нужно будет удалить после тестов =====================
 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 owner{
@@ -213,9 +206,7 @@ export const actionFeedFindOne = (arr, sortOne, limitOne, promiseName = 'Feed',
 }))
 
 
-
-// Запрос ленты с пропуском определенного количества постов/комментов
-// ====================== и это удалить после теста ====================
+// Запрос ленты с пропуском определенного количества постов/комментов (нигде больit не используется, можно будет кикать после проверки на фронте)
 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{
@@ -241,7 +232,6 @@ export const actionFeedFindOneSkip = (arr, sortOne, skipOne, limitOne, promiseNa
 }))
 
 
-
 // Запрос на подсчет количества постов юзера
 export const actionPostsCount = (id, promiseName) => actionPromise('PROMISE', promiseName, gql(`query PostsCount ($postsCount: String){
   PostCount(query: $postsCount)
@@ -250,7 +240,6 @@ export const actionPostsCount = (id, promiseName) => actionPromise('PROMISE', pr
 }))
 
 
-
 // Запрос на создание поста
 export const actionCreatePost = params => actionPromise('PROMISE', 'CreatePost', gql(`mutation CreatePost($createNewPost: PostInput){
   PostUpsert(post: $createNewPost){
@@ -261,8 +250,6 @@ export const actionCreatePost = params => actionPromise('PROMISE', 'CreatePost',
 }))
 
 
-
-
 // запрос на создание комментария с последующим добавлением его к посту
 export const actionAddComment = (NameOfPromise, params) => actionPromise('PROMISE', NameOfPromise, gql(`mutation AddComment($createComment: CommentInput){
   CommentUpsert(comment: $createComment){
@@ -273,9 +260,7 @@ export const actionAddComment = (NameOfPromise, params) => actionPromise('PROMIS
 }))
 
 
-
-
-// запрос на поиск всех ответов, которые есть у данного комментария
+// запрос на поиск всех ответов, которые есть у данного комментария (нигде не используется, значит можно удалить после проверки на фронте)
 export const actionFindCommentsAnswerTo = id => actionPromise('PROMISE', 'FindCommentsAnswerTo', gql(`query FindCommentAnswers2($answerTo: String) {
   CommentFind(query: $answerTo){
   _id createdAt text likesCount
@@ -293,11 +278,7 @@ export const actionFindCommentsAnswerTo = id => actionPromise('PROMISE', 'FindCo
 }))
 
 
-
-
-
-
-// запрос на поиск всех комментариев, которые есть у поста
+// запрос на поиск всех комментариев, которые есть у поста (парсим все, потом сортируем)
 export const actionFindCommentsPostOne = id => actionPromise('PROMISE', 'FindComments', gql(`query FindCommentsToPost($commentsToPost: String) {
   CommentFind(query: $commentsToPost){
   _id createdAt text likesCount
@@ -322,8 +303,6 @@ export const actionFindCommentsPostOne = id => actionPromise('PROMISE', 'FindCom
 }))
 
 
-
-
 // поиск всех подписчиков конкретных юзеров(бек фильтрует все дубли)
 export const actionFindFollowers = arr => actionPromise('PROMISE', 'FindFollowers', gql(`query FindFollowers($findFollowers: String){
   UserFind(query: $findFollowers){
@@ -336,6 +315,7 @@ export const actionFindFollowers = arr => actionPromise('PROMISE', 'FindFollower
   findFollowers: JSON.stringify([{ 'followers._id': { $in: arr } }])
 }))
 
+
 // поиск всех подписок конкретных юзеров(бек фильтрует все дубли)
 export const actionFindFollowing = arr => actionPromise('PROMISE', 'FindFollowings', gql(` query FindFollowing($findFollowing: String){
   UserFind(query: $findFollowing){
@@ -349,9 +329,6 @@ export const actionFindFollowing = arr => actionPromise('PROMISE', 'FindFollowin
 }))
 
 
-
-
-
 // добавление  лайка к посту/комментарию
 export const actionAddLike = params => actionPromise('PROMISE', 'AddLike', gql(`mutation addLike($addLike: LikeInput){
   LikeUpsert(like: $addLike){
@@ -378,10 +355,7 @@ export const actionAddLike = params => actionPromise('PROMISE', 'AddLike', gql(`
 }))
 
 
-
-
-
-// удаление лайка с поста/комментария (пример данных: {_id: "6421f0e9cec75c3ebd51bed5"})
+// удаление лайка с поста/комментария
 export const actionDeleteLike = params => actionPromise('PROMISE', 'DeleteLike', gql(`mutation deleteLike($deleteLike: LikeInput){
   LikeDelete(like: $deleteLike){
     _id post{
@@ -398,11 +372,7 @@ export const actionDeleteLike = params => actionPromise('PROMISE', 'DeleteLike',
 }))
 
 
-
-
-
-
-//обновление профил(установка аватара, ник-нейма, логина?, добавления/удаления подписчиков)
+//обновление профиля (установка аватара, ник-нейма, логина?, добавления/удаления подписчиков)
 export const actionUpdateProfile = params => actionPromise('PROMISE', 'UpdateProfile', gql(`mutation setUser($updateProfile: UserInput){
     UserUpsert(user: $updateProfile){
         _id
@@ -412,9 +382,7 @@ export const actionUpdateProfile = params => actionPromise('PROMISE', 'UpdatePro
 }))
 
 
-
-
-// массив запросов на поиск
+// массив запросов на поиск на беке ===================================================================================
 
 // запрос поиска по юзерам
 export const actionSearchUser = (params, name) => actionPromise('SEARCH', name, gql(`query UserSearch($findUser: String){

+ 1 - 3
js/Project/project/src/redux/reducers.js

@@ -1,6 +1,5 @@
 import { combineReducers } from "redux"
 
-
 // раскодируем JWT-токен
 const jwtDecode = function (token) {
     try {
@@ -81,5 +80,4 @@ export const reducers = {
     search: localStoredReducer(createReducer('SEARCH'), 'search')
 }
 
-export const totalReducer = combineReducers(reducers);
-
+export const totalReducer = combineReducers(reducers)

+ 13 - 77
js/Project/project/src/redux/thunks.js

@@ -25,11 +25,9 @@ import {
 } from "./action"
 
 
-
 // Логин и последующая логинизация в authReduser
 export const actionFullLogin = (login, password) =>
     async dispatch => {
-
         localStorage.clear()
 
         const token = await dispatch(actionLogin(login, password))
@@ -45,11 +43,9 @@ export const actionFullLogin = (login, password) =>
     }
 
 
-
 // Регистрация и последующая логинизация
 export const actionFullRegistration = (login, password) =>
     async dispatch => {
-
         const token = await dispatch(actionRegistration(login, password))
 
         if (token !== null) {
@@ -67,30 +63,23 @@ export const actionFullLogout = () =>
         const res = await dispatch(actionAuthLogout())
 
         if (res) localStorage.clear()
-    }
-
-
 
+        return res
+    }
 
 
 // запрос на изменение пароля
 export const actionFullPassChange = (login, oldPass, newPass) =>
     async dispatch => {
-        console.log(login, oldPass, newPass)
-
         const result = await dispatch(actionPassChange(login, oldPass, newPass))
 
         return result
     }
 
 
-
-
-
-// Запрос юзера (данные о пользователе + количество его постов + все его посты(100 шт))
+// Запрос юзера (данные о пользователе + количество его постов + все его посты(100 шт - лимит))
 export const actionFullUserFindOne = _id =>
     dispatch => {
-        console.log('[_id]: ', [_id])
         const requestsAboutUser = [
             actionFindUserOne(_id, 'UserFindOne'),
             actionPostsCount(_id, 'UserPostsCount'),
@@ -102,7 +91,6 @@ export const actionFullUserFindOne = _id =>
     }
 
 
-
 // Запрос AboutMe для главной
 export const actionAboutMe = () =>
     async (dispatch, getState) => {
@@ -144,59 +132,25 @@ export const actionAboutMe = () =>
     }
 
 
-
-// // ================= на удаление (начало)=====================
-// // Запрос на догрузку ленты постов
-// export const actionDownloadFeed = () =>
-//     async (dispatch, getState) => {
-
-//         // console.log('скипаем: ', skip)
-
-//         const followingList = (getState()?.promise?.AboutMe?.payload?.following)?.map(user => user._id)
-
-//         const skipLength = (getState()?.feed?.MyFeed?.payload?.length)
-
-//         if (followingList) {
-//             // const result = await dispatch(actionFeedFindOne(followingList, -1, 5, 'AddFeed', skipLength))
-//             const result = await dispatch(actionFeedFindOne(followingList, -1, 5, 'MyFeed', skipLength))
-
-//             return result
-//         }
-//     }
-// // ================= на удаление(конец) =====================
-
-// ================= на удаление (начало)=====================
-
-
 // Запрос на догрузку ленты моих постов
 export const actionDownloadFeed = () =>
     async (dispatch, getState) => {
-        // console.log('касание')
-
         const followingList = (getState()?.promise?.AboutMe?.payload?.following)?.map(user => user?._id)
 
         const myFeed = (getState()?.feed?.MyFeed?.payload)
 
         const result = await dispatch(actionFeedFindOne(followingList, -1, 10, 'AddFeed', myFeed?.length))
 
-
         return result
     }
-// ================= на удаление(конец) =====================
-
-
 
 
 // Запрос на догрузку ленты постов юзера
 export const actionDownloadUserFeed = () =>
     async (dispatch, getState) => {
-        console.log('касание')
-
         const userId = getState()?.promise?.UserFindOne?.payload?._id
-        console.log('[userId]: ', [userId])
 
         const userFeed = (getState()?.feed?.UserFeed?.payload)
-        console.log('userFeed: ', userFeed)
 
         const result = await dispatch(actionFeedFindOne([userId], -1, 15, 'AddUserFeed', userFeed?.length))
 
@@ -204,24 +158,6 @@ export const actionDownloadUserFeed = () =>
     }
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 // запрос на загрузку картинок на бек
 function fileUpload(file) {
     const formData = new FormData()
@@ -239,8 +175,6 @@ function fileUpload(file) {
 }
 
 function filesUpload(files) {
-    console.log('thunk_files', files)
-
     if (files?.length > 1) {
         return Promise.all(files?.map(fileUpload))
     } else {
@@ -254,7 +188,6 @@ export const actionFilesUpload = files => actionPromise('PROMISE', 'FilesUpload'
 )
 
 
-
 // запрос на создание поста и последующий переход на него
 export const actionFullCreatePost = (params) =>
     async dispatch => {
@@ -268,7 +201,6 @@ export const actionFullCreatePost = (params) =>
     }
 
 
-
 // Загрузка всех комментариев к посту с последующей их сортировкой и построением дерева комментариве
 export const actionFullFindCommentsPostOne = id =>
     async dispatch => {
@@ -278,7 +210,6 @@ export const actionFullFindCommentsPostOne = id =>
     }
 
 
-
 // создание комментария с последующей загрузкой с бека списка всех постов, которые относятся к этой записи
 export const actionFullAddComment = (nameOfPromise, params, id) =>
     async dispatch => {
@@ -287,8 +218,9 @@ export const actionFullAddComment = (nameOfPromise, params, id) =>
         if (typeof newComment._id === 'string') {
             dispatch(actionFullFindCommentsPostOne(id))
         }
-    }
 
+        return newComment
+    }
 
 
 // создание лайка с последующим добавлением к определенной сущности и последующим обновление определенной сущности
@@ -306,8 +238,9 @@ export const actionFullAddLike = params =>
         if (res?.comment) {
             dispatch(actionFullFindCommentsPostOne(res?.comment?.post?._id))
         }
-    }
 
+        return res
+    }
 
 
 // удаление лайка с последующим обновлением определенной сущности
@@ -325,8 +258,9 @@ export const actionFullDeleteLike = params =>
         if (res?.comment) {
             dispatch(actionFullFindCommentsPostOne(res?.comment?.post?._id))
         }
-    }
 
+        return res
+    }
 
 
 // запрос на обновление моего профиля и последующая отправка запроса обо мне на бек
@@ -342,8 +276,9 @@ export const actionFullUpdateProfile = (params, id) =>
         if (res._id == id) {
             dispatch(actionFullUserFindOne(id))
         }
-    }
 
+        return res
+    }
 
 
 // запрос на подписку/отписку на странице пользователя
@@ -355,8 +290,9 @@ export const actionUserPageSubscribing = (params, id) =>
             dispatch(actionAboutMe())
             dispatch(actionFullUserFindOne(id))
         }
-    }
 
+        return res
+    }
 
 
 // запрос на поиск элементов