From 3d20af24c932ed5be54c686e4ab1c16d1d546e75 Mon Sep 17 00:00:00 2001 From: Keannu Bernasol Date: Thu, 14 Dec 2023 14:52:50 +0800 Subject: [PATCH] Added conditional rendering to dashboard page and restrict certain pages select user types --- src/App.tsx | 6 + src/Components/API/API.tsx | 3 +- .../DashboardPage/TechnicianButtons.tsx | 261 ++++++++++ .../DashboardPage/TechnicianLogs.tsx | 94 ++++ .../DashboardPage/TechnicianWidgets.tsx | 180 +++++++ .../RestrictedComponent.tsx | 21 + .../RestrictedPage/RestrictedPage.tsx | 46 ++ src/Components/Types/Types.tsx | 10 + src/Pages/DashboardPage/DashboardPage.tsx | 493 +----------------- 9 files changed, 646 insertions(+), 468 deletions(-) create mode 100644 src/Components/DashboardPage/TechnicianButtons.tsx create mode 100644 src/Components/DashboardPage/TechnicianLogs.tsx create mode 100644 src/Components/DashboardPage/TechnicianWidgets.tsx create mode 100644 src/Components/RestrictedComponent/RestrictedComponent.tsx create mode 100644 src/Components/RestrictedPage/RestrictedPage.tsx diff --git a/src/App.tsx b/src/App.tsx index e5c926d..605f029 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -16,6 +16,7 @@ import EquipmentListPage from "./Pages/EquipmentListPage/EquipmentListPage"; import EquipmentLogsPage from "./Pages/EquipmentLogsPage/EquipmentLogsPage"; import EquipmentInstanceLogsPage from "./Pages/EquipmentInstanceLogsPage/EquipmentInstanceLogsPage"; import EquipmentInstancesFilteredListPage from "./Pages/EquipmentInstancesListPage/EquipmentInstancesFilteredListPage"; +import RestrictedPage from "./Components/RestrictedPage/RestrictedPage"; const queryClient = new QueryClient(); const router = createHashRouter([ @@ -44,6 +45,7 @@ const router = createHashRouter([ element: ( <> + ), @@ -54,6 +56,7 @@ const router = createHashRouter([ element: ( <> + ), @@ -64,6 +67,7 @@ const router = createHashRouter([ element: ( <> + ), @@ -74,6 +78,7 @@ const router = createHashRouter([ element: ( <> + ), @@ -84,6 +89,7 @@ const router = createHashRouter([ element: ( <> + ), diff --git a/src/Components/API/API.tsx b/src/Components/API/API.tsx index 437eb24..2bec00b 100644 --- a/src/Components/API/API.tsx +++ b/src/Components/API/API.tsx @@ -15,6 +15,7 @@ import { PatchEquipmentType, EquipmentLogListType, EquipmentInstanceLogListType, + UserType, } from "../Types/Types"; const debug = true; @@ -135,7 +136,7 @@ export async function UserAPI() { return instance .get("api/v1/accounts/users/me/", config) .then((response) => { - return response.data; + return response.data as UserType; }) .catch(() => { console.log("Error retrieving user data"); diff --git a/src/Components/DashboardPage/TechnicianButtons.tsx b/src/Components/DashboardPage/TechnicianButtons.tsx new file mode 100644 index 0000000..c388b58 --- /dev/null +++ b/src/Components/DashboardPage/TechnicianButtons.tsx @@ -0,0 +1,261 @@ +import { useQueries } from "@tanstack/react-query"; +import styles from "../../styles"; +import { EquipmentsAPI, EquipmentInstancesAPI, UserAPI } from "../API/API"; +import { useNavigate } from "react-router-dom"; +import { Button } from "@mui/material"; +import FormatListBulletedIcon from "@mui/icons-material/FormatListBulleted"; +import AddToQueueIcon from "@mui/icons-material/AddToQueue"; +import NoteAddIcon from "@mui/icons-material/NoteAdd"; +import NoteIcon from "@mui/icons-material/Note"; +import { colors } from "../../styles"; +import ScienceIcon from "@mui/icons-material/Science"; +import ColorizeIcon from "@mui/icons-material/Colorize"; +import { Dispatch, SetStateAction } from "react"; + +type props = { + SetAddSKUModalOpen: Dispatch>; + SetAddItemModalOpen: Dispatch>; +}; +export default function TechnicianButtons(props: props) { + const navigate = useNavigate(); + const queries = useQueries({ + queries: [ + { + queryKey: ["equipments"], + queryFn: EquipmentsAPI, + }, + { + queryKey: ["equipment_instances"], + queryFn: EquipmentInstancesAPI, + }, + { + queryKey: ["user"], + queryFn: UserAPI, + }, + ], + }); + return ( + <> +

+ Equipments +

+
+ + + + +
+
+ + +
+ + ); +} diff --git a/src/Components/DashboardPage/TechnicianLogs.tsx b/src/Components/DashboardPage/TechnicianLogs.tsx new file mode 100644 index 0000000..498c131 --- /dev/null +++ b/src/Components/DashboardPage/TechnicianLogs.tsx @@ -0,0 +1,94 @@ +import { Button } from "@mui/material"; +import { useNavigate } from "react-router-dom"; +import ManageSearchIcon from "@mui/icons-material/ManageSearch"; +import styles from "../../styles"; +import { colors } from "../../styles"; + +export default function TechnicianLogs() { + const navigate = useNavigate(); + return ( + <> +

+ Logs +

+
+ + +
+ + ); +} diff --git a/src/Components/DashboardPage/TechnicianWidgets.tsx b/src/Components/DashboardPage/TechnicianWidgets.tsx new file mode 100644 index 0000000..ee9f39e --- /dev/null +++ b/src/Components/DashboardPage/TechnicianWidgets.tsx @@ -0,0 +1,180 @@ +import { useQueries } from "@tanstack/react-query"; +import styles from "../../styles"; +import { EquipmentsAPI, EquipmentInstancesAPI, UserAPI } from "../API/API"; + +export default function TechnicianWidgets() { + const queries = useQueries({ + queries: [ + { + queryKey: ["equipments"], + queryFn: EquipmentsAPI, + }, + { + queryKey: ["equipment_instances"], + queryFn: EquipmentInstancesAPI, + }, + { + queryKey: ["user"], + queryFn: UserAPI, + }, + ], + }); + return ( +
+
+
+

+ SKUs in Database +

+ +

+ {queries[0].data ? queries[0].data.length : 0} +

+
+
+

+ Items in Database +

+ +

+ {queries[1].data ? queries[1].data.length : 0} +

+
+
+
+
+

+ Functional Items +

+ +

+ {queries[1].data + ? queries[1].data.filter( + (equipment) => equipment.status == "WORKING" + ).length + : 0} +

+
+
+

+ Broken Items +

+ +

+ {queries[1].data + ? queries[1].data.filter( + (equipment) => equipment.status == "BROKEN" + ).length + : 0} +

+
+
+
+ ); +} diff --git a/src/Components/RestrictedComponent/RestrictedComponent.tsx b/src/Components/RestrictedComponent/RestrictedComponent.tsx new file mode 100644 index 0000000..8605ad5 --- /dev/null +++ b/src/Components/RestrictedComponent/RestrictedComponent.tsx @@ -0,0 +1,21 @@ +import React from "react"; +import { UserAPI } from "../API/API"; +import { useQuery } from "@tanstack/react-query"; + +type props = { + allow_only: string; + children: React.ReactNode; +}; +export default function RestrictedComponent(props: props) { + const user = useQuery({ queryKey: ["user"], queryFn: UserAPI }); + if (props.allow_only === "Teacher") { + if (user.data && user.data.is_teacher) { + return <>{props.children}; + } + } else if (props.allow_only === "Technician") { + if (user.data && user.data.is_technician) { + return <>{props.children}; + } + } + return <>; +} diff --git a/src/Components/RestrictedPage/RestrictedPage.tsx b/src/Components/RestrictedPage/RestrictedPage.tsx new file mode 100644 index 0000000..f8cf63f --- /dev/null +++ b/src/Components/RestrictedPage/RestrictedPage.tsx @@ -0,0 +1,46 @@ +import { useEffect } from "react"; +import { useNavigate } from "react-router-dom"; +import { UserAPI } from "../API/API"; +import { toast } from "react-toastify"; +import { useQuery } from "@tanstack/react-query"; + +type props = { + allow_only: string; +}; +export default function RestrictedPage(props: props) { + const navigate = useNavigate(); + const user = useQuery({ queryKey: ["user"], queryFn: UserAPI }); + useEffect(() => { + if (props.allow_only == "Teacher") { + if (user.data && !user.data.is_teacher) { + navigate("/"); + toast("You are not a teacher!", { + position: "bottom-center", + autoClose: 2000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "light", + }); + } + } else if (props.allow_only == "Technician") { + if (user.data && !user.data.is_technician) { + navigate("/"); + toast("You are not a technician!", { + position: "bottom-center", + autoClose: 2000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "light", + }); + } + } + }, [navigate, props.allow_only, user.data]); + + return <>; +} diff --git a/src/Components/Types/Types.tsx b/src/Components/Types/Types.tsx index b2af722..13973c4 100644 --- a/src/Components/Types/Types.tsx +++ b/src/Components/Types/Types.tsx @@ -96,3 +96,13 @@ export type EquipmentInstanceLogType = { }; export type EquipmentInstanceLogListType = Array; + +export type UserType = { + username: string; + email: string; + avatar: string; + first_name: string; + last_name: string; + is_teacher: boolean; + is_technician: boolean; +}; diff --git a/src/Pages/DashboardPage/DashboardPage.tsx b/src/Pages/DashboardPage/DashboardPage.tsx index e7e4093..ec58fa6 100644 --- a/src/Pages/DashboardPage/DashboardPage.tsx +++ b/src/Pages/DashboardPage/DashboardPage.tsx @@ -1,24 +1,21 @@ import Header from "../../Components/Header/Header"; import styles from "../../styles"; import { useQueries } from "@tanstack/react-query"; -import { EquipmentsAPI, EquipmentInstancesAPI } from "../../Components/API/API"; -import { Button, CircularProgress } from "@mui/material"; -import FormatListBulletedIcon from "@mui/icons-material/FormatListBulleted"; -import AddToQueueIcon from "@mui/icons-material/AddToQueue"; -import NoteAddIcon from "@mui/icons-material/NoteAdd"; -import NoteIcon from "@mui/icons-material/Note"; -import ManageSearchIcon from "@mui/icons-material/ManageSearch"; -import { colors } from "../../styles"; -import { useNavigate } from "react-router-dom"; +import { + EquipmentsAPI, + EquipmentInstancesAPI, + UserAPI, +} from "../../Components/API/API"; import { useState } from "react"; import AddSKUModal from "../../Components/AddSKUModal/AddSKUModal"; import Popup from "reactjs-popup"; import AddItemModal from "../../Components/AddItemModal/AddItemModal"; -import ScienceIcon from "@mui/icons-material/Science"; -import ColorizeIcon from "@mui/icons-material/Colorize"; +import RestrictedComponent from "../../Components/RestrictedComponent/RestrictedComponent"; +import TechnicianWidgets from "../../Components/DashboardPage/TechnicianWidgets"; +import TechnicianButtons from "../../Components/DashboardPage/TechnicianButtons"; +import TechnicianLogs from "../../Components/DashboardPage/TechnicianLogs"; +import CircularProgress from "@mui/material/CircularProgress/CircularProgress"; export default function Dashboard() { - const navigate = useNavigate(); - const queries = useQueries({ queries: [ { @@ -29,6 +26,10 @@ export default function Dashboard() { queryKey: ["equipment_instances"], queryFn: EquipmentInstancesAPI, }, + { + queryKey: ["user"], + queryFn: UserAPI, + }, ], }); const isLoading = queries.some((result) => result.isLoading); @@ -66,460 +67,18 @@ export default function Dashboard() { return (
-
-
-
-

- SKUs in Database -

- -

- {queries[0].data ? queries[0].data.length : 0} -

-
-
-

- Items in Database -

- -

- {queries[1].data ? queries[1].data.length : 0} -

-
-
-
-
-

- Functional Items -

- -

- {queries[1].data - ? queries[1].data.filter( - (equipment) => equipment.status == "WORKING" - ).length - : 0} -

-
-
-

- Broken Items -

- -

- {queries[1].data - ? queries[1].data.filter( - (equipment) => equipment.status == "BROKEN" - ).length - : 0} -

-
-
-
-

- Equipments -

-
- - - - -
- -
- - -
-

- Logs -

-
- - -
+ + + + + + + + + SetAddSKUModalOpen(false)}