- Refactor of workflow and steps types to differentiate between editView and normalView.

- Added side panel with steps details
This commit is contained in:
Joao Correia
2025-01-25 03:44:50 +00:00
parent 1f7639a30e
commit f71a7182dd
10 changed files with 225 additions and 100 deletions

View File

@@ -28,10 +28,9 @@ export default function StartedOn({ date }: Props) {
<div>
<p className="pb-1 text-sm font-medium text-gray-800">Started on</p>
<div className="flex items-center">
{/* Display the formatted date and add a title attribute for hover */}
<p
className="text-xs font-medium text-gray-800"
title={fullDateTime} // Shows full date and time on hover
title={fullDateTime}
>
{yearMonthDay}
</p>

View File

@@ -1,15 +1,15 @@
import { WorkflowStep } from "@/interfaces/approval.workflow";
import { EditableWorkflowStep } from "@/interfaces/approval.workflow";
import Option from "@/interfaces/option";
import { CorporateUser, 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";
import Image from "next/image";
interface Props extends WorkflowStep {
interface Props extends Pick<EditableWorkflowStep, 'stepNumber' | 'assignees' | 'finalStep' | 'onDelete'> {
entityTeachers: TeacherUser[];
entityCorporates: CorporateUser[];
onSelectChange: (numberOfSelects: number, index: number, value: Option | null) => void;
@@ -102,7 +102,7 @@ export default function WorkflowEditableStepComponent({
return (
<div className="flex w-full">
<div className="flex flex-col items-center">
<WorkflowStepNumber stepNumber={stepNumber} />
<WorkflowStepNumber stepNumber={stepNumber} completed={false} selected={false} />
{/* Vertical Bar connecting steps */}
{!finalStep && (

View File

@@ -1,17 +1,17 @@
import { ApprovalWorkflow, WorkflowStep } from "@/interfaces/approval.workflow";
import { EditableApprovalWorkflow, EditableWorkflowStep } from "@/interfaces/approval.workflow";
import Option from "@/interfaces/option";
import { CorporateUser, TeacherUser } from "@/interfaces/user";
import { AnimatePresence, AnimateSharedLayout, Reorder, motion } from "framer-motion";
import { AnimatePresence, Reorder, motion } from "framer-motion";
import { useState } from "react";
import { FaRegCheckCircle } from "react-icons/fa";
import { IoIosAddCircleOutline } from "react-icons/io";
import Button from "../Low/Button";
import WorkflowEditableStepComponent from "./WorkflowEditableStepComponent";
import Tip from "./Tip";
import WorkflowEditableStepComponent from "./WorkflowEditableStepComponent";
interface Props {
workflow: ApprovalWorkflow;
onWorkflowChange: (workflow: ApprovalWorkflow) => void;
workflow: EditableApprovalWorkflow;
onWorkflowChange: (workflow: EditableApprovalWorkflow) => void;
entityTeachers: TeacherUser[];
entityCorporates: CorporateUser[];
}
@@ -20,7 +20,7 @@ export default function WorkflowForm({ workflow, onWorkflowChange, entityTeacher
const [stepCounter, setStepCounter] = useState<number>(3); // to guarantee unique keys used for animations
const lastStep = workflow.steps[workflow.steps.length - 1];
const renumberSteps = (steps: WorkflowStep[]): WorkflowStep[] => {
const renumberSteps = (steps: EditableWorkflowStep[]): EditableWorkflowStep[] => {
return steps.map((step, index) => ({
...step,
stepNumber: index + 1,
@@ -28,12 +28,13 @@ export default function WorkflowForm({ workflow, onWorkflowChange, entityTeacher
};
const addStep = () => {
const newStep: WorkflowStep = {
const newStep: EditableWorkflowStep = {
key: stepCounter,
stepType: "approval-by",
stepNumber: workflow.steps.length,
completed: false,
assignees: [null],
firstStep: false,
finalStep: false,
};
setStepCounter((count) => count + 1);
@@ -73,7 +74,7 @@ export default function WorkflowForm({ workflow, onWorkflowChange, entityTeacher
onWorkflowChange({ ...workflow, steps: updatedSteps });
};
const handleReorder = (newOrder: WorkflowStep[]) => {
const handleReorder = (newOrder: EditableWorkflowStep[]) => {
const firstIndex = newOrder.findIndex((s) => s.firstStep);
if (firstIndex !== -1 && firstIndex !== 0) {
const [first] = newOrder.splice(firstIndex, 1);

View File

@@ -16,21 +16,20 @@ export default function WorkflowStepComponent({
stepNumber,
completed,
completedBy,
assignees,
finalStep,
currentStep,
selected = false,
assignees,
assigneesType,
onClick,
}: Props) {
const completedByUser = workflowAssignees.find((assignee) => assignee.id === completedBy);
const assigneesUsers = workflowAssignees.filter(user => assignees!.includes(user.id));
const assigneesUsers = workflowAssignees.filter(user => assignees.includes(user.id));
return (
<div
onClick={onClick}
className={clsx("flex flex-row gap-5 w-[700px] p-6 my-4 rounded-2xl transition ease-in-out duration-300 disabled:cursor-not-allowed cursor-pointer", {
className={clsx("flex flex-row gap-5 w-[600px] p-6 my-4 rounded-2xl transition ease-in-out duration-300 disabled:cursor-not-allowed cursor-pointer", {
"bg-mti-purple-ultralight": selected,
})}
>
@@ -85,9 +84,9 @@ export default function WorkflowStepComponent({
) : (
stepType === "approval-by" && (
<>
<p className="text-sm font-medium text-gray-800">Approval: {getUserTypeLabel(assigneesType)}</p>
{completed && completedBy ? (
<div className={clsx("text-xs font-medium", { "text-mti-purple-ultradark": selected, "text-gray-800": !selected })}>
<p className="text-sm font-medium text-gray-800">Approval: {getUserTypeLabel(completedByUser!.type)} Approval</p>
<UserWithProfilePic
prefix={`Approved by: ${getUserTypeLabelShort(completedByUser!.type)}`}
name={completedByUser!.name}
@@ -96,6 +95,7 @@ export default function WorkflowStepComponent({
</div>
) : !completed && currentStep ? (
<div className={clsx("text-xs font-medium", { "text-mti-purple-ultradark": selected, "text-gray-800": !selected })}>
<p className="text-sm font-medium text-gray-800">Approval: </p>
In Progress... Assignees:
<div className="flex flex-row flex-wrap gap-3 items-center">
{assigneesUsers.map(user => (
@@ -111,6 +111,7 @@ export default function WorkflowStepComponent({
</div>
) : (
<div className={clsx("text-xs font-medium", { "text-mti-purple-ultradark": selected, "text-gray-800": !selected })}>
<p className="text-sm font-medium text-gray-800">Approval: </p>
Waiting for previous steps...
</div>
)}

View File

@@ -2,7 +2,9 @@ import { WorkflowStep } from "@/interfaces/approval.workflow";
import clsx from "clsx";
import { IoCheckmarkDoneSharp, IoCheckmarkSharp } from "react-icons/io5";
export default function WorkflowStepNumber({ stepNumber, selected = false, completed, finalStep }: WorkflowStep) {
type Props = Pick<WorkflowStep, 'stepNumber' | 'completed' | 'finalStep' | 'selected'>
export default function WorkflowStepNumber({ stepNumber, selected = false, completed, finalStep }: Props) {
return (
<div
className={clsx(