Skip to content
169 changes: 164 additions & 5 deletions frontend/src/main-page/users/ApprovedUserCard.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,179 @@
import UserPositionCard from "./UserPositionCard";
import { Button, Menu } from "@chakra-ui/react";
import { FaEllipsisVertical } from "react-icons/fa6";
import { UserStatus } from "../../../../middle-layer/types/UserStatus";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faPencil, faTrash } from "@fortawesome/free-solid-svg-icons";
import ActionConfirmation from "../../custom/ActionConfirmation";
import { useState } from "react";
import { api } from "../../api";
import { User } from "../../../../middle-layer/types/User";
import { toJS } from "mobx";
import { getAppStore } from "../../external/bcanSatchel/store";
import { setActiveUsers } from "../../external/bcanSatchel/actions";

interface ApprovedUserCardProps {
name: string;
userId: string;
email: string;
position: string;
position: UserStatus;
}

const ApprovedUserCard = ({ name, email, position }: ApprovedUserCardProps) => {
const ApprovedUserCard = ({
userId,
email,
position,
}: ApprovedUserCardProps) => {
const store = getAppStore();
const [isChangeGroupModalOpen, setIsChangeGroupModalOpen] = useState(false);
const [isDeleteUserModalOpen, setIsDeleteUserModalOpen] = useState(false);

const changeUserGroup = async () => {
console.log(
`Changing user ${userId} to ${
position === UserStatus.Admin ? "employee" : "admin"
}...`
);

try {
const response = await api("/user/change-role", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
user: {
userId,
email,
position,
} as User,
groupName:
position === UserStatus.Admin
? UserStatus.Employee
: UserStatus.Admin,
requestedBy: toJS(store.user) as User,
}),
});

if (response.ok) {
console.log(
`User ${userId} successfully changed to ${
position === UserStatus.Admin ? "employee" : "admin"
}`
);
alert(
`User ${userId} successfully changed to ${
position === UserStatus.Admin ? "employee" : "admin"
}`
);
const updatedUser = await response.json();
setActiveUsers([...store.activeUsers.filter(u => u.userId !== userId), updatedUser as User]);

setIsChangeGroupModalOpen(false);
} else {
const errorBody = await response.json();
console.error("Error: ", errorBody)
}
} catch (error) {
console.error("Error changing user group: ", error);
}
};

const deleteUser = async () => {
try {
const response = await api("user/delete-user", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
user: {
userId,
email,
position,
} as User,
requestedBy: toJS(store.user) as User,
}),
});

if (response.ok) {
console.log(`User ${userId} has been deleted successfully`);
alert(`User ${userId} has been deleted successfully`);
setActiveUsers(store.activeUsers.filter(u => u.userId !== userId));

} else {
const errorBody = await response.json();
console.error("Error: ", errorBody)
alert("Failed to delete user");
}
setIsDeleteUserModalOpen(false);
} catch (error) {
console.error("Error deleting user:", error);
alert("Error deleting user");
}
};

return (
<div className="bg-white text-lg border rounded-md m-6 p-6 flex justify-around items-center">
<p className="font-semibold w-[140px] text-left">{name}</p>
<p className="w-[140px] text-left">xxxxxxx</p>
<ActionConfirmation
isOpen={isChangeGroupModalOpen}
onCloseDelete={() => setIsChangeGroupModalOpen(false)}
onConfirmDelete={changeUserGroup}
title={`Change User to ${
position === UserStatus.Admin ? "Employee" : "Admin"
}`}
subtitle="Are you sure you want to change to"
boldSubtitle={position === UserStatus.Admin ? "employee" : "admin"}
warningMessage={`By changing to ${
position === UserStatus.Admin ? "employee" : "admin"
}, they will ${
position === UserStatus.Admin
? "gain access to sensitive data."
: "lose access to admin pages."
}`}
/>
<ActionConfirmation
isOpen={isDeleteUserModalOpen}
onCloseDelete={() => setIsDeleteUserModalOpen(false)}
onConfirmDelete={deleteUser}
title="Delete User"
subtitle="Are you sure you want to delete"
boldSubtitle={userId}
warningMessage="By deleting this user, they won't be available in the system anymore."
/>
<p className="font-semibold w-[140px] text-left">{userId}</p>
<p className="w-[140px] text-left">{email}</p>
<div className="w-[140px]">
<UserPositionCard position={position} />
</div>
<div className="absolute right-14">
<Menu.Root>
<Menu.Trigger>
<Button
variant="ghost"
className="focus:outline-none hover:border-none transition-none"
>
<FaEllipsisVertical />
</Button>
</Menu.Trigger>
<Menu.Positioner>
<Menu.Content>
<Button
px={4}
className="text-sm focus:outline-none block w-full bg-[#D3D3D3] border-[#666666] text-[#666666] mb-1"
onClick={() => setIsChangeGroupModalOpen(true)}
>
Change to {position === UserStatus.Admin ? "employee" : "admin"}
{" "}
<FontAwesomeIcon icon={faPencil} />
</Button>
<Button
px={4}
className="text-sm focus:outline-none block w-full bg-[#FFDFDF] border-[#D33221] text-[#D33221]"
onClick={() => setIsDeleteUserModalOpen(true)}
>
Delete user{" "}
<FontAwesomeIcon icon={faTrash} />
</Button>
</Menu.Content>
</Menu.Positioner>
</Menu.Root>
</div>
</div>
);
};
Expand Down
21 changes: 10 additions & 11 deletions frontend/src/main-page/users/PendingUserCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ import { useState } from "react";
const store = getAppStore();

interface PendingUserCardProps {
name: string;
userId: string;
email: string;
position: string;
position: UserStatus;
}


const PendingUserCard = ({
name,
userId,
email,
position,
}: PendingUserCardProps) => {
Expand All @@ -35,16 +35,16 @@ const PendingUserCard = ({
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
user: {
userId: name,
email: email,
position: position as UserStatus,
userId,
email,
position
} as User,
groupName: "Employee",
requestedBy: toJS(store.user) as User,
}),
});
if (response.ok) {
alert(`User ${name} has been approved successfully`);
alert(`User ${userId} has been approved successfully`);
const body = await response.json();
moveUserToActive(body as User)
} else {
Expand All @@ -66,9 +66,9 @@ const PendingUserCard = ({
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
user: {
userId: name,
userId,
email: email,
position: position as UserStatus,
position,
} as User,
requestedBy: toJS(store.user) as User,
}),
Expand All @@ -90,8 +90,7 @@ const PendingUserCard = ({

return (
<div className="bg-white text-lg border rounded-md m-6 p-6 flex justify-around items-center">
<p className="font-semibold w-[140px] text-left">{name}</p>
<p className="w-[140px] text-left">xxxxxxx</p>
<p className="font-semibold w-[140px] text-left">{userId}</p>
<p className="w-[140px] text-left">{email}</p>
<div className="w-[140px]">
<UserPositionCard position={position} />
Expand Down
12 changes: 5 additions & 7 deletions frontend/src/main-page/users/UserPositionCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,17 @@ import { useMemo } from "react";
import { UserStatus } from "../../../../middle-layer/types/UserStatus";

interface UserPositionCardProps {
position: string;
position: UserStatus;
}

const UserPositionCard = ({ position }: UserPositionCardProps) => {
const cardStyles = useMemo(() => {
switch (position.toLowerCase()) {
case "Admin" as UserStatus:
switch (position) {
case UserStatus.Admin:
return "bg-[#BCFFD8] border-[#119548] text-[#119548]";
case "Employee" as UserStatus:
case UserStatus.Employee:
return "bg-[#FFF8CA] border-[#F8CC16] text-[#8a710c]";
case "deactive":
return "bg-[#FFB0B0] border-[#DF0404] text-[#DF0404]";
case "Inactive" as UserStatus:
case UserStatus.Inactive:
default:
return "bg-[#D3D3D3] border-[#666666] text-[#666666]";
}
Expand Down
Loading