Browse Source

fixed goMessage

yankevych0210 1 year ago
parent
commit
9460ad0322

+ 2 - 9
src/components/Editor/Editor.jsx

@@ -15,8 +15,7 @@ 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';
-import { GoMessage } from '../GoMessage/GoMessage';
-import { useTimedPopup } from '../../hooks/useTimedPopup.js';
+import { showSuccessMessage } from '../../store/goMessage/goMessageSlice';
 
 const logos = {
   xml: <HtmlLogo />,
@@ -30,7 +29,6 @@ export default function Editor({ language, displayName, value, onChange }) {
   const editorRef = useRef(null);
   const { id, files } = useSelector((state) => state.currentWork);
   const { isAuth } = useSelector((state) => state.auth);
-  const saveMessage = useTimedPopup();
 
   const handleSave = () => {
     dispatch(setFormatCode());
@@ -46,12 +44,12 @@ export default function Editor({ language, displayName, value, onChange }) {
           js: files.js.text,
         })
       );
-      saveMessage.openPopup();
     }
   };
 
   const handleFormat = () => {
     dispatch(setFormatCode());
+    dispatch(showSuccessMessage('Code formatted.'));
   };
 
   function handleChange(editor, data, value) {
@@ -89,11 +87,6 @@ export default function Editor({ language, displayName, value, onChange }) {
           editorRef.current = editor;
         }}
       />
-      <GoMessage
-        message={'Pen saved.'}
-        close={saveMessage.closePopup}
-        isOpen={saveMessage.isOpen}
-      />
     </Section>
   );
 }

+ 20 - 20
src/components/GoMessage/GoMessage.jsx

@@ -1,18 +1,22 @@
 import style from './GoMessage.module.scss';
 import { GrClose } from 'react-icons/gr';
 import { BsCheckLg } from 'react-icons/bs';
+import { useDispatch, useSelector } from 'react-redux';
+import { clearMessage } from '../../store/goMessage/goMessageSlice';
 
-export const GoMessage = ({ children, type, message, isOpen, close }) => {
-  const getStyle = () => {
-    let top = isOpen ? '20px' : '-200px';
-    let border;
+export const GoMessage = () => {
+  const dispatch = useDispatch();
+  const { isShowing, message, color } = useSelector((state) => state.goMessage);
+
+  if (isShowing) {
+    setTimeout(() => {
+      dispatch(clearMessage());
+    }, 3000);
+  }
 
-    if (type === 'success') {
-      border = '2px solid #46CF73';
-    }
-    if (type === 'warning') {
-      border = '2px solid #ffdd40';
-    }
+  const getStyle = () => {
+    let top = isShowing ? '20px' : '-200px';
+    let border = `2px solid ${color}`;
 
     return {
       top,
@@ -20,19 +24,15 @@ export const GoMessage = ({ children, type, message, isOpen, close }) => {
     };
   };
 
-  if (children) {
-    return (
-      <div style={getStyle()} className={style.message}>
-        {children}
-      </div>
-    );
-  }
-
   return (
     <div style={getStyle()} className={style.message}>
-      <BsCheckLg />
+      {color === '#46CF73' && <BsCheckLg className={style.greenCircle} />}
+      {color === '#ff3b41' && <GrClose className={style.redCircle} />}
       <span>{message}</span>
-      <GrClose onClick={close} />
+      <GrClose
+        className={style.close}
+        onClick={() => dispatch(clearMessage())}
+      />
     </div>
   );
 };

+ 19 - 4
src/components/GoMessage/GoMessage.module.scss

@@ -12,10 +12,10 @@
     padding: 9px 13px 9px 15px;
     color: white;
     transition: .5s all ease-in-out;
-    z-index: 10;
+    z-index: 100 !important;
 
 
-    svg:first-of-type {
+    .greenCircle {
         width:20px;
         height: 20px;
         margin-right: 8px;
@@ -24,10 +24,26 @@
         padding: 2px;
     }
 
-    svg:last-of-type {
+    .redCircle {
+        width:20px;
+        height: 20px;
+        margin-right: 8px;
+        border-radius: 50%;
+        background-color: $redGoMessage;
+        padding: 3px;
+       
+        path {
+           stroke: #ffffff;
+        }
+        
+    }
+
+
+    .close {
         width:13px;
         height: 13px;
         margin-left: 7px;
+
         path {
             stroke: #868DA0;
         }
@@ -38,7 +54,6 @@
             }
         }
     }
-
 }
 
 .open {

+ 18 - 32
src/components/HeaderPen/HeaderPen.jsx

@@ -1,37 +1,43 @@
-import React, { useEffect } from 'react';
 import { useDispatch, useSelector } from 'react-redux';
 import { ReactComponent as Logo } from '../../assets/img/logo.svg';
-import { NavLink, useNavigate } from 'react-router-dom';
+import { NavLink } from 'react-router-dom';
 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 { BsFillCloudFill } from 'react-icons/bs';
 import { FaPen } from 'react-icons/fa/index';
 import { GoMessage } from '../GoMessage/GoMessage';
-import { useTimedPopup } from '../../hooks/useTimedPopup';
-import { usePopup } from '../../hooks/usePopup';
-import { MdLogout } from 'react-icons/md/index';
 
 export const HeaderPen = () => {
   const dispatch = useDispatch();
-  const navigate = useNavigate();
   const { isAuth } = useSelector((state) => state.auth);
   const { id, title, owner, files } = useSelector((state) => state.currentWork);
-  const saveMessage = useTimedPopup();
-  const askToLoginPopup = usePopup();
 
   const logout = () => {
     localStorage.removeItem('authToken');
     dispatch(logout());
   };
 
+  // const loginPrompt = (
+  //   <div className={style.loginPopup}>
+  //     <span>
+  //       You’ll have to Log In or Sign Up to save your Pen. Don’t worry! All your
+  //       work will be saved to your account.
+  //     </span>
+  //     <div>
+  //       <button>close</button>
+  //       <NavLink to={'/login'}>OK</NavLink>
+  //     </div>
+  //   </div>
+  // );
+
+  // TODO: HoldUp component
+
   const handleSaveFiles = () => {
     dispatch(setFormatCode());
 
     if (!isAuth) {
-      askToLoginPopup.open();
-      // if (askToLogin()) navigate('/login');
+      console.log('HoldUp component!!!!');
     } else {
       dispatch(
         saveFiles({
@@ -41,7 +47,6 @@ export const HeaderPen = () => {
           js: files.js.text,
         })
       );
-      saveMessage.openPopup();
     }
   };
 
@@ -57,25 +62,7 @@ export const HeaderPen = () => {
         </div>
       </div>
 
-      <GoMessage type="warning" isOpen={askToLoginPopup.isPopupVisible}>
-        <div className={style.loginPopup}>
-          <span>
-            You’ll have to Log In or Sign Up to save your Pen. Don’t worry! All
-            your work will be saved to your account.
-          </span>
-          <div>
-            <button onClick={askToLoginPopup.close}>close</button>
-            <NavLink to={'/login'}>OK</NavLink>
-          </div>
-        </div>
-      </GoMessage>
-
-      <GoMessage
-        type="success"
-        message={'Pen saved.'}
-        close={saveMessage.closePopup}
-        isOpen={saveMessage.isOpen}
-      />
+      <GoMessage />
 
       <nav>
         <button onClick={handleSaveFiles}>
@@ -93,7 +80,6 @@ export const HeaderPen = () => {
               onClick={logout}
               to="/"
             >
-              <MdLogout />
               Log out
             </NavLink>
           </>

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

@@ -89,15 +89,9 @@
 
     a:last-child {
       @extend %buttonGreen;
-      display: flex;
-      align-items: center;
+
       padding: 13px 16px;
     }
-    svg {
-      width: 16px;
-      height: 16px;
-      margin-right: 4px;
-    }
   }
 
   .loginPopup {

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

@@ -21,20 +21,28 @@
     list-style: none;
     text-decoration: none;
     @include flex($align: center);
+    margin: 3px 0;
 
     svg {
       width: 20px;
     height: 20px;
     margin-right: 5px;
+    color:#5A5F73;
     }
   }
 
   li:hover {
     background-color: $greyMain-hover;
+    svg {
+      color:#ccced5;
+    }
   }
 
   .delete:hover {
     background-color: $redMain;
+    svg {
+      color:white;
+    }
   }
 }
 

+ 0 - 33
src/hooks/useTimedPopup.js

@@ -1,33 +0,0 @@
-import { useState, useEffect } from 'react';
-
-const useTimedPopup = (initialIsOpen = false, timeout = 4000) => {
-  const [isOpen, setIsOpen] = useState(initialIsOpen);
-
-  useEffect(() => {
-    let timeoutId;
-
-    if (isOpen) {
-      timeoutId = setTimeout(() => {
-        setIsOpen(false);
-      }, timeout);
-    }
-
-    return () => clearTimeout(timeoutId);
-  }, [isOpen, timeout]);
-
-  const openPopup = () => {
-    setIsOpen(true);
-  };
-
-  const closePopup = () => {
-    setIsOpen(false);
-  };
-
-  return {
-    isOpen,
-    openPopup,
-    closePopup,
-  };
-};
-
-export { useTimedPopup };

+ 2 - 0
src/layouts/MainLayout.jsx

@@ -1,10 +1,12 @@
 import React from 'react';
+import { GoMessage } from '../components/GoMessage/GoMessage';
 import { Header } from '../components/Header/Header';
 import { Footer } from '../components/Footer/Footer';
 
 export const MainLayout = ({ children, className }) => {
   return (
     <div className={className}>
+      <GoMessage />
       <Header />
       <main>{children}</main>
       <Footer />

+ 0 - 2
src/pages/YourWorksPage/YourWorksPage.jsx

@@ -1,7 +1,5 @@
-import { Header } from '../../components/Header/Header';
 import style from './YourWorksPage.module.scss';
 import { useDispatch, useSelector } from 'react-redux';
-import { Footer } from '../../components/Footer/Footer';
 import { useEffect } from 'react';
 import { getUserIdFromJwt } from '../../utils/getUserIdFromJwt';
 import { usePopup } from '../../hooks/usePopup';

+ 1 - 0
src/scss/_variables.scss

@@ -17,6 +17,7 @@ $redMain-active: #ee141b;
 
 // goMessageColors
 $greenGoMessage: #46CF73;
+$redGoMessage: #ff3b41;
 
 // container
 $containerWidth: 90vw;

+ 13 - 7
src/store/currentWork/actions/saveFiles.js

@@ -1,10 +1,14 @@
-import { createAsyncThunk } from "@reduxjs/toolkit";
-import { getGql } from "../../../services/api";
+import { createAsyncThunk } from '@reduxjs/toolkit';
+import { getGql } from '../../../services/api';
+import {
+  showErrorMessage,
+  showSuccessMessage,
+} from '../../goMessage/goMessageSlice';
 
 export const saveFiles = createAsyncThunk(
-  "currentWork/saveFiles",
+  'currentWork/saveFiles',
 
-  async ({ id, html, css, js }) => {
+  async ({ id, html, css, js }, { dispatch }) => {
     const gql = getGql();
     try {
       const { SnippetUpsert } = await gql.request(
@@ -28,15 +32,17 @@ export const saveFiles = createAsyncThunk(
         {
           snippetId: id,
           newFiles: [
-            { type: "HTML", text: html },
-            { type: "CSS", text: css },
-            { type: "JS", text: js },
+            { type: 'HTML', text: html },
+            { type: 'CSS', text: css },
+            { type: 'JS', text: js },
           ],
         }
       );
 
+      dispatch(showSuccessMessage('Pen saved.'));
       return SnippetUpsert;
     } catch (error) {
+      dispatch(showErrorMessage('Failed to save pen.'));
       console.error(error);
     }
   }

+ 42 - 0
src/store/goMessage/goMessageSlice.js

@@ -0,0 +1,42 @@
+import { createSlice } from '@reduxjs/toolkit';
+
+const initialState = {
+  isShowing: false,
+  message: '',
+  color: '',
+};
+
+export const goMessageSlice = createSlice({
+  name: 'goMessage',
+  initialState,
+  reducers: {
+    clearMessage(state) {
+      state.isShowing = false;
+    },
+
+    showSuccessMessage(state, action) {
+      state.isShowing = true;
+      state.message = action.payload;
+      state.color = '#46CF73';
+    },
+
+    showWarningMessage(state, action) {
+      state.isShowing = true;
+      state.message = action.payload;
+      state.color = '#ffdd40';
+    },
+
+    showErrorMessage(state, action) {
+      state.isShowing = true;
+      state.message = action.payload;
+      state.color = '#ff3b41';
+    },
+  },
+});
+
+export const {
+  showSuccessMessage,
+  showWarningMessage,
+  showErrorMessage,
+  clearMessage,
+} = goMessageSlice.actions;

+ 3 - 1
src/store/store.js

@@ -5,15 +5,17 @@ import { authSlice } from './auth/authSlice';
 import { worksSlice } from './works/worksSlice';
 import { currentWorkSlice } from './currentWork/currentWorkSlice';
 import { userSlice } from './user/userSlice';
+import { goMessageSlice } from './goMessage/goMessageSlice';
 
 const loggerMiddleware = createLogger();
 
 export const store = configureStore({
   reducer: {
     auth: authSlice.reducer,
+    user: userSlice.reducer,
     works: worksSlice.reducer,
+    goMessage: goMessageSlice.reducer,
     currentWork: currentWorkSlice.reducer,
-    user: userSlice.reducer,
 
     middleware: [thunkMiddleware, loggerMiddleware],
   },

+ 6 - 0
src/store/user/actions/changeAvatar.js

@@ -2,6 +2,10 @@ import { createAsyncThunk } from '@reduxjs/toolkit';
 import { getGql } from '../../../services/api';
 import { uploadImage } from './uploadImage';
 import initialUserAvatar from '../../../assets/img/initialUserImage.jpeg';
+import {
+  showErrorMessage,
+  showSuccessMessage,
+} from '../../goMessage/goMessageSlice';
 
 export const changeAvatar = createAsyncThunk(
   'user/changeAvatar',
@@ -39,12 +43,14 @@ export const changeAvatar = createAsyncThunk(
           imageId: imageAction.payload._id,
         }
       );
+      dispatch(showSuccessMessage('Profile Image uploaded.'));
       if (response.UserUpsert.avatar.url) {
         return response.UserUpsert.avatar.url;
       } else {
         return initialUserAvatar;
       }
     } catch (error) {
+      dispatch(showErrorMessage('Something went wrong please try again.'));
       console.log(error);
       return rejectWithValue('Something went wrong please try again.');
     }

+ 13 - 1
src/store/user/actions/changePassword.js

@@ -1,10 +1,14 @@
 import { createAsyncThunk } from '@reduxjs/toolkit';
 import { GraphQLClient } from 'graphql-request';
+import {
+  showSuccessMessage,
+  showErrorMessage,
+} from '../../goMessage/goMessageSlice';
 
 export const changePassword = createAsyncThunk(
   'user/changePassword',
 
-  async ({ login, password, newPassword }, { rejectWithValue }) => {
+  async ({ login, password, newPassword }, { rejectWithValue, dispatch }) => {
     const gql = new GraphQLClient('/graphql', {
       headers: {
         'Content-Type': 'application/json;charset=utf-8',
@@ -28,9 +32,17 @@ export const changePassword = createAsyncThunk(
           newPassword,
         }
       );
+
+      if (response.changePassword) {
+        dispatch(showSuccessMessage('Password changed.'));
+      } else {
+        dispatch(showErrorMessage('Current password incorrect.'));
+      }
+
       return response.changePassword;
     } catch (error) {
       console.log(error);
+      dispatch(showErrorMessage('Something went wrong please try again.'));
       return rejectWithValue('Something went wrong please try again.');
     }
   }

+ 3 - 1
src/store/user/actions/uploadImage.js

@@ -1,8 +1,9 @@
 import { createAsyncThunk } from '@reduxjs/toolkit';
+import { showErrorMessage } from '../../goMessage/goMessageSlice';
 
 export const uploadImage = createAsyncThunk(
   'user/uploadAvatar',
-  async (file, thunkAPI) => {
+  async (file, { thunkAPI, dispatch }) => {
     const formData = new FormData();
     formData.append('photo', file);
 
@@ -18,6 +19,7 @@ export const uploadImage = createAsyncThunk(
 
       return data;
     } catch (error) {
+      dispatch(showErrorMessage('Something went wrong please try again.'));
       return thunkAPI.rejectWithValue(`failed to load image`);
     }
   }