From 011c6e9e30f820c1ecd7c21ef33da51f2289a06c Mon Sep 17 00:00:00 2001 From: Joao Correia Date: Wed, 29 Jan 2025 17:50:03 +0000 Subject: [PATCH] Start implementing with back-end. Create workflows completed and fetching workflows on server side as well, to show them in the table. --- src/hooks/useApprovalWorkflows.tsx | 14 +++++----- src/interfaces/approval.workflow.ts | 6 ++--- src/pages/api/approval-workflows/create.ts | 28 ++++++++++++++++++++ src/pages/approval-workflows/create.tsx | 30 +++++++++++++++++++--- src/pages/approval-workflows/index.tsx | 6 ++--- src/utils/approval.workflows.be.ts | 16 ++++++++++++ 6 files changed, 82 insertions(+), 18 deletions(-) create mode 100644 src/pages/api/approval-workflows/create.ts diff --git a/src/hooks/useApprovalWorkflows.tsx b/src/hooks/useApprovalWorkflows.tsx index 9be0459c..884f1cb4 100644 --- a/src/hooks/useApprovalWorkflows.tsx +++ b/src/hooks/useApprovalWorkflows.tsx @@ -2,25 +2,23 @@ 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 as ApprovalWorkflow[]); + const [workflows, setWorkflows] = useState([]); const [isLoading, setIsLoading] = useState(false); const [isError, setIsError] = useState(false); - /* const getData = useCallback(() => { + const getData = useCallback(() => { setIsLoading(true); axios - .get(`/api/approvalWorkflows`) - .then((response) => setApprovalWorkflows(response.data)) + .get(`/api/approval-workflows`) + .then((response) => setWorkflows(response.data)) .catch((error) => { setIsError(true); }) .finally(() => setIsLoading(false)); }, []); - useEffect(getData, [getData]); */ + useEffect(getData, [getData]); - return { approvalWorkflows, isLoading, isError/* , reload: getData */ }; + return { workflows, isLoading, isError, reload: getData }; } diff --git a/src/interfaces/approval.workflow.ts b/src/interfaces/approval.workflow.ts index 65ae5f4c..8b7efcf1 100644 --- a/src/interfaces/approval.workflow.ts +++ b/src/interfaces/approval.workflow.ts @@ -37,11 +37,11 @@ export interface WorkflowStep { completedDate?: number, assignees: (User["id"])[]; firstStep?: boolean, - currentStep?: boolean, + currentStep: boolean, finalStep?: boolean, - selected: boolean, + selected?: boolean, comments?: string, - onClick: React.MouseEventHandler + onClick?: React.MouseEventHandler } export interface EditableWorkflowStep { diff --git a/src/pages/api/approval-workflows/create.ts b/src/pages/api/approval-workflows/create.ts new file mode 100644 index 00000000..dab8e80f --- /dev/null +++ b/src/pages/api/approval-workflows/create.ts @@ -0,0 +1,28 @@ +// Next.js API route support: https://nextjs.org/docs/api-routes/introduction +import { ApprovalWorkflow } from "@/interfaces/approval.workflow"; +import { sessionOptions } from "@/lib/session"; +import { requestUser } from "@/utils/api"; +import { createApprovalWorkflows } from "@/utils/approval.workflows.be"; +import { withIronSessionApiRoute } from "iron-session/next"; +import type { NextApiRequest, NextApiResponse } from "next"; + +export default withIronSessionApiRoute(handler, sessionOptions); + +async function handler(req: NextApiRequest, res: NextApiResponse) { + if (req.method === "POST") return await post(req, res); +} + +async function post(req: NextApiRequest, res: NextApiResponse) { + const user = await requestUser(req, res); + if (!user) return res.status(401).json({ ok: false }); + + if (!["admin", "developer", "corporate", "mastercorporate"].includes(user.type)) { + return res.status(403).json({ ok: false }); + } + + const approvalWorkflows: ApprovalWorkflow[] = req.body; + + await createApprovalWorkflows(approvalWorkflows); + + return res.status(201).json(approvalWorkflows); +} diff --git a/src/pages/approval-workflows/create.tsx b/src/pages/approval-workflows/create.tsx index a0cd86e4..7dbdae77 100644 --- a/src/pages/approval-workflows/create.tsx +++ b/src/pages/approval-workflows/create.tsx @@ -4,7 +4,7 @@ import Layout from "@/components/High/Layout"; import Button from "@/components/Low/Button"; import Input from "@/components/Low/Input"; import Select from "@/components/Low/Select"; -import { EditableApprovalWorkflow } from "@/interfaces/approval.workflow"; +import { ApprovalWorkflow, EditableApprovalWorkflow } from "@/interfaces/approval.workflow"; import { Entity } from "@/interfaces/entity"; import { CorporateUser, TeacherUser, User } from "@/interfaces/user"; import { sessionOptions } from "@/lib/session"; @@ -13,6 +13,7 @@ import { requestUser } from "@/utils/api"; import { getEntities } from "@/utils/entities.be"; import { shouldRedirectHome } from "@/utils/navigation.disabled"; import { getEntitiesUsers } from "@/utils/users.be"; +import axios from "axios"; import { AnimatePresence, LayoutGroup, motion } from "framer-motion"; import { withIronSessionSsr } from "iron-session/next"; import Head from "next/head"; @@ -20,7 +21,7 @@ import Link from "next/link"; import { useEffect, useState } from "react"; import { BsChevronLeft, BsTrash } from "react-icons/bs"; import { MdFormatListBulletedAdd } from "react-icons/md"; -import { ToastContainer } from "react-toastify"; +import { toast, ToastContainer } from "react-toastify"; import { v4 as uuidv4 } from 'uuid'; export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => { @@ -86,15 +87,36 @@ export default function Home({ user, userEntitiesWithLabel, userEntitiesTeachers const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); - const filteredWorkflows = workflows.map(workflow => ({ + const filteredWorkflows: ApprovalWorkflow[] = workflows.map(workflow => ({ ...workflow, steps: workflow.steps.map(step => ({ ...step, - assignees: step.assignees.filter(assignee => assignee !== null && assignee !== undefined) + currentStep: step.stepNumber === 1 ? true : false, + completed: false, + assignees: step.assignees.filter((assignee): assignee is string => assignee !== null && assignee !== undefined) })) })); + axios + .post(`/api/approval-workflows/create`, filteredWorkflows) + .then(() => toast.success(`Approval Workflows created successfully.`)) + .catch((reason) => { + if (reason.response.status === 401) { + toast.error("Not logged in!"); + return redirect("/login"); + } + if (reason.response.status === 403) { + toast.error("You do not have permission to create Approval Workflows!"); + return; + } + + toast.error("Something went wrong, please try again later."); + return; + }) + console.log("Form submitted! Filtered Values:", filteredWorkflows); + + return redirect("/approval-workflows"); }; const handleAddNewWorkflow = () => { diff --git a/src/pages/approval-workflows/index.tsx b/src/pages/approval-workflows/index.tsx index 30dae0b7..a109fd52 100644 --- a/src/pages/approval-workflows/index.tsx +++ b/src/pages/approval-workflows/index.tsx @@ -25,7 +25,8 @@ import { toast, ToastContainer } from "react-toastify"; import Input from "@/components/Low/Input"; import { FaRegClone } from "react-icons/fa6"; -import approvalWorkflowsData from '../../demo/approval_workflows.json'; // to test locally +import useApprovalWorkflows from "@/hooks/useApprovalWorkflows"; +import { getApprovalWorkflows } from "@/utils/approval.workflows.be"; const columnHelper = createColumnHelper(); @@ -36,8 +37,7 @@ export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => { if (shouldRedirectHome(user) || !["admin", "developer", "teacher", "corporate", "mastercorporate"].includes(user.type)) return redirect("/") - // replace later with useApprovalWorkflows() - const workflows = approvalWorkflowsData as ApprovalWorkflow[]; + const workflows = await getApprovalWorkflows(); const allAssigneeIds: string[] = [ ...new Set( diff --git a/src/utils/approval.workflows.be.ts b/src/utils/approval.workflows.be.ts index 0173ac48..5c7549d3 100644 --- a/src/utils/approval.workflows.be.ts +++ b/src/utils/approval.workflows.be.ts @@ -3,6 +3,22 @@ import client from "@/lib/mongodb"; const db = client.db(process.env.MONGODB_DB); +export const getApprovalWorkflows = async (ids?: string[]) => { + return await db + .collection("approval-workflows") + .find(ids ? { id: { $in: ids } } : {}) + .toArray(); +}; + export const getApprovalWorkflow = async (id: string) => { return await db.collection("approval-workflows").findOne({ id }); }; + +export const createApprovalWorkflow = async (workflow: ApprovalWorkflow) => { + await db.collection("approval-workflows").insertOne(workflow); +} + +export const createApprovalWorkflows = async (workflows: ApprovalWorkflow[]) => { + if (workflows.length === 0) return; + await db.collection("approval-workflows").insertMany(workflows); +}; \ No newline at end of file