mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-25 07:45:47 +00:00
chore(FE-91): rework ApprovalSteps and create helper function for formatting approval workflow
This commit is contained in:
@@ -3,11 +3,24 @@ import Steps from '@/components/steps/Steps';
|
|||||||
import StepItem from '@/components/steps/StepItem';
|
import StepItem from '@/components/steps/StepItem';
|
||||||
import Tooltip from '@/components/Tooltip';
|
import Tooltip from '@/components/Tooltip';
|
||||||
|
|
||||||
import { formatDate } from '@/lib/helper';
|
import { cn, formatDate } from '@/lib/helper';
|
||||||
import { ApprovalsLine } from '@/types/api/api-general';
|
import { BaseApproval, BaseGroupedApproval } from '@/types/api/api-general';
|
||||||
|
import { ApprovalLine } from '@/types/config/constant';
|
||||||
|
|
||||||
|
export type ApprovalStepStatus = 'APPROVED' | 'REJECTED' | 'WAITING' | 'IDLE';
|
||||||
|
|
||||||
|
export type ApprovalStepLog = {
|
||||||
|
action_by?: string;
|
||||||
|
date?: string;
|
||||||
|
notes?: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
interface ApprovalStepsProps {
|
interface ApprovalStepsProps {
|
||||||
approvals: ApprovalsLine;
|
approvals: {
|
||||||
|
name?: string;
|
||||||
|
status: ApprovalStepStatus;
|
||||||
|
logs?: ApprovalStepLog[];
|
||||||
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const ApprovalSteps = ({ approvals }: ApprovalStepsProps) => {
|
const ApprovalSteps = ({ approvals }: ApprovalStepsProps) => {
|
||||||
@@ -15,17 +28,23 @@ const ApprovalSteps = ({ approvals }: ApprovalStepsProps) => {
|
|||||||
<Steps direction='vertical' className='w-full md:steps-horizontal'>
|
<Steps direction='vertical' className='w-full md:steps-horizontal'>
|
||||||
{approvals.map((approval, idx) => {
|
{approvals.map((approval, idx) => {
|
||||||
const stepItemColor =
|
const stepItemColor =
|
||||||
approval.status === 'approved'
|
approval.status === 'APPROVED'
|
||||||
? 'success'
|
? 'success'
|
||||||
: approval.status === 'rejected'
|
: approval.status === 'REJECTED'
|
||||||
? 'error'
|
? 'error'
|
||||||
|
: approval.status === 'WAITING'
|
||||||
|
? 'warning'
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const stepItemIcon =
|
const stepItemIcon =
|
||||||
approval.status === 'approved'
|
approval.status === 'APPROVED'
|
||||||
? 'material-symbols:check-rounded'
|
? 'material-symbols:check-rounded'
|
||||||
: approval.status === 'rejected'
|
: approval.status === 'REJECTED'
|
||||||
? 'material-symbols:close-rounded'
|
? 'material-symbols:close-rounded'
|
||||||
|
: approval.status === 'WAITING'
|
||||||
|
? 'pajamas:dash-circle'
|
||||||
|
: approval.logs && approval.logs.length > 0
|
||||||
|
? 'material-symbols:info-outline-rounded'
|
||||||
: 'bxs:hourglass';
|
: 'bxs:hourglass';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -33,27 +52,53 @@ const ApprovalSteps = ({ approvals }: ApprovalStepsProps) => {
|
|||||||
key={idx}
|
key={idx}
|
||||||
color={stepItemColor}
|
color={stepItemColor}
|
||||||
icon={
|
icon={
|
||||||
approval.status !== 'waiting' && (
|
<Tooltip
|
||||||
<Tooltip
|
color={stepItemColor}
|
||||||
color={stepItemColor}
|
position='right'
|
||||||
position='right'
|
className={{
|
||||||
className={{
|
wrapper: 'md:tooltip-bottom',
|
||||||
wrapper: 'md:tooltip-bottom',
|
}}
|
||||||
}}
|
content={
|
||||||
content={
|
<>
|
||||||
<div className='flex flex-col text-base'>
|
{approval.logs && approval.logs.length > 0 && (
|
||||||
<span>{formatDate(approval.date, 'YYYY-MM-DD')}</span>
|
<div className='flex flex-col gap-2'>
|
||||||
<span>Oleh: {approval.action_by}</span>
|
{approval.logs?.map((approvalLog, logIdx) => (
|
||||||
<span>Catatan: {approval.notes}</span>
|
<div
|
||||||
</div>
|
key={logIdx}
|
||||||
}
|
className='flex flex-col text-base text-start'
|
||||||
>
|
>
|
||||||
<Icon icon={stepItemIcon} width={24} height={24} />
|
{approvalLog.date && (
|
||||||
</Tooltip>
|
<span>
|
||||||
)
|
{formatDate(
|
||||||
|
approvalLog.date,
|
||||||
|
'YYYY-MM-DD, HH:mm:ss'
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
<span>Oleh: {approvalLog.action_by ?? '-'}</span>
|
||||||
|
<span>Catatan: {approvalLog.notes ?? '-'}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
icon={stepItemIcon}
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
className={cn({
|
||||||
|
invisible:
|
||||||
|
approval.status === 'IDLE' &&
|
||||||
|
(!approval.logs ||
|
||||||
|
(approval.logs && approval.logs.length === 0)),
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{approval.role}
|
{approval.name}
|
||||||
</StepItem>
|
</StepItem>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -61,4 +106,76 @@ const ApprovalSteps = ({ approvals }: ApprovalStepsProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const formatGroupedApprovalsToApprovalSteps = (
|
||||||
|
approvalLine: ApprovalLine,
|
||||||
|
groupedApprovals: BaseGroupedApproval[],
|
||||||
|
latestApproval: BaseApproval
|
||||||
|
): ApprovalStepsProps['approvals'] => {
|
||||||
|
const formattedApprovalSteps: ApprovalStepsProps['approvals'] =
|
||||||
|
approvalLine.map((approvalLineItem) => {
|
||||||
|
const approvalGroup = groupedApprovals.find(
|
||||||
|
(approvalGroupItem) =>
|
||||||
|
approvalGroupItem.step_number === approvalLineItem.step_number
|
||||||
|
);
|
||||||
|
|
||||||
|
const currentStepNumber = approvalLineItem.step_number;
|
||||||
|
const lastStepNumber =
|
||||||
|
groupedApprovals[groupedApprovals.length - 1].step_number;
|
||||||
|
|
||||||
|
if (!approvalGroup && currentStepNumber <= lastStepNumber) {
|
||||||
|
throw new Error(
|
||||||
|
`Approval dengan ${approvalLineItem.step_name} tidak ditemukan!`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!approvalGroup) {
|
||||||
|
const isWaiting = currentStepNumber === latestApproval.step_number + 1;
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: approvalLineItem.step_name,
|
||||||
|
status: isWaiting ? 'WAITING' : 'IDLE',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let approvalStatus: ApprovalStepStatus;
|
||||||
|
|
||||||
|
if (approvalGroup.step_number <= latestApproval.step_number) {
|
||||||
|
switch (approvalGroup.approvals[0].action) {
|
||||||
|
case 'CREATED':
|
||||||
|
case 'APPROVED':
|
||||||
|
approvalStatus = 'APPROVED';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'REJECTED':
|
||||||
|
approvalStatus = 'REJECTED';
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
approvalStatus = 'IDLE';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (approvalGroup.step_number === latestApproval.step_number + 1) {
|
||||||
|
approvalStatus = 'WAITING';
|
||||||
|
} else {
|
||||||
|
approvalStatus = 'IDLE';
|
||||||
|
}
|
||||||
|
|
||||||
|
const approvalLogs: ApprovalStepLog[] = approvalGroup.approvals.map(
|
||||||
|
(approval) => ({
|
||||||
|
action_by: approval.action_by.name,
|
||||||
|
date: approval.action_at,
|
||||||
|
notes: approval.notes,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: approvalGroup.step_name,
|
||||||
|
status: approvalStatus,
|
||||||
|
logs: approvalLogs,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return formattedApprovalSteps;
|
||||||
|
};
|
||||||
|
|
||||||
export default ApprovalSteps;
|
export default ApprovalSteps;
|
||||||
|
|||||||
Reference in New Issue
Block a user