mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into feat/create-pdf-component
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { Icon } from '@iconify/react';
|
||||
import { BaseApproval } from '@/types/api/api-general';
|
||||
import Button from '@/components/Button';
|
||||
|
||||
import { cn, formatDate } from '@/lib/helper';
|
||||
|
||||
interface ApprovalStepsV2Props {
|
||||
approvals?: BaseApproval[];
|
||||
steps: {
|
||||
step_number: number;
|
||||
step_name: string;
|
||||
}[];
|
||||
maxVisibleSteps?: number;
|
||||
className?: {
|
||||
wrapper?: string;
|
||||
stepsWrapper?: string;
|
||||
stepsContainer?: string;
|
||||
};
|
||||
}
|
||||
|
||||
const ApprovalStepsV2 = ({
|
||||
approvals,
|
||||
steps,
|
||||
maxVisibleSteps = 2,
|
||||
className,
|
||||
}: ApprovalStepsV2Props) => {
|
||||
const [isSeeAll, setIsSeeAll] = useState(false);
|
||||
const [formattedApprovals, setFormattedApprovals] = useState<
|
||||
(BaseApproval & { isActive: boolean })[]
|
||||
>([]);
|
||||
|
||||
const latestApprovalStepNumber =
|
||||
approvals?.[approvals.length - 1].step_number ?? 0;
|
||||
|
||||
const lastStepNumber = steps[steps.length - 1].step_number;
|
||||
|
||||
const isLatestApprovalStepNumberLessThanLastStepNumber =
|
||||
latestApprovalStepNumber < lastStepNumber;
|
||||
|
||||
const slicedFormattedApprovals = useMemo(() => {
|
||||
return formattedApprovals.slice(0, isSeeAll ? undefined : maxVisibleSteps);
|
||||
}, [formattedApprovals, isSeeAll]);
|
||||
|
||||
const seeMoreClickHandler = () => {
|
||||
setIsSeeAll((prevVal) => !prevVal);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (approvals) {
|
||||
const tempFormattedApprovals: (BaseApproval & { isActive: boolean })[] =
|
||||
[];
|
||||
|
||||
approvals.forEach((approval) => {
|
||||
tempFormattedApprovals.push({
|
||||
...approval,
|
||||
isActive: true,
|
||||
});
|
||||
});
|
||||
|
||||
if (isLatestApprovalStepNumberLessThanLastStepNumber) {
|
||||
const latestApprovalStepNumberIndexInSteps = steps.findIndex(
|
||||
(step) => step.step_number === latestApprovalStepNumber
|
||||
);
|
||||
|
||||
const slicedSteps = steps.slice(
|
||||
latestApprovalStepNumberIndexInSteps + 1
|
||||
);
|
||||
|
||||
slicedSteps.forEach((step) => {
|
||||
tempFormattedApprovals.push({
|
||||
action: 'APPROVED',
|
||||
action_at: new Date().toISOString(),
|
||||
action_by: {
|
||||
id: 0,
|
||||
id_user: 0,
|
||||
email: '',
|
||||
name: '',
|
||||
},
|
||||
step_name: step.step_name,
|
||||
step_number: step.step_number,
|
||||
isActive: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
setFormattedApprovals(tempFormattedApprovals);
|
||||
}
|
||||
}, [approvals]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'w-full p-4 flex flex-col border-b border-base-content/10',
|
||||
className?.wrapper
|
||||
)}
|
||||
>
|
||||
<h4 className='text-base font-medium text-base-content/50 font-roboto'>
|
||||
Progress Details
|
||||
</h4>
|
||||
|
||||
<div
|
||||
className={cn(
|
||||
'mt-6 mb-8 flex flex-col gap-10',
|
||||
className?.stepsWrapper
|
||||
)}
|
||||
>
|
||||
{slicedFormattedApprovals.map((approval, idx) => {
|
||||
const isApprovalActionCreated = approval.action === 'CREATED';
|
||||
const isApprovalActionUpdated = approval.action === 'UPDATED';
|
||||
const isApprovalActionRejected = approval.action === 'REJECTED';
|
||||
const isApprovalActionApproved = approval.action === 'APPROVED';
|
||||
|
||||
const approvalIcon =
|
||||
isApprovalActionCreated || isApprovalActionUpdated
|
||||
? 'heroicons:clock-solid'
|
||||
: isApprovalActionRejected
|
||||
? 'heroicons:x-circle-solid'
|
||||
: isApprovalActionApproved
|
||||
? 'heroicons:check-badge-solid'
|
||||
: 'heroicons:check-badge-solid';
|
||||
|
||||
return (
|
||||
<div key={idx} className='w-full flex flex-row items-stretch gap-3'>
|
||||
<div className='w-fit self-stretch relative'>
|
||||
<div className='w-fit h-fit flex flex-col items-start'>
|
||||
<Icon
|
||||
icon={approvalIcon}
|
||||
width={24}
|
||||
height={24}
|
||||
className={cn({
|
||||
'text-warning':
|
||||
isApprovalActionCreated || isApprovalActionUpdated,
|
||||
'text-error': isApprovalActionRejected,
|
||||
'text-success': isApprovalActionApproved,
|
||||
'text-base-content/20': !approval.isActive,
|
||||
})}
|
||||
/>
|
||||
|
||||
{idx < formattedApprovals.length - 1 && (
|
||||
<div className='absolute top-6 left-1/2 -translate-x-1/2 w-0 min-h-full h-[calc(100%)] mx-auto my-2 border border-dashed border-base-content/10' />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={cn('w-full flex flex-col gap-1 text-base-content', {
|
||||
'text-base-content/20': !approval.isActive,
|
||||
})}
|
||||
>
|
||||
<div className='flex flex-col'>
|
||||
<span className='text-xs'>{approval.step_name}</span>
|
||||
<span className='text-sm font-semibold'>
|
||||
{(isApprovalActionCreated || isApprovalActionUpdated) &&
|
||||
'Diajukan oleh '}
|
||||
{isApprovalActionRejected && 'Ditolak oleh '}
|
||||
{isApprovalActionApproved && 'Disetujui oleh '}
|
||||
{approval.isActive ? approval.action_by.name : '...'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{approval.isActive && (
|
||||
<p className='w-full max-w-60 p-3 bg-base-content/5 rounded-xl text-xs text-base-content/50'>
|
||||
Created at :{' '}
|
||||
{formatDate(approval.action_at, 'DD-MM-YYYY, HH:mm')}
|
||||
<br />
|
||||
Notes : {approval.notes ?? '-'}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<Button
|
||||
variant='outline'
|
||||
color='none'
|
||||
onClick={seeMoreClickHandler}
|
||||
className={cn(
|
||||
'px-3 py-2 gap-2.5 text-sm text-base-content/50 border border-base-content/10 rounded-lg transition-all'
|
||||
)}
|
||||
>
|
||||
<Icon
|
||||
icon='heroicons-outline:chevron-double-down'
|
||||
width={20}
|
||||
height={20}
|
||||
className={cn('transition-all duration-300', {
|
||||
'-rotate-180': isSeeAll,
|
||||
})}
|
||||
/>
|
||||
See {isSeeAll ? 'Less' : 'More'}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ApprovalStepsV2;
|
||||
Reference in New Issue
Block a user