diff --git a/src/app/production/recording/grading/add/page.tsx b/src/app/production/recording/grading/add/page.tsx
deleted file mode 100644
index 9b918d98..00000000
--- a/src/app/production/recording/grading/add/page.tsx
+++ /dev/null
@@ -1,49 +0,0 @@
-'use client';
-
-import { useRouter, useSearchParams } from 'next/navigation';
-import useSWR from 'swr';
-import GradingForm from '@/components/pages/production/recording/grading/form/GradingForm';
-import { RecordingApi } from '@/services/api/production';
-import { isResponseSuccess } from '@/lib/api-helper';
-
-const AddGrading = () => {
- const router = useRouter();
- const searchParams = useSearchParams();
-
- const recordingId = searchParams.get('recording_id');
-
- const { data: recording, isLoading: isLoadingRecording } = useSWR(
- recordingId && recordingId !== 'new' ? [recordingId] : null,
- ([id]) => RecordingApi.getSingle(parseInt(id))
- );
-
- if (
- recordingId &&
- recordingId !== 'new' &&
- !isLoadingRecording &&
- (!recording || !isResponseSuccess(recording))
- ) {
- router.replace('/404');
- return;
- }
-
- return (
-
- {recordingId && recordingId !== 'new' && isLoadingRecording && (
-
- )}
- {(!recordingId ||
- recordingId === 'new' ||
- (!isLoadingRecording && recording && isResponseSuccess(recording))) && (
-
- )}
-
- );
-};
-
-export default AddGrading;
diff --git a/src/app/production/recording/grading/detail/edit/page.tsx b/src/app/production/recording/grading/detail/edit/page.tsx
deleted file mode 100644
index 0a65f528..00000000
--- a/src/app/production/recording/grading/detail/edit/page.tsx
+++ /dev/null
@@ -1,53 +0,0 @@
-'use client';
-
-import { useRouter, useSearchParams } from 'next/navigation';
-import useSWR from 'swr';
-import GradingForm from '@/components/pages/production/recording/grading/form/GradingForm';
-import { RecordingApi } from '@/services/api/production';
-import { isResponseSuccess } from '@/lib/api-helper';
-
-const EditGrading = () => {
- const router = useRouter();
- const searchParams = useSearchParams();
-
- const recordingId = searchParams.get('recordingId');
- const gradingId = searchParams.get('gradingId');
-
- const { data: recording, isLoading: isLoadingRecording } = useSWR(
- recordingId ? [recordingId] : null,
- ([id]) => RecordingApi.getSingle(parseInt(id))
- );
-
- if (!recordingId) {
- router.back();
-
- return (
-
-
-
- );
- }
-
- if (!isLoadingRecording && (!recording || !isResponseSuccess(recording))) {
- router.replace('/404');
- return;
- }
-
- return (
-
- {isLoadingRecording && (
-
- )}
- {!isLoadingRecording && recording && isResponseSuccess(recording) && (
- egg.id === parseInt(gradingId || '0')
- )}
- />
- )}
-
- );
-};
-
-export default EditGrading;
diff --git a/src/app/production/recording/grading/detail/page.tsx b/src/app/production/recording/grading/detail/page.tsx
deleted file mode 100644
index 6a5fbcba..00000000
--- a/src/app/production/recording/grading/detail/page.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-'use client';
-
-import { useRouter, useSearchParams } from 'next/navigation';
-import useSWR from 'swr';
-import GradingForm from '@/components/pages/production/recording/grading/form/GradingForm';
-import { RecordingApi } from '@/services/api/production';
-import { isResponseSuccess } from '@/lib/api-helper';
-
-const DetailGrading = () => {
- const router = useRouter();
- const searchParams = useSearchParams();
-
- const gradingId = searchParams.get('gradingId');
-
- const { data: grading, isLoading: isLoadingGrading } = useSWR(
- gradingId ? [gradingId] : null,
- ([id]) => RecordingApi.getSingle(parseInt(id))
- );
-
- if (!gradingId) {
- router.back();
-
- return (
-
-
-
- );
- }
-
- if (!isLoadingGrading && (!grading || !isResponseSuccess(grading))) {
- router.replace('/404');
- return;
- }
-
- return (
-
- {isLoadingGrading && (
-
- )}
- {!isLoadingGrading && grading && isResponseSuccess(grading) && (
- egg.id === parseInt(gradingId)
- )}
- />
- )}
-
- );
-};
-
-export default DetailGrading;
diff --git a/src/app/production/recording/grading/layout.tsx b/src/app/production/recording/grading/layout.tsx
deleted file mode 100644
index 7220dfa1..00000000
--- a/src/app/production/recording/grading/layout.tsx
+++ /dev/null
@@ -1,11 +0,0 @@
-import SuspenseHelper from '@/components/helper/SuspenseHelper';
-
-const Layout = ({
- children,
-}: Readonly<{
- children: React.ReactNode;
-}>) => {
- return {children};
-};
-
-export default Layout;
diff --git a/src/components/pages/production/recording/grading/form/GradingForm.tsx b/src/components/pages/production/recording/grading/form/GradingForm.tsx
deleted file mode 100644
index 417c6356..00000000
--- a/src/components/pages/production/recording/grading/form/GradingForm.tsx
+++ /dev/null
@@ -1,1050 +0,0 @@
-'use client';
-
-import { useMemo, useState, useEffect, useCallback } from 'react';
-import { useRouter, useSearchParams } from 'next/navigation';
-import { useFormik } from 'formik';
-import { Icon } from '@iconify/react';
-
-import Button from '@/components/Button';
-import NumberInput from '@/components/input/NumberInput';
-import SelectInput, { OptionType } from '@/components/input/SelectInput';
-import CheckboxInput from '@/components/input/CheckboxInput';
-import ConfirmationModal from '@/components/modal/ConfirmationModal';
-import Card from '@/components/Card';
-import Badge from '@/components/Badge';
-
-import {
- CreateGradingPayload,
- UpdateGradingPayload,
- RecordingEgg,
- GradingEgg,
- Recording,
-} from '@/types/api/production/recording';
-import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
-import { type BaseApiResponse } from '@/types/api/api-general';
-
-import {
- RecordingGradingFormSchema,
- RecordingGradingFormValues,
- UpdateRecordingGradingFormSchema,
- getRecordingGradingFormInitialValues,
-} from '@/components/pages/production/recording/form/RecordingForm.schema';
-
-import { cn, formatDate } from '@/lib/helper';
-import toast from 'react-hot-toast';
-import { isResponseError } from '@/lib/api-helper';
-
-import {
- RecordingApi,
- ProjectFlockKandangApi,
-} from '@/services/api/production';
-
-import { useModal } from '@/components/Modal';
-import useSWR from 'swr';
-
-// INTERFACES & PROPS
-interface GradingFormProps {
- type?: 'add' | 'edit' | 'detail';
- initialValues?: RecordingEgg & {
- grading_eggs?: GradingEgg[];
- gradings?: { grade: string; qty: number }[];
- };
-}
-
-const GradingForm = ({ type = 'add', initialValues }: GradingFormProps) => {
- // HOOKS & ROUTER
- const router = useRouter();
- const searchParams = useSearchParams();
- const recordingId = searchParams.get('recording_id');
-
- // STATE MANAGEMENT
- const [selectedGradingItems, setSelectedGradingItems] = useState(
- []
- );
- const [gradingFormErrorMessage, setGradingFormErrorMessage] = useState('');
- const [isDeleteLoading, setIsDeleteLoading] = useState(false);
- const deleteModal = useModal();
-
- // API DATA FETCHING
- const recordingUrl = useMemo(() => {
- const recordingIdToUse = recordingId;
- if (!recordingIdToUse) return null;
- return `${RecordingApi.basePath}/${recordingIdToUse}`;
- }, [recordingId]);
-
- const { data: recordingData } = useSWR(
- recordingUrl,
- recordingUrl ? RecordingApi.getAllFetcher : null
- );
-
- // DATA PROCESSING
- const recording =
- recordingData?.status === 'success'
- ? (recordingData.data as unknown as Recording)
- : undefined;
-
- const projectFlockKandangUrl = useMemo(() => {
- if (!recording?.project_flock_kandang_id) return null;
- return `${ProjectFlockKandangApi.basePath}/${recording.project_flock_kandang_id}`;
- }, [recording?.project_flock_kandang_id]);
-
- const { data: projectFlockKandangData } = useSWR(
- projectFlockKandangUrl,
- projectFlockKandangUrl ? ProjectFlockKandangApi.getAllFetcher : null
- );
-
- const projectFlockKandang =
- projectFlockKandangData?.status === 'success'
- ? (projectFlockKandangData.data as unknown as ProjectFlockKandang)
- : 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;
- const konsumsiBaikEggId = konsumsiBaikEggData?.id;
-
- const isDataLoading =
- !recording ||
- (totalKonsumsiBaikEggs === 0 &&
- recording?.project_flock_category === 'LAYING');
-
- // FORM HANDLERS
- const createGradingHandler = useCallback(
- async (payload: CreateGradingPayload) => {
- const res = (await RecordingApi.createGrading(payload)) as
- | BaseApiResponse
- | undefined;
-
- if (!res || isResponseError(res)) {
- setGradingFormErrorMessage(res?.message || 'Failed to add Grading');
- return;
- }
-
- toast.success(res?.message || 'Successfully added Grading!');
- router.push('/production/recording');
- },
- [router]
- );
-
- const updateGradingHandler = useCallback(
- async (gradingId: number, payload: UpdateGradingPayload) => {
- const res = (await RecordingApi.updateGrading(gradingId, payload)) as
- | BaseApiResponse
- | undefined;
-
- if (!res || isResponseError(res)) {
- setGradingFormErrorMessage(res?.message || 'Failed to update Grading');
- return;
- }
- toast.success(res?.message || 'Successfully updated Grading!');
- router.refresh();
- router.push('/production/recording');
- },
- [router]
- );
-
- const deleteRecordingClickHandler = useCallback(() => {
- deleteModal.openModal();
- }, [deleteModal]);
-
- const confirmationModalDeleteClickHandler = useCallback(async () => {
- if (!initialValues?.id) return;
-
- setIsDeleteLoading(true);
- try {
- const res = (await RecordingApi.deleteGrading(initialValues.id)) as
- | BaseApiResponse
- | undefined;
-
- if (!res || isResponseError(res)) {
- setGradingFormErrorMessage(res?.message || 'Failed to delete Grading');
- return;
- }
- deleteModal.closeModal();
- toast.success(res?.message || 'Successfully delete Grading!');
- router.push('/production/recording');
- } catch {
- setGradingFormErrorMessage('Failed to delete Grading');
- } finally {
- setIsDeleteLoading(false);
- }
- }, [deleteModal, initialValues?.id, router]);
-
- // FORMIK SETUP
- const formikInitialValues = useMemo(() => {
- let recordingEggId: number | undefined = konsumsiBaikEggId;
-
- if (!recordingEggId && initialValues?.id) {
- recordingEggId = initialValues.id;
- }
-
- if (!recordingEggId) {
- recordingEggId = parseInt(recordingId || '0') || 0;
- }
-
- let gradingData: {
- recording_egg_id: number;
- grade: string;
- qty: number;
- }[] = [];
-
- if (initialValues?.grading_eggs && initialValues.grading_eggs.length > 0) {
- gradingData = initialValues.grading_eggs.map((grading: GradingEgg) => ({
- recording_egg_id: recordingEggId,
- grade: grading.grade,
- qty: grading.qty,
- }));
- } else if (initialValues?.gradings && initialValues.gradings.length > 0) {
- gradingData = initialValues.gradings.map(
- (grading: { grade: string; qty: number }) => ({
- recording_egg_id: recordingEggId,
- grade: grading.grade,
- qty: grading.qty,
- })
- );
- }
-
- return getRecordingGradingFormInitialValues({
- recording_egg_id: recordingEggId,
- eggs_grading: gradingData,
- });
- }, [initialValues, recordingId, konsumsiBaikEggId]);
-
- const formik = useFormik({
- initialValues: formikInitialValues,
- enableReinitialize: true,
- validationSchema: (() => {
- return type === 'edit'
- ? UpdateRecordingGradingFormSchema
- : RecordingGradingFormSchema;
- })(),
- validateOnChange: true,
- validateOnBlur: true,
- onSubmit: async (values) => {
- const gradingPayload = {
- eggs_grading: (values.eggs_grading ?? []).map((grading) => ({
- recording_egg_id: grading.recording_egg_id,
- grade: grading.grade,
- qty: grading.qty || 0,
- })),
- };
-
- switch (type) {
- case 'add':
- await createGradingHandler(gradingPayload as CreateGradingPayload);
- break;
- case 'edit':
- await updateGradingHandler(
- initialValues?.id as number,
- gradingPayload as UpdateGradingPayload
- );
- break;
- }
- },
- });
-
- 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 isGradingIncomplete =
- currentGradingTotal < totalKonsumsiBaikEggs && totalKonsumsiBaikEggs > 0;
- const hasUserStartedGrading = currentGradingTotal > 0;
-
- // GRADING HANDLERS
- const addGrading = () => {
- let recordingEggId: number | undefined = konsumsiBaikEggId;
-
- if (!recordingEggId && initialValues?.id) {
- recordingEggId = initialValues.id;
- }
-
- if (!recordingEggId) {
- recordingEggId = parseInt(recordingId || '0') || 0;
- }
-
- const newGrading = [
- ...(formik.values.eggs_grading || []),
- {
- recording_egg_id: recordingEggId,
- grade: '',
- qty: '',
- },
- ];
- formik.setFieldValue('eggs_grading', newGrading);
- };
-
- const handleGradingGradeChangeWrapper = useCallback(
- (idx: number) => (selectedOption: OptionType | OptionType[] | null) => {
- const option = selectedOption as OptionType | null;
- formik.setFieldValue(`eggs_grading.${idx}.grade`, option?.label || '');
- },
- [formik]
- );
-
- const handleGradingQtyChangeWrapper = useCallback(
- (idx: number) => (e: React.ChangeEvent) => {
- const value = parseFloat(e.target.value) || 0;
- formik.setFieldValue(`eggs_grading.${idx}.qty`, value);
- },
- [formik]
- );
-
- const removeGrading = (idx: number) => {
- const updatedGrading = formik.values.eggs_grading?.filter(
- (_, i) => i !== idx
- );
- formik.setFieldValue('eggs_grading', updatedGrading);
- };
-
- const removeSelectedGrading = () => {
- const updatedGrading = formik.values.eggs_grading?.filter(
- (_, idx) => !selectedGradingItems.includes(idx)
- );
- formik.setFieldValue('eggs_grading', updatedGrading);
- setSelectedGradingItems([]);
- };
-
- // VALIDATION HELPERS
- const isRepeaterInputError = (
- arrayName: 'eggs_grading',
- column: string,
- idx: number
- ) => {
- const touched = formik.touched as Record;
- const errors = formik.errors as Record;
-
- if (!touched[arrayName] || !Array.isArray(touched[arrayName])) {
- return {
- isError: false,
- errorMessage: '',
- };
- }
-
- const touchedField = (touched[arrayName] as unknown[])?.[idx] as Record<
- string,
- unknown
- >;
- const errorField = (errors[arrayName] as unknown[])?.[idx] as Record<
- string,
- unknown
- >;
-
- return {
- isError: touchedField && Boolean(errorField?.[column]),
- errorMessage:
- touchedField && errorField?.[column]
- ? (errorField[column] as string)
- : '',
- };
- };
-
- // EFFECTS
- useEffect(() => {
- if (isDataLoading) {
- toast.dismiss('grading-exceeds');
- toast.dismiss('grading-incomplete');
- return;
- }
-
- if (isGradingExceedsAvailable && currentGradingTotal > 0) {
- toast.error(
- `Total grading (${currentGradingTotal}) melebihi telur yang tersedia (${totalKonsumsiBaikEggs})!`,
- {
- id: 'grading-exceeds',
- 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 {
- toast.dismiss('grading-exceeds');
- toast.dismiss('grading-incomplete');
- }
- }, [
- isDataLoading,
- isGradingExceedsAvailable,
- isGradingIncomplete,
- hasUserStartedGrading,
- currentGradingTotal,
- totalKonsumsiBaikEggs,
- ]);
-
- useEffect(() => {
- if (
- konsumsiBaikEggId &&
- formik.values.eggs_grading &&
- formik.values.eggs_grading.length === 0
- ) {
- formik.setFieldValue('eggs_grading', [
- { recording_egg_id: konsumsiBaikEggId, grade: '', qty: '' },
- ]);
- }
- }, [konsumsiBaikEggId, formik.values.eggs_grading.length]);
-
- return (
- <>
-
-
-
-
- {type === 'add' && 'Tambah Grading'}
- {type === 'edit' && 'Edit Grading'}
- {type === 'detail' && 'Detail Grading'}
-
-
-
-
-
-
- {/* ===== MODALS ===== */}
- {type !== 'add' && (
- <>
-
- >
- )}
- >
- );
-};
-
-export default GradingForm;
diff --git a/src/services/api/production.ts b/src/services/api/production.ts
index 4266f6b7..ea06615a 100644
--- a/src/services/api/production.ts
+++ b/src/services/api/production.ts
@@ -9,8 +9,6 @@ import {
CreateRecordingPayload,
Recording,
UpdateRecordingPayload,
- CreateGradingPayload,
- UpdateGradingPayload,
NextDayRecording,
} from '@/types/api/production/recording';
import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
@@ -64,28 +62,6 @@ export class RecordingService extends BaseApiService<
});
}
- async createGrading(
- payload: CreateGradingPayload
- ): Promise | undefined> {
- return await this.customRequest>('gradings', {
- method: 'POST',
- payload,
- });
- }
-
- async updateGrading(
- gradingId: number,
- payload: UpdateGradingPayload
- ): Promise | undefined> {
- return await this.customRequest>(
- `gradings/${gradingId}`,
- {
- method: 'PUT',
- payload,
- }
- );
- }
-
async deleteGrading(
gradingId: number
): Promise | undefined> {