feat(FE-170,174,175): enhance grading button with consumable eggs validation and update rejection notes

This commit is contained in:
rstubryan
2025-11-18 11:11:32 +07:00
parent 6022ff2dae
commit 4dd50622a9
3 changed files with 46 additions and 4 deletions
@@ -2,6 +2,7 @@
import { useCallback, useState, useMemo, useEffect } from 'react';
import { RefObject } from 'react';
import { useRouter } from 'next/navigation';
import useSWR from 'swr';
import { Icon } from '@iconify/react';
import { SortingState, CellContext } from '@tanstack/react-table';
@@ -34,6 +35,7 @@ import { Area } from '@/types/api/master-data/area';
import { Location } from '@/types/api/master-data/location';
import { Kandang } from '@/types/api/master-data/kandang';
import { BaseApproval, BaseApiResponse } from '@/types/api/api-general';
import { router } from 'next/client';
const RowOptionsMenu = ({
type = 'dropdown',
@@ -42,6 +44,7 @@ const RowOptionsMenu = ({
approveClickHandler,
rejectClickHandler,
isGradingCompleted,
hasConsumableEggs,
}: {
type: 'dropdown' | 'collapse';
props: CellContext<Recording, unknown>;
@@ -49,6 +52,7 @@ const RowOptionsMenu = ({
approveClickHandler: () => void;
rejectClickHandler: () => void;
isGradingCompleted: (recording: Recording) => boolean;
hasConsumableEggs: (recording: Recording) => boolean;
}) => {
const isLayingCategory =
props.row.original.project_flock_category === 'LAYING';
@@ -63,6 +67,7 @@ const RowOptionsMenu = ({
const isApproved = isRecordingApproved(props.row.original);
const isGradingDone = isGradingCompleted(props.row.original);
const hasConsumable = hasConsumableEggs(props.row.original);
const getApprovalTooltip = () => {
if (isLayingCategory && !isGradingDone) {
@@ -95,10 +100,26 @@ const RowOptionsMenu = ({
</Button>
{isLayingCategory && !isGradingDone && (
<Button
href={`recording/grading/add?recording_id=${props.row.original.id}`}
variant='ghost'
color='info'
className='justify-start text-sm'
className={`justify-start text-sm ${!hasConsumable ? 'cursor-not-allowed opacity-50' : ''}`}
onClick={(e) => {
if (!hasConsumable) {
e.preventDefault();
toast.error(
'Tidak bisa melakukan grading karena tidak ada Telur Konsumsi Baik'
);
} else {
router.push(
`/production/recording/grading/add?recording_id=${props.row.original.id}`
);
}
}}
title={
hasConsumable
? 'Lanjut ke proses grading untuk telur konsumsi baik'
: 'Tidak bisa melakukan grading karena tidak ada Telur Konsumsi Baik'
}
>
<Icon icon='material-symbols:egg' width={16} height={16} />
Grading
@@ -365,6 +386,8 @@ const ApprovalHistoryModal = ({
};
const RecordingTable = () => {
const router = useRouter();
const {
state: tableFilterState,
updateFilter,
@@ -475,6 +498,23 @@ const RecordingTable = () => {
);
}, []);
const hasConsumableEggs = useCallback((recording: Recording): boolean => {
if (!recording.eggs || recording.eggs.length === 0) return false;
return recording.eggs.some((egg) => {
if (!egg.product_warehouse || !egg.product_warehouse.product)
return false;
if (Number(egg.qty) <= 0) return false;
const productName = egg.product_warehouse.product.name.toLowerCase();
return (
productName.includes('konsumsi') &&
productName.includes('baik') &&
Number(egg.qty) > 0
);
});
}, []);
const searchChangeHandler = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
updateFilter('search', e.target.value);
@@ -981,6 +1021,7 @@ const RecordingTable = () => {
approveClickHandler={approveClickHandler}
rejectClickHandler={rejectClickHandler}
isGradingCompleted={isGradingCompleted}
hasConsumableEggs={hasConsumableEggs}
/>
</RowDropdownOptions>
)}
@@ -994,6 +1035,7 @@ const RecordingTable = () => {
approveClickHandler={approveClickHandler}
rejectClickHandler={rejectClickHandler}
isGradingCompleted={isGradingCompleted}
hasConsumableEggs={hasConsumableEggs}
/>
</RowCollapseOptions>
)}
@@ -1165,7 +1165,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const rejectResponse = await RecordingApi.reject(
initialValues?.id as number,
'Rejected via Form'
''
);
if (isResponseSuccess(rejectResponse)) {
+1 -1
View File
@@ -50,7 +50,7 @@ export class RecordingService extends BaseApiService<
async reject(
idOrIds: number | number[],
notes: string = 'Rejected via Form'
notes: string = ''
): Promise<BaseApiResponse<Recording[]> | undefined> {
const approvable_ids = Array.isArray(idOrIds) ? idOrIds : [idOrIds];
return await this.customRequest<BaseApiResponse<Recording[]>>('approvals', {