Untitled

Take this noob dai
 avatar
unknown
typescript
a month ago
49 kB
3
Indexable
import { MoreVertical } from 'lucide-react';
import { useCallback, useMemo } from 'react';

import {
    AccessManager,
    APPROVAL_CONTROLLER_ROUTE,
    ApprovalListingType,
    ApprovalStatusTypeEnum,
    ApprovalStepTypeEnum,
    FetchData,
    FormatCurrency,
    FormatDisplayDate,
    GetObjectFromArray,
    GetUniqueObjectsFromArray,
    IndexOfObjectInArray,
    IsEmptyArray,
    IsUndefinedOrNull,
    ObjectDto,
    PRODUCT_IDENTIFIER,
    SortArrayObjectBy,
    toastBackendError,
    useApp,
    useGetEmployeeId,
    useUserHook,
    VerificationStatusTypeEnum,
} from '@finnoto/core';
import { EmployeeAdvanceApprovalController } from '@finnoto/core/src/backend/ap/employee/controllers/employee.advance.approval.controller';
import { ExpenseApprovalController } from '@finnoto/core/src/backend/ap/expense/controllers/expense.approval.controller';
import { PurchaseOrderApprovalController } from '@finnoto/core/src/backend/ap/purchase/controllers/purchase.order.approval.controller';
import { PurchaseRequestApprovalController } from '@finnoto/core/src/backend/ap/purchase/controllers/purchase.request.approval.controller';
import { ProjectApprovalController } from '@finnoto/core/src/backend/ap/workflow/controllers';
import {
    Avatar,
    Button,
    cn,
    Collapse,
    ConfirmUtil,
    DropdownMenu,
    FormatDisplayDateStyled,
    handleActivityTimeline,
    Icon,
    NoDataFound,
    SlidingPane,
    Toast,
} from '@finnoto/design-system';

import { EmployeeIconImage } from '@Components/BusinessImage/businessImage.component';
import {
    handleNavigationEmployeeDetail,
    openOverrideApproval,
    openTransferApproval,
} from '@Utils/functions.utils';

import { ApprovalNonCheckedSvgIcon, VerifiedTickSvgIcon } from 'assets';

interface InvoiceApprovalWorkflowProps {
    data: ObjectDto;
    workflows: ObjectDto[];
    currentActiveWorkflow?: ObjectDto;
    isAnyRejected?: boolean;
    canApproveInvoice?: boolean;
    active_approval?: ObjectDto;
    type?: ApprovalListingType;
    openEdit?: () => void;
    callback?: () => void;
}

const InvoiceApprovalWorkflow = ({
    data,
    workflows,
    currentActiveWorkflow,
    isAnyRejected,
    canApproveInvoice,
    active_approval,
    type = 'expense',
    openEdit = () => {},
    callback = () => {},
}: InvoiceApprovalWorkflowProps) => {
    const { id: document_id, party_status_id } = data || {};
    const { user } = useUserHook();

    const isCreatorIsCurrentUser = useMemo(() => {
        if (!data?.created_by) return false;
        return data?.created_by === user?.id;
    }, [data?.created_by, user?.id]);

    const className = APPROVAL_CONTROLLER_ROUTE[type];

    const { product_id } = useApp();
    const isFinopsPortal = useMemo(
        () => product_id === PRODUCT_IDENTIFIER.FINOPS,
        [product_id]
    );

    const getStageLevels = useCallback(() => {
        return SortArrayObjectBy(
            GetUniqueObjectsFromArray(
                workflows?.map((workflow) => workflow.stage_level),
                'id'
            ),
            'level',
            'desc'
        ).filter(Boolean);
    }, [workflows]);

    const availableApprovals = useMemo<
        {
            label: string;
            stage_level_id?: number;
            visible: boolean;
        }[]
    >(() => {
        const stageLevels = getStageLevels();
        return stageLevels.map((stageLevel) => ({
            label: stageLevel.name,
            stage_level_id: stageLevel.id,
            visible: true,
        }));
    }, [getStageLevels]);

    const skipLevel = async (id: number, next = () => {}) => {
        const { success, response } = await FetchData({
            className,
            method: 'skipLevel',
            methodParams: { expenseId: document_id, id },
        });

        if (!success) {
            Toast.error({
                description: response.message || 'Something went wrong!',
            });
            return next();
        }

        Toast.success({ description: 'Successfully skipped level!' });
        callback();
        next();
    };

    const dropSkipLevel = async (id: number, next = () => {}) => {
        const { success, response } = await FetchData({
            className,
            method: 'dropSkipLevel',
            methodParams: { expenseId: document_id, id },
        });

        if (!success) {
            Toast.error({
                description: response.message || 'Something went wrong!',
            });
            return next();
        }

        Toast.success({ description: 'Successfully skipped drop!' });
        callback();
        next();
    };

    const dropTransfer = async (id: number) => {
        const { success, response } = await FetchData({
            className,
            method: 'dropTransfer',
            methodParams: { expenseId: document_id, id },
        });

        if (!success) {
            Toast.error({
                description: response.message || 'Something went wrong!',
            });
            return;
        }

        Toast.success({ description: 'Successfully Transfer Dropped.' });
        callback();
    };

    const getWorkflows = useCallback(
        (level_id: number) => {
            return (
                workflows?.filter(
                    (workflow) => workflow.stage_level_id === level_id
                ) || []
            );
        },
        [workflows]
    );

    const getWorkflowStatus = useCallback((approval_type: number) => {
        // TODO: Add other statuses

        return false;
    }, []);

    const shouldShowReset = useMemo(() => {
        if (isAnyRejected || !currentActiveWorkflow) return false;
        if (IsEmptyArray(workflows)) return true;
        if (getWorkflowStatus(currentActiveWorkflow?.stage_level_id))
            return false;

        const currentWorkflows = getWorkflows(
            currentActiveWorkflow?.stage_level_id
        );

        if (IsEmptyArray(currentWorkflows)) return true;
        if (currentWorkflows[currentWorkflows.length - 1].activity_datetime)
            return true;

        return false;
    }, [
        workflows,
        isAnyRejected,
        currentActiveWorkflow,
        getWorkflowStatus,
        getWorkflows,
    ]);

    const party_rejected =
        party_status_id === VerificationStatusTypeEnum.REJECTED;

    // if (IsEmptyArray(workflows)) {
    //     return (
    //         <div className='flex items-center justify-center w-full h-full'>
    //             <NoDataFound />
    //         </div>
    //     );
    // }

    return (
        <div id='approval-workflows' className='w-full h-full gap-4 col-flex'>
            <div className='flex items-center justify-between'>
                <div className='font-medium text-base-primary'>
                    Approval Workflows
                </div>
            </div>

            <div className='gap-4 pb-4 overflow-auto col-flex'>
                {availableApprovals.map((approval) => {
                    if (!approval.visible) return null;
                    const workflows = getWorkflows(approval.stage_level_id);

                    const workflow_name = (() => {
                        const workflow = workflows.find((workflow) => {
                            return workflow.rule_id > 10;
                        });

                        return workflow?.rule?.name;
                    })();

                    return (
                        <div
                            key={approval.stage_level_id}
                            className='gap-4 p-4 border rounded-t bg-base-200 col-flex border-base-300'
                            id={`approval-${approval.stage_level_id}`}
                            aria-label={approval.label}
                        >
                            <div className='justify-between approval-workflow-header row-flex'>
                                <div className='items-center gap-1 row-flex'>
                                    {getWorkflowStatus(
                                        approval.stage_level_id
                                    ) && (
                                        <Icon
                                            source={VerifiedTickSvgIcon}
                                            iconColor='text-success'
                                            isSvg
                                        />
                                    )}
                                    <h2 className='text-sm font-medium approval-workflow-title'>
                                        {approval.label}
                                    </h2>
                                    {!!workflow_name && (
                                        <h3 className='text-sm font-medium approval-workflow-title'>
                                            ({workflow_name})
                                        </h3>
                                    )}
                                </div>
                            </div>
                            <div className='gap-3 col-flex'>
                                {workflows.map((workflow, index) => {
                                    const isApproved =
                                        workflow.activity_id ===
                                        ApprovalStatusTypeEnum.APPROVED;

                                    const isRejected =
                                        workflow.activity_id ===
                                        ApprovalStatusTypeEnum.REJECTED;

                                    const isSkipped =
                                        !!workflow.is_skipped && !isApproved;

                                    const isInProgress =
                                        workflow.id === active_approval?.id;

                                    const canSkip = (() => {
                                        let skip = true;

                                        if (isSkipped || isApproved)
                                            return false;

                                        if (workflows.length - 1 === index)
                                            return false;

                                        for (
                                            let i = workflows.length - 1;
                                            i >= 0;
                                            i--
                                        ) {
                                            if (!skip) break;
                                            if (index < i) {
                                                skip =
                                                    workflows[i].activity_id !==
                                                    ApprovalStatusTypeEnum.APPROVED;
                                            }
                                        }

                                        return skip;
                                    })();

                                    const groupTransfers = (
                                        approvalList: ObjectDto[]
                                    ) => {
                                        const newList = [];

                                        approvalList.forEach((approval) => {
                                            if (!approval.parent_id)
                                                return newList.push(approval);

                                            const parentIndex =
                                                IndexOfObjectInArray(
                                                    approvalList,
                                                    'id',
                                                    approval.parent_id
                                                );

                                            if (parentIndex > -1) {
                                                const parent =
                                                    approvalList[parentIndex];

                                                if (
                                                    !IsEmptyArray(
                                                        approval.transferredApproval
                                                    )
                                                ) {
                                                    if (
                                                        IsEmptyArray(
                                                            parent.transferredApproval
                                                        )
                                                    ) {
                                                        parent.transferredApproval =
                                                            [
                                                                ...approval.transferredApproval,
                                                            ];
                                                        return;
                                                    }
                                                    parent.transferredApproval.push(
                                                        ...approval.transferredApproval
                                                    );
                                                }
                                            }
                                        });

                                        return newList;
                                    };

                                    const approvals = (() => {
                                        const approvalList = [];

                                        SortArrayObjectBy(
                                            (workflow.workflow_users as any[]) ||
                                                [],
                                            'id',
                                            'desc'
                                        ).forEach((approval, _, approvals) => {
                                            if (!approval?.user) return;

                                            if (approval.parent_id) {
                                                let approvalIndex =
                                                    IndexOfObjectInArray(
                                                        approvalList,
                                                        'id',
                                                        approval.parent_id
                                                    );

                                                if (approvalIndex > -1) {
                                                    approvalList[
                                                        approvalIndex
                                                    ].transferredApproval = [
                                                        approval,
                                                    ];
                                                    return;
                                                }

                                                approvalList.push({
                                                    ...GetObjectFromArray(
                                                        approvals,
                                                        'id',
                                                        approval.parent_id
                                                    ),
                                                    transferredApproval: [
                                                        approval,
                                                    ],
                                                });
                                                return;
                                            }

                                            if (
                                                IndexOfObjectInArray(
                                                    approvalList,
                                                    'id',
                                                    approval.id
                                                ) === -1
                                            ) {
                                                approvalList.push(approval);
                                            }
                                        });

                                        return groupTransfers(approvalList);
                                    })();

                                    const userGroupStatus = (() => {
                                        if (
                                            isApproved ||
                                            isRejected ||
                                            isSkipped ||
                                            workflow.approval_type_id !==
                                                ApprovalStepTypeEnum.USER_GROUP
                                        ) {
                                            return null;
                                        }

                                        const { property, users } =
                                            workflow?.attributes || {};

                                        const approvedCount = approvals.filter(
                                            (approval) =>
                                                !approval.parent_id &&
                                                approval.activity_id ===
                                                    ApprovalStatusTypeEnum.APPROVED
                                        ).length;

                                        let toApproveCount = 1;

                                        if (property.all) {
                                            toApproveCount = users;
                                        }
                                        if (property.percentage) {
                                            toApproveCount = Math.ceil(
                                                (users * property.percentage) /
                                                    100
                                            );
                                        }

                                        return {
                                            total: toApproveCount,
                                            progress: approvedCount,
                                        };
                                    })();

                                    const canTransfer = (() => {
                                        let transfer = true;

                                        if (isApproved || isAnyRejected)
                                            return false;

                                        for (
                                            let i = workflows.length - 1;
                                            i >= 0;
                                            i--
                                        ) {
                                            if (!transfer) break;
                                            if (index < i) {
                                                transfer =
                                                    workflows[i].activity_id !==
                                                    ApprovalStatusTypeEnum.APPROVED;
                                            }
                                        }

                                        return transfer;
                                    })();

                                    const getIcon = () => {
                                        if (isRejected) return 'close';
                                        if (isApproved) return 'check';
                                        if (isSkipped) return 'skip_next';
                                        return ApprovalNonCheckedSvgIcon;
                                    };

                                    const getIconAppearance = () => {
                                        if (isSkipped)
                                            return 'bg-info text-info-content';
                                        if (isRejected)
                                            return 'bg-error text-error-content';
                                        if (isApproved)
                                            return 'bg-success text-success-content';
                                        return 'text-base-secondary';
                                    };

                                    return (
                                        <Collapse
                                            key={workflow.id}
                                            title={
                                                <div className='items-center justify-between row-flex'>
                                                    <div className='items-center gap-6 row-flex'>
                                                        <div className='items-center gap-2 row-flex'>
                                                            <div
                                                                className={cn(
                                                                    'flex rounded-full bg-base-300 text-base-100 p-[2px] relative',
                                                                    getIconAppearance()
                                                                )}
                                                            >
                                                                <Icon
                                                                    source={getIcon()}
                                                                    size={14}
                                                                    className='z-[1]'
                                                                    isSvg
                                                                />

                                                                {isInProgress &&
                                                                    !isSkipped &&
                                                                    !party_rejected && (
                                                                        <span className='absolute top-0 left-0 w-full h-full rounded-full opacity-50 animate-ping bg-primary'></span>
                                                                    )}
                                                            </div>
                                                            <span className='level-number'>
                                                                Level{' '}
                                                                {index + 1}
                                                            </span>
                                                        </div>
                                                        <span className='level-name'>
                                                            {workflow.name}
                                                        </span>
                                                        {userGroupStatus && (
                                                            <span className='level-progress-remaining'>
                                                                {`${userGroupStatus.progress} / ${userGroupStatus.total} Remaining`}
                                                            </span>
                                                        )}
                                                    </div>
                                                    <div className='gap-2 row-flex'>
                                                        {!isAnyRejected &&
                                                            !isApproved &&
                                                            canSkip &&
                                                            AccessManager.hasRoleIdentifier(
                                                                'ua_approval_overrider'
                                                            ) &&
                                                            workflows.length >
                                                                1 && (
                                                                <Button
                                                                    className='opacity-0 group-hover/title:opacity-100'
                                                                    appearance='success'
                                                                    size='xs'
                                                                    progress
                                                                    onClick={(
                                                                        next,
                                                                        e
                                                                    ) => {
                                                                        e.preventDefault();
                                                                        e.stopPropagation();
                                                                        skipLevel(
                                                                            workflow.id,
                                                                            next
                                                                        );
                                                                    }}
                                                                >
                                                                    Skip
                                                                </Button>
                                                            )}
                                                        {!isAnyRejected &&
                                                            isSkipped &&
                                                            !isApproved &&
                                                            !workflow
                                                                ?.attributes
                                                                ?.no_edit &&
                                                            AccessManager.hasRoleIdentifier(
                                                                'ua_approval_overrider'
                                                            ) && (
                                                                <Button
                                                                    className='opacity-0 group-hover/title:opacity-100'
                                                                    appearance='error'
                                                                    size='xs'
                                                                    progress
                                                                    onClick={(
                                                                        next,
                                                                        e
                                                                    ) => {
                                                                        e.preventDefault();
                                                                        e.stopPropagation();
                                                                        dropSkipLevel(
                                                                            workflow.id,
                                                                            next
                                                                        );
                                                                    }}
                                                                >
                                                                    Drop Skip
                                                                </Button>
                                                            )}
                                                        {/* {isApproved && (
                                                            <Badge
                                                                size='md'
                                                                appearance='success'
                                                                label='Approved'
                                                            />
                                                        )}
                                                        {isRejected && (
                                                            <Badge
                                                                size='md'
                                                                appearance='error'
                                                                label='Rejected'
                                                            />
                                                        )} */}
                                                        {/* {isSkipped && (
                                                            <Badge
                                                                size='md'
                                                                appearance='info'
                                                                label='Skipped'
                                                            />
                                                        )} */}
                                                        {/* {isInProgress && (
                                                            <Badge
                                                                size='md'
                                                                appearance='warning'
                                                                label='In Progress'
                                                            />
                                                        )} */}
                                                        {workflow.activity_datetime &&
                                                            FormatDisplayDateStyled(
                                                                {
                                                                    value: workflow.activity_datetime,
                                                                }
                                                            )}
                                                    </div>
                                                </div>
                                            }
                                            headerClassName='bg-base-100 p-3 px-4 gap-2 group/title workflow-level-header rounded'
                                            titleClassName='text-sm font-normal text-base-primary'
                                            defaultExpand={
                                                isInProgress ||
                                                (currentActiveWorkflow?.stage_level_id ===
                                                    approval.stage_level_id &&
                                                    index === 0)
                                            }
                                        >
                                            <ApprovalLevelUsers
                                                {...{
                                                    workflow,
                                                    approvals,
                                                    document_id,
                                                    type,
                                                    canTransfer,
                                                    callback,
                                                    dropTransfer,
                                                    party_rejected,
                                                    isFinopsPortal,
                                                    isInProgress,
                                                    isCreatorIsCurrentUser,
                                                }}
                                            />
                                        </Collapse>
                                    );
                                })}
                            </div>
                        </div>
                    );
                })}
            </div>

            {shouldShowReset && !IsEmptyArray(workflows) && (
                <div className='col-flex'>
                    <div className='text-sm'>
                        <a
                            className='link link-hover'
                            onClick={() =>
                                openOverrideApproval(data, type, callback)
                            }
                        >
                            Click here
                        </a>{' '}
                        to override the approval workflow
                    </div>
                </div>
            )}
            {shouldShowReset && IsEmptyArray(workflows) && (
                <div className='col-flex'>
                    {AccessManager.canEditExpense({
                        product_id,
                        canApproveDocument: canApproveInvoice,
                        data,
                    }) ? (
                        <div className='text-sm'>
                            <a className='link link-hover' onClick={openEdit}>
                                Click here
                            </a>{' '}
                            to add poc to generate approval workflow.
                        </div>
                    ) : (
                        <div className='text-sm'>
                            Contact your expense manager to add correct poc to
                            create approval workflow
                        </div>
                    )}
                </div>
            )}
            {!shouldShowReset && IsEmptyArray(workflows) && (
                <NoDataFound title='No workflows found' />
            )}
        </div>
    );
};

const ApprovalLevelUsers = ({
    approvals,
    workflow,
    document_id,
    type,
    canTransfer,
    party_rejected,
    dropTransfer,
    callback,
    isFinopsPortal,
    isInProgress,
    isCreatorIsCurrentUser,
}: {
    document_id: number;
    type: ApprovalListingType;
    workflow: ObjectDto;
    approvals: ObjectDto[];
    canTransfer?: boolean;
    party_rejected?: boolean;
    dropTransfer?: (id: number) => void;
    callback?: Function;
    isFinopsPortal?: boolean;
    isInProgress?: boolean;
    isCreatorIsCurrentUser?: boolean;
}) => {
    return (
        <div className='border col-flex approvals'>
            {approvals.map((approval) => {
                const transferredApprovalLength =
                    approval?.transferredApproval?.length;

                return (
                    <div
                        key={approval.id}
                        className='p-4 border-b rounded-b approval col-flex last:border-b-0 bg-base-100'
                    >
                        <div className='gap-4 col-flex'>
                            <ApprovalUserCard
                                {...{
                                    document_id,
                                    type,
                                    workflow,
                                    approval,
                                    canTransfer,
                                    party_rejected,
                                    dropTransfer,
                                    isTransferred: !IsEmptyArray(
                                        approval.transferredApproval
                                    ),
                                    isFinopsPortal,
                                    callback,
                                    isInProgress,
                                    isCreatorIsCurrentUser,
                                    transferId: !IsEmptyArray(
                                        approval.transferredApproval
                                    )
                                        ? approval?.transferredApproval[
                                              transferredApprovalLength - 1
                                          ]?.id
                                        : approval.id,
                                }}
                            />
                            {!IsEmptyArray(approval.transferredApproval) ? (
                                <>
                                    {approval.transferredApproval.map(
                                        (
                                            tApproval: ObjectDto,
                                            index: number,
                                            tArray: ObjectDto[]
                                        ) => {
                                            return (
                                                <ApprovalUserCard
                                                    key={index}
                                                    {...{
                                                        document_id,
                                                        type,
                                                        workflow,
                                                        approval: tApproval,
                                                        canTransfer,
                                                        party_rejected,
                                                        dropTransfer,
                                                        isTransferred:
                                                            tArray.length - 1 >
                                                            index,
                                                        callback,
                                                        isFinopsPortal,
                                                        isInProgress,
                                                        isCreatorIsCurrentUser,
                                                    }}
                                                />
                                            );
                                        }
                                    )}
                                </>
                            ) : null}
                        </div>

                        {approval.attributes?.reason || approval.comments ? (
                            <div className='w-full my-2 border-b border-dashed' />
                        ) : null}

                        {approval.attributes?.reason ? (
                            <div className='text-sm text-base-secondary'>
                                Reason :{' '}
                                <span className='text-base-primary'>
                                    {approval.attributes?.reason}
                                </span>
                            </div>
                        ) : null}
                        {approval.comments ? (
                            <div className='text-sm text-base-secondary'>
                                Comments :{' '}
                                <span className='text-base-primary'>
                                    {approval.comments}
                                </span>
                            </div>
                        ) : null}
                    </div>
                );
            })}
        </div>
    );
};

const ApprovalUserCard = ({
    document_id,
    type,
    workflow,
    approval,
    canTransfer,
    party_rejected,
    isTransferred,
    dropTransfer,
    callback,
    isFinopsPortal,
    isInProgress,
    isCreatorIsCurrentUser,
    transferId,
}: {
    document_id: number;
    type: ApprovalListingType;
    workflow: ObjectDto;
    approval: ObjectDto;
    canTransfer?: boolean;
    party_rejected?: boolean;
    isTransferred?: boolean;
    dropTransfer?: (id: number) => void;
    callback?: Function;
    isFinopsPortal?: boolean;
    isInProgress?: boolean;
    isCreatorIsCurrentUser?: boolean;
    transferId?: number;
}) => {
    const { user, employee } = approval;
    const { image_url } = user || {};
    const { isSuccess: handleSuccessEmployeNavigation } = useGetEmployeeId();

    const actions = [
        {
            name: 'Transfer',
            visible:
                !!canTransfer &&
                !approval.parent_id &&
                IsEmptyArray(approval.transferredApproval) &&
                approval?.activity_id !== ApprovalStatusTypeEnum.APPROVED &&
                AccessManager.hasRoleIdentifier('ua_approval_overrider'),
            action: () => {
                openTransferApproval({
                    document_id,
                    type,
                    level_id: approval.id,
                    current_user_id: approval.user_id,
                    callback: () => {
                        SlidingPane.close();
                        callback();
                    },
                });
            },
        },
        {
            name: 'Delete Transfer',
            visible:
                !!canTransfer &&
                !IsEmptyArray(approval.transferredApproval) &&
                approval.transferredApproval.length === 1 &&
                AccessManager.hasRoleIdentifier('ua_approval_overrider'),
            action: () => dropTransfer(approval.transferredApproval[0].id),
        },
        {
            name: 'Send Notification',

            action: () => {
                ConfirmUtil({
                    message: 'Are you sure you want to send notification?',
                    title: 'Send Notification',
                    cancelAppearance: 'error',
                    appearance: 'success',
                    onConfirmPress: () => {
                        SendNotification({
                            typeId: document_id,
                            type,
                            approvalId: transferId ?? approval.id,
                        });
                    },
                });
            },

            visible: isInProgress && isCreatorIsCurrentUser,
        },
    ];

    return (
        <div
            key={approval?.id}
            className={cn(
                'approval-user text-sm approve-card col-flex flex-1',
                handleActivityTimeline(approval?.activity_id)
            )}
        >
            <div className='grid grid-cols-3 gap-4'>
                <div
                    className={cn(' gap-3 row-flex', {
                        'items-center': image_url,
                    })}
                >
                    {image_url ? (
                        <Avatar
                            source={image_url}
                            alt={employee?.name || user?.name}
                            size='32'
                            shape='rounded'
                            color='vendor'
                        />
                    ) : (
                        <EmployeeIconImage className='w-8 h-8' size={18} />
                    )}

                    <div className='col-flex'>
                        <button
                            onClick={(e) => {
                                if (!isFinopsPortal) return;
                                handleNavigationEmployeeDetail(
                                    handleSuccessEmployeNavigation,
                                    user.id
                                );
                            }}
                            className={cn(
                                'flex items-center gap-2 font-medium approval-user-name ',
                                isFinopsPortal && 'table-link'
                            )}
                        >
                            {employee?.name || user?.name}
                        </button>
                        <span className='text-xs approval-user-email'>
                            {user?.email}
                        </span>
                    </div>
                </div>
                <div className='text-center approval-status'>
                    {!isTransferred && approval.activity_datetime && (
                        <>
                            {approval?.activity_id ===
                                ApprovalStatusTypeEnum.APPROVED && (
                                <div className='text-success'>Approved</div>
                            )}
                            {approval?.activity_id ===
                                ApprovalStatusTypeEnum.REJECTED && (
                                <div className='text-error'>Rejected</div>
                            )}
                        </>
                    )}
                    {!isTransferred && !approval.activity_datetime && (
                        <>
                            {!party_rejected &&
                                !workflow.is_skipped &&
                                !workflow.activity_datetime && (
                                    <div className={'text-warning'}>
                                        Pending Approval
                                    </div>
                                )}
                            {!!workflow.is_skipped && (
                                <div className='text-info'>Skipped</div>
                            )}
                        </>
                    )}
                    {isTransferred && (
                        <div className={'text-info'}>Transferred</div>
                    )}
                </div>
                <div className='justify-between gap-2 row-flex'>
                    <div className='flex-1 gap-1 text-right col-flex'>
                        {approval.activity_datetime ? (
                            <span className='text-xs text-base-primary'>
                                {FormatDisplayDate(
                                    approval.activity_datetime,
                                    true
                                )}
                            </span>
                        ) : null}
                        {!IsUndefinedOrNull(approval.attributes?.limit) ? (
                            <div className={'text-xs text-base-secondary'}>
                                Threshold :{' '}
                                <span className='text-base-primary'>
                                    {FormatCurrency({
                                        amount: approval.attributes?.limit || 0,
                                    })}{' '}
                                    & Above
                                </span>
                            </div>
                        ) : null}
                    </div>
                    {!approval.parent_id &&
                        ![
                            ApprovalStatusTypeEnum.APPROVED,
                            ApprovalStatusTypeEnum.REJECTED,
                        ].includes(approval?.activity_id) &&
                        actions.some((action) => action.visible !== false) && (
                            <div>
                                <DropdownMenu actions={actions} align='end'>
                                    <div className='p-2 border rounded cursor-pointer select-none hover:bg-base-200 approval-actions'>
                                        <MoreVertical size={16} />
                                    </div>
                                </DropdownMenu>
                            </div>
                        )}
                </div>
            </div>
        </div>
    );
};

export default InvoiceApprovalWorkflow;

const SendNotification = async ({
    typeId,
    type,
    approvalId,
}: {
    typeId: number;
    type: string;
    approvalId: number;
}) => {
    const controllers = {
        expense: ExpenseApprovalController,
        advance: EmployeeAdvanceApprovalController,
        purchase_request: PurchaseRequestApprovalController,
        purchase_order: PurchaseOrderApprovalController,
        project: ProjectApprovalController,
    };
    const className = controllers[type];

    const { success, response } = await FetchData({
        className,
        methodParams: {
            expenseId: typeId,
            id: approvalId,
        },
        method: 'notify',
    });
    if (!success) return toastBackendError(response, 'Something went wrong!');
    Toast.success({
        description: 'Notification sent successfully',
    });
};
Leave a Comment