From 18c4cb9d1bcd6bff463b3e6da6f5ddb43a8416cf Mon Sep 17 00:00:00 2001 From: edwin6666 Date: Tue, 1 Aug 2023 10:45:45 -0400 Subject: [PATCH 01/35] Delete Environment Variables --- .env | 9 --------- cypress.env.json | 9 +++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) delete mode 100644 .env create mode 100644 cypress.env.json diff --git a/.env b/.env deleted file mode 100644 index bde21b0..0000000 --- a/.env +++ /dev/null @@ -1,9 +0,0 @@ -REACT_APP_POST_URL=http://localhost:4000/api/posts -REACT_APP_POST_DELETE=http://localhost:4000/api/posts/ -REACT_APP_UPDATE_POST=http://localhost:4000/api/posts/ -REACT_APP_API_LOGIN=http://localhost:4000/api/auth/signin -REACT_APP_API_SIGNUP=http://localhost:4000/api/auth/signup -REACT_APP_POST_ID=http://localhost:4000/api/posts/ -REACT_APP_API_URL=https://api.example.com -REACT_APP_API_URL=https://api.example.com -REACT_APP_API_URL=https://api.example.com \ No newline at end of file diff --git a/cypress.env.json b/cypress.env.json new file mode 100644 index 0000000..6d86aed --- /dev/null +++ b/cypress.env.json @@ -0,0 +1,9 @@ +{ + "nameTechtalk": "Test User", + "usernameSignUp":"TestUser", + "emailSignUp": "testuser@localhost", + "passwordSignUp": "123456789", + + "usernameLogin": "admin@localhost", + "passwordLogin": "admin" +} From 1a9bea712edb0da73a1e493e4782148d33cf8438 Mon Sep 17 00:00:00 2001 From: Edwin Mendoza Rodriguez <49256757+Edwin6666@users.noreply.github.com> Date: Mon, 11 Sep 2023 11:22:44 -0400 Subject: [PATCH 02/35] Feat Application with notifications (#26) * Delete Environment Variables * Fix README * Fix Title README * Feat Clone funcionality in README * Delete Clone documentacion README * Feat author in README * Feat when we do Crud operation in the project * Fix wrong button conditional * Refactor console.log in code * Delete Console and use semantic html in Postcard * Refactor semantic html --- .gitignore | 2 +- README.md | 64 ++++++++--------------------- package-lock.json | 2 +- package.json | 2 +- src/api/posts.js | 2 + src/components/PostCard.jsx | 32 +++++++++++---- src/components/RequiresAuth.jsx | 22 +++++----- src/components/signup/Signup.jsx | 7 +--- src/components/signup/SignupForm.js | 9 ++-- src/context/postContext.js | 12 +++--- src/hooks/useAuthentication.js | 2 +- src/pages/Contact.js | 62 +++++++++++++++++----------- src/pages/PostForm.js | 29 +++++++------ 13 files changed, 122 insertions(+), 125 deletions(-) diff --git a/.gitignore b/.gitignore index 4d29575..7d5217e 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,7 @@ .env.development.local .env.test.local .env.production.local - +.env npm-debug.log* yarn-debug.log* yarn-error.log* diff --git a/README.md b/README.md index 58beeac..a90f663 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,23 @@ -# Getting Started with Create React App +# 📂 TechTalk News (Mini-project for Cincinnatus Institute of Craftsmanship) +The most relevant news of technological advances -This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). +# Description +Techtalk is a project made based on a blog or digital newspaper to publish news, which allows you to publish images and videos accompanied by their title and description, consists of a full stack web application using React, Express, Tailwind and Json Web Token Authentication. -## Available Scripts +# Screenshot +![Alt text](image.png) +![Alt text](image-1.png) + +## Instalation + +Add your environment variables according to your data, example: +### REACT_APP_API_URL=http://localhost:5000/api In the project directory, you can run: +### `npm install` +This command installs all the dependencies necessary for its operation + ### `npm start` Runs the app in the development mode.\ @@ -14,10 +26,7 @@ Open [http://localhost:3000](http://localhost:3000) to view it in your browser. The page will reload when you make changes.\ You may also see any lint errors in the console. -### `npm test` -Launches the test runner in the interactive watch mode.\ -See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. ### `npm run build` @@ -27,44 +36,5 @@ It correctly bundles React in production mode and optimizes the build for the be The build is minified and the filenames include the hashes.\ Your app is ready to be deployed! -See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. - -### `npm run eject` - -**Note: this is a one-way operation. Once you `eject`, you can't go back!** - -If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. - -Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. - -You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. - -## Learn More - -You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). - -To learn React, check out the [React documentation](https://reactjs.org/). - -### Code Splitting - -This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) - -### Analyzing the Bundle Size - -This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) - -### Making a Progressive Web App - -This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) - -### Advanced Configuration - -This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) - -### Deployment - -This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) - -### `npm run build` fails to minify - -This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) +# Authors +@Edwin6666 \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index dd5ac03..fa71499 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,7 @@ "moment": "^2.29.4", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-hot-toast": "^2.4.0", + "react-hot-toast": "^2.4.1", "react-icons": "^4.8.0", "react-router-dom": "^6.14.2", "react-scripts": "5.0.1", diff --git a/package.json b/package.json index 334c917..7d961ce 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "moment": "^2.29.4", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-hot-toast": "^2.4.0", + "react-hot-toast": "^2.4.1", "react-icons": "^4.8.0", "react-router-dom": "^6.14.2", "react-scripts": "5.0.1", diff --git a/src/api/posts.js b/src/api/posts.js index 1046063..381f369 100644 --- a/src/api/posts.js +++ b/src/api/posts.js @@ -6,6 +6,8 @@ const DeletePost = process.env.REACT_APP_POST_DELETE; const PostId = process.env.REACT_APP_POST_ID; + + export const getPostsRequest = async () => await axios.get(PostUrl, {}); diff --git a/src/components/PostCard.jsx b/src/components/PostCard.jsx index 8ee23a7..58e39f6 100644 --- a/src/components/PostCard.jsx +++ b/src/components/PostCard.jsx @@ -27,7 +27,7 @@ export function insertMedia(filePath) { } } -export function PostCard({ post, user }) { +export function PostCard({ post }) { const { deletePost } = usePosts(); const navigate = useNavigate(); @@ -38,8 +38,7 @@ export function PostCard({ post, user }) { (t) => (

- {" "} - Do you want to Delete? {id} + Do you want to Delete? {post.title}

@@ -84,20 +97,21 @@ export function PostCard({ post, user }) {
- {" "} diff --git a/src/components/RequiresAuth.jsx b/src/components/RequiresAuth.jsx index ae66dfd..53565e7 100644 --- a/src/components/RequiresAuth.jsx +++ b/src/components/RequiresAuth.jsx @@ -1,14 +1,16 @@ -import React from 'react' +import React from "react"; import { useLocation, Navigate, Outlet } from "react-router-dom"; import useAuth from "../hooks/useAuth"; -const RequiresAuth = ( {allowedRoles } ) => { - const { auth }= useAuth() - const location = useLocation() - - return ( - auth?.roles?.find(role => allowedRoles?.includes(role.name)) ? : - ) -} +const RequiresAuth = ({ allowedRoles }) => { + const { auth } = useAuth(); + const location = useLocation(); -export default RequiresAuth; \ No newline at end of file + return auth?.roles?.find((role) => allowedRoles?.includes(role.name)) ? ( + + ) : ( + + ); +}; + +export default RequiresAuth; diff --git a/src/components/signup/Signup.jsx b/src/components/signup/Signup.jsx index 2d1d18d..e9e4e81 100644 --- a/src/components/signup/Signup.jsx +++ b/src/components/signup/Signup.jsx @@ -87,13 +87,8 @@ const Signup = () => { />
- +

{error}

- {error && ( -
- {error} -
- )}
- {error && ( -
- {error} -
- )} + {error} diff --git a/src/pages/PostForm.js b/src/pages/PostForm.js index 0ae5673..c3ace26 100644 --- a/src/pages/PostForm.js +++ b/src/pages/PostForm.js @@ -3,7 +3,8 @@ import { usePosts } from "../context/postContext"; import { useNavigate, useParams, Link } from "react-router-dom"; import * as Yup from "yup"; import { useEffect, useState } from "react"; - +import { Toaster, toast } from "react-hot-toast"; +import { getPostsRequest } from "../api/posts"; export function PostForm() { const { createPost, getPost, updatePost } = usePosts(); const navigate = useNavigate(); @@ -51,8 +52,17 @@ export function PostForm() { } else { await createPost(values); } + + try { + + toast.success("Post saved successfully and posts list updated!"); + } catch (error) { + toast.error("Error updating posts list."); + } + actions.setSubmitting(false); navigate("/admin"); + await getPostsRequest(); }} enableReinitialize > @@ -108,19 +118,13 @@ export function PostForm() { +
+
+
Processing...
+
) : ( "Save" )} @@ -128,6 +132,7 @@ export function PostForm() { )} +
); From 30d2cc79e3d045865de1d35323964e37e179dd15 Mon Sep 17 00:00:00 2001 From: Edwin Mendoza Rodriguez <49256757+Edwin6666@users.noreply.github.com> Date: Tue, 19 Sep 2023 11:28:43 -0400 Subject: [PATCH 03/35] feat (auth): user data protected by cookies (#27) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Delete Environment Variables * Fix README * Fix Title README * Feat Clone funcionality in README * Delete Clone documentacion README * Feat author in README * Feat when we do Crud operation in the project * Fix wrong button conditional * Refactor console.log in code * Delete Console and use semantic html in Postcard * Refactor semantic html * Feat display of registered users * Feat: Implementing persistence authentication using cookies 🍪 Details: In this commit, persistent authentication has been implemented using cookies to maintain the user's session between sessions. This allows users to remain authenticated even after restarting the page or closing the browser. User data is now securely stored in a cookie, improving user experience and ensuring smooth browsing. -When editing a post it is displayed automatically without having to restart the page 🐞 A critical bug has also been fixed: -The bug that caused user data to be lost when restarting the page has been resolved. Previously, users experienced the annoyance of having to log in again every time they reloaded the page. Now, user data is properly maintained thanks to the persistence of cookies, providing a smoother and more satisfying experience. This commit marks an important step towards a more robust and reliable user experience! 🚀 * Fix: Login or logout in the nabvar depending on the session -Resolution of a bug that did not show whether the session had been logged in or not * Delete Console * Fix: bug that made infinite calls to the backend * Fix: (Nabvar): improving navigation based on permissions Details: The navigation bar has been changed according to each view, now the admin should not see the user view --- package-lock.json | 9 +++++ package.json | 1 + src/App.js | 3 +- src/api/posts.js | 21 ++++++----- src/components/Navbar/Navbar.jsx | 35 +++++++++++++----- src/components/RequiresAuth.jsx | 13 +++++-- src/context/AuthProvider.js | 3 ++ src/context/postContext.js | 18 +++++++--- src/hooks/useAuthentication.js | 28 +++++++++------ src/index.js | 2 ++ src/pages/HomePage.js | 8 ++++- src/pages/HomePageUser.js | 9 +++-- src/pages/Users.js | 61 ++++++++++++++++++++++++++++++++ 13 files changed, 172 insertions(+), 39 deletions(-) create mode 100644 src/pages/Users.js diff --git a/package-lock.json b/package-lock.json index fa71499..fdb425a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "eslint": "^8.43.0", "eslint-config-react-app": "^7.0.1", "formik": "^2.2.9", + "js-cookie": "^3.0.5", "jsonwebtoken": "^9.0.0", "moment": "^2.29.4", "react": "^18.2.0", @@ -11688,6 +11689,14 @@ "jiti": "bin/jiti.js" } }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "engines": { + "node": ">=14" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", diff --git a/package.json b/package.json index 7d961ce..bf64568 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "eslint": "^8.43.0", "eslint-config-react-app": "^7.0.1", "formik": "^2.2.9", + "js-cookie": "^3.0.5", "jsonwebtoken": "^9.0.0", "moment": "^2.29.4", "react": "^18.2.0", diff --git a/src/App.js b/src/App.js index a604abb..1a36b23 100644 --- a/src/App.js +++ b/src/App.js @@ -9,7 +9,7 @@ import { HomePageUser } from "./pages/HomePageUser"; import Navbar from "./components/Navbar/Navbar"; import ContactForm from "./pages/Contact"; import { Carousel } from "./components/Carousel/Carousel"; - +import UserList from "./pages/Users"; function App() { return ( @@ -29,6 +29,7 @@ function App() { } /> } /> } /> + } /> {/* Catch all */} diff --git a/src/api/posts.js b/src/api/posts.js index 381f369..7059e98 100644 --- a/src/api/posts.js +++ b/src/api/posts.js @@ -1,4 +1,5 @@ import axios from "axios"; +import Cookies from "js-cookie"; const PostUrl = process.env.REACT_APP_POST_URL; const UpdatePost = process.env.REACT_APP_UPDATE_POST; @@ -7,11 +8,15 @@ const PostId = process.env.REACT_APP_POST_ID; +const getTokenFromCookie = () => { + return Cookies.get("token") || ""; +}; + export const getPostsRequest = async () => await axios.get(PostUrl, {}); -export const createPostRequest = async (post, token) => { +export const createPostRequest = async (post) => { const form = new FormData(); for (let key in post) { @@ -21,24 +26,24 @@ export const createPostRequest = async (post, token) => { return await axios.post(PostUrl, form, { headers: { "Content-Type": "multipart/form-data", - - Authorization: `Bearer ${token}`, + Authorization: `Bearer ${getTokenFromCookie()}`, }, }); }; -export const deletePostRequest = async (id, token) => +export const deletePostRequest = async (id) => await axios.delete(DeletePost + id, { headers: { - Authorization: `Bearer ${token}`, + Authorization: `Bearer ${getTokenFromCookie()}`, }, }); export const getPostRequest = async (id) => await axios.get(PostId + id); - export const updatePostRequest = async (id, newFields, token) => + +export const updatePostRequest = async (id, newFields) => await axios.put(`${UpdatePost}/${id}`, newFields, { headers: { - Authorization: `Bearer ${token}`, + Authorization: `Bearer ${getTokenFromCookie()}`, }, - }); \ No newline at end of file + }); diff --git a/src/components/Navbar/Navbar.jsx b/src/components/Navbar/Navbar.jsx index 0497621..b53a610 100644 --- a/src/components/Navbar/Navbar.jsx +++ b/src/components/Navbar/Navbar.jsx @@ -3,6 +3,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faSignOutAlt } from "@fortawesome/free-solid-svg-icons"; import { Link, useLocation } from "react-router-dom"; import useAuth from "../../hooks/useAuth"; +import Cookies from 'js-cookie'; const Navbar = () => { const location = useLocation(); @@ -10,10 +11,14 @@ const Navbar = () => { const isHomePage = location.pathname === "/"; const isFormPage = location.pathname === "/new"; const isAdminPage = location.pathname === "/admin"; - const { setAuth, auth } = useAuth(); + const userListPage = location.pathname === "/users" + const isContactPage = location.pathname === "/contact" + const { setAuth } = useAuth(); const handleLogout = () => { setAuth({ roles: null, token: null }); + Cookies.remove('token'); + Cookies.remove('roles'); window.location = "/login"; }; @@ -60,12 +65,14 @@ const Navbar = () => { open ? "flex" : "hidden" } pb-4 md:pb-0 md:flex md:justify-end md:flex-row navbar-transition animate-flip-down duration-700`} > - - Home - + {!isAdminPage && !isFormPage && !userListPage && ( + + Home + + )} {!isHomePage && isAdminPage && ( { )} - {!isHomePage && isFormPage && ( + {!isHomePage && isFormPage && !isContactPage && ( { Admin Page )} + + {!isHomePage && isAdminPage &&( + + Users List + + )} + {isHomePage && ( { className="flex flex-row text-gray-900 bg-gray-200 items-center w-full px-4 py-2 mt-2 text-sm font-semibold text-left bg-transparent rounded-lg dark-mode:bg-transparent dark-mode:focus:text-white dark-mode:hover:text-white dark-mode:focus:bg-gray-600 dark-mode:hover:bg-gray-600 md:w-auto md:inline md:mt-0 md:ml-4 hover:text-gray-900 focus:text-gray-900 hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:shadow-outline " onClick={handleLogout} > - {auth.token ? "Logout" : "Login"}{" "} + {Cookies.get('token') ? "Logout" : "Login"}{" "} diff --git a/src/components/RequiresAuth.jsx b/src/components/RequiresAuth.jsx index 53565e7..5a47988 100644 --- a/src/components/RequiresAuth.jsx +++ b/src/components/RequiresAuth.jsx @@ -1,12 +1,19 @@ import React from "react"; import { useLocation, Navigate, Outlet } from "react-router-dom"; -import useAuth from "../hooks/useAuth"; + +import Cookies from "js-cookie"; const RequiresAuth = ({ allowedRoles }) => { - const { auth } = useAuth(); const location = useLocation(); - return auth?.roles?.find((role) => allowedRoles?.includes(role.name)) ? ( + const userRoles = Cookies.get("roles"); + + const isAuthorized = + userRoles && + allowedRoles.some((allowedRole) => userRoles.includes(allowedRole)); + + return isAuthorized ? ( + ) : ( diff --git a/src/context/AuthProvider.js b/src/context/AuthProvider.js index 9388742..f95265c 100644 --- a/src/context/AuthProvider.js +++ b/src/context/AuthProvider.js @@ -1,11 +1,14 @@ import React from "react"; import { createContext, useState } from "react"; + const AuthContext = createContext({}); export const AuthProvider = ({ children }) => { const [auth, setAuth] = useState({}); + + return ( {children} diff --git a/src/context/postContext.js b/src/context/postContext.js index f85a5ed..635162d 100644 --- a/src/context/postContext.js +++ b/src/context/postContext.js @@ -1,4 +1,4 @@ -import { useState, createContext, useContext, useEffect } from "react"; +import { useState, createContext, useContext } from "react"; import { getPostsRequest, createPostRequest, @@ -7,6 +7,7 @@ import { updatePostRequest, } from "../api/posts"; import useAuth from "../hooks/useAuth"; +import { toast } from "react-hot-toast"; export const postContext = createContext(); @@ -19,12 +20,14 @@ export const PostProvider = ({ children }) => { const [posts, setPosts] = useState([]); const { auth } = useAuth(); - useEffect(() => { - (async () => { + const getAllPost = async () => { + try { const res = await getPostsRequest(); setPosts(res.data); - })(); - }, []); + } catch (error) { + toast.error(error); + } + } const createPost = async (post) => { try { @@ -38,6 +41,7 @@ export const PostProvider = ({ children }) => { const deletePost = async (id) => { await deletePostRequest(id, auth.token); setPosts(posts.filter((post) => post._id !== id)); + getAllPost() }; const getPost = async (id) => { @@ -53,12 +57,16 @@ export const PostProvider = ({ children }) => { const updatePost = async (id, post) => { const res = await updatePostRequest(id, post, auth.token); setPosts(posts.map((post) => (post.id === id ? res.data : post))); + + getAllPost() + }; return ( { - const { setAuth } = useAuth(); const navigate = useNavigate(); const LoginUrl = process.env.REACT_APP_API_LOGIN; + const authenticate = async (data) => { try { const url = LoginUrl; const { data: res } = await axios.post(url, data); const roles = res?.roles; const token = res?.token; - setAuth({ roles, token }); - + + + if (!roles || !token) { + throw new Error("No roles or token received in response."); + } + + Cookies.set("token", token, { secure: true, sameSite: "strict" }); + + if (roles === "admin") { navigate("/"); } else { navigate("/admin"); } } catch (error) { - if ( - error.response && - error.response.status >= 400 && - error.response.status <= 500 - ) { - return error.response.data.message; + if (error.response) { + if (error.response.status === 401) { + toast.error("invalid credential"); + } else if (error.response.status === 500) { + toast.error("internal server error"); + } } } }; diff --git a/src/index.js b/src/index.js index 81592b2..3eebc9d 100644 --- a/src/index.js +++ b/src/index.js @@ -5,6 +5,8 @@ import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; import { BrowserRouter, Routes, Route } from 'react-router-dom'; +import axios from 'axios'; +axios.defaults.withCredentials = true; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( diff --git a/src/pages/HomePage.js b/src/pages/HomePage.js index 90666cf..8feee22 100644 --- a/src/pages/HomePage.js +++ b/src/pages/HomePage.js @@ -1,10 +1,16 @@ +import { useEffect } from "react"; import { usePosts } from "../context/postContext"; import { VscEmptyWindow } from 'react-icons/vsc' import { PostCard } from "../components/PostCard"; export function HomePage() { - const { posts } = usePosts(); + const { posts, getAllPost } = usePosts(); + + useEffect(() => { + getAllPost(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); if (posts.length === 0) { return ( diff --git a/src/pages/HomePageUser.js b/src/pages/HomePageUser.js index 2d117e0..e9c5f6a 100644 --- a/src/pages/HomePageUser.js +++ b/src/pages/HomePageUser.js @@ -1,10 +1,15 @@ +import { useEffect } from "react"; import { usePosts } from "../context/postContext"; import { VscEmptyWindow } from 'react-icons/vsc' import { PostCardUser } from "../components/PostCardUser"; export function HomePageUser() { - const { posts } = usePosts(); - + const { posts, getAllPost } = usePosts(); + + useEffect(() => { + getAllPost() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) if (posts.length === 0) return (
diff --git a/src/pages/Users.js b/src/pages/Users.js new file mode 100644 index 0000000..1c2dc22 --- /dev/null +++ b/src/pages/Users.js @@ -0,0 +1,61 @@ +import React, { useEffect, useState } from "react"; +import axios from "axios"; + +function UserList() { + const [users, setUsers] = useState([]); + + + useEffect(() => { + axios + .get("http://localhost:4000/api/users") + .then((response) => { + setUsers(response.data); + }) + .catch((error) => { + + }); + }, []); + + return ( +
+
+

+ Users List +

+
+ + + + + + + + + + + + {users.map((user) => ( + + + + + + + + + + ))} + +
UsernameEmailRolDateEdit
{user.username}{user.email} + {user.roles}{user.createdAt} + +
+
+
+
+ ); +} + +export default UserList; From 4d001de358e5e5bcb8298383fbdf6cf80ac63f9d Mon Sep 17 00:00:00 2001 From: Edwin Mendoza Rodriguez <49256757+Edwin6666@users.noreply.github.com> Date: Tue, 19 Sep 2023 22:40:56 -0400 Subject: [PATCH 04/35] Fix: navigate to home by clicking on the logo (#28) --- src/components/Navbar/Navbar.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Navbar/Navbar.jsx b/src/components/Navbar/Navbar.jsx index b53a610..f9419b5 100644 --- a/src/components/Navbar/Navbar.jsx +++ b/src/components/Navbar/Navbar.jsx @@ -34,7 +34,7 @@ const Navbar = () => {
TechTalk News From 8afe00a46ebf0aa5c9a59e6acc3220747c5e497a Mon Sep 17 00:00:00 2001 From: Edwin Mendoza Rodriguez <49256757+Edwin6666@users.noreply.github.com> Date: Wed, 27 Sep 2023 13:56:06 -0400 Subject: [PATCH 05/35] refactor changing HTML tags for semantic tags (#29) * Fix: navigate to home by clicking on the logo * Refactor semantic html in login and navbar * feat(semantics): Change HTML tags for semantic tags Replaced most non-semantic HTML tags in the code by appropriate semantic tags to improve the structure and content accessibility. * Fix warning in cosole * Fix The admin cannot have the user view and vice versa. --- src/components/Login/Login.jsx | 41 ++++----- src/components/Navbar/Navbar.jsx | 46 ++++++----- src/components/PostCard.jsx | 8 +- src/components/PostCardUser.jsx | 20 ++--- src/components/signup/Signup.jsx | 32 ++++--- src/components/signup/SignupForm.js | 124 +++++++++++++--------------- src/pages/Contact.js | 12 +-- src/pages/HomePage.js | 23 +++--- src/pages/NotFoundPage.js | 4 +- src/pages/PostForm.js | 12 +-- src/pages/Users.js | 10 +-- 11 files changed, 151 insertions(+), 181 deletions(-) diff --git a/src/components/Login/Login.jsx b/src/components/Login/Login.jsx index eb47b3a..f570819 100644 --- a/src/components/Login/Login.jsx +++ b/src/components/Login/Login.jsx @@ -17,41 +17,35 @@ const Signin = () => { return (
-
+
-
-

TechTalk News

+
+

TechTalk News

Welcome to TechTalk, the go-to social network for technology and news enthusiasts! Here, you can connect with a passionate community that shares your interests and discover the latest trends in the digital world.

-
+
-
+ -
+
); }; + export default Signin; diff --git a/src/components/Navbar/Navbar.jsx b/src/components/Navbar/Navbar.jsx index f9419b5..256182e 100644 --- a/src/components/Navbar/Navbar.jsx +++ b/src/components/Navbar/Navbar.jsx @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faSignOutAlt } from "@fortawesome/free-solid-svg-icons"; import { Link, useLocation } from "react-router-dom"; import useAuth from "../../hooks/useAuth"; -import Cookies from 'js-cookie'; +import Cookies from "js-cookie"; const Navbar = () => { const location = useLocation(); @@ -11,14 +11,15 @@ const Navbar = () => { const isHomePage = location.pathname === "/"; const isFormPage = location.pathname === "/new"; const isAdminPage = location.pathname === "/admin"; - const userListPage = location.pathname === "/users" - const isContactPage = location.pathname === "/contact" + const userListPage = location.pathname === "/users"; + const isContactPage = location.pathname === "/contact"; + const { setAuth } = useAuth(); const handleLogout = () => { setAuth({ roles: null, token: null }); - Cookies.remove('token'); - Cookies.remove('roles'); + Cookies.remove("token"); + Cookies.remove("roles"); window.location = "/login"; }; @@ -27,10 +28,13 @@ const Navbar = () => { const toggleMenu = () => { setOpen(!open); }; + if (isLoginPage) { + return null; + } return ( -
-
+
+
-
-
+ + ); }; diff --git a/src/components/PostCard.jsx b/src/components/PostCard.jsx index 58e39f6..3121254 100644 --- a/src/components/PostCard.jsx +++ b/src/components/PostCard.jsx @@ -83,8 +83,8 @@ export function PostCard({ post }) { }; return ( -
-
+
+
img Logo
@@ -116,7 +116,7 @@ export function PostCard({ post }) {
-
+
{post.image && insertMedia(post.image.url)} @@ -126,6 +126,6 @@ export function PostCard({ post }) { {post.description}

-
+ ); } diff --git a/src/components/PostCardUser.jsx b/src/components/PostCardUser.jsx index 021a655..ba2a790 100644 --- a/src/components/PostCardUser.jsx +++ b/src/components/PostCardUser.jsx @@ -4,11 +4,10 @@ import logoImg from "../Images/postimg.jpg"; export function PostCardUser({ post }) { const normalDate = moment(post.createdAt).format("DD/MM/YYYY"); + return ( - -
- -
+
+
logo
@@ -16,7 +15,6 @@ export function PostCardUser({ post }) { TechTalk

- {normalDate}

@@ -33,18 +31,20 @@ export function PostCardUser({ post }) { strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" - d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z " + d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z" />
-
+ + {post.image && insertMedia(post.image.url)}

{post.title}

-

{post.description}

+

+ {post.description} +

-
- + ); } diff --git a/src/components/signup/Signup.jsx b/src/components/signup/Signup.jsx index e9e4e81..56b8074 100644 --- a/src/components/signup/Signup.jsx +++ b/src/components/signup/Signup.jsx @@ -5,16 +5,16 @@ const Signup = () => { const { data, error, handleChange, handleSubmit } = useSignupLogic(); return ( -
-
-
+
+
+
Join us Now -
-
+ +

Enter your credentials to get access account -

+

-
+
-
-
- -
+

+ + ); }; diff --git a/src/components/signup/SignupForm.js b/src/components/signup/SignupForm.js index 238008b..6c8372d 100644 --- a/src/components/signup/SignupForm.js +++ b/src/components/signup/SignupForm.js @@ -3,7 +3,7 @@ import useForm from "../../hooks/useForm"; import useAuth from "../../hooks/useAuth"; import axios from "axios"; import toast from 'react-hot-toast'; - +import Cookies from 'js-cookie' const SignupForm = ({ onSuccess }) => { const initialState = { username: "", @@ -22,6 +22,7 @@ const SignupForm = ({ onSuccess }) => { const roles = res?.roles; const token = res?.token; setAuth({ roles, token }); + Cookies.set("token", token, { secure: true, sameSite: "strict" }); resetForm(); onSuccess(); } catch (error) { @@ -38,80 +39,67 @@ const SignupForm = ({ onSuccess }) => { return (
-
- -
-
- -
- + +
+
+
+
-
- -
-
- -
- + + +
+
+
+
-
- -
-
- - - -
- + + +
+
+ + +
+
- {error} + {error}