From 37066c9e1b70b4957aa8bb30bd62850d09ce3bb1 Mon Sep 17 00:00:00 2001 From: ozerodb <50593663+ozerodb@users.noreply.github.com> Date: Wed, 3 Jan 2024 13:35:45 +0100 Subject: [PATCH] refactored frontend following best practices --- frontend/index.html | 104 ++++++----------- frontend/public/hkn_logo_white_vector.svg | 74 ++++++++++++ frontend/public/notfound404.jpg | Bin 0 -> 37104 bytes frontend/src/App.css | 85 ++------------ frontend/src/App.css.old | 82 ++++++++++++++ frontend/src/App.jsx | 105 ++++++++---------- frontend/src/Auth0ProviderWithNavigate.jsx | 32 ++++++ frontend/src/LoginButton.tsx | 22 ---- frontend/src/MyNavbar.jsx | 47 -------- .../ApplyForm.jsx.old} | 0 frontend/src/components/AuthGuard.jsx | 17 +++ .../AvailabilitiesCell.jsx} | 0 .../AvailabilitiesTable.jsx} | 18 +-- frontend/src/components/HKNavbar.jsx | 74 ++++++++++++ frontend/src/components/HomeButton.jsx | 15 +++ frontend/src/components/LoadingSpinner.jsx | 11 ++ frontend/src/components/LoginButton.jsx | 23 ++++ frontend/src/components/LogoutButton.jsx | 19 ++++ frontend/src/components/PageHeader.jsx | 14 +++ frontend/src/components/PageLayout.jsx | 17 +++ frontend/src/index.css | 4 - frontend/src/index.jsx | 17 +++ frontend/src/logo.svg | 1 - frontend/src/main.jsx | 21 ---- frontend/src/pages/ApplyPage.jsx | 13 +++ frontend/src/pages/AvailabilitiesPage.jsx | 32 ++++++ frontend/src/pages/DebugPage.jsx | 41 +++++++ frontend/src/pages/HomePage.jsx | 36 ++++++ frontend/src/pages/NotFoundPage.jsx | 14 +++ .../src/{ApiRequests.tsx => services/API.ts} | 0 30 files changed, 629 insertions(+), 309 deletions(-) create mode 100644 frontend/public/hkn_logo_white_vector.svg create mode 100644 frontend/public/notfound404.jpg create mode 100644 frontend/src/App.css.old create mode 100644 frontend/src/Auth0ProviderWithNavigate.jsx delete mode 100644 frontend/src/LoginButton.tsx delete mode 100644 frontend/src/MyNavbar.jsx rename frontend/src/{SignupForm.jsx => components/ApplyForm.jsx.old} (100%) create mode 100644 frontend/src/components/AuthGuard.jsx rename frontend/src/{AvaiabilitiesCell.jsx => components/AvailabilitiesCell.jsx} (100%) rename frontend/src/{AvaiabilitiesTable.tsx => components/AvailabilitiesTable.jsx} (94%) create mode 100644 frontend/src/components/HKNavbar.jsx create mode 100644 frontend/src/components/HomeButton.jsx create mode 100644 frontend/src/components/LoadingSpinner.jsx create mode 100644 frontend/src/components/LoginButton.jsx create mode 100644 frontend/src/components/LogoutButton.jsx create mode 100644 frontend/src/components/PageHeader.jsx create mode 100644 frontend/src/components/PageLayout.jsx create mode 100644 frontend/src/index.jsx delete mode 100644 frontend/src/logo.svg delete mode 100644 frontend/src/main.jsx create mode 100644 frontend/src/pages/ApplyPage.jsx create mode 100644 frontend/src/pages/AvailabilitiesPage.jsx create mode 100644 frontend/src/pages/DebugPage.jsx create mode 100644 frontend/src/pages/HomePage.jsx create mode 100644 frontend/src/pages/NotFoundPage.jsx rename frontend/src/{ApiRequests.tsx => services/API.ts} (100%) diff --git a/frontend/index.html b/frontend/index.html index 191149a..e8f3372 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -1,71 +1,39 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - HKRecruitment - - - -
- - - + + + + + + + + + + + + + + + + + + + + + + + + + + + HKRecruitment + + + + +
+ + + + \ No newline at end of file diff --git a/frontend/public/hkn_logo_white_vector.svg b/frontend/public/hkn_logo_white_vector.svg new file mode 100644 index 0000000..e894e19 --- /dev/null +++ b/frontend/public/hkn_logo_white_vector.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/public/notfound404.jpg b/frontend/public/notfound404.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0c0862874aebdddeb2b2d48f7c649308fdac1054 GIT binary patch literal 37104 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 thead { - vertical-align: bottom; - background-color: rgba(55, 81, 113, 1); -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } +a { + color: var(--hkwhite); } diff --git a/frontend/src/App.css.old b/frontend/src/App.css.old new file mode 100644 index 0000000..7c12824 --- /dev/null +++ b/frontend/src/App.css.old @@ -0,0 +1,82 @@ +.App { + text-align: center; +} + +.App-logo { + height: 40vmin; + pointer-events: none; +} + +@media (prefers-reduced-motion: no-preference) { + .App-logo { + animation: App-logo-spin infinite 20s linear; + } +} + +.App-header { + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: black; +} +.active { + background: green !important; + color: white !important; +} + +.App-link { + color: #61dafb; +} + +.black { + color: white; + background-color: #282c34; + background: #282c34; +} + +.pink { + color: black; + background-color: pink; + background: pink; +} + +.submitButton { + background-color: #00629b !important; + background: #00629b !important; +} +.myNavbar { + background-color: #f9f9f9; +} +.table { + --bs-table-bg: rgba(55, 81, 113, 0.8) !important ; + --bs-table-accent-bg: transparent; + --bs-table-striped-color: white !important; + --bs-table-striped-bg: rgba(55, 81, 113, 0.8) !important ; + --bs-table-active-color: white !important; + --bs-table-active-bg: rgba(0, 0, 0, 0.1); + --bs-table-hover-color: white !important ; + --bs-table-hover-bg: rgba(0, 0, 0, 0.075); + width: 100%; + margin-bottom: 1rem; + color: white important!; + vertical-align: top; + border-color: #dee2e6; +} + +.table > thead { + vertical-align: bottom; + background-color: rgba(55, 81, 113, 1); +} + +@keyframes App-logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 7c17f28..f602f42 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,70 +1,55 @@ -import "./App.css"; -import "bootstrap/dist/css/bootstrap.min.css"; -import React, { useEffect, useState } from "react"; -import MyNavbar from "./MyNavbar"; -import SignupForm from "./SignupForm"; -import { Route } from "react-router-dom"; -import { Navigate } from "react-router-dom"; -import { Routes } from "react-router-dom"; +import React from "react"; +import { Route, Routes } from "react-router-dom"; import { useAuth0 } from "@auth0/auth0-react"; -import AvaiabilitiesTable from "./AvaiabilitiesTable"; -function App() { - function parseJwt(token) { - return JSON.parse(Buffer.from(token.split(".")[1], "base64").toString()); - } +import Alert from "react-bootstrap/Alert"; - const { - isLoading, - isAuthenticated, - error, - user, - loginWithRedirect, - logout, - getAccessTokenSilently, - } = useAuth0(); +import HKNavbar from "./components/HKNavbar"; +import PageLayout from "./components/PageLayout"; +import LoadingSpinner from "./components/LoadingSpinner"; +import AuthGuard from "./components/AuthGuard"; - const [accessToken, setAccessToken] = useState(""); +import HomePage from "./pages/HomePage"; +import ApplyPage from "./pages/ApplyPage"; +import AvailabilitiesPage from "./pages/AvailabilitiesPage"; +import DebugPage from "./pages/DebugPage"; +import NotFoundPage from "./pages/NotFoundPage"; - useEffect(() => { - if (isAuthenticated) { - getAccessTokenSilently({ - audience: import.meta.env.VITE_AUTH0_AUDIENCE, - grant_type: "client_credentials", - }).then((token) => { - setAccessToken(parseJwt(token)); - }); - } - }, [isAuthenticated]); +import "./App.css"; - return ( - - - } - /> - } /> - - ); -} -export default App; +function App() { + const { isLoading } = useAuth0(); -function AfterLogin(props) { return ( -
- {" "} - - {props.isAuthenticated && - !props.user.email.endsWith("@hknpolito.org") && } - {props.isAuthenticated && props.user.email.endsWith("@hknpolito.org") && ( - - )} -
+ <> + + + + Note: all of this is work-in-progress, stuff will change! + + {isLoading ? ( + + ) : ( + + } /> + } + /> + } + /> + } + /> + } /> + + )} + + ); } + +export default App; diff --git a/frontend/src/Auth0ProviderWithNavigate.jsx b/frontend/src/Auth0ProviderWithNavigate.jsx new file mode 100644 index 0000000..24ab643 --- /dev/null +++ b/frontend/src/Auth0ProviderWithNavigate.jsx @@ -0,0 +1,32 @@ +import { Auth0Provider } from "@auth0/auth0-react"; +import React from "react"; +import { useNavigate } from "react-router-dom"; + +export const Auth0ProviderWithNavigate = ({ children }) => { + const navigate = useNavigate(); + + const domain = import.meta.env.VITE_AUTH0_DOMAIN; + const clientId = import.meta.env.VITE_AUTH0_CLIENTID; + const audience = import.meta.env.VITE_AUTH0_AUDIENCE; + const redirectUri = window.location.origin; + + const onRedirectCallback = (appState) => { + navigate(appState?.returnTo || window.location.pathname); + }; + + if (!(domain && clientId && redirectUri)) { + return null; + } + + return ( + + {children} + + ); +}; diff --git a/frontend/src/LoginButton.tsx b/frontend/src/LoginButton.tsx deleted file mode 100644 index be1df82..0000000 --- a/frontend/src/LoginButton.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from "react"; -import { useAuth0 } from "@auth0/auth0-react"; -import Button from "react-bootstrap/Button"; - -const LoginButton = () => { - const { isAuthenticated, loginWithRedirect, logout } = useAuth0(); - - return ( - - ); -}; - -export default LoginButton; diff --git a/frontend/src/MyNavbar.jsx b/frontend/src/MyNavbar.jsx deleted file mode 100644 index 44bc283..0000000 --- a/frontend/src/MyNavbar.jsx +++ /dev/null @@ -1,47 +0,0 @@ -import React, { ReactPropTypes } from "react"; -import Navbar from "react-bootstrap/Navbar"; -import Container from "react-bootstrap/Container"; -import Row from "react-bootstrap/Row"; -import LoginButton from "./LoginButton"; - -import Col from "react-bootstrap/Col"; -import { useAuth0 } from "@auth0/auth0-react"; - -const MyNavbar = (props) => { - const { isLoading, isAuthenticated, error, user, loginWithRedirect, logout } = - useAuth0(); - - return ( - - - - - - {" "} - HKRecruitment - - - - {" "} -

- {isAuthenticated - ? "Hello " + user.name.split(" ")[0] + "!" - : "Login"} -

- - - - -
-
-
- ); -}; - -export default MyNavbar; diff --git a/frontend/src/SignupForm.jsx b/frontend/src/components/ApplyForm.jsx.old similarity index 100% rename from frontend/src/SignupForm.jsx rename to frontend/src/components/ApplyForm.jsx.old diff --git a/frontend/src/components/AuthGuard.jsx b/frontend/src/components/AuthGuard.jsx new file mode 100644 index 0000000..4034e33 --- /dev/null +++ b/frontend/src/components/AuthGuard.jsx @@ -0,0 +1,17 @@ +import { withAuthenticationRequired } from "@auth0/auth0-react"; +import React from "react"; +import LoadingSpinner from "./LoadingSpinner"; + +const AuthGuard = ({ component }) => { + const Component = withAuthenticationRequired(component, { + onRedirecting: () => ( +
+ +
+ ), + }); + + return ; +}; + +export default AuthGuard; diff --git a/frontend/src/AvaiabilitiesCell.jsx b/frontend/src/components/AvailabilitiesCell.jsx similarity index 100% rename from frontend/src/AvaiabilitiesCell.jsx rename to frontend/src/components/AvailabilitiesCell.jsx diff --git a/frontend/src/AvaiabilitiesTable.tsx b/frontend/src/components/AvailabilitiesTable.jsx similarity index 94% rename from frontend/src/AvaiabilitiesTable.tsx rename to frontend/src/components/AvailabilitiesTable.jsx index 712b46b..fff90b3 100644 --- a/frontend/src/AvaiabilitiesTable.tsx +++ b/frontend/src/components/AvailabilitiesTable.jsx @@ -2,12 +2,12 @@ import Table from "react-bootstrap/Table"; import Container from "react-bootstrap/Container"; import Row from "react-bootstrap/Row"; import Col from "react-bootstrap/Col"; -import AvaiabilitiesCell from "./AvaiabilitiesCell"; +import AvaiabilitiesCell from "./AvailabilitiesCell"; import moment from "moment"; import { useState, useEffect } from "react"; import { createUserSchema } from "@hkrecruitment/shared"; import React from "react"; -import { getApplicants, getUsers, getInterviewsByDates } from "./ApiRequests"; +// import { getApplicants, getUsers, getInterviewsByDates } from "../services/API"; function AvaiabilitiesTable(props) { //const start = "2014-09-08T08:00:00"; @@ -29,13 +29,13 @@ function AvaiabilitiesTable(props) { // Suppongo che interviews restituisca un array di colloqui fissati in un certo periodo, ciascuno con data e ora const [interviews, setInterviews] = useState(null); - useEffect(() => { - if (startDate !== null) { - setInterviews( - getInterviewsByDates(startDate.getDate(), startDate.getDate() + 7) - ); - } - }, [startDate]); + // useEffect(() => { + // if (startDate !== null) { + // setInterviews( + // getInterviewsByDates(startDate.getDate(), startDate.getDate() + 7) + // ); + // } + // }, [startDate]); // Crea una matrice 16x7 a partire dalle interviste let fill = [[], []]; diff --git a/frontend/src/components/HKNavbar.jsx b/frontend/src/components/HKNavbar.jsx new file mode 100644 index 0000000..2e63ebe --- /dev/null +++ b/frontend/src/components/HKNavbar.jsx @@ -0,0 +1,74 @@ +import React from "react"; +import { useAuth0 } from "@auth0/auth0-react"; + +import Navbar from "react-bootstrap/Navbar"; +import Container from "react-bootstrap/Container"; +import Row from "react-bootstrap/Row"; +import Image from "react-bootstrap/Image"; +import { Link } from "react-router-dom"; +import Col from "react-bootstrap/Col"; +import NavDropdown from "react-bootstrap/NavDropdown"; + +import LogoutButton from "./LogoutButton"; +import LoginButton from "./LoginButton"; +import LoadingSpinner from "./LoadingSpinner"; + +const HKNavbar = () => { + const { isLoading, isAuthenticated, user } = useAuth0(); + + return ( + + + + + + + Home + + + + + +

HKRecruitment

+ + + + {isLoading ? ( + + ) : !isAuthenticated ? ( + + ) : ( + <> + + } + > + {user.name} + + + + + )} + +
+
+
+ ); +}; + +export default HKNavbar; diff --git a/frontend/src/components/HomeButton.jsx b/frontend/src/components/HomeButton.jsx new file mode 100644 index 0000000..008af93 --- /dev/null +++ b/frontend/src/components/HomeButton.jsx @@ -0,0 +1,15 @@ +import React from "react"; +import { Link } from "react-router-dom"; +import { Button } from "react-bootstrap"; + +const HomeButton = () => { + return ( + + + + ); +}; + +export default HomeButton; diff --git a/frontend/src/components/LoadingSpinner.jsx b/frontend/src/components/LoadingSpinner.jsx new file mode 100644 index 0000000..0a73893 --- /dev/null +++ b/frontend/src/components/LoadingSpinner.jsx @@ -0,0 +1,11 @@ +import { Spinner } from "react-bootstrap"; + +const LoadingSpinner = () => { + return ( +
+ +
+ ); +}; + +export default LoadingSpinner; diff --git a/frontend/src/components/LoginButton.jsx b/frontend/src/components/LoginButton.jsx new file mode 100644 index 0000000..2014a16 --- /dev/null +++ b/frontend/src/components/LoginButton.jsx @@ -0,0 +1,23 @@ +import React from "react"; +import { Button } from "react-bootstrap"; +import { useAuth0 } from "@auth0/auth0-react"; + +const LoginButton = () => { + const { loginWithRedirect } = useAuth0(); + + const handleLogin = async () => { + await loginWithRedirect({ + appState: { + returnTo: window.location.pathname, + }, + }); + }; + + return ( + + ); +}; + +export default LoginButton; diff --git a/frontend/src/components/LogoutButton.jsx b/frontend/src/components/LogoutButton.jsx new file mode 100644 index 0000000..7d5ca55 --- /dev/null +++ b/frontend/src/components/LogoutButton.jsx @@ -0,0 +1,19 @@ +import React from "react"; +import { Button } from "react-bootstrap"; +import { useAuth0 } from "@auth0/auth0-react"; + +const LogoutButton = () => { + const { logout } = useAuth0(); + + const handleLogout = () => { + logout({ + logoutParams: { + returnTo: window.location.origin, + }, + }); + }; + + return ; +}; + +export default LogoutButton; diff --git a/frontend/src/components/PageHeader.jsx b/frontend/src/components/PageHeader.jsx new file mode 100644 index 0000000..84c8e64 --- /dev/null +++ b/frontend/src/components/PageHeader.jsx @@ -0,0 +1,14 @@ +import React from "react"; +import { Container } from "react-bootstrap"; +import HomeButton from "./HomeButton"; + +const PageHeader = ({ children }) => { + return ( + + +

{children}

+
+ ); +}; + +export default PageHeader; diff --git a/frontend/src/components/PageLayout.jsx b/frontend/src/components/PageLayout.jsx new file mode 100644 index 0000000..c31625a --- /dev/null +++ b/frontend/src/components/PageLayout.jsx @@ -0,0 +1,17 @@ +import React from "react"; +import { Container, Row, Col } from "react-bootstrap"; + +const PageLayout = ({ children }) => { + return ( + + + + {/* Main content column (takes 8 columns on medium-sized screens and larger) */} + {children} + + + + ); +}; + +export default PageLayout; diff --git a/frontend/src/index.css b/frontend/src/index.css index 7183f7b..4a1df4d 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -11,7 +11,3 @@ code { font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } - -.active { - color: green; -} diff --git a/frontend/src/index.jsx b/frontend/src/index.jsx new file mode 100644 index 0000000..c0dee18 --- /dev/null +++ b/frontend/src/index.jsx @@ -0,0 +1,17 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import { BrowserRouter } from "react-router-dom"; +import { Auth0ProviderWithNavigate } from "./Auth0ProviderWithNavigate"; +import "./index.css"; +import "bootstrap/dist/css/bootstrap.min.css"; +import App from "./App"; + +ReactDOM.createRoot(document.getElementById("root")).render( + + + + + + + +); diff --git a/frontend/src/logo.svg b/frontend/src/logo.svg deleted file mode 100644 index 9dfc1c0..0000000 --- a/frontend/src/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx deleted file mode 100644 index 3a52bed..0000000 --- a/frontend/src/main.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from "react"; -import ReactDOM from "react-dom/client"; -import "./index.css"; -import App from "./App"; -import { BrowserRouter } from "react-router-dom"; -import { Auth0Provider } from "@auth0/auth0-react"; - -ReactDOM.createRoot(document.getElementById("root")).render( - - - - - - - -); diff --git a/frontend/src/pages/ApplyPage.jsx b/frontend/src/pages/ApplyPage.jsx new file mode 100644 index 0000000..a957be8 --- /dev/null +++ b/frontend/src/pages/ApplyPage.jsx @@ -0,0 +1,13 @@ +import React from "react"; +import PageHeader from "../components/PageHeader"; + +function ApplyPage() { + return ( + <> + Apply +

This page will be used by non-members to apply.

+ + ); +} + +export default ApplyPage; diff --git a/frontend/src/pages/AvailabilitiesPage.jsx b/frontend/src/pages/AvailabilitiesPage.jsx new file mode 100644 index 0000000..6c97699 --- /dev/null +++ b/frontend/src/pages/AvailabilitiesPage.jsx @@ -0,0 +1,32 @@ +import React, { useEffect, useState } from "react"; +import { useAuth0 } from "@auth0/auth0-react"; +import AvailabilitiesTable from "../components/AvailabilitiesTable"; +import PageHeader from "../components/PageHeader"; + +function AvailabilitiesPage() { + const { isAuthenticated, getAccessTokenSilently } = useAuth0(); + const [accessToken, setAccessToken] = useState(""); + + /* AUTH */ + useEffect(() => { + if (isAuthenticated) { + getAccessTokenSilently({ + audience: import.meta.env.VITE_AUTH0_AUDIENCE, + grant_type: "client_credentials", + }).then((token) => { + setAccessToken(token); + }); + } + }, [isAuthenticated]); + + return ( + <> + Availabilities +

This page will be used by members to manage their availabilities.

+ + + + ); +} + +export default AvailabilitiesPage; diff --git a/frontend/src/pages/DebugPage.jsx b/frontend/src/pages/DebugPage.jsx new file mode 100644 index 0000000..6012989 --- /dev/null +++ b/frontend/src/pages/DebugPage.jsx @@ -0,0 +1,41 @@ +import React, { useEffect, useState } from "react"; +import PageHeader from "../components/PageHeader"; +import { useAuth0 } from "@auth0/auth0-react"; +import Accordion from "react-bootstrap/Accordion"; + +function DebugPage() { + const { isAuthenticated, user, getAccessTokenSilently } = useAuth0(); + const [accessToken, setAccessToken] = useState(""); + + /* AUTH */ + useEffect(() => { + if (isAuthenticated) { + getAccessTokenSilently({ + audience: import.meta.env.VITE_AUTH0_AUDIENCE, + grant_type: "client_credentials", + }).then((token) => { + setAccessToken(token); + }); + } + }, [isAuthenticated]); + + return ( + <> + Debug + + + User info + +
{JSON.stringify(user, null, 2)}
+
+
+ + Access Token + {accessToken} + +
+ + ); +} + +export default DebugPage; diff --git a/frontend/src/pages/HomePage.jsx b/frontend/src/pages/HomePage.jsx new file mode 100644 index 0000000..da2da34 --- /dev/null +++ b/frontend/src/pages/HomePage.jsx @@ -0,0 +1,36 @@ +import React from "react"; +import { Link } from "react-router-dom"; +import { useAuth0 } from "@auth0/auth0-react"; + +function HomePage() { + const { isAuthenticated, user } = useAuth0(); + + return ( + <> + {isAuthenticated ? ( +

Welcome, {user.given_name}.

+ ) : ( +

Welcome, anonymous.

+ )} +

This is the HKN Polito Recruitment Platform.

+ + {isAuthenticated ? ( + <> +
+

Available pages:

+ Apply +
+ Availabilities +
+ Debug + + ) : ( + <> +

To get started, please login.

+ + )} + + ); +} + +export default HomePage; diff --git a/frontend/src/pages/NotFoundPage.jsx b/frontend/src/pages/NotFoundPage.jsx new file mode 100644 index 0000000..266765b --- /dev/null +++ b/frontend/src/pages/NotFoundPage.jsx @@ -0,0 +1,14 @@ +import React from "react"; +import Image from "react-bootstrap/Image"; +import PageHeader from "../components/PageHeader"; + +function NotFoundPage() { + return ( + <> + 404 - Page not found + + + ); +} + +export default NotFoundPage; diff --git a/frontend/src/ApiRequests.tsx b/frontend/src/services/API.ts similarity index 100% rename from frontend/src/ApiRequests.tsx rename to frontend/src/services/API.ts