refactor(FE): Add Unit VP approval and rename Manager

This commit is contained in:
rstubryan
2026-01-12 11:11:11 +07:00
parent 2b2dd0a026
commit ec16c6c47e
4 changed files with 239 additions and 47 deletions
@@ -59,34 +59,40 @@ const ExpenseRequestContent = ({
const isLatestApprovalRejectedOrDone =
isLatestApprovalRejected ||
initialValues?.latest_approval.step_number === 5;
initialValues?.latest_approval.step_number === 6;
const isCurrentApprovalOnManager =
const isCurrentApprovalOnHeadArea =
!isLatestApprovalRejected &&
initialValues?.latest_approval.step_number === 1;
const isCurrentApprovalOnFinance =
const isCurrentApprovalOnUnitVicePresident =
!isLatestApprovalRejected &&
initialValues?.latest_approval.step_number === 2;
const isCurrentApprovalOnFinance =
!isLatestApprovalRejected &&
initialValues?.latest_approval.step_number === 3;
const isCurrentApprovalOnRealization =
!isLatestApprovalRejected &&
initialValues?.latest_approval.step_number === 4;
initialValues?.latest_approval.step_number === 5;
const showEditButton =
initialValues?.latest_approval.step_number !== 5 &&
initialValues?.latest_approval.step_number !== 6 &&
(initialValues?.latest_approval.step_number === 1 ||
initialValues?.latest_approval.step_number === 2 ||
initialValues?.latest_approval.step_number === 3);
initialValues?.latest_approval.step_number === 3 ||
initialValues?.latest_approval.step_number === 4);
const showRejectButton =
!isLatestApprovalRejected &&
(initialValues?.latest_approval.step_number === 1 ||
initialValues?.latest_approval.step_number === 2);
initialValues?.latest_approval.step_number === 2 ||
initialValues?.latest_approval.step_number === 3);
const isExpenseCanBeRealized =
!isLatestApprovalRejected &&
initialValues?.latest_approval.step_number === 3;
initialValues?.latest_approval.step_number === 4;
// Modal hooks
const deleteModal = useModal();
@@ -174,8 +180,15 @@ const ExpenseRequestContent = ({
let approveResponse: BaseApiResponse<Expense> | undefined = undefined;
if (isCurrentApprovalOnManager) {
approveResponse = await ExpenseApi.approveManager(
if (isCurrentApprovalOnHeadArea) {
approveResponse = await ExpenseApi.approveHeadArea(
initialValues.id,
notes
);
}
if (isCurrentApprovalOnUnitVicePresident) {
approveResponse = await ExpenseApi.approveUnitVicePresident(
initialValues.id,
notes
);
@@ -207,8 +220,15 @@ const ExpenseRequestContent = ({
let rejectResponse: BaseApiResponse<Expense> | undefined = undefined;
if (isCurrentApprovalOnManager) {
rejectResponse = await ExpenseApi.rejectManager(initialValues.id, notes);
if (isCurrentApprovalOnHeadArea) {
rejectResponse = await ExpenseApi.rejectHeadArea(initialValues.id, notes);
}
if (isCurrentApprovalOnUnitVicePresident) {
rejectResponse = await ExpenseApi.rejectUnitVicePresident(
initialValues.id,
notes
);
}
if (isCurrentApprovalOnFinance) {
@@ -255,8 +275,8 @@ const ExpenseRequestContent = ({
{/* TODO: apply RBAC */}
<div className='w-full max-w-5xl mx-auto flex flex-col sm:flex-row justify-end gap-2'>
{isCurrentApprovalOnManager && (
<RequirePermission permissions='lti.expense.approve.manager'>
{isCurrentApprovalOnHeadArea && (
<RequirePermission permissions='lti.expense.approve.head_area'>
<Button
variant='outline'
color='info'
@@ -264,7 +284,21 @@ const ExpenseRequestContent = ({
className='w-full sm:w-fit'
>
<Icon icon='lucide-lab:farm' width={24} height={24} />
Approve Manager
Approve Head Area
</Button>
</RequirePermission>
)}
{isCurrentApprovalOnUnitVicePresident && (
<RequirePermission permissions='lti.expense.approve.unit_vice_president'>
<Button
variant='outline'
color='success'
onClick={approveClickHandler}
className='w-full sm:w-fit'
>
<Icon icon='tdesign:money' width={24} height={24} />
Approve Unit Vice President
</Button>
</RequirePermission>
)}
@@ -304,7 +338,8 @@ const ExpenseRequestContent = ({
{showRejectButton && (
<RequirePermission
permissions={[
'lti.expense.approve.manager',
'lti.expense.approve.head_area',
'lti.expense.approve.unit_vice_president',
'lti.expense.approve.finance',
]}
>
@@ -454,8 +489,8 @@ const ExpenseRequestContent = ({
<th>:</th>
<td>
{formatCurrency(
initialValues?.latest_approval.step_number === 4 ||
initialValues?.latest_approval.step_number === 5
initialValues?.latest_approval.step_number === 5 ||
initialValues?.latest_approval.step_number === 6
? (initialValues?.total_realisasi ?? 0)
: (initialValues?.total_pengajuan ?? 0)
)}
+63 -18
View File
@@ -55,15 +55,16 @@ const RowOptionsMenu = ({
deleteClickHandler: () => void;
}) => {
const showEditButton =
props.row.original.latest_approval.step_number !== 5 &&
props.row.original.latest_approval.step_number !== 6 &&
(props.row.original.latest_approval.step_number === 1 ||
props.row.original.latest_approval.step_number === 2 ||
props.row.original.latest_approval.step_number === 3);
props.row.original.latest_approval.step_number === 3 ||
props.row.original.latest_approval.step_number === 4);
// TODO: apply RBAC
const showRealizationButton =
props.row.original.latest_approval.action !== 'REJECTED' &&
props.row.original.latest_approval.step_number === 3;
props.row.original.latest_approval.step_number === 4;
return (
<RowOptionsMenuWrapper type={type}>
@@ -193,7 +194,7 @@ const ExpensesTable = () => {
parseInt(item)
);
const isAllSelectedRowLatestApprovalOnManager = useMemo(() => {
const isAllSelectedRowLatestApprovalOnHeadArea = useMemo(() => {
return selectedRowIds.every((rowId) => {
if (!isResponseSuccess(expenses)) return false;
@@ -202,11 +203,28 @@ const ExpensesTable = () => {
const isLatestApprovalRejected =
expenseItem?.latest_approval.action === 'REJECTED';
const isCurrentApprovalOnManager =
const isCurrentApprovalOnHeadArea =
!isLatestApprovalRejected &&
expenseItem?.latest_approval.step_number === 1;
return isCurrentApprovalOnManager;
return isCurrentApprovalOnHeadArea;
});
}, [expenses, selectedRowIds]);
const isAllSelectedRowLatestApprovalOnUnitVicePresident = useMemo(() => {
return selectedRowIds.every((rowId) => {
if (!isResponseSuccess(expenses)) return false;
const expenseItem = expenses.data.find((item) => item.id === rowId);
const isLatestApprovalRejected =
expenseItem?.latest_approval.action === 'REJECTED';
const isCurrentApprovalOnUnitVicePresident =
!isLatestApprovalRejected &&
expenseItem?.latest_approval.step_number === 2;
return isCurrentApprovalOnUnitVicePresident;
});
}, [expenses, selectedRowIds]);
@@ -221,7 +239,7 @@ const ExpensesTable = () => {
const isCurrentApprovalOnFinance =
!isLatestApprovalRejected &&
expenseItem?.latest_approval.step_number === 2;
expenseItem?.latest_approval.step_number === 3;
return isCurrentApprovalOnFinance;
});
@@ -238,7 +256,7 @@ const ExpensesTable = () => {
const isCurrentApprovalOnRealization =
!isLatestApprovalRejected &&
expenseItem?.latest_approval.step_number === 4;
expenseItem?.latest_approval.step_number === 5;
return isCurrentApprovalOnRealization;
});
@@ -397,7 +415,7 @@ const ExpensesTable = () => {
) => {
return (
row.original.latest_approval.action !== 'REJECTED' &&
row.original.latest_approval.step_number !== 5
row.original.latest_approval.step_number !== 6
);
};
@@ -441,8 +459,13 @@ const ExpensesTable = () => {
let bulkApproveResponse: BaseApiResponse<Expense> | undefined = undefined;
if (isAllSelectedRowLatestApprovalOnManager) {
bulkApproveResponse = await ExpenseApi.bulkApproveManager(
if (isAllSelectedRowLatestApprovalOnHeadArea) {
bulkApproveResponse = await ExpenseApi.bulkApproveHeadArea(
selectedRowIds,
notes
);
} else if (isAllSelectedRowLatestApprovalOnUnitVicePresident) {
bulkApproveResponse = await ExpenseApi.bulkApproveUnitVicePresident(
selectedRowIds,
notes
);
@@ -478,8 +501,13 @@ const ExpensesTable = () => {
let bulkRejectResponse: BaseApiResponse<Expense> | undefined = undefined;
if (isAllSelectedRowLatestApprovalOnManager) {
bulkRejectResponse = await ExpenseApi.bulkRejectManager(
if (isAllSelectedRowLatestApprovalOnHeadArea) {
bulkRejectResponse = await ExpenseApi.bulkRejectHeadArea(
selectedRowIds,
notes
);
} else if (isAllSelectedRowLatestApprovalOnUnitVicePresident) {
bulkRejectResponse = await ExpenseApi.bulkRejectUnitVicePresident(
selectedRowIds,
notes
);
@@ -594,16 +622,31 @@ const ExpensesTable = () => {
{selectedRowIds.length > 0 && (
<>
<RequirePermission permissions='lti.expense.approve.manager'>
<RequirePermission permissions='lti.expense.approve.head_area'>
<Button
variant='outline'
color='info'
onClick={bulkApproveClickHandler}
disabled={!isAllSelectedRowLatestApprovalOnManager}
disabled={!isAllSelectedRowLatestApprovalOnHeadArea}
className='w-full sm:w-fit'
>
<Icon icon='lucide-lab:farm' width={24} height={24} />
Approve Manager
Approve Head Area
</Button>
</RequirePermission>
<RequirePermission permissions='lti.expense.approve.unit_vice_president'>
<Button
variant='outline'
color='success'
onClick={bulkApproveClickHandler}
disabled={
!isAllSelectedRowLatestApprovalOnUnitVicePresident
}
className='w-full sm:w-fit'
>
<Icon icon='tdesign:money' width={24} height={24} />
Approve Unit Vice President
</Button>
</RequirePermission>
@@ -622,7 +665,8 @@ const ExpensesTable = () => {
<RequirePermission
permissions={[
'lti.expense.approve.manager',
'lti.expense.approve.head_area',
'lti.expense.approve.unit_vice_president',
'lti.expense.approve.finance',
]}
>
@@ -631,7 +675,8 @@ const ExpensesTable = () => {
color='error'
onClick={bulkRejectClickHandler}
disabled={
!isAllSelectedRowLatestApprovalOnManager &&
!isAllSelectedRowLatestApprovalOnHeadArea &&
!isAllSelectedRowLatestApprovalOnUnitVicePresident &&
!isAllSelectedRowLatestApprovalOnFinance
}
className='w-full sm:w-fit'