import { EditableWorkflowStep } from "@/interfaces/approval.workflow"; import Option from "@/interfaces/option"; import { CorporateUser, DeveloperUser, MasterCorporateUser, TeacherUser } from "@/interfaces/user"; import Image from "next/image"; import { useEffect, useMemo, useState } from "react"; import { AiOutlineUserAdd } from "react-icons/ai"; import { BsTrash } from "react-icons/bs"; import { LuGripHorizontal } from "react-icons/lu"; import WorkflowStepNumber from "./WorkflowStepNumber"; import WorkflowStepSelects from "./WorkflowStepSelects"; interface Props extends Pick { entityApprovers: (TeacherUser | CorporateUser | MasterCorporateUser | DeveloperUser)[]; onSelectChange: (numberOfSelects: number, index: number, value: Option | null) => void; isCompleted: boolean, } export default function WorkflowEditableStepComponent({ stepNumber, assignees = [null], finalStep, onDelete, onSelectChange, entityApprovers, isCompleted, }: Props) { const [selects, setSelects] = useState<(Option | null | undefined)[]>([null]); const [isAdding, setIsAdding] = useState(false); const approverOptions: Option[] = useMemo(() => entityApprovers .map((approver) => ({ value: approver.id, label: approver.name, icon: () => {approver.name} })) .sort((a, b) => a.label.localeCompare(b.label)), [entityApprovers] ); useEffect(() => { if (assignees && assignees.length > 0) { const initialSelects = assignees.map((assignee) => typeof assignee === 'string' ? approverOptions.find(option => option.value === assignee) || null : null ); 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, approverOptions]); const selectedValues = useMemo(() => selects.filter((opt): opt is Option => !!opt).map(opt => opt.value), [selects] ); const availableApproverOptions = useMemo(() => approverOptions.filter(opt => !selectedValues.includes(opt.value)), [approverOptions, selectedValues] ); const handleAddSelectComponent = () => { setIsAdding(true); // I hate to use flags... but it was the only way i was able to prevent onSelectChange to cause parent component from re-rendering in the midle of EditableWorkflowStep rerender. setSelects(prev => [...prev, null]); }; useEffect(() => { if (isAdding) { onSelectChange(selects.length, selects.length - 1, null); setIsAdding(false); } }, [selects.length, isAdding, onSelectChange]); const handleSelectChangeAt = (numberOfSelects: number, index: number, option: Option | null) => { const updated = [...selects]; updated[index] = option; setSelects(updated); onSelectChange(numberOfSelects, index, option); }; return (
{/* Vertical Bar connecting steps */} {!finalStep && (
)}
{stepNumber !== 1 && !finalStep && !isCompleted ? :
}
{stepNumber !== 1 && !finalStep && ( )}
); };