feat(FE-170,174,175): add validation for incomplete grading in GradingForm

This commit is contained in:
rstubryan
2025-11-19 19:05:45 +07:00
parent 9c69369a51
commit c876824c8f
@@ -256,6 +256,8 @@ const GradingForm = ({ type = 'add', initialValues }: GradingFormProps) => {
}, [formik.values.eggs_grading]); }, [formik.values.eggs_grading]);
const isGradingExceedsAvailable = currentGradingTotal > totalKonsumsiBaikEggs; const isGradingExceedsAvailable = currentGradingTotal > totalKonsumsiBaikEggs;
const isGradingIncomplete = currentGradingTotal < totalKonsumsiBaikEggs && totalKonsumsiBaikEggs > 0;
const hasUserStartedGrading = currentGradingTotal > 0;
// GRADING HANDLERS // GRADING HANDLERS
const addGrading = () => { const addGrading = () => {
@@ -355,10 +357,21 @@ const GradingForm = ({ type = 'add', initialValues }: GradingFormProps) => {
duration: 3000, duration: 3000,
} }
); );
toast.dismiss('grading-incomplete');
} else if (isGradingIncomplete && hasUserStartedGrading) {
toast.error(
`Total grading (${currentGradingTotal}) tidak sama dengan total telur konsumsi baik yang tersedia (${totalKonsumsiBaikEggs})! Semua telur harus digrading.`,
{
id: 'grading-incomplete',
duration: 3000,
}
);
toast.dismiss('grading-exceeds');
} else { } else {
toast.dismiss('grading-exceeds'); toast.dismiss('grading-exceeds');
toast.dismiss('grading-incomplete');
} }
}, [isGradingExceedsAvailable, currentGradingTotal, totalKonsumsiBaikEggs]); }, [isGradingExceedsAvailable, isGradingIncomplete, hasUserStartedGrading, currentGradingTotal, totalKonsumsiBaikEggs]);
useEffect(() => { useEffect(() => {
if ( if (
@@ -559,7 +572,9 @@ const GradingForm = ({ type = 'add', initialValues }: GradingFormProps) => {
className={`rounded-lg p-4 border-2 ${ className={`rounded-lg p-4 border-2 ${
isGradingExceedsAvailable isGradingExceedsAvailable
? 'bg-red-50 border-red-200' ? 'bg-red-50 border-red-200'
: 'bg-green-50 border-green-200' : isGradingIncomplete && hasUserStartedGrading
? 'bg-yellow-50 border-yellow-200'
: 'bg-green-50 border-green-200'
}`} }`}
> >
<div className='flex items-center justify-between mb-3'> <div className='flex items-center justify-between mb-3'>
@@ -578,21 +593,29 @@ const GradingForm = ({ type = 'add', initialValues }: GradingFormProps) => {
</div> </div>
<div <div
className={`rounded-full p-2 ${ className={`rounded-full p-2 ${
isGradingExceedsAvailable ? 'bg-red-100' : 'bg-green-100' isGradingExceedsAvailable
? 'bg-red-100'
: isGradingIncomplete && hasUserStartedGrading
? 'bg-yellow-100'
: 'bg-green-100'
}`} }`}
> >
<Icon <Icon
icon={ icon={
isGradingExceedsAvailable isGradingExceedsAvailable
? 'material-symbols:error' ? 'material-symbols:error'
: 'material-symbols:check-circle' : isGradingIncomplete && hasUserStartedGrading
? 'material-symbols:warning'
: 'material-symbols:check-circle'
} }
width={20} width={20}
height={20} height={20}
className={ className={
isGradingExceedsAvailable isGradingExceedsAvailable
? 'text-red-600' ? 'text-red-600'
: 'text-green-600' : isGradingIncomplete && hasUserStartedGrading
? 'text-yellow-600'
: 'text-green-600'
} }
/> />
</div> </div>
@@ -606,7 +629,9 @@ const GradingForm = ({ type = 'add', initialValues }: GradingFormProps) => {
className={`font-semibold ${ className={`font-semibold ${
isGradingExceedsAvailable isGradingExceedsAvailable
? 'text-red-600' ? 'text-red-600'
: 'text-green-600' : isGradingIncomplete && hasUserStartedGrading
? 'text-yellow-600'
: 'text-green-600'
}`} }`}
> >
{currentGradingTotal} / {totalKonsumsiBaikEggs} {currentGradingTotal} / {totalKonsumsiBaikEggs}
@@ -617,7 +642,9 @@ const GradingForm = ({ type = 'add', initialValues }: GradingFormProps) => {
className={`h-full transition-all duration-300 ${ className={`h-full transition-all duration-300 ${
isGradingExceedsAvailable isGradingExceedsAvailable
? 'bg-red-500' ? 'bg-red-500'
: 'bg-green-500' : isGradingIncomplete && hasUserStartedGrading
? 'bg-yellow-500'
: 'bg-green-500'
}`} }`}
style={{ style={{
width: `${Math.min((currentGradingTotal / totalKonsumsiBaikEggs) * 100, 100)}%`, width: `${Math.min((currentGradingTotal / totalKonsumsiBaikEggs) * 100, 100)}%`,
@@ -634,6 +661,16 @@ const GradingForm = ({ type = 'add', initialValues }: GradingFormProps) => {
<span>Melebihi batas tersedia</span> <span>Melebihi batas tersedia</span>
</div> </div>
)} )}
{isGradingIncomplete && hasUserStartedGrading && (
<div className='flex items-center gap-1 text-xs text-yellow-600 mt-1'>
<Icon
icon='material-symbols:info'
width={12}
height={12}
/>
<span>Grading belum lengkap, semua telur harus digrading</span>
</div>
)}
</div> </div>
</div> </div>
</div> </div>
@@ -775,14 +812,17 @@ const GradingForm = ({ type = 'add', initialValues }: GradingFormProps) => {
decimalSeparator='.' decimalSeparator='.'
isError={ isError={
isRepeaterInputError('eggs_grading', 'qty', idx) isRepeaterInputError('eggs_grading', 'qty', idx)
.isError || isGradingExceedsAvailable .isError ||
(isGradingExceedsAvailable || (isGradingIncomplete && hasUserStartedGrading))
} }
errorMessage={ errorMessage={
isRepeaterInputError('eggs_grading', 'qty', idx) isRepeaterInputError('eggs_grading', 'qty', idx)
.errorMessage || .errorMessage ||
(isGradingExceedsAvailable (isGradingExceedsAvailable
? `Total grading melebihi telur yang tersedia (${totalKonsumsiBaikEggs})` ? `Total grading melebihi telur yang tersedia (${totalKonsumsiBaikEggs})`
: undefined) : isGradingIncomplete && hasUserStartedGrading
? `Total grading (${currentGradingTotal}) harus sama dengan total telur konsumsi baik (${totalKonsumsiBaikEggs})`
: undefined)
} }
readOnly={type === 'detail'} readOnly={type === 'detail'}
className={{ className={{
@@ -903,7 +943,8 @@ const GradingForm = ({ type = 'add', initialValues }: GradingFormProps) => {
disabled={ disabled={
!formik.isValid || !formik.isValid ||
formik.isSubmitting || formik.isSubmitting ||
isGradingExceedsAvailable isGradingExceedsAvailable ||
(isGradingIncomplete && hasUserStartedGrading)
} }
> >
Submit Submit