code refactoring

This commit is contained in:
Joao Correia
2025-01-23 22:12:25 +00:00
parent a4f60455b5
commit c921d54d50
3 changed files with 55 additions and 54 deletions

View File

@@ -7,6 +7,7 @@ import { BsTrash } from "react-icons/bs";
import { LuGripHorizontal } from "react-icons/lu"; import { LuGripHorizontal } from "react-icons/lu";
import WorkflowStepNumber from "./WorkflowStepNumber"; import WorkflowStepNumber from "./WorkflowStepNumber";
import WorkflowStepSelects from "./WorkflowStepSelects"; import WorkflowStepSelects from "./WorkflowStepSelects";
import Image from "next/image";
interface Props extends WorkflowStep { interface Props extends WorkflowStep {
entityTeachers: TeacherUser[]; entityTeachers: TeacherUser[];
@@ -31,7 +32,7 @@ export default function WorkflowEditableStepComponent({
.map((teacher) => ({ .map((teacher) => ({
value: teacher.id, value: teacher.id,
label: teacher.name, label: teacher.name,
icon: () => <img src={teacher.profilePicture} alt={teacher.name} /> icon: () => <Image src={teacher.profilePicture} alt={teacher.name} />
})) }))
.sort((a, b) => a.label.localeCompare(b.label)), .sort((a, b) => a.label.localeCompare(b.label)),
[entityTeachers] [entityTeachers]
@@ -42,7 +43,7 @@ export default function WorkflowEditableStepComponent({
.map((corporate) => ({ .map((corporate) => ({
value: corporate.id, value: corporate.id,
label: corporate.name, label: corporate.name,
icon: () => <img src={corporate.profilePicture} alt={corporate.name} /> icon: () => <Image src={corporate.profilePicture} alt={corporate.name} />
})) }))
.sort((a, b) => a.label.localeCompare(b.label)), .sort((a, b) => a.label.localeCompare(b.label)),
[entityCorporates] [entityCorporates]
@@ -55,9 +56,16 @@ export default function WorkflowEditableStepComponent({
const initialSelects = assignees.map((assignee) => const initialSelects = assignees.map((assignee) =>
typeof assignee === 'string' ? allOptions.find(opt => opt.value === assignee) || null : null 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]); }, [assignees, allOptions]);

View File

@@ -23,18 +23,8 @@ interface Props {
} }
export default function WorkflowForm({ workflow, onWorkflowChange, entityTeachers, entityCorporates }: Props) { export default function WorkflowForm({ workflow, onWorkflowChange, entityTeachers, entityCorporates }: Props) {
const [steps, setSteps] = useState<WorkflowStep[]>(workflow.steps);
const [stepCounter, setStepCounter] = useState<number>(3); // to guarantee unique keys used for animations const [stepCounter, setStepCounter] = useState<number>(3); // to guarantee unique keys used for animations
const lastStep = steps[steps.length - 1]; const lastStep = workflow.steps[workflow.steps.length - 1];
useEffect(() => {
setSteps(workflow.steps);
}, [workflow]);
useEffect(() => {
const updatedWorkflow = { ...workflow, steps };
onWorkflowChange(updatedWorkflow);
}, [steps]);
const renumberSteps = (steps: WorkflowStep[]): WorkflowStep[] => { const renumberSteps = (steps: WorkflowStep[]): WorkflowStep[] => {
return steps.map((step, index) => ({ return steps.map((step, index) => ({
@@ -44,35 +34,34 @@ export default function WorkflowForm({ workflow, onWorkflowChange, entityTeacher
}; };
const addStep = () => { const addStep = () => {
setSteps((prev) => {
const newStep: WorkflowStep = { const newStep: WorkflowStep = {
key: stepCounter, key: stepCounter,
stepType: "approval-by", stepType: "approval-by",
stepNumber: steps.length, stepNumber: workflow.steps.length,
completed: false, completed: false,
assignees: [null], assignees: [null],
}; };
setStepCounter((count) => count + 1); setStepCounter((count) => count + 1);
const updatedSteps = [...prev.slice(0, -1), newStep, lastStep]; const updatedSteps = [
return renumberSteps(updatedSteps); ...workflow.steps.slice(0, -1),
}); newStep,
lastStep
];
onWorkflowChange({ ...workflow, steps: renumberSteps(updatedSteps) });
}; };
const handleDelete = (key: number | undefined) => { const handleDelete = (key: number | undefined) => {
if (key) { if (!key) return;
setSteps((prev) => {
const updatedSteps = prev.filter((step) => step.key !== key); const updatedSteps = workflow.steps.filter((step) => step.key !== key);
return renumberSteps(updatedSteps); onWorkflowChange({ ...workflow, steps: renumberSteps(updatedSteps) });
});
}
}; };
const handleSelectChange = (key: number | undefined, numberOfSelects: number, index: number, selectedOption: Option | null) => { const handleSelectChange = (key: number | undefined, numberOfSelects: number, index: number, selectedOption: Option | null) => {
if (key === undefined) return; if (!key) return;
setSteps((prevSteps) => const updatedSteps = workflow.steps.map((step) => {
prevSteps.map((step) => {
if (step.key !== key) return step; if (step.key !== key) return step;
const assignees = step.assignees ?? []; const assignees = step.assignees ?? [];
@@ -85,8 +74,9 @@ export default function WorkflowForm({ workflow, onWorkflowChange, entityTeacher
} }
return { ...step, assignees: newAssignees }; return { ...step, assignees: newAssignees };
}) });
);
onWorkflowChange({ ...workflow, steps: updatedSteps });
}; };
const handleReorder = (newOrder: WorkflowStep[]) => { const handleReorder = (newOrder: WorkflowStep[]) => {
@@ -101,7 +91,8 @@ export default function WorkflowForm({ workflow, onWorkflowChange, entityTeacher
const [final] = newOrder.splice(finalIndex, 1); const [final] = newOrder.splice(finalIndex, 1);
newOrder.push(final); newOrder.push(final);
} }
setSteps(renumberSteps(newOrder));
onWorkflowChange({ ...workflow, steps: renumberSteps(newOrder) });
}; };
return ( return (
@@ -119,13 +110,13 @@ export default function WorkflowForm({ workflow, onWorkflowChange, entityTeacher
<Reorder.Group <Reorder.Group
axis="y" axis="y"
values={steps} values={workflow.steps}
onReorder={handleReorder} onReorder={handleReorder}
className="flex flex-col gap-0" className="flex flex-col gap-0"
> >
<AnimatePresence> <AnimatePresence>
{steps.map((step, index) => ( {workflow.steps.map((step, index) => (
<Reorder.Item <Reorder.Item
key={step.key} key={step.key}
value={step} value={step}

View File

@@ -118,7 +118,7 @@ export default function Home({ user, userEntitiesWithLabel, userEntitiesTeachers
setWorkflows(prev => prev.filter(wf => wf.id !== id)); setWorkflows(prev => prev.filter(wf => wf.id !== id));
if (selectedWorkflowId === 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 Add New Workflow
</Button> </Button>
{workflows.length !== 0 && <div className="bg-gray-300 w-[1px]"></div>}
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
{workflows.map((workflow) => ( {workflows.map((workflow) => (
<Button <Button
@@ -172,7 +174,7 @@ export default function Home({ user, userEntitiesWithLabel, userEntitiesTeachers
onClick={() => handleSelectWorkflow(workflow.id)} onClick={() => handleSelectWorkflow(workflow.id)}
className="min-w-fit text-lg font-medium flex items-center gap-2 text-left" className="min-w-fit text-lg font-medium flex items-center gap-2 text-left"
> >
{workflow.name.trim() === "" ? "New Workflow" : workflow.name} {workflow.name.trim() === "" ? "Workflow" : workflow.name}
</Button> </Button>
))} ))}
@@ -213,7 +215,7 @@ export default function Home({ user, userEntitiesWithLabel, userEntitiesTeachers
placeholder="Entity..." placeholder="Entity..."
/> />
<Button <Button
color="purple" color="red"
variant="solid" variant="solid"
onClick={() => handleDeleteWorkflow(currentWorkflow.id)} onClick={() => handleDeleteWorkflow(currentWorkflow.id)}
type="button" type="button"