diff --git a/src/components/ApprovalWorkflows/WorkflowEditableStepComponent.tsx b/src/components/ApprovalWorkflows/WorkflowEditableStepComponent.tsx index 18dc8599..2a44303b 100644 --- a/src/components/ApprovalWorkflows/WorkflowEditableStepComponent.tsx +++ b/src/components/ApprovalWorkflows/WorkflowEditableStepComponent.tsx @@ -7,6 +7,7 @@ import { BsTrash } from "react-icons/bs"; import { LuGripHorizontal } from "react-icons/lu"; import WorkflowStepNumber from "./WorkflowStepNumber"; import WorkflowStepSelects from "./WorkflowStepSelects"; +import Image from "next/image"; interface Props extends WorkflowStep { entityTeachers: TeacherUser[]; @@ -31,7 +32,7 @@ export default function WorkflowEditableStepComponent({ .map((teacher) => ({ value: teacher.id, label: teacher.name, - icon: () => {teacher.name} + icon: () => {teacher.name} })) .sort((a, b) => a.label.localeCompare(b.label)), [entityTeachers] @@ -42,7 +43,7 @@ export default function WorkflowEditableStepComponent({ .map((corporate) => ({ value: corporate.id, label: corporate.name, - icon: () => {corporate.name} + icon: () => {corporate.name} })) .sort((a, b) => a.label.localeCompare(b.label)), [entityCorporates] @@ -55,9 +56,16 @@ export default function WorkflowEditableStepComponent({ const initialSelects = assignees.map((assignee) => typeof assignee === 'string' ? allOptions.find(opt => opt.value === assignee) || null : null ); - if (JSON.stringify(initialSelects) !== JSON.stringify(selects)) { - setSelects(initialSelects); - } + + setSelects((prevSelects) => { + // This is needed to avoid unnecessary re-renders which can cause warning of a child component being re-rendered while parent is in the midle of also re-rendering. + const areEqual = initialSelects.length === prevSelects.length && initialSelects.every((option, idx) => option?.value === prevSelects[idx]?.value); + + if (!areEqual) { + return initialSelects; + } + return prevSelects; + }); } }, [assignees, allOptions]); diff --git a/src/components/ApprovalWorkflows/WorkflowForm.tsx b/src/components/ApprovalWorkflows/WorkflowForm.tsx index 2e105745..9361ded4 100644 --- a/src/components/ApprovalWorkflows/WorkflowForm.tsx +++ b/src/components/ApprovalWorkflows/WorkflowForm.tsx @@ -23,18 +23,8 @@ interface Props { } export default function WorkflowForm({ workflow, onWorkflowChange, entityTeachers, entityCorporates }: Props) { - const [steps, setSteps] = useState(workflow.steps); const [stepCounter, setStepCounter] = useState(3); // to guarantee unique keys used for animations - const lastStep = steps[steps.length - 1]; - - useEffect(() => { - setSteps(workflow.steps); - }, [workflow]); - - useEffect(() => { - const updatedWorkflow = { ...workflow, steps }; - onWorkflowChange(updatedWorkflow); - }, [steps]); + const lastStep = workflow.steps[workflow.steps.length - 1]; const renumberSteps = (steps: WorkflowStep[]): WorkflowStep[] => { return steps.map((step, index) => ({ @@ -44,49 +34,49 @@ export default function WorkflowForm({ workflow, onWorkflowChange, entityTeacher }; const addStep = () => { - setSteps((prev) => { - const newStep: WorkflowStep = { - key: stepCounter, - stepType: "approval-by", - stepNumber: steps.length, - completed: false, - assignees: [null], - }; - setStepCounter((count) => count + 1); + const newStep: WorkflowStep = { + key: stepCounter, + stepType: "approval-by", + stepNumber: workflow.steps.length, + completed: false, + assignees: [null], + }; + setStepCounter((count) => count + 1); - const updatedSteps = [...prev.slice(0, -1), newStep, lastStep]; - return renumberSteps(updatedSteps); - }); + const updatedSteps = [ + ...workflow.steps.slice(0, -1), + newStep, + lastStep + ]; + onWorkflowChange({ ...workflow, steps: renumberSteps(updatedSteps) }); }; const handleDelete = (key: number | undefined) => { - if (key) { - setSteps((prev) => { - const updatedSteps = prev.filter((step) => step.key !== key); - return renumberSteps(updatedSteps); - }); - } + if (!key) return; + + const updatedSteps = workflow.steps.filter((step) => step.key !== key); + onWorkflowChange({ ...workflow, steps: renumberSteps(updatedSteps) }); }; const handleSelectChange = (key: number | undefined, numberOfSelects: number, index: number, selectedOption: Option | null) => { - if (key === undefined) return; + if (!key) return; - setSteps((prevSteps) => - prevSteps.map((step) => { - if (step.key !== key) return step; + const updatedSteps = workflow.steps.map((step) => { + if (step.key !== key) return step; - const assignees = step.assignees ?? []; - let newAssignees = [...assignees]; + const assignees = step.assignees ?? []; + let newAssignees = [...assignees]; - if (numberOfSelects === assignees.length) { // means no new select was added and instead one was changed - newAssignees[index] = selectedOption?.value; - } else if (numberOfSelects === assignees.length + 1) { // means a new select was added - newAssignees.push(selectedOption?.value || null); - } + if (numberOfSelects === assignees.length) { // means no new select was added and instead one was changed + newAssignees[index] = selectedOption?.value; + } else if (numberOfSelects === assignees.length + 1) { // means a new select was added + newAssignees.push(selectedOption?.value || null); + } - return { ...step, assignees: newAssignees }; - }) - ); + return { ...step, assignees: newAssignees }; + }); + + onWorkflowChange({ ...workflow, steps: updatedSteps }); }; const handleReorder = (newOrder: WorkflowStep[]) => { @@ -101,7 +91,8 @@ export default function WorkflowForm({ workflow, onWorkflowChange, entityTeacher const [final] = newOrder.splice(finalIndex, 1); newOrder.push(final); } - setSteps(renumberSteps(newOrder)); + + onWorkflowChange({ ...workflow, steps: renumberSteps(newOrder) }); }; return ( @@ -119,13 +110,13 @@ export default function WorkflowForm({ workflow, onWorkflowChange, entityTeacher - {steps.map((step, index) => ( + {workflow.steps.map((step, index) => ( prev.filter(wf => wf.id !== id)); if (selectedWorkflowId === id) { - setSelectedWorkflowId(undefined); + workflows.length > 0 ? setSelectedWorkflowId(workflows[0].id) : setSelectedWorkflowId(undefined); } }; @@ -159,6 +159,8 @@ export default function Home({ user, userEntitiesWithLabel, userEntitiesTeachers Add New Workflow + {workflows.length !== 0 &&
} +
{workflows.map((workflow) => ( ))} @@ -213,7 +215,7 @@ export default function Home({ user, userEntitiesWithLabel, userEntitiesTeachers placeholder="Entity..." />