Browse Source

created settingsPage / imageUploader

yankevych0210 1 year ago
parent
commit
bb3323199b
55 changed files with 485 additions and 187 deletions
  1. 9 7
      src/App.js
  2. BIN
      src/assets/img/initialUserImage.jpeg
  3. 2 2
      src/components/common/Console/Console.jsx
  4. 1 2
      src/components/common/Console/Console.module.scss
  5. 0 0
      src/components/ConsoleItem/ConsoleItem.jsx
  6. 8 0
      src/components/ConsoleItem/ConsoleItem.module.scss
  7. 10 10
      src/components/pages/YourWorksPage/CreateWorkPopup/CreateWorkPopup.jsx
  8. 1 1
      src/components/pages/YourWorksPage/CreateWorkPopup/CreateWorkPopup.module.scss
  9. 6 6
      src/components/common/Editor/Editor.jsx
  10. 0 0
      src/components/Editor/Editor.module.scss
  11. 0 0
      src/components/Editor/themes/twilight.css
  12. 6 6
      src/components/common/Editors/Editors.jsx
  13. 0 0
      src/components/Editors/Editors.module.scss
  14. 2 2
      src/components/common/Footer/Footer.jsx
  15. 0 0
      src/components/Footer/Footer.module.scss
  16. 52 0
      src/components/Header/Header.jsx
  17. 16 3
      src/components/common/Header/Header.module.scss
  18. 4 4
      src/components/common/HeaderPen/HeaderPen.jsx
  19. 1 1
      src/components/common/HeaderPen/HeaderPen.module.scss
  20. 17 0
      src/components/ImageUploader/ImageUploader.jsx
  21. 42 0
      src/components/ImageUploader/ImageUploader.module.scss
  22. 0 0
      src/components/Input/Input.jsx
  23. 1 1
      src/components/common/Input/Input.module.scss
  24. 0 0
      src/components/Preview/Preview.jsx
  25. 0 0
      src/components/Preview/Preview.module.scss
  26. 26 0
      src/components/UserPopup/UserPopup.jsx
  27. 50 0
      src/components/UserPopup/UserPopup.module.scss
  28. 6 6
      src/components/common/WorkCard/WorkCard.jsx
  29. 4 1
      src/components/common/WorkCard/WorkCard.module.scss
  30. 4 4
      src/components/common/WorkCard/WorkCardPopup/WorkCardPopup.jsx
  31. 1 1
      src/components/common/WorkCard/WorkCardPopup/WorkCardPopup.module.scss
  32. 0 0
      src/components/Works/Works.jsx
  33. 1 1
      src/components/common/Works/Works.module.scss
  34. 0 7
      src/components/common/ConsoleItem/ConsoleItem.module.scss
  35. 0 40
      src/components/common/Header/Header.jsx
  36. 0 0
      src/pages/ErrorPage/ErrorPage.jsx
  37. 1 1
      src/components/pages/ErrorPage/ErrorPage.module.scss
  38. 13 13
      src/components/pages/HomePage/HomePage.jsx
  39. 1 1
      src/components/pages/HomePage/HomePage.module.scss
  40. 0 0
      src/pages/LoadingPage/LoadingPage.jsx
  41. 1 1
      src/components/pages/LoadingPage/LoadingPage.module.scss
  42. 17 17
      src/components/pages/LoginPage/LoginPage.jsx
  43. 1 1
      src/components/pages/LoginPage/LoginPage.module.scss
  44. 6 6
      src/components/pages/PenPage/PenPage.jsx
  45. 1 1
      src/components/pages/PenPage/PenPage.module.scss
  46. 22 0
      src/pages/SettingsPage/SettingsPage.jsx
  47. 33 0
      src/pages/SettingsPage/SettingsPage.module.scss
  48. 16 16
      src/components/pages/SignUpPage/SignUpPage.jsx
  49. 1 1
      src/components/pages/SignUpPage/SignUpPage.module.scss
  50. 8 8
      src/components/pages/YourWorksPage/YourWorksPage.jsx
  51. 2 2
      src/components/pages/YourWorksPage/YourWorksPage.module.scss
  52. 10 8
      src/store/auth/actions/loginAction.js
  53. 8 6
      src/store/store.js
  54. 41 0
      src/store/user/actions/fetchUser.js
  55. 33 0
      src/store/user/userSlice.js

+ 9 - 7
src/App.js

@@ -1,10 +1,11 @@
 import { Routes, Route } from 'react-router-dom';
-import { LoginPage } from './components/pages/LoginPage/LoginPage';
-import { ErrorPage } from './components/pages/ErrorPage/ErrorPage';
-import { HomePage } from './components/pages/HomePage/HomePage';
-import { PenPage } from './components/pages/PenPage/PenPage';
-import { SignUpPage } from './components/pages/SignUpPage/SignUpPage';
-import { YourWorks } from './components/pages/YourWorksPage/YourWorksPage';
+import { ErrorPage } from './pages/ErrorPage/ErrorPage';
+import { HomePage } from './pages/HomePage/HomePage';
+import { PenPage } from './pages/PenPage/PenPage';
+import { YourWorksPage } from './pages/YourWorksPage/YourWorksPage';
+import { LoginPage } from './pages/LoginPage/LoginPage';
+import { SignUpPage } from './pages/SignUpPage/SignUpPage';
+import { SettingsPage } from './pages/SettingsPage/SettingsPage';
 
 //  TODO:
 //  1. icons
@@ -23,7 +24,8 @@ function App() {
       <Route path="/pen" element={<PenPage />} />
       <Route path="/login" element={<LoginPage />} />
       <Route path="/signup" element={<SignUpPage />} />
-      <Route path="/your-works" element={<YourWorks />} />
+      <Route path="/settings" element={<SettingsPage />} />
+      <Route path="/your-works" element={<YourWorksPage />} />
       <Route path="/your-works/:id" element={<PenPage />} />
       <Route path="*" element={<ErrorPage />} />
     </Routes>

BIN
src/assets/img/initialUserImage.jpeg


+ 2 - 2
src/components/common/Console/Console.jsx

@@ -1,5 +1,5 @@
 import style from './Console.module.scss';
-import { useConsole } from '../../../hooks/useConsole';
+import { useConsole } from '../../hooks/useConsole';
 import { useEffect } from 'react';
 import { useSelector } from 'react-redux';
 import ConsoleItem from '../ConsoleItem/ConsoleItem';
@@ -11,7 +11,7 @@ export function Console({ isOpen, close }) {
   useEffect(() => {
     const timeout = setTimeout(() => {
       appConsole.readCode(files.js.text);
-    }, 800);
+    }, 700);
 
     return () => {
       clearTimeout(timeout);

+ 1 - 2
src/components/common/Console/Console.module.scss

@@ -1,4 +1,4 @@
-@import '../../../scss/index.scss';
+@import '../../scss/index.scss';
 
 .console {
   display: flex;
@@ -43,7 +43,6 @@
   input {
     color: white;
     height: auto;
-    width: 100%;
     padding: 7px;
     font-size: 15px;
     background-color: #343539;

src/components/common/ConsoleItem/ConsoleItem.jsx → src/components/ConsoleItem/ConsoleItem.jsx


+ 8 - 0
src/components/ConsoleItem/ConsoleItem.module.scss

@@ -0,0 +1,8 @@
+@import '../../scss/index.scss';
+
+.consoleItem {
+    padding: 10px 10px 5px;
+    border-bottom: 1px solid #5A5F73;
+    font-size: 17px;
+    font-weight: 500;
+}

+ 10 - 10
src/components/pages/YourWorksPage/CreateWorkPopup/CreateWorkPopup.jsx

@@ -1,13 +1,13 @@
-import { useDispatch, useSelector } from "react-redux";
-import { useInput } from "../../../../hooks/useInput";
-import { createWork } from "../../../../store/works/actions/createWork";
-import { Input } from "../../../common/Input/Input";
-import style from "./CreateWorkPopup.module.scss";
+import { useDispatch, useSelector } from 'react-redux';
+import { useInput } from '../../hooks/useInput';
+import { createWork } from '../../store/works/actions/createWork';
+import { Input } from '../Input/Input';
+import style from './CreateWorkPopup.module.scss';
 
 export const CreateWorkPopup = ({ popupRef, close }) => {
   const dispatch = useDispatch();
-  const title = useInput("");
-  const description = useInput("");
+  const title = useInput('');
+  const description = useInput('');
   const { error } = useSelector((state) => state.works);
 
   const handleCreateWork = (e) => {
@@ -25,13 +25,13 @@ export const CreateWorkPopup = ({ popupRef, close }) => {
         <button onClick={close}>✕</button>
       </header>
       <form onSubmit={handleCreateWork} className={style.container}>
-        <Input title={"Title"} value={title.value} onChange={title.onChange} />
+        <Input title={'Title'} value={title.value} onChange={title.onChange} />
         <Input
           value={description.value}
           onChange={description.onChange}
-          title={"Description"}
+          title={'Description'}
         />
-        <button type={"submit"} className={style.save}>
+        <button type={'submit'} className={style.save}>
           Create
         </button>
       </form>

+ 1 - 1
src/components/pages/YourWorksPage/CreateWorkPopup/CreateWorkPopup.module.scss

@@ -1,4 +1,4 @@
-@import "../../../../scss/index.scss";
+@import "../../scss/index.scss";
 
 .CreateWorkPopup {
   width: 760px;

+ 6 - 6
src/components/common/Editor/Editor.jsx

@@ -7,13 +7,13 @@ import { Controlled as ControlledEditor } from 'react-codemirror2';
 import { useDispatch, useSelector } from 'react-redux';
 import style from './Editor.module.scss';
 import './themes/twilight.css';
-import { ReactComponent as HtmlLogo } from '../../../assets/img/htmlLogo.svg';
-import { ReactComponent as CssLogo } from '../../../assets/img/cssLogo.svg';
-import { ReactComponent as JsLogo } from '../../../assets/img/jsLogo.svg';
+import { ReactComponent as HtmlLogo } from '../../assets/img/htmlLogo.svg';
+import { ReactComponent as CssLogo } from '../../assets/img/cssLogo.svg';
+import { ReactComponent as JsLogo } from '../../assets/img/jsLogo.svg';
 import { Section } from 'react-simple-resizer';
-import { saveFiles } from '../../../store/currentWork/actions/saveFiles';
-import { setFormatCode } from '../../../store/currentWork/currentWorkSlice';
-import { askToLogin } from '../../../utils/askToLogin.js';
+import { saveFiles } from '../../store/currentWork/actions/saveFiles';
+import { setFormatCode } from '../../store/currentWork/currentWorkSlice';
+import { askToLogin } from '../../utils/askToLogin.js';
 import { useNavigate } from 'react-router-dom';
 
 const logos = {

src/components/common/Editor/Editor.module.scss → src/components/Editor/Editor.module.scss


src/components/common/Editor/themes/twilight.css → src/components/Editor/themes/twilight.css


+ 6 - 6
src/components/common/Editors/Editors.jsx

@@ -1,8 +1,8 @@
-import React from "react";
-import { Bar, Container } from "react-simple-resizer";
-import Editor from "../Editor/Editor";
-import style from "./Editors.module.scss";
-import { useSelector } from "react-redux";
+import React from 'react';
+import { Bar, Container } from 'react-simple-resizer';
+import Editor from '../Editor/Editor';
+import style from './Editors.module.scss';
+import { useSelector } from 'react-redux';
 import {
   setHtml,
   setCss,
@@ -10,7 +10,7 @@ import {
   setLocalHtml,
   setLocalCss,
   setLocalJs,
-} from "../../../store/currentWork/currentWorkSlice";
+} from '../../store/currentWork/currentWorkSlice';
 
 export const Editors = () => {
   const { isAuth } = useSelector((state) => state.auth);

src/components/common/Editors/Editors.module.scss → src/components/Editors/Editors.module.scss


+ 2 - 2
src/components/common/Footer/Footer.jsx

@@ -1,5 +1,5 @@
-import style from "./Footer.module.scss";
-import { ReactComponent as LogoSmall } from "../../../assets/img/logo.svg";
+import style from './Footer.module.scss';
+import { ReactComponent as LogoSmall } from '../../assets/img/logo.svg';
 
 export const Footer = () => {
   return (

src/components/common/Footer/Footer.module.scss → src/components/Footer/Footer.module.scss


+ 52 - 0
src/components/Header/Header.jsx

@@ -0,0 +1,52 @@
+import { NavLink } from 'react-router-dom';
+import style from './Header.module.scss';
+import { ReactComponent as LogoBig } from '../../assets/img/logoBig.svg';
+import { useDispatch, useSelector } from 'react-redux';
+import { fetchUser } from '../../store/user/actions/fetchUser';
+import { useEffect } from 'react';
+import { getUserIdFromJwt } from '../../utils/getUserIdFromJwt';
+import userInitImage from '../../assets/img/initialUserImage.jpeg';
+import { usePopup } from '../../hooks/usePopup';
+import { UserPopup } from '../UserPopup/UserPopup';
+
+export const Header = () => {
+  const dispatch = useDispatch();
+  const { isAuth } = useSelector((state) => state.auth);
+  const { avatar } = useSelector((state) => state.user);
+  const userPopup = usePopup();
+
+  useEffect(() => {
+    if (isAuth) {
+      const userId = getUserIdFromJwt(localStorage.authToken);
+      dispatch(fetchUser(userId));
+    }
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, []);
+
+  return (
+    <header className={style.header}>
+      <NavLink className={style.logoBlock} to="/">
+        <LogoBig />
+      </NavLink>
+
+      {isAuth ? (
+        <nav>
+          <img
+            src={avatar ? avatar : userInitImage}
+            onClick={userPopup.open}
+            alt="userImage"
+          />
+          <UserPopup
+            popupRef={userPopup.ref}
+            isOpen={userPopup.isPopupVisible}
+          />
+        </nav>
+      ) : (
+        <nav>
+          <NavLink to="/login">Log in</NavLink>
+          <NavLink to="/signup">Sign up</NavLink>
+        </nav>
+      )}
+    </header>
+  );
+};

+ 16 - 3
src/components/common/Header/Header.module.scss

@@ -1,18 +1,31 @@
-@import "../../../scss/index.scss";
+@import "../../scss/index.scss";
 
 .header {
   @include container();
   @include flex($justify: space-between, $align: center);
   padding: 25px 0;
+  position: relative;
+  z-index: 2;
 
   a {
     svg {
       @extend %logo;
-
-      z-index: 10 !important;
+     
     }
   }
 
+
+
+  img {
+    width: 44px;
+    height: 44px;
+    border-radius: 3px;
+    background-size: contain;
+    background-position: 50%;
+    cursor: pointer;
+  }
+
+
   nav {
     z-index: 0;
     a:first-child {

+ 4 - 4
src/components/common/HeaderPen/HeaderPen.jsx

@@ -1,11 +1,11 @@
 import React from 'react';
 import { useDispatch, useSelector } from 'react-redux';
-import { ReactComponent as Logo } from '../../../assets/img/logo.svg';
+import { ReactComponent as Logo } from '../../assets/img/logo.svg';
 import { NavLink, useNavigate } from 'react-router-dom';
-import { saveFiles } from '../../../store/currentWork/actions/saveFiles';
+import { saveFiles } from '../../store/currentWork/actions/saveFiles';
 import style from './HeaderPen.module.scss';
-import { setFormatCode } from '../../../store/currentWork/currentWorkSlice';
-import { askToLogin } from '../../../utils/askToLogin';
+import { setFormatCode } from '../../store/currentWork/currentWorkSlice';
+import { askToLogin } from '../../utils/askToLogin';
 
 export const HeaderPen = () => {
   const dispatch = useDispatch();

+ 1 - 1
src/components/common/HeaderPen/HeaderPen.module.scss

@@ -1,4 +1,4 @@
-@import "../../../scss/index.scss";
+@import "../../scss/index.scss";
 
 .header {
   @include container($width: 98vw);

+ 17 - 0
src/components/ImageUploader/ImageUploader.jsx

@@ -0,0 +1,17 @@
+import React from 'react';
+import style from './ImageUploader.module.scss';
+import initialUserImage from '../../assets/img/initialUserImage.jpeg';
+
+export const ImageUploader = () => {
+  return (
+    <div className={style.imageUploader}>
+      <img src={initialUserImage} alt="userImage" />
+      <div className={style.info}>
+        <span>Upload a New Profile Image</span>
+        <button>Choose File</button>
+        <span>Ideal dimensions are 500px x 500px.</span>
+        <span>Maximum file size is 5mb.</span>
+      </div>
+    </div>
+  );
+};

+ 42 - 0
src/components/ImageUploader/ImageUploader.module.scss

@@ -0,0 +1,42 @@
+@import '../../scss/index.scss';
+
+.imageUploader {
+    width: 65%;
+    height: 250px;
+    border-radius: 6px;
+    background-color:#1e1f26;
+    float: right;
+    padding: 30px;
+    display: flex;
+    margin-bottom: 30px;
+
+    img {
+        height: 100%;
+        border-radius: 3px;
+        margin-right: 25px;
+    }
+
+    .info {
+        display: flex;
+        flex-direction: column;
+
+        span:first-of-type {
+            font-weight: 700;
+            font-size: 18px;
+           margin: 15px 0;
+        }
+
+        button {
+            @extend %buttonGrey;
+            font-size: 16px;
+            font-weight: 600;
+            width: fit-content;
+            margin: 20px 0;
+        }
+
+        span:nth-child(3),
+        span:nth-child(4) {
+            color:#b7bbc8;
+        }
+    }
+}

src/components/common/Input/Input.jsx → src/components/Input/Input.jsx


+ 1 - 1
src/components/common/Input/Input.module.scss

@@ -1,4 +1,4 @@
-@import "../../../scss/index.scss";
+@import "../../scss/index.scss";
 
 .root {
   @include flex(column);

src/components/common/Preview/Preview.jsx → src/components/Preview/Preview.jsx


src/components/common/Preview/Preview.module.scss → src/components/Preview/Preview.module.scss


+ 26 - 0
src/components/UserPopup/UserPopup.jsx

@@ -0,0 +1,26 @@
+import { useDispatch } from 'react-redux';
+import { useNavigate } from 'react-router-dom';
+import { logout } from '../../store/auth/authSlice';
+import style from './UserPopup.module.scss';
+
+export const UserPopup = ({ isOpen, popupRef }) => {
+  const dispatch = useDispatch();
+  const navigate = useNavigate();
+
+  const handleLogout = () => {
+    localStorage.removeItem('authToken');
+    navigate('/');
+    dispatch(logout());
+  };
+
+  if (!isOpen) return null;
+  return (
+    <ul ref={popupRef} className={style.userPopup}>
+      <li onClick={() => navigate('/your-works')}>Your Works</li>
+      <li>New Pen</li>
+      <hr />
+      <li onClick={() => navigate('/settings')}>Settings</li>
+      <li onClick={handleLogout}>Log Out</li>
+    </ul>
+  );
+};

+ 50 - 0
src/components/UserPopup/UserPopup.module.scss

@@ -0,0 +1,50 @@
+@import '../../scss/index.scss';
+
+.userPopup {
+    position: absolute;
+    top: 80px;
+    right: 0;
+    width: 200px;
+    padding: 10px 0;
+    background-color: #1E1F25;   
+    border-radius: 6px 0 6px 6px;
+    z-index: 3;
+  
+
+    li,a {
+        
+        list-style: none;
+        color: #e3e4e8;
+        padding: 0.6rem 25px 0.6rem 20px;
+       font-weight: 700;
+       font-size: 17px;
+       text-decoration:none;
+      
+      
+
+       &:hover {
+        background-color: #444958;
+       }
+
+       &:last-of-type {
+        &:hover {
+            background-color: $redMain;
+        }
+       }
+    }
+
+    a {
+        display: block;
+        width:100%;
+    }
+
+    hr {
+        width: 92%;
+        height: 2px;
+        margin: 5px auto;
+        background-color: #2C3039 ;
+        border: none;
+    }
+
+   
+}

+ 6 - 6
src/components/common/WorkCard/WorkCard.jsx

@@ -1,8 +1,8 @@
-import style from "./WorkCard.module.scss";
-import { NavLink } from "react-router-dom";
-import { usePopup } from "../../../hooks/usePopup";
-import { WorkCardPopup } from "./WorkCardPopup/WorkCardPopup";
-import { Preview } from "../Preview/Preview";
+import style from './WorkCard.module.scss';
+import { NavLink } from 'react-router-dom';
+import { usePopup } from '../../hooks/usePopup';
+import { WorkCardPopup } from '../WorkCardPopup/WorkCardPopup';
+import { Preview } from '../Preview/Preview';
 
 export const WorkCard = ({ work }) => {
   const { isPopupVisible, toggle, ref: menuRef } = usePopup();
@@ -16,7 +16,7 @@ export const WorkCard = ({ work }) => {
   if (work.title === null) return null;
   return (
     <NavLink className={style.card} to={`/your-works/${work._id}`}>
-      <div style={{ pointerEvents: "none" }} className={style.preview}>
+      <div style={{ pointerEvents: 'none' }} className={style.preview}>
         <Preview
           html={html.text}
           css={`

+ 4 - 1
src/components/common/WorkCard/WorkCard.module.scss

@@ -1,4 +1,4 @@
-@import "../../../scss/index.scss";
+@import "../../scss/index.scss";
 
 .card {
   position: relative;
@@ -11,14 +11,17 @@
   color: white;
   text-decoration: none;
   transition: all 0.2s ease;
+  z-index: 1;
 
   .preview {
+    position: relative;
     border-top-right-radius: inherit;
     border-top-left-radius: inherit;
     width: 100%;
     height: 65%;
     background: white;
     overflow: hidden;
+    z-index: 1;
   }
 
   .info {

+ 4 - 4
src/components/common/WorkCard/WorkCardPopup/WorkCardPopup.jsx

@@ -1,7 +1,7 @@
-import { useDispatch } from "react-redux";
-import { deleteWork } from "../../../../store/works/actions/deleteWork";
-import { updateWorkInfo } from "../../../../store/works/actions/updateWorkInfo";
-import style from "./WorkCardPopup.module.scss";
+import { useDispatch } from 'react-redux';
+import { deleteWork } from '../../store/works/actions/deleteWork';
+import { updateWorkInfo } from '../../store/works/actions/updateWorkInfo';
+import style from './WorkCardPopup.module.scss';
 
 export const WorkCardPopup = ({ menuRef, isVisible, work }) => {
   const dispatch = useDispatch();

+ 1 - 1
src/components/common/WorkCard/WorkCardPopup/WorkCardPopup.module.scss

@@ -1,4 +1,4 @@
-@import "../../../../scss/index.scss";
+@import "../../scss/index.scss";
 
 .menuPopup {
   position: absolute;

src/components/common/Works/Works.jsx → src/components/Works/Works.jsx


+ 1 - 1
src/components/common/Works/Works.module.scss

@@ -1,4 +1,4 @@
-@import "../../../scss/index.scss";
+@import "../../scss/index.scss";
 
 .works {
   display: grid;

+ 0 - 7
src/components/common/ConsoleItem/ConsoleItem.module.scss

@@ -1,7 +0,0 @@
-@import '../../../scss/index.scss';
-
-.consoleItem {
-  border-bottom: 1px solid #5a5f73;
-  font-size: 17px;
-  font-weight: 500;
-}

+ 0 - 40
src/components/common/Header/Header.jsx

@@ -1,40 +0,0 @@
-import { NavLink, useLocation } from "react-router-dom";
-import style from "./Header.module.scss";
-import { ReactComponent as LogoBig } from "../../../assets/img/logoBig.svg";
-import { useDispatch, useSelector } from "react-redux";
-
-export const Header = () => {
-  const dispatch = useDispatch();
-  const { isAuth } = useSelector((state) => state.auth);
-
-  const logout = () => {
-    localStorage.removeItem("authToken");
-    dispatch(logout());
-  };
-
-  return (
-    <header className={style.header}>
-      <NavLink className={style.logoBlock} to="/">
-        <LogoBig />
-      </NavLink>
-
-      {isAuth ? (
-        <nav>
-          <NavLink to="/your-works">Your works</NavLink>
-          <NavLink
-            style={{ backgroundColor: "#dc143c" }}
-            onClick={logout}
-            to="/"
-          >
-            Log out
-          </NavLink>
-        </nav>
-      ) : (
-        <nav>
-          <NavLink to="/login">Log in</NavLink>
-          <NavLink to="/signup">Sign up</NavLink>
-        </nav>
-      )}
-    </header>
-  );
-};

src/components/pages/ErrorPage/ErrorPage.jsx → src/pages/ErrorPage/ErrorPage.jsx


+ 1 - 1
src/components/pages/ErrorPage/ErrorPage.module.scss

@@ -1,4 +1,4 @@
-@import '../../../scss/index.scss';
+@import '../../scss/index.scss';
 
 .errorPage {
   position: relative;

+ 13 - 13
src/components/pages/HomePage/HomePage.jsx

@@ -1,16 +1,16 @@
-import { Link } from "react-router-dom";
-import { Header } from "../../common/Header/Header";
-import { Footer } from "../../common/Footer/Footer";
-import style from "./HomePage.module.scss";
+import { Link } from 'react-router-dom';
+import { Header } from '../../components/Header/Header';
+import { Footer } from '../../components/Footer/Footer';
+import style from './HomePage.module.scss';
 
-import { ReactComponent as HomeLine } from "../../../assets/img/homeline.svg";
-import { ReactComponent as MainSvg } from "../../../assets/img/home.svg";
-import { ReactComponent as LogoBig } from "../../../assets/img/logo.svg";
-import { ReactComponent as HomeLineTwo } from "../../../assets/img/linehometwo.svg";
-import { ReactComponent as Icon1 } from "../../../assets/img/icon1.svg";
-import { ReactComponent as Icon2 } from "../../../assets/img/icon2.svg";
-import { ReactComponent as Icon3 } from "../../../assets/img/icon3.svg";
-import { useSelector } from "react-redux";
+import { ReactComponent as HomeLine } from '../../assets/img/homeline.svg';
+import { ReactComponent as MainSvg } from '../../assets/img/home.svg';
+import { ReactComponent as LogoBig } from '../../assets/img/logo.svg';
+import { ReactComponent as HomeLineTwo } from '../../assets/img/linehometwo.svg';
+import { ReactComponent as Icon1 } from '../../assets/img/icon1.svg';
+import { ReactComponent as Icon2 } from '../../assets/img/icon2.svg';
+import { ReactComponent as Icon3 } from '../../assets/img/icon3.svg';
+import { useSelector } from 'react-redux';
 
 export const HomePage = () => {
   const { isAuth } = useSelector((state) => state.auth);
@@ -30,7 +30,7 @@ export const HomePage = () => {
             build test cases to learn and debug, and find inspiration.
           </p>
 
-          <Link className={style.link} to={isAuth ? "/your-works" : "/pen"}>
+          <Link className={style.link} to={isAuth ? '/your-works' : '/pen'}>
             Start Codding
           </Link>
         </div>

+ 1 - 1
src/components/pages/HomePage/HomePage.module.scss

@@ -1,4 +1,4 @@
-@import "../../../scss/index.scss";
+@import "../../scss/index.scss";
 
 .homePage {
   position: relative;

src/components/pages/LoadingPage/LoadingPage.jsx → src/pages/LoadingPage/LoadingPage.jsx


+ 1 - 1
src/components/pages/LoadingPage/LoadingPage.module.scss

@@ -1,4 +1,4 @@
-@import "../../../scss/index.scss";
+@import "../../scss/index.scss";
 
 .loadingPage {
   width: 100vw;

+ 17 - 17
src/components/pages/LoginPage/LoginPage.jsx

@@ -1,19 +1,19 @@
-import style from "./LoginPage.module.scss";
-import { ReactComponent as LogoBig } from "../../../assets/img/logoBig.svg";
-import { NavLink, useNavigate } from "react-router-dom";
-import { useEffect } from "react";
-import { useDispatch, useSelector } from "react-redux";
-import { login } from "../../../store/auth/actions/loginAction";
-import { Input } from "../../common/Input/Input";
-import { useInput } from "../../../hooks/useInput";
-import { LoadingPage } from "../LoadingPage/LoadingPage";
+import style from './LoginPage.module.scss';
+import { ReactComponent as LogoBig } from '../../assets/img/logoBig.svg';
+import { NavLink, useNavigate } from 'react-router-dom';
+import { useEffect } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { login } from '../../store/auth/actions/loginAction';
+import { Input } from '../../components/Input/Input';
+import { useInput } from '../../hooks/useInput';
+import { LoadingPage } from '../LoadingPage/LoadingPage';
 
 export const LoginPage = () => {
   const navigate = useNavigate();
   const dispatch = useDispatch();
   const { isAuth, loading, error } = useSelector((state) => state.auth);
-  const loginName = useInput("");
-  const password = useInput("");
+  const loginName = useInput('');
+  const password = useInput('');
 
   const handleFormSubmit = (e) => {
     e.preventDefault();
@@ -27,10 +27,10 @@ export const LoginPage = () => {
   };
 
   useEffect(() => {
-    if (isAuth) navigate("/your-works");
+    if (isAuth) navigate('/your-works');
     if (error) {
-      loginName.setValue("");
-      password.setValue("");
+      loginName.setValue('');
+      password.setValue('');
     }
   }, [isAuth, error]);
 
@@ -46,14 +46,14 @@ export const LoginPage = () => {
       {error && <span>{error}</span>}
 
       <Input
-        title={"Login"}
+        title={'Login'}
         value={loginName.value}
         onChange={loginName.onChange}
       />
 
       <Input
-        type={"password"}
-        title={"Password"}
+        type={'password'}
+        title={'Password'}
         value={password.value}
         onChange={password.onChange}
       />

+ 1 - 1
src/components/pages/LoginPage/LoginPage.module.scss

@@ -1,4 +1,4 @@
-@import "../../../scss/index.scss";
+@import "../../scss/index.scss";
 
 .container {
   position: relative;

+ 6 - 6
src/components/pages/PenPage/PenPage.jsx

@@ -1,16 +1,16 @@
 import React, { useEffect, useState } from 'react';
-import { Preview } from '../../common/Preview/Preview';
+import { Preview } from '../../components/Preview/Preview';
 import { useDispatch, useSelector } from 'react-redux';
-import { fetchCurrentWork } from '../../../store/currentWork/actions/fetchCurrentWork';
+import { fetchCurrentWork } from '../../store/currentWork/actions/fetchCurrentWork';
 import { useParams } from 'react-router-dom';
 import { LoadingPage } from '../LoadingPage/LoadingPage';
-import { HeaderPen } from '../../common/HeaderPen/HeaderPen';
+import { HeaderPen } from '../../components/HeaderPen/HeaderPen';
 import style from './PenPage.module.scss';
 import { Bar, Container, Section } from 'react-simple-resizer';
-import { Editors } from '../../common/Editors/Editors';
+import { Editors } from '../../components/Editors/Editors';
 import { ErrorPage } from '../ErrorPage/ErrorPage';
-import { Console } from '../../common/Console/Console';
-import { usePopup } from '../../../hooks/usePopup';
+import { Console } from '../../components/Console/Console';
+import { usePopup } from '../../hooks/usePopup';
 
 export const PenPage = () => {
   const dispatch = useDispatch();

+ 1 - 1
src/components/pages/PenPage/PenPage.module.scss

@@ -1,4 +1,4 @@
-@import "../../../scss/index.scss";
+@import "../../scss/index.scss";
 
 .container {
   width: 100vw;

+ 22 - 0
src/pages/SettingsPage/SettingsPage.jsx

@@ -0,0 +1,22 @@
+import React from 'react';
+import { Header } from '../../components/Header/Header';
+import style from './SettingsPage.module.scss';
+import { ImageUploader } from '../../components/ImageUploader/ImageUploader';
+
+export const SettingsPage = () => {
+  return (
+    <div className={style.settings}>
+      <Header />
+
+      <div className={style.container}>
+        <h1>Settings</h1>
+
+        <h2>Profile Image</h2>
+        <ImageUploader />
+
+        <h2>About You</h2>
+        <div className={style.imageSection}></div>
+      </div>
+    </div>
+  );
+};

+ 33 - 0
src/pages/SettingsPage/SettingsPage.module.scss

@@ -0,0 +1,33 @@
+@import '../../scss/index.scss';
+
+.settings {
+    height: 100vh;
+    background-color: #131417;
+
+    .container {
+        @include container();
+        margin-top: 20px;
+        color: #FDFDFD;
+       
+
+        h1 {
+            padding-bottom: 13px;
+            border-bottom: 2px solid $greenMain;
+            margin-bottom: 35px;
+        }
+
+        h2:first-of-type {
+            display: inline-block;
+            margin-bottom: 260px;
+            width: 35%;   
+        }
+
+        h2:nth-of-type(2) {
+            display: inline-block;
+            width: 35%;   
+        }
+      
+
+
+    }
+}

+ 16 - 16
src/components/pages/SignUpPage/SignUpPage.jsx

@@ -1,21 +1,21 @@
-import style from "./SignUpPage.module.scss";
-import { ReactComponent as LogoBig } from "../../../assets/img/logoBig.svg";
-import { NavLink, useNavigate } from "react-router-dom";
-import { useEffect } from "react";
-import { useDispatch, useSelector } from "react-redux";
-import { registration } from "../../../store/auth/actions/registrationAction";
-import { useInput } from "../../../hooks/useInput";
-import { Input } from "../../common/Input/Input";
-import { Validate } from "../../../utils/Validate";
-import { LoadingPage } from "../LoadingPage/LoadingPage";
+import style from './SignUpPage.module.scss';
+import { ReactComponent as LogoBig } from '../../assets/img/logoBig.svg';
+import { NavLink, useNavigate } from 'react-router-dom';
+import { useEffect } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { registration } from '../../store/auth/actions/registrationAction';
+import { useInput } from '../../hooks/useInput';
+import { Input } from '../../components/Input/Input';
+import { Validate } from '../../utils/Validate';
+import { LoadingPage } from '../LoadingPage/LoadingPage';
 
 export const SignUpPage = () => {
   const dispatch = useDispatch();
   const navigate = useNavigate();
   const { isAuth, error, loading } = useSelector((state) => state.auth);
-  const userName = useInput("", Validate.userName);
-  const password = useInput("", Validate.password);
-  const confirmPassword = useInput("", (value) =>
+  const userName = useInput('', Validate.userName);
+  const password = useInput('', Validate.password);
+  const confirmPassword = useInput('', (value) =>
     Validate.confirmPassword(value, password.value)
   );
   const isError =
@@ -40,7 +40,7 @@ export const SignUpPage = () => {
   };
 
   useEffect(() => {
-    if (isAuth) navigate("/your-works");
+    if (isAuth) navigate('/your-works');
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [isAuth]);
 
@@ -64,7 +64,7 @@ export const SignUpPage = () => {
 
       <Input
         title="Password"
-        type={"password"}
+        type={'password'}
         value={password.value}
         onChange={password.onChange}
         error={password.error}
@@ -72,7 +72,7 @@ export const SignUpPage = () => {
 
       <Input
         title="Confirm Password"
-        type={"password"}
+        type={'password'}
         value={confirmPassword.value}
         onChange={confirmPassword.onChange}
         error={confirmPassword.error}

+ 1 - 1
src/components/pages/SignUpPage/SignUpPage.module.scss

@@ -1,4 +1,4 @@
-@import "../../../scss/index.scss";
+@import "../../scss/index.scss";
 
 .container {
   display: flex;

+ 8 - 8
src/components/pages/YourWorksPage/YourWorksPage.jsx

@@ -1,16 +1,16 @@
-import { Header } from '../../common/Header/Header';
+import { Header } from '../../components/Header/Header';
 import style from './YourWorksPage.module.scss';
 import { useDispatch, useSelector } from 'react-redux';
-import { Footer } from '../../common/Footer/Footer';
+import { Footer } from '../../components/Footer/Footer';
 import { useEffect } from 'react';
-import { getUserIdFromJwt } from '../../../utils/getUserIdFromJwt';
-import { usePopup } from '../../../hooks/usePopup';
-import { CreateWorkPopup } from './CreateWorkPopup/CreateWorkPopup';
+import { getUserIdFromJwt } from '../../utils/getUserIdFromJwt';
+import { usePopup } from '../../hooks/usePopup';
+import { CreateWorkPopup } from '../../components/CreateWorkPopup/CreateWorkPopup';
 import { LoadingPage } from '../LoadingPage/LoadingPage';
-import { fetchWorks } from '../../../store/works/actions/fetchWorks';
-import { Works } from '../../common/Works/Works';
+import { fetchWorks } from '../../store/works/actions/fetchWorks';
+import { Works } from '../../components/Works/Works';
 
-export const YourWorks = () => {
+export const YourWorksPage = () => {
   const dispatch = useDispatch();
   const { isAuth } = useSelector((state) => state.auth);
   const { isLoading } = useSelector((state) => state.works);

+ 2 - 2
src/components/pages/YourWorksPage/YourWorksPage.module.scss

@@ -1,4 +1,4 @@
-@import "../../../scss/index.scss";
+@import "../../scss/index.scss";
 
 .yourWorks {
   @include flex($direction: column, $justify: start);
@@ -13,7 +13,7 @@
     margin-bottom: 40px;
 
     .worksTab {
-      margin: 30px 0 10px;
+      margin: 20px 0 10px;
       border-bottom: 3px solid #2c303a;
       padding-bottom: 10px;
 

+ 10 - 8
src/store/auth/actions/loginAction.js

@@ -1,10 +1,11 @@
-import { createAsyncThunk } from "@reduxjs/toolkit";
-import { getGql } from "../../../services/api";
-import { getUserIdFromJwt } from "../../../utils/getUserIdFromJwt";
-import { fetchWorks } from "../../works/actions/fetchWorks";
+import { createAsyncThunk } from '@reduxjs/toolkit';
+import { getGql } from '../../../services/api';
+import { getUserIdFromJwt } from '../../../utils/getUserIdFromJwt';
+import { fetchUser } from '../../user/actions/fetchUser';
+import { fetchWorks } from '../../works/actions/fetchWorks';
 
 export const login = createAsyncThunk(
-  "auth/login",
+  'auth/login',
 
   async (userData, { dispatch, rejectWithValue }) => {
     const gql = getGql();
@@ -22,18 +23,19 @@ export const login = createAsyncThunk(
       );
 
       if (response.login) {
-        localStorage.setItem("authToken", response.login);
+        localStorage.setItem('authToken', response.login);
 
         const userId = getUserIdFromJwt(localStorage.authToken);
         dispatch(fetchWorks(userId));
+        dispatch(fetchUser(userId));
       } else {
         return rejectWithValue(
-          "The username or password you entered is incorrect, please try again."
+          'The username or password you entered is incorrect, please try again.'
         );
       }
     } catch (error) {
       console.log(error);
-      return rejectWithValue("Something went wrong please try again.");
+      return rejectWithValue('Something went wrong please try again.');
     }
   }
 );

+ 8 - 6
src/store/store.js

@@ -1,9 +1,10 @@
-import { configureStore } from "@reduxjs/toolkit";
-import thunkMiddleware from "redux-thunk";
-import { createLogger } from "redux-logger";
-import { authSlice } from "./auth/authSlice";
-import { worksSlice } from "./works/worksSlice";
-import { currentWorkSlice } from "./currentWork/currentWorkSlice";
+import { configureStore } from '@reduxjs/toolkit';
+import thunkMiddleware from 'redux-thunk';
+import { createLogger } from 'redux-logger';
+import { authSlice } from './auth/authSlice';
+import { worksSlice } from './works/worksSlice';
+import { currentWorkSlice } from './currentWork/currentWorkSlice';
+import { userSlice } from './user/userSlice';
 
 const loggerMiddleware = createLogger();
 
@@ -12,6 +13,7 @@ export const store = configureStore({
     auth: authSlice.reducer,
     works: worksSlice.reducer,
     currentWork: currentWorkSlice.reducer,
+    user: userSlice.reducer,
 
     middleware: [thunkMiddleware, loggerMiddleware],
   },

+ 41 - 0
src/store/user/actions/fetchUser.js

@@ -0,0 +1,41 @@
+import { createAsyncThunk } from '@reduxjs/toolkit';
+import { getGql } from '../../../services/api';
+
+export const fetchUser = createAsyncThunk(
+  'user/Fetch',
+
+  async (id, { rejectWithValue }) => {
+    const gql = getGql();
+    try {
+      const response = await gql.request(
+        ` 
+        query GetUser($query: String!) {
+            UserFindOne(query: $query) {
+              _id
+              login
+              nick
+              avatar {
+                url
+              }
+            }
+          }
+          `,
+        {
+          query: JSON.stringify([
+            {
+              _id: id,
+            },
+          ]),
+        }
+      );
+      console.log(response.UserFindOne);
+
+      if (response.UserFindOne) {
+        return response.UserFindOne;
+      }
+    } catch (error) {
+      console.log(error);
+      return rejectWithValue('Something went wrong please try again.');
+    }
+  }
+);

+ 33 - 0
src/store/user/userSlice.js

@@ -0,0 +1,33 @@
+import { createSlice } from '@reduxjs/toolkit';
+import { fetchUser } from './actions/fetchUser';
+
+const initialState = {
+  id: '',
+  login: '',
+  nick: '',
+  avatar: '',
+  isLoading: false,
+};
+
+export const userSlice = createSlice({
+  name: 'user',
+  initialState,
+  reducers: {},
+  extraReducers: (builder) => {
+    builder.addCase(fetchUser.pending, (state) => {
+      state.isLoading = true;
+    });
+
+    builder.addCase(fetchUser.fulfilled, (state, action) => {
+      state.isLoading = false;
+      state.id = action.payload._id;
+      state.login = action.payload.login;
+      state.avatar = action.payload.avatar;
+    });
+
+    builder.addCase(fetchUser.rejected, (state, action) => {
+      state.isLoading = false;
+      state.error = action.error.message;
+    });
+  },
+});