mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
feat(FE-170,175): enhance GradingForm with total egg consumption display and validation for grading limits
This commit is contained in:
@@ -15,6 +15,7 @@ import {
|
||||
UpdateGradingPayload,
|
||||
RecordingEgg,
|
||||
GradingEgg,
|
||||
Recording,
|
||||
} from '@/types/api/production/recording';
|
||||
import {
|
||||
type FormStepStatus,
|
||||
@@ -31,6 +32,7 @@ import toast from 'react-hot-toast';
|
||||
import { RecordingApi } from '@/services/api/production';
|
||||
import { isResponseError } from '@/lib/api-helper';
|
||||
import { useModal } from '@/components/Modal';
|
||||
import useSWR from 'swr';
|
||||
|
||||
import Card from '@/components/Card';
|
||||
import StepItem from '@/components/steps/StepItem';
|
||||
@@ -54,18 +56,36 @@ const GradingForm = ({ type = 'add', initialValues }: GradingFormProps) => {
|
||||
const deleteModal = useModal();
|
||||
|
||||
// ===== API DATA FETCHING =====
|
||||
// const existingGradingsUrl = useMemo(() => {
|
||||
// const recordingEggIdToUse = recordingId || initialValues?.id?.toString();
|
||||
// if (!recordingEggIdToUse) return null;
|
||||
// return `${RecordingApi.basePath}/gradings?recording_egg_id=${recordingEggIdToUse}`;
|
||||
// }, [recordingId, initialValues]);
|
||||
const recordingUrl = useMemo(() => {
|
||||
const recordingIdToUse = recordingId;
|
||||
if (!recordingIdToUse) return null;
|
||||
return `${RecordingApi.basePath}/${recordingIdToUse}`;
|
||||
}, [recordingId]);
|
||||
|
||||
// const { data: existingGradings } = useSWR(
|
||||
// existingGradingsUrl,
|
||||
// existingGradingsUrl ? RecordingApi.getAllFetcher : null
|
||||
// );
|
||||
const { data: recordingData } = useSWR(
|
||||
recordingUrl,
|
||||
recordingUrl ? RecordingApi.getAllFetcher : null
|
||||
);
|
||||
|
||||
// ===== DATA PROCESSING =====
|
||||
const recording =
|
||||
recordingData?.status === 'success'
|
||||
? (recordingData.data as unknown as Recording)
|
||||
: undefined;
|
||||
|
||||
const konsumsiBaikEggData = useMemo(() => {
|
||||
if (!recording?.eggs) return null;
|
||||
|
||||
const konsumsiBaikEgg = recording.eggs.find((egg: RecordingEgg) =>
|
||||
egg.product_warehouse?.product?.name
|
||||
?.toLowerCase()
|
||||
.includes('konsumsi baik')
|
||||
);
|
||||
|
||||
return konsumsiBaikEgg || null;
|
||||
}, [recording]);
|
||||
|
||||
const totalKonsumsiBaikEggs = konsumsiBaikEggData?.qty || 0;
|
||||
|
||||
// ===== FORM HANDLERS =====
|
||||
const createGradingHandler = useCallback(
|
||||
@@ -180,7 +200,14 @@ const GradingForm = ({ type = 'add', initialValues }: GradingFormProps) => {
|
||||
},
|
||||
});
|
||||
|
||||
// Grading Handlers
|
||||
const currentGradingTotal = useMemo(() => {
|
||||
return (formik.values.eggs_grading || []).reduce((total, grading) => {
|
||||
return total + (Number(grading.qty) || 0);
|
||||
}, 0);
|
||||
}, [formik.values.eggs_grading]);
|
||||
|
||||
const isGradingExceedsAvailable = currentGradingTotal > totalKonsumsiBaikEggs;
|
||||
|
||||
const addGrading = () => {
|
||||
let recordingEggId: number | undefined = initialValues?.id;
|
||||
|
||||
@@ -385,7 +412,7 @@ const GradingForm = ({ type = 'add', initialValues }: GradingFormProps) => {
|
||||
className={
|
||||
type === 'detail'
|
||||
? 'flex flex-col gap-6'
|
||||
: 'grid grid-cols-3 gap-4'
|
||||
: 'grid grid-cols-2 gap-4'
|
||||
}
|
||||
>
|
||||
{type === 'detail' && initialValues ? (
|
||||
@@ -398,6 +425,32 @@ const GradingForm = ({ type = 'add', initialValues }: GradingFormProps) => {
|
||||
{formik.values.eggs_grading?.[0]?.recording_egg_id || '-'}
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Total Telur Konsumsi Baik Info */}
|
||||
<div>
|
||||
<span className='text-sm text-gray-600'>
|
||||
Total Telur Konsumsi Baik
|
||||
</span>
|
||||
<div className='flex items-center gap-2'>
|
||||
<p className='font-semibold text-lg'>
|
||||
{totalKonsumsiBaikEggs}
|
||||
</p>
|
||||
<span className='text-sm text-gray-500'>telur</span>
|
||||
</div>
|
||||
<div className='flex items-center gap-2 mt-1'>
|
||||
<span className='text-sm'>Total yang digrading:</span>
|
||||
<span
|
||||
className={`font-semibold ${isGradingExceedsAvailable ? 'text-error' : 'text-success'}`}
|
||||
>
|
||||
{currentGradingTotal} / {totalKonsumsiBaikEggs}
|
||||
</span>
|
||||
</div>
|
||||
{isGradingExceedsAvailable && (
|
||||
<div className='text-error text-sm mt-1'>
|
||||
⚠️ Total grading melebihi available telur!
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
@@ -506,7 +559,6 @@ const GradingForm = ({ type = 'add', initialValues }: GradingFormProps) => {
|
||||
{ value: 'Grade B', label: 'Grade B' },
|
||||
{ value: 'Grade C', label: 'Grade C' },
|
||||
{ value: 'Grade D', label: 'Grade D' },
|
||||
{ value: 'Extra', label: 'Extra' },
|
||||
]}
|
||||
placeholder='Pilih Grade'
|
||||
isError={
|
||||
@@ -538,11 +590,14 @@ const GradingForm = ({ type = 'add', initialValues }: GradingFormProps) => {
|
||||
decimalSeparator='.'
|
||||
isError={
|
||||
isRepeaterInputError('eggs_grading', 'qty', idx)
|
||||
.isError
|
||||
.isError || isGradingExceedsAvailable
|
||||
}
|
||||
errorMessage={
|
||||
isRepeaterInputError('eggs_grading', 'qty', idx)
|
||||
.errorMessage
|
||||
.errorMessage ||
|
||||
(isGradingExceedsAvailable
|
||||
? `Total grading melebihi available telur (${totalKonsumsiBaikEggs})`
|
||||
: undefined)
|
||||
}
|
||||
readOnly={type === 'detail'}
|
||||
className={{
|
||||
@@ -660,10 +715,20 @@ const GradingForm = ({ type = 'add', initialValues }: GradingFormProps) => {
|
||||
color='primary'
|
||||
className='px-4'
|
||||
isLoading={formik.isSubmitting}
|
||||
disabled={!formik.isValid || formik.isSubmitting}
|
||||
disabled={
|
||||
!formik.isValid ||
|
||||
formik.isSubmitting ||
|
||||
isGradingExceedsAvailable
|
||||
}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
{isGradingExceedsAvailable && (
|
||||
<div className='text-error text-sm mt-2 text-right'>
|
||||
Total grading ({currentGradingTotal}) melebihi available
|
||||
telur ({totalKonsumsiBaikEggs})
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user