From 71cb9bdff687c7e9b2345b189f5062153e427fc5 Mon Sep 17 00:00:00 2001 From: minhtrannhat Date: Fri, 21 Jul 2023 22:37:28 -0400 Subject: [PATCH] Feat(Frontend): Added Routing --- frontend/package-lock.json | 39 +++++++++++++++++++++++++ frontend/package.json | 1 + frontend/src/App.tsx | 7 ++++- frontend/src/Router.tsx | 9 ++++++ frontend/src/components/RequireAuth.tsx | 22 ++++++++++++++ frontend/src/components/ScrollToTop.tsx | 16 ++++++++++ frontend/src/setupTests.ts | 4 +++ 7 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 frontend/src/Router.tsx create mode 100644 frontend/src/components/RequireAuth.tsx create mode 100644 frontend/src/components/ScrollToTop.tsx diff --git a/frontend/package-lock.json b/frontend/package-lock.json index accc93b..6deaaa1 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -23,6 +23,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-helmet-async": "^1.3.0", + "react-router-dom": "^6.14.2", "react-scripts": "^5.0.1", "typescript": "^4.9.5", "web-vitals": "^2.1.4", @@ -3743,6 +3744,14 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@remix-run/router": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.7.2.tgz", + "integrity": "sha512-7Lcn7IqGMV+vizMPoEl5F0XDshcdDYtMI6uJLQdQz5CfZAwy3vvGKYSUk789qndt5dEC4HfSjviSYlSoHGL2+A==", + "engines": { + "node": ">=14" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -15342,6 +15351,36 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.14.2.tgz", + "integrity": "sha512-09Zss2dE2z+T1D03IheqAFtK4UzQyX8nFPWx6jkwdYzGLXd5ie06A6ezS2fO6zJfEb/SpG6UocN2O1hfD+2urQ==", + "dependencies": { + "@remix-run/router": "1.7.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.14.2.tgz", + "integrity": "sha512-5pWX0jdKR48XFZBuJqHosX3AAHjRAzygouMTyimnBPOLdY3WjzUSKhus2FVMihUFWzeLebDgr4r8UeQFAct7Bg==", + "dependencies": { + "@remix-run/router": "1.7.2", + "react-router": "6.14.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 640e87a..ebb2717 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -18,6 +18,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-helmet-async": "^1.3.0", + "react-router-dom": "^6.14.2", "react-scripts": "^5.0.1", "typescript": "^4.9.5", "web-vitals": "^2.1.4", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index df77705..b4555a2 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -19,6 +19,9 @@ import { Helmet, HelmetProvider } from "react-helmet-async"; // Authentication Context: Check if user is logged in or not import { AuthContextProvider } from "./AuthContext"; +// React router +import Router from "./Router"; + function App() { return ( @@ -27,7 +30,9 @@ function App() { Todo - + + + diff --git a/frontend/src/Router.tsx b/frontend/src/Router.tsx new file mode 100644 index 0000000..76746c4 --- /dev/null +++ b/frontend/src/Router.tsx @@ -0,0 +1,9 @@ +import { BrowserRouter, Routes } from "react-router-dom"; + +const Router = () => { + + {} + ; +}; + +export default Router; diff --git a/frontend/src/components/RequireAuth.tsx b/frontend/src/components/RequireAuth.tsx new file mode 100644 index 0000000..3648393 --- /dev/null +++ b/frontend/src/components/RequireAuth.tsx @@ -0,0 +1,22 @@ +import { useContext } from "react"; +import { Navigate, useLocation } from "react-router-dom"; +import { AuthContext } from "src/AuthContext"; + +interface IProps { + children: React.ReactNode; +} + +const RequireAuth = ({ children }: IProps) => { + const { authenticated } = useContext(AuthContext); + + const location = useLocation(); + + if (authenticated) { + return <>{children}; + } else { + // re-route user back to login page if not logged in + return ; + } +}; + +export default RequireAuth; diff --git a/frontend/src/components/ScrollToTop.tsx b/frontend/src/components/ScrollToTop.tsx new file mode 100644 index 0000000..47a604b --- /dev/null +++ b/frontend/src/components/ScrollToTop.tsx @@ -0,0 +1,16 @@ +import { useEffect } from "react"; +import { useLocation } from "react-router"; + +const ScrollToTop = () => { + const { pathname } = useLocation(); + + // pathname changes => scroll to top + // scrolling only on navigation + useEffect(() => { + window.scrollTo(0, 0); + }, [pathname]); + + return null; +}; + +export default ScrollToTop; diff --git a/frontend/src/setupTests.ts b/frontend/src/setupTests.ts index 1dd407a..350a8fd 100644 --- a/frontend/src/setupTests.ts +++ b/frontend/src/setupTests.ts @@ -3,3 +3,7 @@ // expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom import "@testing-library/jest-dom"; + +window.scrollTo = (x, y) => { + document.documentElement.scrollTop = y; +};