Переглянути джерело

written logic for unregistered users

yankevych0210 1 рік тому
батько
коміт
4bbd534c16

+ 0 - 77
package-lock.json

@@ -8,9 +8,6 @@
       "name": "project-code-pen",
       "version": "0.1.0",
       "dependencies": {
-        "@fortawesome/fontawesome-svg-core": "^6.3.0",
-        "@fortawesome/free-solid-svg-icons": "^6.3.0",
-        "@fortawesome/react-fontawesome": "^0.2.0",
         "@reduxjs/toolkit": "^1.9.3",
         "@testing-library/jest-dom": "^5.16.5",
         "@testing-library/react": "^13.4.0",
@@ -2209,51 +2206,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/@fortawesome/fontawesome-common-types": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.3.0.tgz",
-      "integrity": "sha512-4BC1NMoacEBzSXRwKjZ/X/gmnbp/HU5Qqat7E8xqorUtBFZS+bwfGH5/wqOC2K6GV0rgEobp3OjGRMa5fK9pFg==",
-      "hasInstallScript": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/@fortawesome/fontawesome-svg-core": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.3.0.tgz",
-      "integrity": "sha512-uz9YifyKlixV6AcKlOX8WNdtF7l6nakGyLYxYaCa823bEBqyj/U2ssqtctO38itNEwXb8/lMzjdoJ+aaJuOdrw==",
-      "hasInstallScript": true,
-      "dependencies": {
-        "@fortawesome/fontawesome-common-types": "6.3.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/@fortawesome/free-solid-svg-icons": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.3.0.tgz",
-      "integrity": "sha512-x5tMwzF2lTH8pyv8yeZRodItP2IVlzzmBuD1M7BjawWgg9XAvktqJJ91Qjgoaf8qJpHQ8FEU9VxRfOkLhh86QA==",
-      "hasInstallScript": true,
-      "dependencies": {
-        "@fortawesome/fontawesome-common-types": "6.3.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/@fortawesome/react-fontawesome": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz",
-      "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==",
-      "dependencies": {
-        "prop-types": "^15.8.1"
-      },
-      "peerDependencies": {
-        "@fortawesome/fontawesome-svg-core": "~1 || ~6",
-        "react": ">=16.3"
-      }
-    },
     "node_modules/@gar/promisify": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
@@ -20922,35 +20874,6 @@
         }
       }
     },
-    "@fortawesome/fontawesome-common-types": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.3.0.tgz",
-      "integrity": "sha512-4BC1NMoacEBzSXRwKjZ/X/gmnbp/HU5Qqat7E8xqorUtBFZS+bwfGH5/wqOC2K6GV0rgEobp3OjGRMa5fK9pFg=="
-    },
-    "@fortawesome/fontawesome-svg-core": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.3.0.tgz",
-      "integrity": "sha512-uz9YifyKlixV6AcKlOX8WNdtF7l6nakGyLYxYaCa823bEBqyj/U2ssqtctO38itNEwXb8/lMzjdoJ+aaJuOdrw==",
-      "requires": {
-        "@fortawesome/fontawesome-common-types": "6.3.0"
-      }
-    },
-    "@fortawesome/free-solid-svg-icons": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.3.0.tgz",
-      "integrity": "sha512-x5tMwzF2lTH8pyv8yeZRodItP2IVlzzmBuD1M7BjawWgg9XAvktqJJ91Qjgoaf8qJpHQ8FEU9VxRfOkLhh86QA==",
-      "requires": {
-        "@fortawesome/fontawesome-common-types": "6.3.0"
-      }
-    },
-    "@fortawesome/react-fontawesome": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz",
-      "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==",
-      "requires": {
-        "prop-types": "^15.8.1"
-      }
-    },
     "@gar/promisify": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",

+ 0 - 3
package.json

@@ -4,9 +4,6 @@
   "private": true,
   "proxy": "http://snippet.node.ed.asmer.org.ua",
   "dependencies": {
-    "@fortawesome/fontawesome-svg-core": "^6.3.0",
-    "@fortawesome/free-solid-svg-icons": "^6.3.0",
-    "@fortawesome/react-fontawesome": "^0.2.0",
     "@reduxjs/toolkit": "^1.9.3",
     "@testing-library/jest-dom": "^5.16.5",
     "@testing-library/react": "^13.4.0",

+ 1 - 2
src/App.js

@@ -5,13 +5,12 @@ 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 { SandboxPage } from "./components/pages/SandboxPage/SandboxPage";
 
 function App() {
   return (
     <Routes>
       <Route path="/" element={<HomePage />} />
-      <Route path="/sandbox" element={<SandboxPage />} />
+      <Route path="/pen" element={<PenPage />} />
       <Route path="/login" element={<LoginPage />} />
       <Route path="/signup" element={<SignUpPage />} />
       <Route path="/your-works" element={<YourWorks />} />

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

@@ -1,17 +1,17 @@
-import React, { useState } from "react";
+import React from "react";
 import "codemirror/lib/codemirror.css";
 import "codemirror/mode/xml/xml";
 import "codemirror/mode/javascript/javascript";
 import "codemirror/mode/css/css";
 import { Controlled as ControlledEditor } from "react-codemirror2";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { faCompressAlt, faExpandAlt } from "@fortawesome/free-solid-svg-icons";
 import { useDispatch } 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 { Section } from "react-simple-resizer";
+
 export default function Editor(props) {
   const { language, displayName, value, onChange } = props;
   const dispatch = useDispatch();
@@ -27,7 +27,8 @@ export default function Editor(props) {
   }
 
   return (
-    <div className={style.editor}>
+    // Section use for resizers
+    <Section className={style.editor}>
       <div className={style.header}>
         <h2>
           {logos[language]}
@@ -48,6 +49,6 @@ export default function Editor(props) {
           autoCorrect: true,
         }}
       />
-    </div>
+    </Section>
   );
 }

+ 37 - 31
src/components/common/Editors/Editors.jsx

@@ -1,46 +1,52 @@
 import React from "react";
-import { Bar, Container, Section } from "react-simple-resizer";
+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,
+  setJs,
+  setLocalHtml,
+  setLocalCss,
+  setLocalJs,
+} from "../../../store/currentWork/currentWorkSlice";
 
-export const Editors = (props) => {
-  const { html, setHtmlValue, css, setCssValue, js, setJsValue } = props;
+export const Editors = () => {
+  const { isAuth } = useSelector((state) => state.auth);
+  const { files } = useSelector((state) => state.currentWork);
+  const { html, css, js } = files;
 
+  const setHtmlText = isAuth ? setHtml : setLocalHtml;
+  const setCssText = isAuth ? setCss : setLocalCss;
+  const setJsText = isAuth ? setJs : setLocalJs;
   return (
-    <Container width={"100vw"} height={"100%"} className={style.editors}>
+    <Container className={style.editors}>
       <Bar className={style.bar} />
-      <Section
-        children={
-          <Editor
-            language="xml"
-            displayName={`HTML`}
-            value={html}
-            onChange={setHtmlValue}
-          />
-        }
+
+      <Editor
+        language="xml"
+        displayName={`HTML`}
+        value={html.text}
+        onChange={setHtmlText}
       />
 
       <Bar className={style.bar} />
-      <Section
-        children={
-          <Editor
-            language="css"
-            displayName="CSS"
-            value={css}
-            onChange={setCssValue}
-          />
-        }
+
+      <Editor
+        language="css"
+        displayName="CSS"
+        value={css.text}
+        onChange={setCssText}
       />
+
       <Bar className={style.bar} />
-      <Section
-        children={
-          <Editor
-            language="javascript"
-            displayName="JS"
-            value={js}
-            onChange={setJsValue}
-          />
-        }
+
+      <Editor
+        language="javascript"
+        displayName="JS"
+        value={js.text}
+        onChange={setJsText}
       />
     </Container>
   );

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

@@ -5,7 +5,7 @@ import { useDispatch, useSelector } from "react-redux";
 
 export const Header = () => {
   const dispatch = useDispatch();
-  const { isLogged } = useSelector((state) => state.auth);
+  const { isAuth } = useSelector((state) => state.auth);
 
   const logout = () => {
     localStorage.removeItem("authToken");
@@ -18,7 +18,7 @@ export const Header = () => {
         <LogoBig />
       </NavLink>
 
-      {isLogged ? (
+      {isAuth ? (
         <nav>
           <NavLink to="/your-works">Your works</NavLink>
           <NavLink

+ 32 - 7
src/components/common/HeaderPen/HeaderPen.jsx

@@ -1,18 +1,43 @@
 import React from "react";
 import { useDispatch, useSelector } from "react-redux";
 import { ReactComponent as Logo } from "../../../assets/img/logo.svg";
-import { NavLink } from "react-router-dom";
+import { NavLink, useNavigate } from "react-router-dom";
+import { saveFiles } from "../../../store/currentWork/actions/saveFiles";
 import style from "./HeaderPen.module.scss";
 
-export const HeaderPen = ({ onSave, workTitle, workOwner }) => {
+export const HeaderPen = () => {
   const dispatch = useDispatch();
-  const { isLogged } = useSelector((state) => state.auth);
+  const navigate = useNavigate();
+  const { isAuth } = useSelector((state) => state.auth);
+  const { id, title, owner, files } = useSelector((state) => state.currentWork);
+
+  const askToLogin = () => {
+    const unAuthMessage = `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.`;
+    // eslint-disable-next-line no-restricted-globals
+    if (confirm(unAuthMessage)) navigate("/login");
+  };
 
   const logout = () => {
     localStorage.removeItem("authToken");
     dispatch(logout());
   };
 
+  const handleSaveFiles = () => {
+    if (isAuth) {
+      dispatch(
+        saveFiles({
+          id,
+          html: files.html.text,
+          css: files.css.text,
+          js: files.js.text,
+        })
+      );
+    } else {
+      askToLogin();
+    }
+  };
+
   return (
     <header className={style.header}>
       <div className={style.logoBlock}>
@@ -20,15 +45,15 @@ export const HeaderPen = ({ onSave, workTitle, workOwner }) => {
           <Logo />
         </NavLink>
         <div className={style.workInfo}>
-          <h1>{workTitle}</h1>
-          <span>{workOwner}</span>
+          <h1>{title}</h1>
+          <span>{owner?.login}</span>
         </div>
       </div>
 
       <nav>
-        <button onClick={() => onSave()}>Save</button>
+        <button onClick={handleSaveFiles}>Save</button>
 
-        {isLogged ? (
+        {isAuth ? (
           <>
             <NavLink to="/your-works">Your works</NavLink>
             <NavLink

+ 1 - 1
src/components/common/Preview/Preview.jsx

@@ -23,7 +23,7 @@ export const Preview = ({ html, css, js }) => {
       <iframe
         srcDoc={srcDoc}
         title="output"
-        sandbox="allow-forms allow-modals allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation-by-user-activation allow-downloads allow-presentation"
+        sandbox="allow-forms allow-modals  allow-popups  allow-scripts allow-top-navigation-by-user-activation allow-downloads allow-presentation"
       />
     </div>
   );

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

@@ -1,12 +1,11 @@
 .pane {
   width: 100%;
-  height: auto;
+  height: 100%;
 
   iframe {
     display: block;
     width: 100%;
     height: 100%;
     border: none;
-    transform-origin: 0 0;
   }
 }

+ 2 - 5
src/components/pages/HomePage/HomePage.jsx

@@ -13,7 +13,7 @@ import { ReactComponent as Icon3 } from "../../../assets/img/icon3.svg";
 import { useSelector } from "react-redux";
 
 export const HomePage = () => {
-  const { isLogged } = useSelector((state) => state.auth);
+  const { isAuth } = useSelector((state) => state.auth);
 
   return (
     <div className={style.homePage}>
@@ -30,10 +30,7 @@ export const HomePage = () => {
             build test cases to learn and debug, and find inspiration.
           </p>
 
-          <Link
-            className={style.link}
-            to={isLogged ? "/your-works" : "/sandbox"}
-          >
+          <Link className={style.link} to={isAuth ? "/your-works" : "/pen"}>
             Start Codding
           </Link>
         </div>

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

@@ -11,7 +11,7 @@ import { LoadingPage } from "../LoadingPage/LoadingPage";
 export const LoginPage = () => {
   const navigate = useNavigate();
   const dispatch = useDispatch();
-  const { isLogged, loading, error } = useSelector((state) => state.auth);
+  const { isAuth, loading, error } = useSelector((state) => state.auth);
   const loginName = useInput("");
   const password = useInput("");
 
@@ -27,12 +27,12 @@ export const LoginPage = () => {
   };
 
   useEffect(() => {
-    if (isLogged) navigate("/your-works");
+    if (isAuth) navigate("/your-works");
     if (error) {
       loginName.setValue("");
       password.setValue("");
     }
-  }, [isLogged, error]);
+  }, [isAuth, error]);
 
   if (loading) return <LoadingPage />;
   return (

+ 22 - 52
src/components/pages/PenPage/PenPage.jsx

@@ -1,75 +1,45 @@
-import React, { useEffect } from "react";
-import Editor from "../../common/Editor/Editor";
+import React, { useEffect, useState } from "react";
 import { Preview } from "../../common/Preview/Preview";
 import { useDispatch, useSelector } from "react-redux";
 import { fetchCurrentWork } from "../../../store/currentWork/actions/fetchCurrentWork";
 import { useParams } from "react-router-dom";
 import { LoadingPage } from "../LoadingPage/LoadingPage";
-import { saveFiles } from "../../../store/currentWork/actions/saveFiles";
 import { HeaderPen } from "../../common/HeaderPen/HeaderPen";
 import style from "./PenPage.module.scss";
-import {
-  setHtml,
-  setCss,
-  setJs,
-} from "../../../store/currentWork/currentWorkSlice";
+import { Bar, Container, Section } from "react-simple-resizer";
+import { Editors } from "../../common/Editors/Editors";
+import { ErrorPage } from "../ErrorPage/ErrorPage";
 
 export const PenPage = () => {
   const dispatch = useDispatch();
   const { id } = useParams();
-  const { title, owner, files, isLoading, error } = useSelector(
-    (state) => state.currentWork
-  );
-  const [html, css, js] = files;
+  const { isLoading, error, files } = useSelector((state) => state.currentWork);
+  const [isSizeChanged, setIsSizeChanged] = useState(false);
+  const { html, css, js } = files;
 
   useEffect(() => {
     dispatch(fetchCurrentWork(id));
   }, []);
 
-  const handleSave = () => {
-    const newFiles = {
-      id,
-      html: html.text,
-      css: css.text,
-      js: js.text,
-    };
-
-    dispatch(saveFiles(newFiles));
-  };
-
   if (isLoading) return <LoadingPage />;
+  if (error) return <ErrorPage />;
   return (
-    <>
-      <HeaderPen
-        workTitle={title}
-        onSave={handleSave}
-        workOwner={owner.login}
-      />
+    <Container
+      vertical={true}
+      className={style.container}
+      onActivate={() => setIsSizeChanged(true)}
+      afterResizing={() => setIsSizeChanged(false)}
+    >
+      <HeaderPen />
 
-      <div className={style.editors}>
-        <Editor
-          language="xml"
-          displayName={`HTML`}
-          value={html.text}
-          onChange={setHtml}
-        />
-        <Editor
-          language="css"
-          displayName="CSS"
-          value={css.text}
-          onChange={setCss}
-        />
-        <Editor
-          language="javascript"
-          displayName="JS"
-          value={js.text}
-          onChange={setJs}
-        />
-      </div>
+      <Section children={<Editors />} />
 
-      <div className={style.line}></div>
+      <Bar className={style.barVertical} />
 
-      <Preview html={html.text} css={css.text} js={js.text} />
-    </>
+      <Section
+        style={isSizeChanged ? { pointerEvents: "none" } : null}
+        children={<Preview html={html.text} css={css.text} js={js.text} />}
+      />
+    </Container>
   );
 };

+ 0 - 51
src/components/pages/SandboxPage/SandboxPage.jsx

@@ -1,51 +0,0 @@
-import Editor from "../../common/Editor/Editor";
-import { Preview } from "../../common/Preview/Preview";
-import { HeaderPen } from "../../common/HeaderPen/HeaderPen";
-import style from "../../pages/PenPage/PenPage.module.scss";
-import { useLocalStorage } from "../../../hooks/useLocalStorage";
-import { useNavigate } from "react-router-dom";
-import { Container, Section, Bar } from "react-simple-resizer";
-import { Editors } from "../../common/Editors/Editors";
-import { useCallback, useState } from "react";
-
-export const SandboxPage = () => {
-  const [html, setHtmlValue] = useLocalStorage(`html`, "");
-  const [css, setCssValue] = useLocalStorage(`css`, "");
-  const [js, setJsValue] = useLocalStorage(`js`, "");
-  const navigate = useNavigate();
-
-  const handleSave = () => {
-    if (
-      // eslint-disable-next-line no-restricted-globals
-      confirm(`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.`)
-    ) {
-      navigate("/login");
-    }
-  };
-
-  return (
-    <Container vertical={true} className={style.container}>
-      <HeaderPen
-        workTitle={"Untitled"}
-        onSave={handleSave}
-        workOwner={"Captain anonymous"}
-      />
-      <Section
-        children={
-          <Editors
-            html={html}
-            setHtmlValue={setHtmlValue}
-            css={css}
-            setCssValue={setCssValue}
-            js={js}
-            setJsValue={setJsValue}
-          />
-        }
-      />
-
-      <Bar className={style.barVertical} />
-      <Section children={<Preview html={html} css={css} js={js} />} />
-    </Container>
-  );
-};

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

@@ -12,7 +12,7 @@ import { LoadingPage } from "../LoadingPage/LoadingPage";
 export const SignUpPage = () => {
   const dispatch = useDispatch();
   const navigate = useNavigate();
-  const { isLogged, error, loading } = useSelector((state) => state.auth);
+  const { isAuth, error, loading } = useSelector((state) => state.auth);
   const userName = useInput("", Validate.userName);
   const password = useInput("", Validate.password);
   const confirmPassword = useInput("", (value) =>
@@ -40,8 +40,8 @@ export const SignUpPage = () => {
   };
 
   useEffect(() => {
-    if (isLogged) navigate("/your-works");
-  }, [isLogged]);
+    if (isAuth) navigate("/your-works");
+  }, [isAuth]);
 
   if (loading) return <LoadingPage />;
   return (

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

@@ -13,11 +13,11 @@ import { fetchWorks } from "../../../store/works/actions/fetchWorks";
 export const YourWorks = () => {
   const dispatch = useDispatch();
   const { works, isLoading } = useSelector((state) => state.works);
-  const { isLogged } = useSelector((state) => state.auth);
+  const { isAuth } = useSelector((state) => state.auth);
   const { isPopupVisible, ref, open, close } = usePopup();
 
   useEffect(() => {
-    if (isLogged) {
+    if (isAuth) {
       const userId = getUserIdFromJwt(localStorage.authToken);
       dispatch(fetchWorks(userId));
     }

+ 3 - 3
src/store/auth/authSlice.js

@@ -3,7 +3,7 @@ import { login } from "./actions/loginAction";
 import { registration } from "./actions/registrationAction";
 
 const initialState = {
-  isLogged: localStorage.getItem("authToken") ? true : false,
+  isAuth: localStorage.getItem("authToken") ? true : false,
   loading: false,
   error: null,
 };
@@ -13,7 +13,7 @@ export const authSlice = createSlice({
   initialState,
   reducers: {
     logout(state) {
-      state.loggedIn = false;
+      state.isAuth = false;
     },
   },
   extraReducers: (builder) => {
@@ -23,7 +23,7 @@ export const authSlice = createSlice({
     });
     builder.addCase(login.fulfilled, (state) => {
       state.loading = false;
-      state.isLogged = true;
+      state.isAuth = true;
     });
     builder.addCase(login.rejected, (state, action) => {
       state.loading = false;

+ 25 - 1
src/store/currentWork/actions/fetchCurrentWork.js

@@ -1,10 +1,23 @@
 import { createAsyncThunk } from "@reduxjs/toolkit";
 import { getGql } from "../../../services/api";
+import { setEmptyFilesInLS } from "../../../utils/setEmptyFilesInLS";
 
 export const fetchCurrentWork = createAsyncThunk(
   "currentWork/fetch",
 
   async (id) => {
+    if (!id) {
+      if (!localStorage.getItem("localFiles")) {
+        setEmptyFilesInLS();
+      }
+      return {
+        _id: null,
+        title: "Untitled",
+        owner: { login: "Captain anonymous" },
+        files: JSON.parse(localStorage.getItem("localFiles")),
+      };
+    }
+
     const gql = getGql();
     try {
       const { SnippetFindOne } = await gql.request(
@@ -29,8 +42,19 @@ export const fetchCurrentWork = createAsyncThunk(
           query: JSON.stringify([{ _id: id }]),
         }
       );
+      const files = {
+        html: {},
+        css: {},
+        js: {},
+      };
+
+      SnippetFindOne.files.forEach((file) => {
+        if (file.type === "HTML") files.html = file;
+        if (file.type === "CSS") files.css = file;
+        if (file.type === "JS") files.js = file;
+      });
 
-      return SnippetFindOne;
+      return { ...SnippetFindOne, files: files };
     } catch (error) {
       console.error(error);
     }

+ 42 - 9
src/store/currentWork/currentWorkSlice.js

@@ -3,13 +3,14 @@ import { fetchCurrentWork } from "./actions/fetchCurrentWork";
 import { saveFiles } from "./actions/saveFiles";
 
 const initialState = {
+  id: "",
   title: "",
   owner: { id: "", login: "" },
-  files: [
-    { text: "", type: "HTML" },
-    { text: "", type: "CSS" },
-    { text: "", type: "JS" },
-  ],
+  files: {
+    html: { text: "", type: "HTML" },
+    css: { text: "", type: "CSS" },
+    js: { text: "", type: "JS" },
+  },
   isLoading: false,
   error: null,
 };
@@ -19,13 +20,44 @@ export const currentWorkSlice = createSlice({
   initialState,
   reducers: {
     setHtml(state, action) {
-      state.files[0].text = action.payload;
+      state.files.html.text = action.payload;
     },
     setCss(state, action) {
-      state.files[1].text = action.payload;
+      state.files.css.text = action.payload;
     },
     setJs(state, action) {
-      state.files[2].text = action.payload;
+      state.files.js.text = action.payload;
+    },
+
+    setLocalHtml(state, action) {
+      state.files.html.text = action.payload;
+      localStorage.setItem(
+        "localFiles",
+        JSON.stringify({
+          ...state.files,
+          html: { type: "HTML", text: action.payload },
+        })
+      );
+    },
+    setLocalCss(state, action) {
+      state.files.css.text = action.payload;
+      localStorage.setItem(
+        "localFiles",
+        JSON.stringify({
+          ...state.files,
+          css: { type: "CSS", text: action.payload },
+        })
+      );
+    },
+    setLocalJs(state, action) {
+      state.files.js.text = action.payload;
+      localStorage.setItem(
+        "localFiles",
+        JSON.stringify({
+          ...state.files,
+          js: { type: "JS", text: action.payload },
+        })
+      );
     },
   },
   extraReducers: (builder) => {
@@ -35,6 +67,7 @@ export const currentWorkSlice = createSlice({
     });
     builder.addCase(fetchCurrentWork.fulfilled, (state, action) => {
       state.isLoading = false;
+      state.id = action.payload._id;
       state.title = action.payload.title;
       state.owner = action.payload.owner;
       state.files = action.payload.files;
@@ -56,5 +89,5 @@ export const currentWorkSlice = createSlice({
   },
 });
 
-export const { setCurrentWork, setHtml, setCss, setJs } =
+export const { setHtml, setCss, setJs, setLocalHtml, setLocalCss, setLocalJs } =
   currentWorkSlice.actions;

+ 10 - 0
src/utils/setEmptyFilesInLS.js

@@ -0,0 +1,10 @@
+export const setEmptyFilesInLS = () => {
+  localStorage.setItem(
+    "localFiles",
+    JSON.stringify({
+      html: { type: "HTML", text: "" },
+      css: { type: "CSS", text: "" },
+      js: { type: "JS", text: "" },
+    })
+  );
+};