diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx
index daffc144..f8db74f3 100644
--- a/src/components/Sidebar.tsx
+++ b/src/components/Sidebar.tsx
@@ -14,6 +14,7 @@ import {
BsClipboardData,
BsPeople,
} from "react-icons/bs";
+import { GoWorkflow } from "react-icons/go";
import { CiDumbbell } from "react-icons/ci";
import { RiLogoutBoxFill } from "react-icons/ri";
import Link from "next/link";
@@ -183,6 +184,16 @@ export default function Sidebar({
isMinimized={isMinimized}
/>
)}
+ {checkAccess(user, ["admin", "developer", "teacher", "corporate", "mastercorporate"]) && (
+
+ )}
diff --git a/src/demo/approval_workflows.json b/src/demo/approval_workflows.json
new file mode 100644
index 00000000..0637a088
--- /dev/null
+++ b/src/demo/approval_workflows.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/src/hooks/useApprovalWorkflows.tsx b/src/hooks/useApprovalWorkflows.tsx
new file mode 100644
index 00000000..c0cc273f
--- /dev/null
+++ b/src/hooks/useApprovalWorkflows.tsx
@@ -0,0 +1,26 @@
+import { ApprovalWorkflow } from "@/interfaces/approval.workflow";
+import axios from "axios";
+import { useCallback, useEffect, useState } from "react";
+
+import approvalWorkflowsData from '../demo/approval_workflows.json' // to test locally
+
+export default function useApprovalWorkflows() {
+ const [approvalWorkflows, setApprovalWorkflows] = useState
(approvalWorkflowsData);
+ const [isLoading, setIsLoading] = useState(false);
+ const [isError, setIsError] = useState(false);
+
+ /* const getData = useCallback(() => {
+ setIsLoading(true);
+ axios
+ .get(`/api/approvalWorkflows`)
+ .then((response) => setApprovalWorkflows(response.data))
+ .catch((error) => {
+ setIsError(true);
+ })
+ .finally(() => setIsLoading(false));
+ }, []);
+
+ useEffect(getData, [getData]); */
+
+ return { approvalWorkflows, isLoading, isError/* , reload: getData */ };
+}
diff --git a/src/interfaces/approval.workflow.ts b/src/interfaces/approval.workflow.ts
new file mode 100644
index 00000000..c91b06f5
--- /dev/null
+++ b/src/interfaces/approval.workflow.ts
@@ -0,0 +1,17 @@
+import {Module} from ".";
+
+export interface ApprovalWorkflow {
+ id: string;
+ name: string;
+ module: Module;
+ status: ApprovalWorkflowStatus;
+ approvers: string;
+ step: string;
+}
+
+export type ApprovalWorkflowStatus = "approved" | "pending" | "rejected";
+export const ApprovalWorkflowStatusLabel: {[key in ApprovalWorkflowStatus]: string} = {
+ approved: "Approved",
+ pending: "Pending",
+ rejected: "Rejected",
+};
diff --git a/src/pages/approval-workflows.tsx b/src/pages/approval-workflows.tsx
new file mode 100644
index 00000000..795a2262
--- /dev/null
+++ b/src/pages/approval-workflows.tsx
@@ -0,0 +1,186 @@
+import Layout from "@/components/High/Layout";
+import Select from "@/components/Low/Select";
+import useApprovalWorkflows from "@/hooks/useApprovalWorkflows";
+import useUser from "@/hooks/useUser";
+import useUsers from "@/hooks/useUsers";
+import { ApprovalWorkflow, ApprovalWorkflowStatus, ApprovalWorkflowStatusLabel } from "@/interfaces/approval.workflow";
+import { sessionOptions } from "@/lib/session";
+import { redirect } from "@/utils";
+import { requestUser } from "@/utils/api";
+import { shouldRedirectHome } from "@/utils/navigation.disabled";
+import { createColumnHelper, flexRender, getCoreRowModel, useReactTable } from "@tanstack/react-table";
+import clsx from "clsx";
+import { withIronSessionSsr } from "iron-session/next";
+import Head from "next/head";
+import { useEffect, useState } from "react";
+import { ToastContainer } from "react-toastify";
+
+const columnHelper = createColumnHelper();
+
+export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => {
+ const user = await requestUser(req, res)
+ if (!user) return redirect("/login")
+
+ if (shouldRedirectHome(user) || !["admin", "developer", "teacher", "corporate", "mastercorporate"].includes(user.type))
+ return redirect("/")
+
+ return {
+ props: { user },
+ };
+}, sessionOptions);
+
+const StatusClassNames: { [key in ApprovalWorkflowStatus]: string } = {
+ approved: "bg-mti-green-light",
+ pending: "bg-mti-orange-light",
+ rejected: "bg-mti-red-light",
+};
+
+const escapedURL = process.env.NEXT_PUBLIC_WEBSITE_URL || "".replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
+const fromHomepage = [new RegExp(`^${escapedURL}`), /\/contact$/];
+
+type CustomStatus = ApprovalWorkflowStatus | "all" | "pending";
+
+const STATUS_OPTIONS = [
+ {
+ label: "All",
+ value: "all",
+ filter: (x: ApprovalWorkflow) => true,
+ },
+ {
+ label: "Approved",
+ value: "approved",
+ filter: (x: ApprovalWorkflow) => x.status === "approved",
+ },
+ {
+ label: "Pending",
+ value: "pending",
+ filter: (x: ApprovalWorkflow) => x.status === "pending",
+ },
+ {
+ label: "Rejected",
+ value: "rejected",
+ filter: (x: ApprovalWorkflow) => x.status === "rejected",
+ },
+];
+
+export default function ApprovalWorkflows() {
+ const [filteredApprovalWorkflows, setFilteredApprovalWorkflows] = useState([]);
+ const [selectedApprovalWorkflow, setSelectedApprovalWorkflow] = useState();
+
+ const [statusFilter, setStatusFilter] = useState("pending");
+
+ const { user } = useUser({ redirectTo: "/login" });
+
+ const { approvalWorkflows/* , reload */ } = useApprovalWorkflows();
+
+ useEffect(() => {
+ const filters = [];
+ if (statusFilter) {
+ const filter = STATUS_OPTIONS.find((x) => x.value === statusFilter)?.filter;
+ if (filter) filters.push(filter);
+ }
+ setFilteredApprovalWorkflows([...filters.reduce((d, f) => d.filter(f), approvalWorkflows)]);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [approvalWorkflows, statusFilter]);
+
+ const columns = [
+ /* columnHelper.accessor("id", {
+ header: "ID",
+ cell: (info) => info.getValue(),
+ }), */
+ columnHelper.accessor("name", {
+ header: "Name",
+ cell: (info) => info.getValue(),
+ }),
+ columnHelper.accessor("module", {
+ header: "Module",
+ cell: (info) => info.getValue(),
+ }),
+ columnHelper.accessor("status", {
+ header: "Status",
+ cell: (info) => (
+
+ {ApprovalWorkflowStatusLabel[info.getValue()]}
+
+ ),
+ }),
+ columnHelper.accessor("approvers", {
+ header: "Approvers",
+ cell: (info) => info.getValue(),
+ }),
+ columnHelper.accessor("step", {
+ header: "Step",
+ cell: (info) => info.getValue(),
+ }),
+ ];
+
+ const table = useReactTable({
+ data: filteredApprovalWorkflows,
+ columns: columns,
+ getCoreRowModel: getCoreRowModel(),
+ });
+
+ return (
+ <>
+
+ Approval Workflows Panel | EnCoach
+
+
+
+
+
+ {user && (
+
+ Approval Workflows
+
+
+
+
+
+
+
+
+
+ {table.getHeaderGroups().map((headerGroup) => (
+
+ {headerGroup.headers.map((header) => (
+ |
+ {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
+ |
+ ))}
+
+ ))}
+
+
+ {table.getRowModel().rows.map((row) => (
+ setSelectedApprovalWorkflow(row.original)}
+ key={row.id}>
+ {row.getVisibleCells().map((cell) => (
+ |
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
+ |
+ ))}
+
+ ))}
+
+
+
+ )}
+ >
+ );
+}