diff --git a/package.json b/package.json index b0f35e4c..43102b99 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "country-codes-list": "^1.6.11", "currency-symbol-map": "^5.1.0", "daisyui": "^3.1.5", + "deep-diff": "^1.0.2", "eslint": "8.33.0", "eslint-config-next": "13.1.6", "exceljs": "^4.4.0", @@ -97,6 +98,7 @@ "devDependencies": { "@simbathesailor/use-what-changed": "^2.0.0", "@types/blob-stream": "^0.1.33", + "@types/deep-diff": "^1.0.5", "@types/formidable": "^3.4.0", "@types/howler": "^2.2.11", "@types/lodash": "^4.14.191", diff --git a/src/interfaces/approval.workflow.ts b/src/interfaces/approval.workflow.ts index 84a6567d..38d4c7f5 100644 --- a/src/interfaces/approval.workflow.ts +++ b/src/interfaces/approval.workflow.ts @@ -37,6 +37,7 @@ export interface WorkflowStep { finalStep?: boolean, selected?: boolean, comments?: string, + examChanges?: string[], onClick?: React.MouseEventHandler } diff --git a/src/pages/api/exam/[module]/index.ts b/src/pages/api/exam/[module]/index.ts index 8c114e14..e78986e9 100644 --- a/src/pages/api/exam/[module]/index.ts +++ b/src/pages/api/exam/[module]/index.ts @@ -6,6 +6,8 @@ import client from "@/lib/mongodb"; import { sessionOptions } from "@/lib/session"; import { mapBy } from "@/utils"; import { requestUser } from "@/utils/api"; +import { getApprovalWorkflowsByExamId, updateApprovalWorkflows } from "@/utils/approval.workflows.be"; +import { generateExamDifferences } from "@/utils/exam.differences"; import { getExams } from "@/utils/exams.be"; import { isAdmin } from "@/utils/users"; import { withIronSessionApiRoute } from "iron-session/next"; @@ -108,8 +110,26 @@ async function POST(req: NextApiRequest, res: NextApiResponse) { responseStatus = 207; responseMessage = `Successfully created exam with ID: "${exam.id}" but something went wrong while creating the Approval Workflow(s).`; } + } else { // if exam was updated, log the updates + const approvalWorkflows = await getApprovalWorkflowsByExamId(exam.id); + + if (approvalWorkflows) { + const differences = generateExamDifferences(docSnap as Exam, exam as Exam); + if (differences) { + approvalWorkflows.forEach((workflow) => { + const currentStepIndex = workflow.steps.findIndex(step => !step.completed || step.rejected); + + if (workflow.steps[currentStepIndex].examChanges === undefined) { + workflow.steps[currentStepIndex].examChanges = [...differences]; + } else { + workflow.steps[currentStepIndex].examChanges!.push(...differences); + } + }); + await updateApprovalWorkflows("active-workflows", approvalWorkflows); + } + } } - + res.status(responseStatus).json({ message: responseMessage, }); diff --git a/src/pages/approval-workflows/[id]/index.tsx b/src/pages/approval-workflows/[id]/index.tsx index b9087217..2e7f6402 100644 --- a/src/pages/approval-workflows/[id]/index.tsx +++ b/src/pages/approval-workflows/[id]/index.tsx @@ -29,7 +29,7 @@ import { FaSpinner, FaWpforms } from "react-icons/fa6"; import { FiSave } from "react-icons/fi"; import { IoMdCheckmarkCircleOutline } from "react-icons/io"; import { IoDocumentTextOutline } from "react-icons/io5"; -import { MdOutlineDoubleArrow } from "react-icons/md"; +import { MdKeyboardArrowDown, MdKeyboardArrowUp, MdOutlineDoubleArrow } from "react-icons/md"; import { RiThumbUpLine } from "react-icons/ri"; import { RxCrossCircled } from "react-icons/rx"; import { TiEdit } from "react-icons/ti"; @@ -89,6 +89,7 @@ export default function Home({ user, initialWorkflow, id, workflowAssignees, wor const [selectedStepIndex, setSelectedStepIndex] = useState(currentStepIndex); const [selectedStep, setSelectedStep] = useState(currentWorkflow.steps[selectedStepIndex]); const [isPanelOpen, setIsPanelOpen] = useState(true); + const [isAccordionOpen, setIsAccordionOpen] = useState(false); const [comments, setComments] = useState(selectedStep.comments || ""); const [viewExamIsLoading, setViewExamIsLoading] = useState(false); const [editExamIsLoading, setEditExamIsLoading] = useState(false); @@ -517,11 +518,53 @@ export default function Home({ user, initialWorkflow, id, workflowAssignees, wor
+ {/* Accordion for Exam Changes */} +
+
setIsAccordionOpen((prev) => !prev)} + > +

+ Changes ({currentWorkflow.steps[selectedStepIndex].examChanges?.length || "0"}) +

+ {isAccordionOpen ? ( + + ) : ( + + )} +
+ + {isAccordionOpen && ( + +
+ {currentWorkflow.steps[selectedStepIndex].examChanges?.length ? ( + currentWorkflow.steps[selectedStepIndex].examChanges!.map((change, index) => ( +

+ {change} +

+ )) + ) : ( +

No changes made so far.

+ )} +
+
+ )} +
+
+ +
+