diff --git a/client/src/components/UpdateAccountModule.tsx b/client/src/components/UpdateAccountModule.tsx index 4f8eb0a..13d16be 100644 --- a/client/src/components/UpdateAccountModule.tsx +++ b/client/src/components/UpdateAccountModule.tsx @@ -3,7 +3,7 @@ import * as Yup from "yup"; import config from "../config"; import { useEffect, useState } from "react"; import { retrieveUserInformation } from "../security/users"; -import { Button } from "@nextui-org/react"; +import { Accordion, AccordionItem, Button } from "@nextui-org/react"; import { Form, Formik } from "formik"; import NextUIFormikInput from "./NextUIFormikInput"; import { PencilSquareIcon } from "../icons"; @@ -83,89 +83,153 @@ export default function UpdateAccountModule({ phoneNumber: "", }; + const archiveAccount = () => { + axios + .put( + config.serverAddress + "/users/archive/" + userInformation.id, + null, + { + headers: { + Authorization: `Bearer ${accessToken}`, + }, + } + ) + .then(() => { + navigate("/login"); + }) + .catch((err) => { + console.log("Archive failed: " + err); + }); + }; + return (
{userInformation && ( -
- - {({ isValid, dirty }) => ( -
-
-

Update your information

-
- - -
-
-
-
-
- - -
-
- - - +65 -

- } - /> +
+
+ + {({ isValid, dirty }) => ( + +
+

+ Update your information +

+
+ +
-
-
-
- +
+
+
+ + +
+
+ + + +65 +

+ } + /> +
+
+
+
+
+ +
+ + )} + +
+
+ + +

More actions

+

+ Click to show more options collapsed for security + purposes. +

+
+ } + className="rounded-xl -m-2 px-4 py-2 bg-neutral-100 dark:bg-neutral-800 border-2 border-transparent hover:border-neutral-200 dark:hover:border-neutral-700 transition-colors" + > +
+
+

Danger zone

+

+ These actions may be destructive. Proceed with caution. +

+
+
+ + +
- - )} - + + +
)}
diff --git a/client/src/pages/ManageUserAccountPage.tsx b/client/src/pages/ManageUserAccountPage.tsx index 4405c85..d60a676 100644 --- a/client/src/pages/ManageUserAccountPage.tsx +++ b/client/src/pages/ManageUserAccountPage.tsx @@ -1,7 +1,6 @@ import { useParams } from "react-router-dom"; import DefaultLayout from "../layouts/default"; import UpdateAccountModule from "../components/UpdateAccountModule"; -import { Accordion, AccordionItem, Button } from "@nextui-org/react"; export default function ManageUserAccountPage() { let { accessToken } = useParams(); // TODO: Replace AT from props with AT from localstorage @@ -11,31 +10,6 @@ export default function ManageUserAccountPage() {
- - -
-
-

Danger zone

-

- These actions may be destructive. Proceed with caution. -

-
-
- - -
-
-
-
diff --git a/server/models/User.js b/server/models/User.js index c9f2d58..55d3564 100644 --- a/server/models/User.js +++ b/server/models/User.js @@ -27,6 +27,10 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.STRING(100), allowNull: false, }, + isArchived: { + type: DataTypes.BOOLEAN(), + allowNull: false, + }, }, { tableName: "users", diff --git a/server/routes/users.js b/server/routes/users.js index 20e0a87..43c41a7 100644 --- a/server/routes/users.js +++ b/server/routes/users.js @@ -39,11 +39,16 @@ let optionalValidationSchema = yup.object({ router.post("/register", async (req, res) => { let data = req.body; - let user = await User.findOne({ + + let userByEmail = await User.findOne({ where: { email: data.email }, }); - if (user) { - res.status(400).json({ message: "Email already exists." }); + let userByNumber = await User.findOne({ + where: { phoneNumber: data.phoneNumber }, + }); + + if (userByEmail || userByNumber) { + res.status(400).json({ message: "Email or phone number already exists." }); return; } try { @@ -83,11 +88,19 @@ router.get("/all", async (req, res) => { router.get("/individual/:id", validateToken, async (req, res) => { let id = req.params.id; let user = await User.findByPk(id); + if (!user) { res.sendStatus(404); return; } - res.json(user); + + if (user.isArchived) { + res.status(400).json({ + message: `Account ${id} is archived.`, + }); + } else { + res.json(user); + } }); router.put("/individual/:id", validateToken, async (req, res) => { @@ -188,4 +201,28 @@ router.get("/auth", validateToken, (req, res) => { }); }); +router.put("/archive/:id", validateToken, async (req, res) => { + let id = req.params.id; + let user = await User.findByPk(id); + + if (!user) { + res.sendStatus(404); + return; + } + + try { + await User.update( + { isArchived: true }, + { + where: { id: id }, + } + ); + res.json({ + message: "User archived successfully.", + }); + } catch (err) { + res.status(400).json({ errors: err.errors }); + } +}); + module.exports = router;