diff --git a/client/package-lock.json b/client/package-lock.json index f7bb226f..ab169765 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -24,7 +24,9 @@ "react-dom": "^18.2.0", "react-router-dom": "^6.17.0", "react-scripts": "5.0.1", - "typescript": "^5.2.2", + "react-toastify": "^9.1.3", + "toastify-js": "^1.12.0", + "typescript": "^4.9.5", "web-vitals": "^2.1.4" } }, @@ -15338,6 +15340,26 @@ } } }, + "node_modules/react-toastify": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz", + "integrity": "sha512-fPfb8ghtn/XMxw3LkxQBk3IyagNpF/LIKjOBflbexr2AWxAH1MJgvnESwEwBn9liLFXgTKWgBSdZpw9m4OTHTg==", + "dependencies": { + "clsx": "^1.1.1" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, + "node_modules/react-toastify/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -17041,6 +17063,11 @@ "node": ">=8.0" } }, + "node_modules/toastify-js": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/toastify-js/-/toastify-js-1.12.0.tgz", + "integrity": "sha512-HeMHCO9yLPvP9k0apGSdPUWrUbLnxUKNFzgUoZp1PHCLploIX/4DSQ7V8H25ef+h4iO9n0he7ImfcndnN6nDrQ==" + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -17258,15 +17285,15 @@ } }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=14.17" + "node": ">=4.2.0" } }, "node_modules/unbox-primitive": { @@ -29187,6 +29214,21 @@ "workbox-webpack-plugin": "^6.4.1" } }, + "react-toastify": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz", + "integrity": "sha512-fPfb8ghtn/XMxw3LkxQBk3IyagNpF/LIKjOBflbexr2AWxAH1MJgvnESwEwBn9liLFXgTKWgBSdZpw9m4OTHTg==", + "requires": { + "clsx": "^1.1.1" + }, + "dependencies": { + "clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==" + } + } + }, "react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -30440,6 +30482,11 @@ "is-number": "^7.0.0" } }, + "toastify-js": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/toastify-js/-/toastify-js-1.12.0.tgz", + "integrity": "sha512-HeMHCO9yLPvP9k0apGSdPUWrUbLnxUKNFzgUoZp1PHCLploIX/4DSQ7V8H25ef+h4iO9n0he7ImfcndnN6nDrQ==" + }, "toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -30606,9 +30653,9 @@ } }, "typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==" + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" }, "unbox-primitive": { "version": "1.0.2", diff --git a/client/package.json b/client/package.json index de12ca33..0dba8c8b 100644 --- a/client/package.json +++ b/client/package.json @@ -19,7 +19,9 @@ "react-dom": "^18.2.0", "react-router-dom": "^6.17.0", "react-scripts": "5.0.1", - "typescript": "^5.2.2", + "react-toastify": "^9.1.3", + "toastify-js": "^1.12.0", + "typescript": "^4.9.5", "web-vitals": "^2.1.4" }, "scripts": { diff --git a/client/src/App.tsx b/client/src/App.tsx index 06874267..dc00a55b 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -7,14 +7,34 @@ import Login from "./components/authentication/Login"; import SignUp from "./components/authentication/SignUp"; import "./App.css"; +import { ToastContainer } from "react-toastify"; +import { getToken } from "./utils/localStorageUtils"; const App = () => { + // TODO: Find a way to validate token + // TODO: use userToken to restrict access for not logged in status + const userToken = getToken(); + return ( - - } /> - } /> - } /> - + <> + + + } /> + } /> + } /> + + ); }; diff --git a/client/src/components/authentication/Login.tsx b/client/src/components/authentication/Login.tsx index 51119fa6..147f3ac0 100644 --- a/client/src/components/authentication/Login.tsx +++ b/client/src/components/authentication/Login.tsx @@ -1,4 +1,4 @@ -import React, { FormEvent } from "react"; +import React, { FormEvent, useState } from "react"; import Button from "@mui/material/Button"; import CssBaseline from "@mui/material/CssBaseline"; @@ -8,8 +8,42 @@ import Box from "@mui/material/Box"; import Typography from "@mui/material/Typography"; import Container from "@mui/material/Container"; +import { toast } from "react-toastify"; +import { useNavigate } from "react-router-dom"; +import axios from "axios"; + +import { storeToken } from "../../utils/localStorageUtils"; + const Login = () => { + const navigate = useNavigate(); + const [formData, setFormData] = useState({ + username: "", + password: "", + }); + const handleSubmit = (e: FormEvent) => { + e.preventDefault(); + + const requestUrl = "http://127.0.0.1:8000/socialdistribution/login/"; + + const form = new FormData(); + form.append("username", formData.username); + form.append("password", formData.password); + + axios + .post(requestUrl, form, { + headers: { "Content-Type": "multipart/form-data" }, + }) + .then((response: any) => { + storeToken(response.data.token); + + toast.success("You are now logged in"); + + navigate("/home-page"); + }) + .catch((error) => { + toast.error("Wrong password or user does not exist"); + }); return; }; @@ -18,7 +52,6 @@ const Login = () => { { margin="normal" required fullWidth - id="email" - label="Email" - name="email" - autoComplete="email" + id="username" + label="Username" + name="username" + autoComplete="username" autoFocus + onChange={(e) => { + setFormData({ ...formData, username: e.target.value }); + }} /> { label="Password" type="password" id="password" + onChange={(e) => { + setFormData({ ...formData, password: e.target.value }); + }} />