use custom hook to render approval workflows list instead of reloading full page.
This commit is contained in:
24
src/hooks/useApprovalWorkflows.tsx
Normal file
24
src/hooks/useApprovalWorkflows.tsx
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import { ApprovalWorkflow } from "@/interfaces/approval.workflow";
|
||||||
|
import axios from "axios";
|
||||||
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
|
||||||
|
export default function useApprovalWorkflows() {
|
||||||
|
const [workflows, setWorkflows] = useState<ApprovalWorkflow[]>([]);
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [isError, setIsError] = useState(false);
|
||||||
|
|
||||||
|
const getData = useCallback(() => {
|
||||||
|
setIsLoading(true);
|
||||||
|
axios
|
||||||
|
.get<ApprovalWorkflow[]>(`/api/approval-workflows`)
|
||||||
|
.then((response) => setWorkflows(response.data))
|
||||||
|
.catch((error) => {
|
||||||
|
setIsError(true);
|
||||||
|
})
|
||||||
|
.finally(() => setIsLoading(false));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(getData, [getData]);
|
||||||
|
|
||||||
|
return { workflows, isLoading, isError, reload: getData };
|
||||||
|
}
|
||||||
23
src/pages/api/approval-workflows/index.ts
Normal file
23
src/pages/api/approval-workflows/index.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||||
|
import { sessionOptions } from "@/lib/session";
|
||||||
|
import { requestUser } from "@/utils/api";
|
||||||
|
import { getApprovalWorkflows } 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 === "GET") return await get(req, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function get(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 });
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).json(await getApprovalWorkflows("configured-workflows"));
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ import Layout from "@/components/High/Layout";
|
|||||||
import Button from "@/components/Low/Button";
|
import Button from "@/components/Low/Button";
|
||||||
import Input from "@/components/Low/Input";
|
import Input from "@/components/Low/Input";
|
||||||
import Select from "@/components/Low/Select";
|
import Select from "@/components/Low/Select";
|
||||||
|
import useApprovalWorkflows from "@/hooks/useApprovalWorkflows";
|
||||||
import { Module, ModuleTypeLabels } from "@/interfaces";
|
import { Module, ModuleTypeLabels } from "@/interfaces";
|
||||||
import { ApprovalWorkflow, ApprovalWorkflowStatus, ApprovalWorkflowStatusLabel, StepTypeLabel } from "@/interfaces/approval.workflow";
|
import { ApprovalWorkflow, ApprovalWorkflowStatus, ApprovalWorkflowStatusLabel, StepTypeLabel } from "@/interfaces/approval.workflow";
|
||||||
import { Entity, EntityWithRoles } from "@/interfaces/entity";
|
import { Entity, EntityWithRoles } from "@/interfaces/entity";
|
||||||
@@ -51,7 +52,7 @@ export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => {
|
|||||||
return {
|
return {
|
||||||
props: serialize({
|
props: serialize({
|
||||||
user,
|
user,
|
||||||
workflows,
|
initialWorkflows: workflows,
|
||||||
workflowsAssignees: await getSpecificUsers(allAssigneeIds),
|
workflowsAssignees: await getSpecificUsers(allAssigneeIds),
|
||||||
userEntitiesWithLabel: await getEntities(user.entities.map(entity => entity.id)),
|
userEntitiesWithLabel: await getEntities(user.entities.map(entity => entity.id)),
|
||||||
}),
|
}),
|
||||||
@@ -87,12 +88,21 @@ const STATUS_OPTIONS = [
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
user: User,
|
user: User,
|
||||||
workflows: ApprovalWorkflow[],
|
initialWorkflows: ApprovalWorkflow[],
|
||||||
workflowsAssignees: User[],
|
workflowsAssignees: User[],
|
||||||
userEntitiesWithLabel: Entity[],
|
userEntitiesWithLabel: Entity[],
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ApprovalWorkflows({ user, workflows, workflowsAssignees, userEntitiesWithLabel }: Props) {
|
export default function ApprovalWorkflows({ user, initialWorkflows, workflowsAssignees, userEntitiesWithLabel }: Props) {
|
||||||
|
|
||||||
|
const {workflows, reload} = useApprovalWorkflows();
|
||||||
|
const currentWorkflows = workflows || initialWorkflows;
|
||||||
|
|
||||||
|
const [filteredWorkflows, setFilteredWorkflows] = useState<ApprovalWorkflow[]>([]);
|
||||||
|
|
||||||
|
const [statusFilter, setStatusFilter] = useState<CustomStatus>(undefined);
|
||||||
|
const [entityFilter, setEntityFilter] = useState<CustomEntity>(undefined);
|
||||||
|
const [nameFilter, setNameFilter] = useState<string>("");
|
||||||
|
|
||||||
const ENTITY_OPTIONS = [
|
const ENTITY_OPTIONS = [
|
||||||
...userEntitiesWithLabel
|
...userEntitiesWithLabel
|
||||||
@@ -104,13 +114,6 @@ export default function ApprovalWorkflows({ user, workflows, workflowsAssignees,
|
|||||||
.sort((a, b) => a.label.localeCompare(b.label)),
|
.sort((a, b) => a.label.localeCompare(b.label)),
|
||||||
];
|
];
|
||||||
|
|
||||||
const [filteredWorkflows, setFilteredWorkflows] = useState<ApprovalWorkflow[]>([]);
|
|
||||||
|
|
||||||
const [statusFilter, setStatusFilter] = useState<CustomStatus>(undefined);
|
|
||||||
const [entityFilter, setEntityFilter] = useState<CustomEntity>(undefined);
|
|
||||||
const [nameFilter, setNameFilter] = useState<string>("");
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const filters: Array<(workflow: ApprovalWorkflow) => boolean> = [];
|
const filters: Array<(workflow: ApprovalWorkflow) => boolean> = [];
|
||||||
|
|
||||||
@@ -135,10 +138,10 @@ export default function ApprovalWorkflows({ user, workflows, workflowsAssignees,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply all filters
|
// Apply all filters
|
||||||
const filtered = workflows.filter(workflow => filters.every(filterFn => filterFn(workflow)));
|
const filtered = currentWorkflows.filter(workflow => filters.every(filterFn => filterFn(workflow)));
|
||||||
setFilteredWorkflows(filtered);
|
setFilteredWorkflows(filtered);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [workflows, statusFilter, entityFilter, nameFilter]);
|
}, [currentWorkflows, statusFilter, entityFilter, nameFilter]);
|
||||||
|
|
||||||
|
|
||||||
const handleNameFilterChange = (name: ApprovalWorkflow["name"]) => {
|
const handleNameFilterChange = (name: ApprovalWorkflow["name"]) => {
|
||||||
@@ -153,7 +156,7 @@ export default function ApprovalWorkflows({ user, workflows, workflowsAssignees,
|
|||||||
.delete(`/api/approval-workflows/${id}`)
|
.delete(`/api/approval-workflows/${id}`)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success(`Successfully deleted ${name} Approval Workflow.`);
|
toast.success(`Successfully deleted ${name} Approval Workflow.`);
|
||||||
router.reload();
|
reload();
|
||||||
})
|
})
|
||||||
.catch((reason) => {
|
.catch((reason) => {
|
||||||
if (reason.response.status === 404) {
|
if (reason.response.status === 404) {
|
||||||
@@ -215,7 +218,7 @@ export default function ApprovalWorkflows({ user, workflows, workflowsAssignees,
|
|||||||
const currentStep = steps.find((step) => !step.completed);
|
const currentStep = steps.find((step) => !step.completed);
|
||||||
const rejected = steps.find((step) => step.rejected);
|
const rejected = steps.find((step) => step.rejected);
|
||||||
|
|
||||||
if(rejected) return "";
|
if (rejected) return "";
|
||||||
|
|
||||||
const assignees = currentStep?.assignees.map((assigneeId) => {
|
const assignees = currentStep?.assignees.map((assigneeId) => {
|
||||||
const assignee = workflowsAssignees.find((user) => user.id === assigneeId);
|
const assignee = workflowsAssignees.find((user) => user.id === assigneeId);
|
||||||
|
|||||||
Reference in New Issue
Block a user