implement rejection of steps

This commit is contained in:
Joao Correia
2025-01-31 20:56:40 +00:00
parent 662e3b0266
commit a0229cd971
8 changed files with 170 additions and 126 deletions

View File

@@ -28,6 +28,7 @@ import { RiThumbUpLine } from "react-icons/ri";
import { toast, ToastContainer } from "react-toastify";
import { IoMdCheckmarkCircleOutline } from "react-icons/io";
import { FiSave } from "react-icons/fi";
import { RxCrossCircled } from "react-icons/rx";
export const getServerSideProps = withIronSessionSsr(async ({ req, res, params }) => {
const user = await requestUser(req, res);
@@ -71,7 +72,7 @@ interface Props {
export default function Home({ user, workflow, workflowAssignees, workflowRequester }: Props) {
const steps = workflow.steps;
let currentStep = steps.findIndex(step => !step.completed);
let currentStep = steps.findIndex(step => !step.completed || step.rejected);
if (currentStep === -1)
currentStep = steps.length - 1;
@@ -110,9 +111,7 @@ export default function Home({ user, workflow, workflowAssignees, workflowReques
.then(() => {
toast.success("Comments saved successfully.");
setIsRedirecting(true);
setTimeout(() => {
router.reload();
}, 1000);
router.reload();
})
.catch((reason) => {
if (reason.response.status === 401) {
@@ -129,7 +128,6 @@ export default function Home({ user, workflow, workflowAssignees, workflowReques
};
const handleApproveStep = () => {
if (!confirm(`Are you sure you want to approve this step?`)) return;
setIsLoading(true);
const updatedWorkflow: ApprovalWorkflow = {
@@ -151,9 +149,48 @@ export default function Home({ user, workflow, workflowAssignees, workflowReques
.then(() => {
toast.success("Step approved successfully.");
setIsRedirecting(true);
setTimeout(() => {
router.reload();
}, 1000);
router.reload();
})
.catch((reason) => {
if (reason.response.status === 401) {
toast.error("Not logged in!");
} else if (reason.response.status === 403) {
toast.error("You do not have permission to approve this step!");
} else {
toast.error("Something went wrong, please try again later.");
}
setIsLoading(false);
console.log("Submitted Values:", updatedWorkflow);
return;
})
};
const handleRejectStep = () => {
if (!confirm(`Are you sure you want to reject this step?`)) return;
setIsLoading(true);
const updatedWorkflow: ApprovalWorkflow = {
...workflow,
status: "rejected",
steps: workflow.steps.map((step, index) =>
index === selectedStepIndex ?
{
...step,
completed: true,
completedBy: user.id,
completedDate: Date.now(),
rejected: true,
}
: step
)
};
axios
.put(`/api/approval-workflows/${workflow._id}`, updatedWorkflow)
.then(() => {
toast.success("Step rejected successfully.");
setIsRedirecting(true);
router.reload();
})
.catch((reason) => {
if (reason.response.status === 401) {
@@ -219,6 +256,7 @@ export default function Home({ user, workflow, workflowAssignees, workflowReques
key={index}
completed={step.completed}
completedBy={step.completedBy}
rejected={step.rejected}
stepNumber={step.stepNumber}
stepType={step.stepType}
assignees={step.assignees}
@@ -276,7 +314,7 @@ export default function Home({ user, workflow, workflowAssignees, workflowReques
{selectedStep.completed ? (
<div className={"text-base font-medium text-gray-500 flex flex-col gap-6"}>
Approved on {new Date(selectedStep.completedDate!).toLocaleString("en-CA", {
{selectedStep.rejected ? "Rejected" : "Approved"} on {new Date(selectedStep.completedDate!).toLocaleString("en-CA", {
year: "numeric",
month: "2-digit",
day: "2-digit",
@@ -286,7 +324,7 @@ export default function Home({ user, workflow, workflowAssignees, workflowReques
hour12: false,
}).replace(", ", " at ")}
<div className="flex flex-row gap-1 text-sm">
<p className="text-base">Approved by:</p>
<p className="text-base">{selectedStep.rejected ? "Rejected" : "Approved"} by:</p>
{(() => {
const assignee = workflowAssignees.find(
(assignee) => assignee.id === selectedStep.completedBy
@@ -324,33 +362,61 @@ export default function Home({ user, workflow, workflowAssignees, workflowReques
</div>
)}
{selectedStepIndex === currentStep && !selectedStep.completed &&
<Button
type="submit"
color="purple"
variant="solid"
disabled={!selectedStep.assignees.includes(user.id) || isLoading}
onClick={handleApproveStep}
padding="px-6 py-2"
className="mb-3 w-full text-lg flex items-center justify-center gap-2 text-left"
>
{isRedirecting ? (
<>
<FaSpinner className="animate-spin size-5" />
Reloading...
</>
) : isLoading ? (
<>
<FaSpinner className="animate-spin size-5" />
Loading...
</>
) : (
<>
<IoMdCheckmarkCircleOutline size={20} />
Approve Step
</>
)}
</Button>
{selectedStepIndex === currentStep && !selectedStep.completed && !selectedStep.rejected &&
<div className="flex flex-row gap-2 ">
<Button
type="submit"
color="purple"
variant="solid"
disabled={!selectedStep.assignees.includes(user.id) || isLoading}
onClick={handleApproveStep}
padding="px-6 py-2"
className="mb-3 w-full text-lg flex items-center justify-center gap-2 text-left"
>
{isRedirecting ? (
<>
<FaSpinner className="animate-spin size-5" />
Reloading...
</>
) : isLoading ? (
<>
<FaSpinner className="animate-spin size-5" />
Loading...
</>
) : (
<>
<IoMdCheckmarkCircleOutline size={20} />
Approve Step
</>
)}
</Button>
<Button
type="submit"
color="red"
variant="solid"
disabled={!selectedStep.assignees.includes(user.id) || isLoading}
onClick={handleRejectStep}
padding="px-6 py-2"
className="mb-3 w-1/2 text-lg flex items-center justify-center gap-2 text-left"
>
{isRedirecting ? (
<>
<FaSpinner className="animate-spin size-5" />
Reloading...
</>
) : isLoading ? (
<>
<FaSpinner className="animate-spin size-5" />
Loading...
</>
) : (
<>
<RxCrossCircled size={20} />
Reject Step
</>
)}
</Button>
</div>
}
<hr className="my-4 h-[4px] bg-mti-purple-ultralight rounded-full w-full" />
@@ -361,7 +427,7 @@ export default function Home({ user, workflow, workflowAssignees, workflowReques
placeholder="Input comments here"
className="w-full h-64 p-2 border-2 rounded-xl shadow-lg focus:border-mti-purple focus:outline-none mt-3 resize-none"
/>
<Button
type="submit"
color="purple"