mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
feat(FE-170,175): enhance RecordingTable with grading completion checks and approval logic
This commit is contained in:
@@ -41,12 +41,14 @@ const RowOptionsMenu = ({
|
||||
deleteClickHandler,
|
||||
approveClickHandler,
|
||||
rejectClickHandler,
|
||||
isGradingCompleted,
|
||||
}: {
|
||||
type: 'dropdown' | 'collapse';
|
||||
props: CellContext<Recording, unknown>;
|
||||
deleteClickHandler: () => void;
|
||||
approveClickHandler: () => void;
|
||||
rejectClickHandler: () => void;
|
||||
isGradingCompleted: (recording: Recording) => boolean;
|
||||
}) => {
|
||||
const isLayingCategory =
|
||||
props.row.original.project_flock_category === 'LAYING';
|
||||
@@ -60,6 +62,7 @@ const RowOptionsMenu = ({
|
||||
};
|
||||
|
||||
const isApproved = isRecordingApproved(props.row.original);
|
||||
const isGradingDone = isGradingCompleted(props.row.original);
|
||||
|
||||
return (
|
||||
<RowOptionsMenuWrapper type={type}>
|
||||
@@ -81,7 +84,7 @@ const RowOptionsMenu = ({
|
||||
<Icon icon='mdi:pencil-outline' width={16} height={16} />
|
||||
Edit
|
||||
</Button>
|
||||
{isLayingCategory && (
|
||||
{isLayingCategory && !isGradingDone && (
|
||||
<Button
|
||||
href={`recording/grading/add?recording_id=${props.row.original.id}`}
|
||||
variant='ghost'
|
||||
@@ -98,6 +101,11 @@ const RowOptionsMenu = ({
|
||||
variant='ghost'
|
||||
color='success'
|
||||
className='justify-start text-sm'
|
||||
title={
|
||||
isGradingDone
|
||||
? 'Recording bisa disetujui karena sudah grading'
|
||||
: 'Recording bisa disetujui'
|
||||
}
|
||||
>
|
||||
<Icon icon='material-symbols:check' width={16} height={16} />
|
||||
Approve
|
||||
@@ -109,6 +117,11 @@ const RowOptionsMenu = ({
|
||||
variant='ghost'
|
||||
color='error'
|
||||
className='justify-start text-sm'
|
||||
title={
|
||||
isGradingDone
|
||||
? 'Recording bisa ditolak karena sudah grading'
|
||||
: 'Recording bisa ditolak'
|
||||
}
|
||||
>
|
||||
<Icon icon='material-symbols:close' width={16} height={16} />
|
||||
Reject
|
||||
@@ -431,11 +444,28 @@ const RecordingTable = () => {
|
||||
isLoadingOptions: isLoadingKandang,
|
||||
} = useSelect<Kandang>(KandangApi.basePath, 'id', 'name');
|
||||
|
||||
const isRecordingApproved = useCallback((recording: Recording) => {
|
||||
return (
|
||||
recording.approval?.action === 'APPROVED' &&
|
||||
recording.approval?.step_name === 'Disetujui' &&
|
||||
recording.approval?.step_number === 3
|
||||
const isRecordingFullyApproved = useCallback(
|
||||
(recording: Recording): boolean => {
|
||||
return (
|
||||
recording.approval?.action === 'APPROVED' &&
|
||||
recording.approval?.step_name === 'Disetujui' &&
|
||||
recording.approval?.step_number === 3
|
||||
);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const isRecordingApproved = useCallback(
|
||||
(recording: Recording) => {
|
||||
return isRecordingFullyApproved(recording);
|
||||
},
|
||||
[isRecordingFullyApproved]
|
||||
);
|
||||
|
||||
const isGradingCompleted = useCallback((recording: Recording): boolean => {
|
||||
return !!(
|
||||
recording.egg_grading_status === 'COMPLETED' ||
|
||||
(recording.approval?.step_number && recording.approval.step_number >= 1)
|
||||
);
|
||||
}, []);
|
||||
|
||||
@@ -472,7 +502,7 @@ const RecordingTable = () => {
|
||||
|
||||
if (eligibleRowIds.length === 0) {
|
||||
toast.error(
|
||||
'Tidak ada recording yang bisa disetujui (sudah disetujui sebelumnya)'
|
||||
'Tidak ada recording yang bisa disetujui (sudah disetujui final)'
|
||||
);
|
||||
setIsApproveLoading(false);
|
||||
return;
|
||||
@@ -505,7 +535,7 @@ const RecordingTable = () => {
|
||||
|
||||
if (eligibleRowIds.length === 0) {
|
||||
toast.error(
|
||||
'Tidak ada recording yang bisa ditolak (sudah disetujui sebelumnya)'
|
||||
'Tidak ada recording yang bisa ditolak (sudah disetujui final)'
|
||||
);
|
||||
setIsRejectLoading(false);
|
||||
return;
|
||||
@@ -531,7 +561,6 @@ const RecordingTable = () => {
|
||||
setIsRejectLoading(false);
|
||||
};
|
||||
|
||||
// Filter out already approved recordings for bulk actions
|
||||
const eligibleRowIds = useMemo(() => {
|
||||
if (!isResponseSuccess(recordings) || !recordings.data) return [];
|
||||
return selectedRowIds.filter((id) => {
|
||||
@@ -564,8 +593,15 @@ const RecordingTable = () => {
|
||||
setApprovalNotes('');
|
||||
approveModal.openModal();
|
||||
}}
|
||||
disabled={selectedRowIds.length === 0}
|
||||
disabled={
|
||||
selectedRowIds.length === 0 || eligibleRowIds.length === 0
|
||||
}
|
||||
className='w-full sm:w-fit'
|
||||
title={
|
||||
eligibleRowIds.length === 0
|
||||
? 'Tidak ada Recording yang bisa disetujui (sudah disetujui final)'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
<Icon icon='material-symbols:check' width={24} height={24} />
|
||||
Approve
|
||||
@@ -578,8 +614,15 @@ const RecordingTable = () => {
|
||||
setApprovalNotes('');
|
||||
rejectModal.openModal();
|
||||
}}
|
||||
disabled={selectedRowIds.length === 0}
|
||||
disabled={
|
||||
selectedRowIds.length === 0 || eligibleRowIds.length === 0
|
||||
}
|
||||
className='w-full sm:w-fit'
|
||||
title={
|
||||
eligibleRowIds.length === 0
|
||||
? 'Tidak ada Recording yang bisa ditolak (sudah disetujui final)'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
<Icon icon='material-symbols:close' width={24} height={24} />
|
||||
Reject
|
||||
@@ -692,27 +735,46 @@ const RecordingTable = () => {
|
||||
columns={[
|
||||
{
|
||||
id: 'select',
|
||||
header: ({ table }) => (
|
||||
<div className='w-full flex flex-row justify-center'>
|
||||
<CheckboxInput
|
||||
name='allRow'
|
||||
checked={table.getIsAllRowsSelected()}
|
||||
indeterminate={table.getIsSomeRowsSelected()}
|
||||
onChange={table.getToggleAllRowsSelectedHandler()}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
header: ({ table }) => {
|
||||
const allRows = table.getRowModel().rows;
|
||||
const selectableRows = allRows.filter((row) => {
|
||||
const recording = row.original;
|
||||
return !isRecordingApproved(recording);
|
||||
});
|
||||
const hasOnlyUnselectableRows = selectableRows.length === 0;
|
||||
|
||||
return (
|
||||
<div className='w-full flex flex-row justify-center'>
|
||||
<CheckboxInput
|
||||
name='allRow'
|
||||
checked={table.getIsAllRowsSelected()}
|
||||
indeterminate={table.getIsSomeRowsSelected()}
|
||||
onChange={table.getToggleAllRowsSelectedHandler()}
|
||||
disabled={hasOnlyUnselectableRows}
|
||||
title={
|
||||
hasOnlyUnselectableRows
|
||||
? 'Tidak ada Recording yang bisa dipilih (sudah disetujui final)'
|
||||
: ''
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
cell: ({ row }) => {
|
||||
const isApproved = isRecordingApproved(row.original);
|
||||
const isDisabled = !row.getCanSelect() || isApproved;
|
||||
let tooltip = '';
|
||||
if (isApproved) tooltip = 'Recording sudah disetujui final';
|
||||
|
||||
return (
|
||||
<div>
|
||||
<CheckboxInput
|
||||
name='row'
|
||||
checked={row.getIsSelected()}
|
||||
disabled={!row.getCanSelect() || isApproved}
|
||||
disabled={isDisabled}
|
||||
indeterminate={row.getIsSomeSelected()}
|
||||
onChange={row.getToggleSelectedHandler()}
|
||||
title={isApproved ? 'Recording sudah disetujui' : ''}
|
||||
title={tooltip}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@@ -887,6 +949,7 @@ const RecordingTable = () => {
|
||||
deleteClickHandler={deleteClickHandler}
|
||||
approveClickHandler={approveClickHandler}
|
||||
rejectClickHandler={rejectClickHandler}
|
||||
isGradingCompleted={isGradingCompleted}
|
||||
/>
|
||||
</RowDropdownOptions>
|
||||
)}
|
||||
@@ -899,6 +962,7 @@ const RecordingTable = () => {
|
||||
deleteClickHandler={deleteClickHandler}
|
||||
approveClickHandler={approveClickHandler}
|
||||
rejectClickHandler={rejectClickHandler}
|
||||
isGradingCompleted={isGradingCompleted}
|
||||
/>
|
||||
</RowCollapseOptions>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user