Browse Source

04.03.2023 13:30

Volddemar4ik 2 years ago
parent
commit
13a5a76dce

BIN
js/Project/project/public/images/logo.jpeg


+ 16 - 193
js/Project/project/src/App.js

@@ -1,154 +1,24 @@
 // import logo from './logo.svg';
 import './App.css';
-import React, { useState, useEffect } from 'react';
+import React from 'react';
 import { Router, Route, Link, Redirect, Switch, useParams } from 'react-router-dom';
-import { createStore, combineRedusers, applyMiddleware } from 'redux';
-import thunk from 'redux-thunk';
 import { Provider, connect, useDispatch, useSelector } from 'react-redux';
-import { CUser } from './components/user';
+import { store } from './components/redux/index';
+import createHistory from "history/createBrowserHistory";
 
-// импорт страниц
+
+// импорт структуры страницы
 import AsideMenu from './components/pages/structure/aside_menu';
 
+// импорт страниц
+import { CUser } from './components/user';
 import { ReduxFeed } from './components/feed';
 import { CComments } from './components/post';
-import { CreatePost } from './components/pages/create_post';
-
-
-import createHistory from "history/createBrowserHistory";
-
-// ==============================================================================
-// создание promiseReducer
-function promiseReducer(state = {}, { type, status, payload, error, nameOfPromise }) {
-    if (type === 'PROMISE') {
-        return {
-            ...state,
-            [nameOfPromise]: { status, payload, error }
-        }
-    }
-    return state
-}
-
-// акшоны для promiseReducer
-const actionPending = nameOfPromise => ({ nameOfPromise, type: 'PROMISE', status: 'PENDING' })
-const actionFulfilled = (nameOfPromise, payload) => ({ nameOfPromise, type: 'PROMISE', status: 'FULFILLED', payload })
-const actionRejected = (nameOfPromise, error) => ({ nameOfPromise, type: 'PROMISE', status: 'REJECTED', error })
-const actionPromise = (nameOfPromise, promise) =>
-    async dispatch => {
-        dispatch(actionPending(nameOfPromise)) //сигнализируем redux, что промис начался
-        try {
-            const payload = await promise //ожидаем промиса
-            dispatch(actionFulfilled(nameOfPromise, payload)) //сигнализируем redux, что промис успешно выполнен
-            return payload //в месте запуска store.dispatch с этим thunk можно так же получить результат промиса
-        }
-        catch (error) {
-            dispatch(actionRejected(nameOfPromise, error)) //в случае ошибки - сигнализируем redux, что промис несложился
-        }
-    }
-
-// =============================================================
-// функция getGql
-function getGql(endpoint) {
-    return async function gql(query, variables = {}) {
+import { CreatePost } from './components/create_post';
+import Header from './components/header';
 
-        let headers = {
-            'Content-Type': 'application/json;charset=utf-8',
-            'Accept': 'application/json',
-        }
-        if (('authToken' in localStorage)) {
-            headers.Authorization = 'Bearer ' + localStorage.authToken
-        }
-
-        let result = await fetch(endpoint, {
-            method: 'POST',
-            headers,
-            body: JSON.stringify({
-                query,
-                variables
-            })
-        }).then(res => res.json())
-
-        if (('errors' in result) && !('data' in result)) {
-            throw new Error(JSON.stringify(result.errors))
-        }
-
-        result = Object.values(result.data)[0]
-
-        return result
-    }
-}
-
-const gql = getGql('http://hipstagram.node.ed.asmer.org.ua/graphql')
-
-// запрос на все посты (для ленты общей)
-const actionfindPosts = () => actionPromise('PostsFind', gql(`query AllPostsFind ($allPosts: String){
-  PostFind(query: $allPosts){
-    _id createdAt title text likesCount
-    images {
-      url
-    }
-    owner {
-      _id login nick
-    }
-    
-  }
-}`, {
-    allPosts: JSON.stringify([{}])
-}))
-
-// запрос на конкретный пост
-export const actionFindPostOne = _id => actionPromise('PostFindOne', gql(`query OnePostFind ($postOne: String){
-  PostFindOne (query: $postOne) {
-    _id createdAt title text likesCount
-    images {
-      url
-    }
-    comments {
-      _id createdAt text answers {
-        _id createdAt text likes {
-          _id
-        }
-        likesCount owner {
-          _id login nick  avatar {
-            _id url
-          }
-        }
-      }
-      likesCount
-    }
-    owner {
-      _id login nick
-    }
-    
-  }
-}`, {
-    postOne: JSON.stringify([{ _id }])
-}))
-
-// запрос на конкретного юзера
-// const actionFindUserOne = _id => actionPromise('UserFindOne', gql(`query OneUserFind ($userOne: String) {
-//   UserFindOne(query: $userOne) {
-//     _id createdAt login nick 
-//     avatar {
-//       _id url
-//     } 
-//      followers {
-//       _id login nick avatar {_id url}
-//     }
-//     following {
-//        _id login nick avatar {_id url}
-//     }
-//   }
-// }`, {
-//     userOne: JSON.stringify([{ _id }])
-// }))
-
-const store = createStore(promiseReducer, applyMiddleware(thunk))
-store.subscribe(() => console.log(store.getState()))
-
-store.dispatch(actionfindPosts())
-// store.dispatch(actionCategoryFind())
-// store.dispatch(actionFindUserOne())
+// url проекта
+export const url = 'http://hipstagram.node.ed.asmer.org.ua/graphql'
 
 
 const history = createHistory()
@@ -163,8 +33,6 @@ const Registration = () =>
         Регистрация
     </div>
 
-
-
 const PageAbout = () =>
     <div>
         Страница "О нас"
@@ -176,63 +44,18 @@ const Page404 = () =>
     </div>
 
 
-
-
-
-
-
-
-
-// ==================================================
-// страница одного поста
-// const CComments = connect(state => ({ post: state?.PostFindOne?.payload }), { loadPost: actionFindPostOne })(Comments)
-
-
-// function Comments({ post = {}, loadPost }) {
-
-//     const { postId } = useParams() // отслеживаем изменения в урле
-//     // const post2 = useSelector(state => state?.CategoryGoodsAndSubCategoryGoods?.payload)
-//     console.log(66, postId)
-
-//     useEffect(() => { loadPost(postId) }, [postId]) // перезапускаем loadPost, если произошло изменение в урле
-
-//     // console.log(post)
-
-//     return (
-//         <div>
-//             {/* <div>{user} and {postId}</div> */}
-//             тут будут отображаться все комментарии под постом
-//             <h2>{post.createdAt}</h2>
-//         </div>
-//     )
-// }
-
-
-
-
-
-
-
-
-
-// ==================================================
-// страница юзера
-// const CUser = connect(state => ({ user: state?.UserFindOne?.payload }), { loadUser: actionFindUserOne })(User)
-
-// ====================================================
-
 function App() {
     return (
         <Provider store={store}>
             <Router history={history}>
                 <div className="wrapper" style={{ display: 'flex', minHeight: '100hv' }}>
 
-                    <AsideMenu />
+                    {/* <AsideMenu /> */}
                     <section style={{ width: '50%', margin: '0 auto', minHeight: '100hv', display: 'flex', flexDirection: 'column' }}>
-                        <header style={{ backgroundColor: '#dbffe7' }}>
-                            Тут будут какие-то заголовки или что-то вроде этого
-                        </header>
-                        <main style={{ backgroundColor: '#dcdbff', flex: '1 1 auto' }}>
+                        {/* <main style={{ backgroundColor: '#dcdbff', flex: '1 1 auto' }}> */}
+                        <main>
+                            <Header />
+
                             {/* прописывание редиректа */}
                             {/* <Redirect from='/direct' to='/profile' /> */}
 

js/Project/project/src/components/pages/create_post/index.js → js/Project/project/src/components/create_post/index.js


+ 3 - 5
js/Project/project/src/components/feed/card.js

@@ -10,16 +10,14 @@ import MoreVertIcon from '@mui/icons-material/MoreVert';
 import FavoriteBorderRoundedIcon from '@mui/icons-material/FavoriteBorderRounded';
 import SendIcon from '@mui/icons-material/Send';
 import ChatBubbleOutlineIcon from '@mui/icons-material/ChatBubbleOutline';
-import { Link } from 'react-router-dom';
 import TurnedInNotIcon from '@mui/icons-material/TurnedInNot';
 import Grid from '@mui/material/Unstable_Grid2';
-import { MyCarousel } from './carousel';
 import Box from '@mui/material/Box';
+import { Link } from 'react-router-dom';
 
-// урл бека
-const url = 'http://hipstagram.node.ed.asmer.org.ua/'
-
+import { MyCarousel } from './carousel';
 
+import { url } from '../../App';
 
 export function RecipeReviewCard({ postData }) {
     // формируем дату поста

+ 1 - 1
js/Project/project/src/components/feed/carousel.js

@@ -41,7 +41,7 @@ function Item(props) {
             alignItems: 'center'
         }}>
             <img src={props.item.url} style={{
-                width: '100%',
+                width: '100%'
             }} />
         </div>
     )

+ 10 - 3
js/Project/project/src/components/feed/index.js

@@ -1,13 +1,18 @@
 import * as React from 'react';
+import { connect } from 'react-redux';
+import { store } from '../redux';
+// import { store } from './components/redux/index';   // почему не этот?
+import { url } from '../../App';
+
 import Box from '@mui/material/Box';
 import Stack from '@mui/material/Stack';
 import Paper from '@mui/material/Paper';
 import { styled } from '@mui/material/styles';
-import { connect } from 'react-redux';
+
+import { actionfindPosts } from '../redux/action';
+
 import { RecipeReviewCard as Card } from './card';
 
-// урл бека
-const url = 'http://hipstagram.node.ed.asmer.org.ua/'
 
 // сам item для поста
 const Item = styled(Paper)(({ theme }) => ({
@@ -30,4 +35,6 @@ function Feed({ posts = [] }) {
     )
 }
 
+store.dispatch(actionfindPosts())
+
 export const ReduxFeed = connect(state => ({ posts: state.PostsFind.payload }))(Feed)

+ 94 - 0
js/Project/project/src/components/header/index.js

@@ -0,0 +1,94 @@
+import React, { useState } from 'react';
+import AppBar from '@mui/material/AppBar';
+import Box from '@mui/material/Box';
+import Toolbar from '@mui/material/Toolbar';
+import IconButton from '@mui/material/IconButton';
+import Typography from '@mui/material/Typography';
+import Menu from '@mui/material/Menu';
+import Container from '@mui/material/Container';
+import Avatar from '@mui/material/Avatar';
+import Tooltip from '@mui/material/Tooltip';
+import MenuItem from '@mui/material/MenuItem';
+import InstagramIcon from '@mui/icons-material/Instagram';
+
+const settings = ['Профиль', 'Выйти'];
+
+function ResponsiveAppBar() {
+    const [anchorElUser, setAnchorElUser] = useState(null);
+
+    const handleOpenUserMenu = (event) => {
+        setAnchorElUser(event.currentTarget);
+    };
+
+    const handleCloseUserMenu = () => {
+        setAnchorElUser(null);
+    };
+
+    const consolling = () => {
+        console.log('click')
+        // < Redirect to = '/' />
+    }
+
+    return (
+        <AppBar position="sticky" top='0' color='inherit'>
+            <Container maxWidth="xl">
+                <Toolbar disableGutters>
+
+                    <InstagramIcon sx={{ display: { xs: 'flex' }, mr: 1 }} />
+
+                    <Typography
+                        variant="h6"
+                        noWrap
+                        component="a"
+                        href="/"
+                        sx={{
+                            mr: 2,
+                            display: { xs: 'none', md: 'flex' },
+                            fontFamily: 'monospace',
+                            fontWeight: 700,
+                            letterSpacing: '.3rem',
+                            color: 'inherit',
+                            textDecoration: 'none',
+                        }}
+                    >
+                        Hipstagram
+                    </Typography>
+
+                    <Box sx={{ flexGrow: 1, display: { xs: 'none', md: 'flex' } }} />
+
+                    <Box sx={{ flexGrow: 0 }}>
+                        <Tooltip title="Настройки">
+                            <IconButton onClick={handleOpenUserMenu} sx={{ p: 0 }}>
+                                <Avatar alt="Remy Sharp" src="/static/images/avatar/2.jpg" />
+                            </IconButton>
+                        </Tooltip>
+                        <Menu
+                            sx={{ mt: '45px' }}
+                            id="menu-appbar"
+                            anchorEl={anchorElUser}
+                            anchorOrigin={{
+                                vertical: 'top',
+                                horizontal: 'right',
+                            }}
+                            keepMounted
+                            transformOrigin={{
+                                vertical: 'top',
+                                horizontal: 'right',
+                            }}
+                            open={Boolean(anchorElUser)}
+                            onClose={handleCloseUserMenu}
+                        >
+                            {settings.map((setting) => (
+                                // <MenuItem key={setting} onClick={handleCloseUserMenu}>
+                                <MenuItem key={setting} onClick={handleCloseUserMenu}>
+                                    <Typography textAlign="center">{setting}</Typography>
+                                </MenuItem>
+                            ))}
+                        </Menu>
+                    </Box>
+                </Toolbar>
+            </Container>
+        </AppBar>
+    );
+}
+export default ResponsiveAppBar;

+ 33 - 5
js/Project/project/src/components/pages/structure/aside_menu.js

@@ -1,16 +1,44 @@
 import { Link } from "react-router-dom"
 
+import Avatar from '@mui/material/Avatar';
+import Stack from '@mui/material/Stack';
+import Badge from '@mui/material/Badge';
+import MailIcon from '@mui/icons-material/Mail';
+import AddAPhotoRoundedIcon from '@mui/icons-material/AddAPhotoRounded';
+
+
+// компонент входящего письма. в пропсах указать количмество писем
+function IncomingMail() {
+    return (
+        <Stack direction="row" spacing={2}>
+            <Badge badgeContent={4} color="secondary">
+                <MailIcon color="action" />
+            </Badge>
+            <Link to="/direct">Директ</Link>
+        </Stack>
+    )
+}
+
 const AsideMenu = () =>
     <aside style={{ width: '15%', minHeight: '100vh', backgroundColor: '#ffdbdb' }}>
-        <Link to="/">Главная(она же Лента)</Link>
-        <br />
-        <Link to="/direct">Директ</Link>
-        <br />
-        <Link to="/about">О нас</Link>
+        <Stack direction="row" spacing={2}>
+            <Avatar sx={{ width: 25, height: 25 }} />
+            <Link to="/user/63f8d0c273ca650acb9353f3" >Ваш профиль</Link>
+        </Stack>
+
+        <IncomingMail />
+
+        <Stack direction="row" spacing={2}>
+            <AddAPhotoRoundedIcon />
+            <Link to="/user/63f8d0c273ca650acb9353f3" >Ваш профиль</Link>
+        </Stack>
+
         <br />
         <Link to="/registration">Регистрация</Link>
         <br />
         <Link to="/autorization">Авторизация</Link>
     </aside>
 
+
+
 export default AsideMenu

+ 2 - 8
js/Project/project/src/components/post/index.js

@@ -7,14 +7,11 @@ import { actionFindPostOne } from '../redux/action';
 
 function Comments({ post = {}, loadPost }) {
 
-    const { postId } = useParams() // отслеживаем изменения в урле
     // const post2 = useSelector(state => state?.CategoryGoodsAndSubCategoryGoods?.payload)
-
+    const { postId } = useParams() // отслеживаем изменения в урле
     useEffect(() => { loadPost(postId) }, [postId]) // перезапускаем loadPost, если произошло изменение в урле
 
-    console.log('postID: ', { postId })
-
-
+    // console.log('postID: ', { postId })
 
     return (
         <div>
@@ -27,7 +24,4 @@ function Comments({ post = {}, loadPost }) {
 }
 
 
-// store.dispatch(actionFindPostOne())
-
-
 export const CComments = connect(state => ({ post: state?.PostFindOne?.payload }), { loadPost: actionFindPostOne })(Comments)

+ 48 - 41
js/Project/project/src/components/redux/action.js

@@ -1,33 +1,5 @@
-// ==============================================================================
-// создание promiseReducer
-function promiseReducer(state = {}, { type, status, payload, error, nameOfPromise }) {
-  if (type === 'PROMISE') {
-    return {
-      ...state,
-      [nameOfPromise]: { status, payload, error }
-    }
-  }
-  return state
-}
-
-// акшоны для promiseReducer
-const actionPending = nameOfPromise => ({ nameOfPromise, type: 'PROMISE', status: 'PENDING' })
-const actionFulfilled = (nameOfPromise, payload) => ({ nameOfPromise, type: 'PROMISE', status: 'FULFILLED', payload })
-const actionRejected = (nameOfPromise, error) => ({ nameOfPromise, type: 'PROMISE', status: 'REJECTED', error })
-const actionPromise = (nameOfPromise, promise) =>
-  async dispatch => {
-    dispatch(actionPending(nameOfPromise)) //сигнализируем redux, что промис начался
-    try {
-      const payload = await promise //ожидаем промиса
-      dispatch(actionFulfilled(nameOfPromise, payload)) //сигнализируем redux, что промис успешно выполнен
-      return payload //в месте запуска store.dispatch с этим thunk можно так же получить результат промиса
-    }
-    catch (error) {
-      dispatch(actionRejected(nameOfPromise, error)) //в случае ошибки - сигнализируем redux, что промис несложился
-    }
-  }
+import { url } from "../../App"
 
-// =============================================================
 // функция getGql
 function getGql(endpoint) {
   return async function gql(query, variables = {}) {
@@ -61,6 +33,24 @@ function getGql(endpoint) {
 
 const gql = getGql('http://hipstagram.node.ed.asmer.org.ua/graphql')
 
+// акшоны для promiseReducer
+export const actionPending = nameOfPromise => ({ nameOfPromise, type: 'PROMISE', status: 'PENDING' })
+export const actionFulfilled = (nameOfPromise, payload) => ({ nameOfPromise, type: 'PROMISE', status: 'FULFILLED', payload })
+export const actionRejected = (nameOfPromise, error) => ({ nameOfPromise, type: 'PROMISE', status: 'REJECTED', error })
+export const actionPromise = (nameOfPromise, promise) =>
+  async dispatch => {
+    dispatch(actionPending(nameOfPromise)) //сигнализируем redux, что промис начался
+    try {
+      const payload = await promise //ожидаем промиса
+      dispatch(actionFulfilled(nameOfPromise, payload)) //сигнализируем redux, что промис успешно выполнен
+      return payload //в месте запуска store.dispatch с этим thunk можно так же получить результат промиса
+    }
+    catch (error) {
+      dispatch(actionRejected(nameOfPromise, error)) //в случае ошибки - сигнализируем redux, что промис несложился
+    }
+  }
+
+// =============================================================
 // запрос на поиск конкретного поста
 export const actionFindPostOne = _id => actionPromise('PostFindOne', gql(`query OnePostFind ($postOne: String){
   PostFindOne (query: $postOne) {
@@ -90,21 +80,38 @@ export const actionFindPostOne = _id => actionPromise('PostFindOne', gql(`query
   postOne: JSON.stringify([{ _id }])
 }))
 
+
 // запрос на поиск конкретного поста
 export const actionFindUserOne = _id => actionPromise('UserFindOne', gql(`query OneUserFind ($userOne: String) {
-  UserFindOne(query: $userOne) {
-    _id createdAt login nick 
-    avatar {
-      _id url
-    } 
-     followers {
-      _id login nick avatar {_id url}
-    }
-    following {
-       _id login nick avatar {_id url}
+    UserFindOne(query: $userOne) {
+      _id createdAt login nick 
+      avatar {
+        _id url
+      } 
+       followers {
+        _id login nick avatar {_id url}
+      }
+      following {
+         _id login nick avatar {_id url}
+      }
     }
-  }
-}`, {
+  }`, {
   userOne: JSON.stringify([{ _id }])
 }))
 
+
+// запрос на поиск всех постов
+export const actionfindPosts = () => actionPromise('PostsFind', gql(`query AllPostsFind ($allPosts: String){
+  PostFind(query: $allPosts){
+    _id createdAt title text likesCount
+    images {
+      url
+    }
+    owner {
+      _id login nick
+    }
+    
+  }
+}`, {
+  allPosts: JSON.stringify([{}])
+}))

+ 19 - 0
js/Project/project/src/components/redux/index.js

@@ -0,0 +1,19 @@
+import { createStore, combineRedusers, applyMiddleware } from 'redux';
+import thunk from "redux-thunk";
+
+import { promiseReducer, localStoredReducer } from "./redusers";
+
+import { actionPending, actionFulfilled, actionRejected, actionPromise } from "./action";
+
+// объект со всеми редьюсерами
+const reducers = {
+    promise: localStoredReducer(promiseReducer, 'promise'),
+    // auth: localStoredReducer(authReducer, 'auth'),
+    // cart: localStoredReducer(cartReducer, 'cart'),
+}
+
+// const totalReducer = combineRedusers(reducers)
+
+// создаем store для редьюсера
+export const store = createStore(promiseReducer, applyMiddleware(thunk))
+store.subscribe(() => console.log(store.getState()))

+ 32 - 0
js/Project/project/src/components/redux/redusers.js

@@ -0,0 +1,32 @@
+// promiseReducer
+export function promiseReducer(state = {}, { type, status, payload, error, nameOfPromise }) {
+    if (type === 'PROMISE') {
+        return {
+            ...state,
+            [nameOfPromise]: { status, payload, error }
+        }
+    }
+    return state
+}
+
+// localStoredReducer
+export function localStoredReducer(originalReducer, localStorageKey) {
+    function wrapper(state, action) {
+        if (!state) {
+            try {
+                return JSON.parse(localStorage[localStorageKey])
+            }
+            catch (error) {
+
+            }
+        }
+        const newState = originalReducer(state, action)
+        localStorage[localStorageKey] = JSON.stringify(newState)
+
+        return newState
+    }
+
+    return wrapper
+}
+
+

+ 5 - 4
js/Project/project/src/components/user/avatar.js

@@ -1,15 +1,16 @@
 import * as React from 'react';
 import Avatar from '@mui/material/Avatar';
 import Stack from '@mui/material/Stack';
+import { url } from '../../App';
 
 export default function ImageAvatars({ userData }) {
-    console.log('UserData: ', userData)
-    console.log('SRC: ', userData.avatar?.url)
-    const url = `http://hipstagram.node.ed.asmer.org.ua/${userData.avatar?.url}`
+    // console.log('UserData: ', userData)
+    // console.log('SRC: ', userData.avatar?.url)
+    const urlAvatar = url.slice(0, -7) + userData.avatar?.url
 
     return (
         <Stack direction="row" spacing={1}>
-            <Avatar alt={userData.login} src={url} sx={{ width: 100, height: 100 }} />
+            <Avatar alt={userData.login} src={urlAvatar} sx={{ width: 100, height: 100 }} />
 
         </Stack>
     );

+ 10 - 16
js/Project/project/src/components/user/index.js

@@ -1,41 +1,35 @@
 import * as React from 'react';
-import CssBaseline from '@mui/material/CssBaseline';
+import { useEffect } from 'react';
+import { useParams } from 'react-router-dom';
+import { connect } from 'react-redux';
+
 import Box from '@mui/material/Box';
 import Container from '@mui/material/Container';
 import StandardImageList from './gallery';
 import Divider from '@mui/material/Divider';
 import Grid from '@mui/material/Unstable_Grid2';
-import ImageAvatars from './avatar';
 import BasicCard from './user_data';
 import AddAPhotoRoundedIcon from '@mui/icons-material/AddAPhotoRounded';
-// import Stack from '@mui/material/Stack';
 import Button from '@mui/material/Button';
-// import Container from '@mui/material/Container';
 import { Link } from 'react-router-dom';
+import ImageAvatars from './avatar';
 
-
-
-
-import { useEffect, useState } from 'react';
-import { useParams } from 'react-router-dom';
-import { connect } from 'react-redux';
-
+// import { actionFindUserOne } from '../redux/action';
+// import { actionFindUserOne } from '../requests/userFindOne';
 import { actionFindUserOne } from '../redux/action';
 
-console.log('action: ', actionFindUserOne)
+// console.log('action: ', actionFindUserOne)
 
 function User({ user = {}, loadUser }) {
 
     const { userId } = useParams()
-
     useEffect(() => { loadUser(userId) }, [userId])
 
-    console.log('userID: ', { userId })
-    console.log('user: ', user)
+    // console.log('userID: ', { userId })
+    // console.log('user: ', user)
 
     return (
         <React.Fragment>
-            {/* <CssBaseline /> */}
             <Container sx={{ minHeight: '100vh' }} maxWidth="100%" >
                 <Box sx={{ margin: "30px 10px" }}>
                     <Grid container spacing={2}>

+ 7 - 7
js/Project/project/src/components/user/user_data.js

@@ -1,15 +1,15 @@
 import * as React from 'react';
-import Box from '@mui/material/Box';
+// import Box from '@mui/material/Box';
 import CardContent from '@mui/material/CardContent';
 import Typography from '@mui/material/Typography';
 
 import Button from '@mui/material/Button';
-import DeleteIcon from '@mui/icons-material/Delete';
-import SendIcon from '@mui/icons-material/Send';
+// import DeleteIcon from '@mui/icons-material/Delete';
+// import SendIcon from '@mui/icons-material/Send';
 import Stack from '@mui/material/Stack';
-
 import ManageAccountsOutlinedIcon from '@mui/icons-material/ManageAccountsOutlined';
 
+// кнопка редактирования профиля
 function UptadeProfile() {
     return (
         // < Stack direction="row" spacing={2} >
@@ -18,8 +18,8 @@ function UptadeProfile() {
     )
 }
 
+// блок пользовательских данных
 export default function BasicCard({ userData }) {
-
     return (
         <CardContent sx={{ width: '100%', paddingTop: 0 }}>
             <Stack direction="row" spacing={5}>
@@ -33,7 +33,7 @@ export default function BasicCard({ userData }) {
                     NaN Публикаций
                 </Typography>
                 <Typography color="text.secondary">
-                    {userData.followers?.length} подписчиков
+                    {userData.followers?.length || '0'} подписчиков
                 </Typography>
                 <Typography color="text.secondary">
                     {userData.following?.length || '0'} подписок
@@ -43,5 +43,5 @@ export default function BasicCard({ userData }) {
                 {userData.nick || ''}
             </Typography>
         </CardContent>
-    );
+    )
 }