diff --git a/src/App.tsx b/src/App.tsx
index 3fdadf4..504e09d 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -18,6 +18,7 @@ import EquipmentInstanceLogsPage from "./Pages/EquipmentInstanceLogsPage/Equipme
import EquipmentInstancesFilteredListPage from "./Pages/EquipmentInstancesListPage/EquipmentInstancesFilteredListPage";
import RestrictedPage from "./Components/RestrictedPage/RestrictedPage";
import TransactionsListPage from "./Pages/TransactionsListPage/TransactionsListPage";
+import AddTransactionPage from "./Pages/AddTransactionPage/AddTransactionPage";
const queryClient = new QueryClient();
const router = createHashRouter([
@@ -125,6 +126,17 @@ const router = createHashRouter([
),
errorElement: ,
},
+ {
+ path: "/new/transaction",
+ element: (
+ <>
+
+
+
+ >
+ ),
+ errorElement: ,
+ },
]);
export default function App() {
diff --git a/src/Components/API/API.tsx b/src/Components/API/API.tsx
index 59131c7..e2dee30 100644
--- a/src/Components/API/API.tsx
+++ b/src/Components/API/API.tsx
@@ -19,6 +19,8 @@ import {
TransactionListType,
TransactionUpdateType,
TransactionType,
+ ClearanceType,
+ TransactionCreateType,
} from "../Types/Types";
const debug = true;
@@ -184,6 +186,29 @@ export function ResetPasswordConfirmAPI(info: ResetPasswordConfirmType) {
});
}
+export async function ClearanceAPI() {
+ const config = await GetConfig();
+ return instance
+ .get("api/v1/accounts/clearance/", config)
+ .then((response) => {
+ return response.data as ClearanceType;
+ })
+ .catch(() => {
+ console.log("Error retrieving clearance status for user");
+ });
+}
+
+export async function TeachersAPI() {
+ const config = await GetConfig();
+ return instance
+ .get("api/v1/accounts/teachers/", config)
+ .then((response) => {
+ return response.data as Array;
+ })
+ .catch(() => {
+ console.log("Error retrieving teachers");
+ });
+}
// Equipment APIs
export async function EquipmentAPI(id: number) {
@@ -330,6 +355,18 @@ export async function EquipmentInstancesAPI() {
});
}
+export async function AvailableEquipmentInstancesAPI() {
+ const config = await GetConfig();
+ return instance
+ .get("api/v1/equipments/equipment_instances/available", config)
+ .then((response) => {
+ return response.data as EquipmentInstanceListType;
+ })
+ .catch(() => {
+ console.log("Error retrieving available equipments");
+ });
+}
+
export async function EquipmentInstanceCreateAPI(
equipment_instance: AddEquipmentInstanceType
) {
@@ -371,6 +408,19 @@ export async function TransactionAPI(id: number) {
});
}
+export async function TransactionCreateAPI(transaction: TransactionCreateType) {
+ const config = await GetConfig();
+ return instance
+ .post(`api/v1/transactions/`, transaction, config)
+ .then((response) => {
+ return [true, response.data as TransactionType];
+ })
+ .catch((error) => {
+ console.log("Error creating transaction");
+ return [false, ParseError(error)];
+ });
+}
+
export async function TransactionUpdateAPI(
transaction: TransactionUpdateType,
id: number
@@ -386,3 +436,27 @@ export async function TransactionUpdateAPI(
return [false, ParseError(error)];
});
}
+
+export async function TransactionsByStudentAPI() {
+ const config = await GetConfig();
+ return instance
+ .get("api/v1/transactions/student/", config)
+ .then((response) => {
+ return response.data as TransactionListType;
+ })
+ .catch(() => {
+ console.log("Error retrieving transactions for current student");
+ });
+}
+
+export async function TransactionsByTeacherAPI() {
+ const config = await GetConfig();
+ return instance
+ .get("api/v1/transactions/teacher/", config)
+ .then((response) => {
+ return response.data as TransactionListType;
+ })
+ .catch(() => {
+ console.log("Error retrieving transactions for current teacher");
+ });
+}
diff --git a/src/Components/DashboardPage/Student/StudentDashboard.tsx b/src/Components/DashboardPage/Student/StudentDashboard.tsx
new file mode 100644
index 0000000..702e93f
--- /dev/null
+++ b/src/Components/DashboardPage/Student/StudentDashboard.tsx
@@ -0,0 +1,62 @@
+import styles from "../../../styles";
+import { Button } from "@mui/material";
+import AddBoxIcon from "@mui/icons-material/AddBox";
+import { colors } from "../../../styles";
+import { useNavigate } from "react-router-dom";
+export default function StudentDashboard() {
+ const navigate = useNavigate();
+ return (
+
+
+ Student Actions
+
+
+
+
+
+ );
+}
diff --git a/src/Components/DashboardPage/Student/StudentTransactionFilterMenu.tsx b/src/Components/DashboardPage/Student/StudentTransactionFilterMenu.tsx
new file mode 100644
index 0000000..be58c39
--- /dev/null
+++ b/src/Components/DashboardPage/Student/StudentTransactionFilterMenu.tsx
@@ -0,0 +1,388 @@
+import styles from "../../../styles";
+import {
+ Button,
+ FormControl,
+ InputLabel,
+ MenuItem,
+ Select,
+ SelectChangeEvent,
+} from "@mui/material";
+import HourglassBottomIcon from "@mui/icons-material/HourglassBottom";
+import CheckCircleIcon from "@mui/icons-material/CheckCircle";
+import FlashOffIcon from "@mui/icons-material/FlashOff";
+import CheckCircleOutlineIcon from "@mui/icons-material/CheckCircleOutline";
+import ShoppingCartCheckoutIcon from "@mui/icons-material/ShoppingCartCheckout";
+import AssignmentReturnedIcon from "@mui/icons-material/AssignmentReturned";
+import CancelOutlinedIcon from "@mui/icons-material/CancelOutlined";
+import CancelIcon from "@mui/icons-material/Cancel";
+import ClearAllIcon from "@mui/icons-material/ClearAll";
+
+type props = {
+ filter: string;
+ setFilter: React.Dispatch>;
+};
+
+export default function StudentTransactionFilterMenu(props: props) {
+ return (
+ <>
+
+ Personal Transactions
+
+
+
+
+
+ Filter Transactions
+
+
+
+
+ >
+ );
+}
diff --git a/src/Components/DashboardPage/Student/StudentTransactionListView.tsx b/src/Components/DashboardPage/Student/StudentTransactionListView.tsx
new file mode 100644
index 0000000..ddc7d62
--- /dev/null
+++ b/src/Components/DashboardPage/Student/StudentTransactionListView.tsx
@@ -0,0 +1,67 @@
+import { useQuery } from "@tanstack/react-query";
+import { TransactionsByStudentAPI } from "../../API/API";
+import styles from "../../../styles";
+import CircularProgress from "@mui/material/CircularProgress/CircularProgress";
+import React, { useState } from "react";
+import TransactionEntry from "../../TransactionEntry/TransactionEntry";
+import StudentTransactionFilterMenu from "./StudentTransactionFilterMenu";
+
+export default function StudentTransactionListView() {
+ const transactions = useQuery({
+ queryKey: ["transactions_student"],
+ queryFn: TransactionsByStudentAPI,
+ });
+ const [filter, setFilter] = useState("");
+ if (transactions.isLoading) {
+ return (
+
+ );
+ }
+ return (
+
+
+
+
+
+ {transactions.data ? (
+ transactions.data
+ .filter((transaction) =>
+ filter !== "" ? transaction.transaction_status == filter : true
+ )
+ .map((transaction) => (
+
+
+
+ ))
+ ) : (
+ <>>
+ )}
+
+
+
+ );
+}
diff --git a/src/Components/DashboardPage/StudentTransactionButtons.tsx b/src/Components/DashboardPage/StudentTransactionButtons.tsx
deleted file mode 100644
index 16151ba..0000000
--- a/src/Components/DashboardPage/StudentTransactionButtons.tsx
+++ /dev/null
@@ -1,254 +0,0 @@
-import styles from "../../styles";
-import { useNavigate } from "react-router-dom";
-import { Button } from "@mui/material";
-import HourglassBottomIcon from '@mui/icons-material/HourglassBottom';
-import ThumbUpIcon from '@mui/icons-material/ThumbUp';
-import CheckCircleIcon from '@mui/icons-material/CheckCircle';
-import FlashOffIcon from '@mui/icons-material/FlashOff';
-import ThumbDownIcon from '@mui/icons-material/ThumbDown';
-import { colors } from "../../styles";
-import Popup from "reactjs-popup";
-import AddItemModal from "../AddItemModal/AddItemModal";
-import AddSKUModal from "../AddSKUModal/AddSKUModal";
-import { useState } from "react";
-
-export default function StudentTransactionButtons() {
- const [addSKUmodalOpen, SetAddSKUModalOpen] = useState(false);
- const [additemmodalOpen, SetAddItemModalOpen] = useState(false);
- const navigate = useNavigate();
- return (
- <>
-
-
- Equipments
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SetAddSKUModalOpen(false)}
- modal
- position={"top center"}
- contentStyle={{
- width: "32rem",
- borderRadius: 16,
- borderColor: "grey",
- borderStyle: "solid",
- borderWidth: 1,
- padding: 16,
- alignContent: "center",
- justifyContent: "center",
- textAlign: "center",
- }}
- >
-
-
- SetAddItemModalOpen(false)}
- modal
- position={"top center"}
- contentStyle={{
- width: "32rem",
- borderRadius: 16,
- borderColor: "grey",
- borderStyle: "solid",
- borderWidth: 1,
- padding: 16,
- alignContent: "center",
- justifyContent: "center",
- textAlign: "center",
- }}
- >
-
-
- >
- );
-}
diff --git a/src/Components/DashboardPage/TechnicianEquipmentButtons.tsx b/src/Components/DashboardPage/Technician/TechnicianEquipmentButtons.tsx
similarity index 97%
rename from src/Components/DashboardPage/TechnicianEquipmentButtons.tsx
rename to src/Components/DashboardPage/Technician/TechnicianEquipmentButtons.tsx
index 9831970..094289d 100644
--- a/src/Components/DashboardPage/TechnicianEquipmentButtons.tsx
+++ b/src/Components/DashboardPage/Technician/TechnicianEquipmentButtons.tsx
@@ -1,17 +1,17 @@
-import styles from "../../styles";
+import styles from "../../../styles";
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 { colors } from "../../../styles";
import ScienceIcon from "@mui/icons-material/Science";
import ColorizeIcon from "@mui/icons-material/Colorize";
import ArticleIcon from '@mui/icons-material/Article';
import Popup from "reactjs-popup";
-import AddItemModal from "../AddItemModal/AddItemModal";
-import AddSKUModal from "../AddSKUModal/AddSKUModal";
+import AddItemModal from "../../AddItemModal/AddItemModal";
+import AddSKUModal from "../../AddSKUModal/AddSKUModal";
import { useState } from "react";
export default function TechnicianEquipmentButtons() {
const [addSKUmodalOpen, SetAddSKUModalOpen] = useState(false);
diff --git a/src/Components/DashboardPage/TechnicianLogButtons.tsx b/src/Components/DashboardPage/Technician/TechnicianLogButtons.tsx
similarity index 96%
rename from src/Components/DashboardPage/TechnicianLogButtons.tsx
rename to src/Components/DashboardPage/Technician/TechnicianLogButtons.tsx
index 74fffe1..22a3b5e 100644
--- a/src/Components/DashboardPage/TechnicianLogButtons.tsx
+++ b/src/Components/DashboardPage/Technician/TechnicianLogButtons.tsx
@@ -1,8 +1,8 @@
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";
+import styles from "../../../styles";
+import { colors } from "../../../styles";
export default function TechnicianLogButtons() {
const navigate = useNavigate();
diff --git a/src/Components/DashboardPage/TechnicianWidgets.tsx b/src/Components/DashboardPage/Technician/TechnicianWidgets.tsx
similarity index 98%
rename from src/Components/DashboardPage/TechnicianWidgets.tsx
rename to src/Components/DashboardPage/Technician/TechnicianWidgets.tsx
index 8c3c239..23bfe42 100644
--- a/src/Components/DashboardPage/TechnicianWidgets.tsx
+++ b/src/Components/DashboardPage/Technician/TechnicianWidgets.tsx
@@ -1,6 +1,6 @@
import { useQueries } from "@tanstack/react-query";
-import styles from "../../styles";
-import { EquipmentsAPI, EquipmentInstancesAPI, UserAPI } from "../API/API";
+import styles from "../../../styles";
+import { EquipmentsAPI, EquipmentInstancesAPI, UserAPI } from "../../API/API";
import CircularProgress from "@mui/material/CircularProgress";
export default function TechnicianWidgets() {
diff --git a/src/Components/Drawer/Drawer.tsx b/src/Components/Drawer/Drawer.tsx
index c84e4e0..34ea5ff 100644
--- a/src/Components/Drawer/Drawer.tsx
+++ b/src/Components/Drawer/Drawer.tsx
@@ -3,7 +3,12 @@ import AccountCircleIcon from "@mui/icons-material/AccountCircle";
import HomeIcon from "@mui/icons-material/Home";
import LogoutIcon from "@mui/icons-material/Logout";
import { useQuery } from "@tanstack/react-query";
-import { UserAPI, setAccessToken, setRefreshToken } from "../API/API";
+import {
+ ClearanceAPI,
+ UserAPI,
+ setAccessToken,
+ setRefreshToken,
+} from "../API/API";
import DrawerButton from "../DrawerButton/DrawerButton";
import { useDispatch } from "react-redux";
import { auth_toggle } from "../Plugins/Redux/Slices/AuthSlice/AuthSlice";
@@ -11,6 +16,12 @@ import { toast } from "react-toastify";
import { useNavigate } from "react-router-dom";
export default function Drawer() {
const user = useQuery({ queryKey: ["user"], queryFn: UserAPI });
+ const clearance = useQuery({
+ enabled:
+ user.isFetched && !user?.data?.is_teacher && !user?.data?.is_technician,
+ queryKey: ["clearance"],
+ queryFn: ClearanceAPI,
+ });
const dispatch = useDispatch();
const navigate = useNavigate();
return (
@@ -62,6 +73,72 @@ export default function Drawer() {
+ {user.isFetched &&
+ user.data &&
+ !user.data.is_teacher &&
+ !user?.data?.is_technician ? (
+ <>
+
+
+
+ Status:
+
+
+ {clearance.data?.cleared}
+
+
+ {`(${clearance.data?.uncleared_transactions} pending)`}
+
+
+ >
+ ) : (
+ <>>
+ )}
+ {props.status}
+
+ );
+}
+export default function TransactionEntry(props: props) {
+ return (
+
+
+
+ ID: {props.transaction.id}
+
+
+ {props.transaction.timestamp}
+
+
+
+
+
+ Borrower: {props.transaction.borrower.name}{" "}
+ {`(ID:${props.transaction.borrower.id})`}
+
+
+ Teacher: {props.transaction.teacher.name}{" "}
+ {`(ID:${props.transaction.teacher.id})`}
+
+
+ {props.transaction.remarks}
+
+
+
+
+ Equipments:
+
+
+ {props.transaction.equipments.map((equipment) => (
+
+ {` - ${equipment.name} (ID:${equipment.id})`}
+
+ ))}
+
+
+
+
+
+ );
+}
diff --git a/src/Components/Types/Types.tsx b/src/Components/Types/Types.tsx
index b8afb35..8d2abcd 100644
--- a/src/Components/Types/Types.tsx
+++ b/src/Components/Types/Types.tsx
@@ -98,6 +98,7 @@ export type EquipmentInstanceLogType = {
export type EquipmentInstanceLogListType = Array
;
export type UserType = {
+ id: number;
username: string;
email: string;
avatar: string;
@@ -122,10 +123,25 @@ export type TransactionType = {
name: string;
}>;
transaction_status: string;
+ timestamp: string;
+ remarks: string;
};
export type TransactionListType = Array;
+export type TransactionCreateType = {
+ equipments: number[];
+ remarks: string;
+ teacher: number;
+ borrower: number;
+ transaction_status: "Pending Approval";
+};
+
export type TransactionUpdateType = {
transaction_status: string;
};
+
+export type ClearanceType = {
+ cleared: string;
+ uncleared_transactions: number;
+};
diff --git a/src/Pages/AddTransactionPage/AddTransactionPage.tsx b/src/Pages/AddTransactionPage/AddTransactionPage.tsx
new file mode 100644
index 0000000..741e9fa
--- /dev/null
+++ b/src/Pages/AddTransactionPage/AddTransactionPage.tsx
@@ -0,0 +1,205 @@
+import { useState } from "react";
+import styles from "../../styles";
+import { colors } from "../../styles";
+import TextField from "@mui/material/TextField";
+import AddToQueueIcon from "@mui/icons-material/AddToQueue";
+import Button from "../../Components/Button/Button";
+import { toast } from "react-toastify";
+import {
+ AvailableEquipmentInstancesAPI,
+ TransactionCreateAPI,
+ TeachersAPI,
+ UserAPI,
+} from "../../Components/API/API";
+import FormControl from "@mui/material/FormControl";
+import FormLabel from "@mui/material/FormLabel";
+import { useQueryClient } from "@tanstack/react-query";
+import { useQuery } from "@tanstack/react-query";
+import {
+ Select,
+ CircularProgress,
+ MenuItem,
+ OutlinedInput,
+} from "@mui/material";
+import React from "react";
+import Header from "../../Components/Header/Header";
+import { useNavigate } from "react-router-dom";
+
+export default function AddTransactionPage() {
+ const navigate = useNavigate();
+ const queryClient = useQueryClient();
+ const [selecteditems, SetSelectedItems] = useState([]);
+ const [selectedteacher, SetSelectedTeacher] = useState(0);
+ const [remarks, SetRemarks] = useState("");
+ const [error, setError] = useState("");
+
+ const equipments = useQuery({
+ queryKey: ["equipment_instances_available"],
+ queryFn: AvailableEquipmentInstancesAPI,
+ });
+
+ const teachers = useQuery({
+ queryKey: ["teachers"],
+ queryFn: TeachersAPI,
+ });
+
+ const user = useQuery({
+ queryKey: ["user"],
+ queryFn: UserAPI,
+ });
+ const isLoading =
+ equipments.isLoading || teachers.isLoading || user.isLoading;
+
+ if (isLoading) {
+ return (
+
+ );
+ }
+ return (
+
+
+
+
+
+
+ Items Requested
+
+
+
+ Assigned Teacher
+
+
+ ) => {
+ SetRemarks(e.target.value);
+ setError("");
+ }}
+ value={remarks}
+ placeholder={"Optionally add a brief description of the request"}
+ />
+
+
{error}
+
+
+ );
+}
diff --git a/src/Pages/DashboardPage/DashboardPage.tsx b/src/Pages/DashboardPage/DashboardPage.tsx
index 6ef2fa7..6e33cda 100644
--- a/src/Pages/DashboardPage/DashboardPage.tsx
+++ b/src/Pages/DashboardPage/DashboardPage.tsx
@@ -1,10 +1,11 @@
import Header from "../../Components/Header/Header";
import styles from "../../styles";
import RestrictedComponent from "../../Components/RestrictedComponent/RestrictedComponent";
-import TechnicianWidgets from "../../Components/DashboardPage/TechnicianWidgets";
-import TechnicianEquipmentButtons from "../../Components/DashboardPage/TechnicianEquipmentButtons";
-import TechnicianLogButtons from "../../Components/DashboardPage/TechnicianLogButtons";
-import StudentTransactionButtons from "../../Components/DashboardPage/StudentTransactionButtons";
+import TechnicianWidgets from "../../Components/DashboardPage/Technician/TechnicianWidgets";
+import TechnicianEquipmentButtons from "../../Components/DashboardPage/Technician/TechnicianEquipmentButtons";
+import TechnicianLogButtons from "../../Components/DashboardPage/Technician/TechnicianLogButtons";
+import StudentTransactionListView from "../../Components/DashboardPage/Student/StudentTransactionListView";
+import StudentDashboard from "../../Components/DashboardPage/Student/StudentDashboard";
export default function Dashboard() {
return (
@@ -15,7 +16,20 @@ export default function Dashboard() {
-
+
+
+
+
Welcome teacher!
diff --git a/src/styles.tsx b/src/styles.tsx
index 2f5cfbf..2e4c3ba 100644
--- a/src/styles.tsx
+++ b/src/styles.tsx
@@ -25,7 +25,6 @@ const styles: { [key: string]: React.CSSProperties } = {
text_dark: {
color: colors.font_dark,
fontWeight: "bold",
-
},
text_light: {
color: colors.font_light,
@@ -88,6 +87,13 @@ const styles: { [key: string]: React.CSSProperties } = {
textAlign: "center",
overflowY: "scroll",
},
+ student_filter_item: {
+ height: 32,
+ width: 32,
+ fill: colors.font_dark,
+ marginLeft: "1rem",
+ marginRight: "1rem",
+ },
};
export default styles;