From 0966b3a40bc231de486efcc0eff3038bdca524a8 Mon Sep 17 00:00:00 2001 From: Markus Cadonau Date: Thu, 30 Mar 2023 17:48:35 +0200 Subject: [PATCH 1/4] Add login component and use environment variables for credentials etc. --- .gitignore | 5 +---- README.md | 15 +++++++++++++ src/App.js | 5 +++++ src/pages/Login.js | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 src/pages/Login.js diff --git a/.gitignore b/.gitignore index 4d29575..fa0f49a 100644 --- a/.gitignore +++ b/.gitignore @@ -13,10 +13,7 @@ # misc .DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local +.env* npm-debug.log* yarn-debug.log* diff --git a/README.md b/README.md index 58beeac..5738062 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,18 @@ +# Exercise in Preparation for MBU's IPA + +## Development + +To use the 4D Test API add a `.env.development` file and include the following lines replacing `` and ``: + + REACT_APP_API_URL= + REACT_APP_API_AUTH_CREDENTIALS= + +### Debugging + +To use a JetBrains IDE to debug, see: [Debugging React Apps Created With Create React App in WebStorm](https://blog.jetbrains.com/webstorm/2017/01/debugging-react-apps/) + +*** + # Getting Started with Create React App This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). diff --git a/src/App.js b/src/App.js index 34e6679..400db74 100644 --- a/src/App.js +++ b/src/App.js @@ -4,6 +4,7 @@ import Home from './pages/Home'; import Tagesmenu from './pages/Tagesmenu' import { createBrowserRouter, RouterProvider } from 'react-router-dom'; import LunchMenu from "./pages/LunchMenu"; +import Login from "./pages/Login"; function App() { @@ -20,6 +21,10 @@ function App() { { path: "/lunch-menu", element: + }, + { + path: "/login", + element: } ]); diff --git a/src/pages/Login.js b/src/pages/Login.js new file mode 100644 index 0000000..26c79e3 --- /dev/null +++ b/src/pages/Login.js @@ -0,0 +1,56 @@ +import {useState} from "react"; + +export default function Login() { + + const [username, setUsername] = useState(""); + const [password, setPassword] = useState(""); + + function handleUsernameChange(event) { + setUsername(event.target.value); + } + + function handlePasswordChange(event) { + setPassword(event.target.value); + } + + function handleSubmit(event) { + event.preventDefault(); + // cf. https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#uploading_json_data + // cf. https://create-react-app.dev/docs/adding-custom-environment-variables/ + fetch(`${process.env.REACT_APP_API_URL}/authentication/login`, { + method: "POST", + headers: { + Authorization: `Basic ${process.env.REACT_APP_API_AUTH_CREDENTIALS}`, + "Content-Type": "application/json" + }, + body: JSON.stringify({ + username, + password + }) + }) + .then(r => r.json()) + .then( + data => { + console.log(data); + // cf. https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage + localStorage.setItem("auth", data?.authToken); + } + ) + .catch(error => console.error(error)); + } + + return ( + // cf. https://getbootstrap.com/docs/5.2/forms/overview/ +
+ + + + + +
+ ); +} From a19911dbd07ce813813dfd26c9928e9624145946 Mon Sep 17 00:00:00 2001 From: Markus Cadonau Date: Thu, 30 Mar 2023 18:05:41 +0200 Subject: [PATCH 2/4] Add potential error message --- src/pages/Login.js | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/pages/Login.js b/src/pages/Login.js index 26c79e3..57cb890 100644 --- a/src/pages/Login.js +++ b/src/pages/Login.js @@ -5,6 +5,8 @@ export default function Login() { const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); + const [errorMessage, setErrorMessage] = useState(""); + function handleUsernameChange(event) { setUsername(event.target.value); } @@ -32,25 +34,35 @@ export default function Login() { .then( data => { console.log(data); - // cf. https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage - localStorage.setItem("auth", data?.authToken); + if (data && data.authToken) { + // cf. https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage + localStorage.setItem("auth", data?.authToken); + setErrorMessage(""); + } else { + setErrorMessage(data.message); + } } ) .catch(error => console.error(error)); } return ( - // cf. https://getbootstrap.com/docs/5.2/forms/overview/ -
- - - - - -
+ <> + {/*cf. https://getbootstrap.com/docs/5.2/forms/overview/*/} +
+ + + + + +
+
+ {errorMessage} +
+ ); } From 3d4615da71389483d554228cebee863c72fc5831 Mon Sep 17 00:00:00 2001 From: Markus Cadonau Date: Thu, 30 Mar 2023 18:15:18 +0200 Subject: [PATCH 3/4] Navigate to home page after successful login --- src/pages/Login.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/Login.js b/src/pages/Login.js index 57cb890..74b92dd 100644 --- a/src/pages/Login.js +++ b/src/pages/Login.js @@ -1,4 +1,5 @@ import {useState} from "react"; +import {useNavigate} from "react-router-dom"; export default function Login() { @@ -7,6 +8,8 @@ export default function Login() { const [errorMessage, setErrorMessage] = useState(""); + const navigate = useNavigate(); + function handleUsernameChange(event) { setUsername(event.target.value); } @@ -38,6 +41,7 @@ export default function Login() { // cf. https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage localStorage.setItem("auth", data?.authToken); setErrorMessage(""); + navigate("/"); } else { setErrorMessage(data.message); } From 6ead2b44cbdcadc84a88ad13112840f60422e220 Mon Sep 17 00:00:00 2001 From: Markus Cadonau Date: Fri, 31 Mar 2023 00:37:24 +0200 Subject: [PATCH 4/4] Use async/await to handle login submit --- src/pages/Login.js | 55 +++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/src/pages/Login.js b/src/pages/Login.js index 74b92dd..8cdd2fd 100644 --- a/src/pages/Login.js +++ b/src/pages/Login.js @@ -18,36 +18,35 @@ export default function Login() { setPassword(event.target.value); } - function handleSubmit(event) { + async function handleSubmit(event) { event.preventDefault(); // cf. https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#uploading_json_data - // cf. https://create-react-app.dev/docs/adding-custom-environment-variables/ - fetch(`${process.env.REACT_APP_API_URL}/authentication/login`, { - method: "POST", - headers: { - Authorization: `Basic ${process.env.REACT_APP_API_AUTH_CREDENTIALS}`, - "Content-Type": "application/json" - }, - body: JSON.stringify({ - username, - password - }) - }) - .then(r => r.json()) - .then( - data => { - console.log(data); - if (data && data.authToken) { - // cf. https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage - localStorage.setItem("auth", data?.authToken); - setErrorMessage(""); - navigate("/"); - } else { - setErrorMessage(data.message); - } - } - ) - .catch(error => console.error(error)); + try { + // cf. https://create-react-app.dev/docs/adding-custom-environment-variables/ + const response = await fetch(`${process.env.REACT_APP_API_URL}/authentication/login`, { + method: "POST", + headers: { + Authorization: `Basic ${process.env.REACT_APP_API_AUTH_CREDENTIALS}`, + "Content-Type": "application/json" + }, + body: JSON.stringify({ + username, + password + }) + }); + const data = await response.json(); + console.log(data); + if (data && data.authToken) { + // cf. https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage + localStorage.setItem("auth", data?.authToken); + setErrorMessage(""); + navigate("/"); + } else { + setErrorMessage(data.message); + } + } catch (error) { + console.error(error); + } } return (