feat(FE-170,174): clean up RecordingForm and RecordingTable components for improved readability and maintainability

This commit is contained in:
rstubryan
2025-10-31 17:27:10 +07:00
parent 19afb80597
commit 1228b45045
2 changed files with 105 additions and 57 deletions
@@ -112,7 +112,9 @@ const RecordingTable = () => {
const [sorting, setSorting] = useState<SortingState>([]); const [sorting, setSorting] = useState<SortingState>([]);
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({}); const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
const [selectedRecording, setSelectedRecording] = useState<Recording | undefined>(undefined); const [selectedRecording, setSelectedRecording] = useState<
Recording | undefined
>(undefined);
const [isDeleteLoading, setIsDeleteLoading] = useState(false); const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const [isBulkApproveLoading, setIsBulkApproveLoading] = useState(false); const [isBulkApproveLoading, setIsBulkApproveLoading] = useState(false);
const [isBulkRejectLoading, setIsBulkRejectLoading] = useState(false); const [isBulkRejectLoading, setIsBulkRejectLoading] = useState(false);
@@ -127,8 +129,12 @@ const RecordingTable = () => {
const [kandangSelectInputValue, setKandangSelectInputValue] = useState(''); const [kandangSelectInputValue, setKandangSelectInputValue] = useState('');
const [selectedArea, setSelectedArea] = useState<OptionType | null>(null); const [selectedArea, setSelectedArea] = useState<OptionType | null>(null);
const [selectedLocation, setSelectedLocation] = useState<OptionType | null>(null); const [selectedLocation, setSelectedLocation] = useState<OptionType | null>(
const [selectedKandang, setSelectedKandang] = useState<OptionType | null>(null); null
);
const [selectedKandang, setSelectedKandang] = useState<OptionType | null>(
null
);
const { const {
data: recordings, data: recordings,
@@ -144,20 +150,20 @@ const RecordingTable = () => {
search: areaSelectInputValue, search: areaSelectInputValue,
limit: '100', limit: '100',
}).toString()}`; }).toString()}`;
const { const { data: areas, isLoading: isLoadingAreas } = useSWR(
data: areas, areaUrl,
isLoading: isLoadingAreas, AreaApi.getAllFetcher
} = useSWR(areaUrl, AreaApi.getAllFetcher); );
const locationUrl = `${LocationApi.basePath}?${new URLSearchParams({ const locationUrl = `${LocationApi.basePath}?${new URLSearchParams({
search: locationSelectInputValue, search: locationSelectInputValue,
area_id: selectedArea != null ? selectedArea.value.toString() : '', area_id: selectedArea != null ? selectedArea.value.toString() : '',
limit: '100', limit: '100',
}).toString()}`; }).toString()}`;
const { const { data: locations, isLoading: isLoadingLocations } = useSWR(
data: locations, locationUrl,
isLoading: isLoadingLocations, LocationApi.getAllFetcher
} = useSWR(locationUrl, LocationApi.getAllFetcher); );
const kandangUrl = `${KandangApi.basePath}?${new URLSearchParams({ const kandangUrl = `${KandangApi.basePath}?${new URLSearchParams({
search: kandangSelectInputValue, search: kandangSelectInputValue,
@@ -165,10 +171,10 @@ const RecordingTable = () => {
selectedLocation != null ? selectedLocation.value.toString() : '', selectedLocation != null ? selectedLocation.value.toString() : '',
limit: '100', limit: '100',
}).toString()}`; }).toString()}`;
const { const { data: kandangs, isLoading: isLoadingKandang } = useSWR(
data: kandangs, kandangUrl,
isLoading: isLoadingKandang, KandangApi.getAllFetcher
} = useSWR(kandangUrl, KandangApi.getAllFetcher); );
// Data to Options Mapping // Data to Options Mapping
const optionsArea = isResponseSuccess(areas) const optionsArea = isResponseSuccess(areas)
@@ -213,7 +219,9 @@ const RecordingTable = () => {
return recordings.data; return recordings.data;
}, [recordings]); }, [recordings]);
const selectedRowIds = Object.keys(rowSelection).map((item) => parseInt(item)); const selectedRowIds = Object.keys(rowSelection).map((item) =>
parseInt(item)
);
const bulkApproveHandler = async () => { const bulkApproveHandler = async () => {
setIsBulkApproveLoading(true); setIsBulkApproveLoading(true);
@@ -233,7 +241,9 @@ const RecordingTable = () => {
await refreshRecordings(); await refreshRecordings();
setRowSelection({}); setRowSelection({});
bulkApproveModal.closeModal(); bulkApproveModal.closeModal();
toast.success(`Successfully approved ${selectedRowIds.length} recordings!`); toast.success(
`Successfully approved ${selectedRowIds.length} recordings!`
);
} }
if (isResponseError(approveResponse)) { if (isResponseError(approveResponse)) {
toast.error(approveResponse?.message as string); toast.error(approveResponse?.message as string);
@@ -260,7 +270,9 @@ const RecordingTable = () => {
refreshRecordings(); refreshRecordings();
setRowSelection({}); setRowSelection({});
bulkRejectModal.closeModal(); bulkRejectModal.closeModal();
toast.success(`Successfully rejected ${selectedRowIds.length} recordings!`); toast.success(
`Successfully rejected ${selectedRowIds.length} recordings!`
);
} }
if (isResponseError(rejectResponse)) { if (isResponseError(rejectResponse)) {
toast.error(rejectResponse?.message as string); toast.error(rejectResponse?.message as string);
@@ -312,7 +324,10 @@ const RecordingTable = () => {
setSelectedArea(selectedValue); setSelectedArea(selectedValue);
setSelectedLocation(null); setSelectedLocation(null);
setSelectedKandang(null); setSelectedKandang(null);
updateFilter('areaFilter', selectedValue ? selectedValue.value.toString() : ''); updateFilter(
'areaFilter',
selectedValue ? selectedValue.value.toString() : ''
);
updateFilter('locationFilter', ''); updateFilter('locationFilter', '');
updateFilter('kandangFilter', ''); updateFilter('kandangFilter', '');
setPage(1); setPage(1);
@@ -332,7 +347,10 @@ const RecordingTable = () => {
const selectedValue = selected as OptionType | null; const selectedValue = selected as OptionType | null;
setSelectedLocation(selectedValue); setSelectedLocation(selectedValue);
setSelectedKandang(null); setSelectedKandang(null);
updateFilter('locationFilter', selectedValue ? selectedValue.value.toString() : ''); updateFilter(
'locationFilter',
selectedValue ? selectedValue.value.toString() : ''
);
updateFilter('kandangFilter', ''); updateFilter('kandangFilter', '');
setPage(1); setPage(1);
}} }}
@@ -351,7 +369,10 @@ const RecordingTable = () => {
onChange={(selected) => { onChange={(selected) => {
const selectedValue = selected as OptionType | null; const selectedValue = selected as OptionType | null;
setSelectedKandang(selectedValue); setSelectedKandang(selectedValue);
updateFilter('kandangFilter', selectedValue ? selectedValue.value.toString() : ''); updateFilter(
'kandangFilter',
selectedValue ? selectedValue.value.toString() : ''
);
setPage(1); setPage(1);
}} }}
className={{ wrapper: 'w-full' }} className={{ wrapper: 'w-full' }}
@@ -371,12 +392,18 @@ const RecordingTable = () => {
]} ]}
value={ value={
tableFilterState.periodFilter tableFilterState.periodFilter
? { value: tableFilterState.periodFilter, label: `Periode ${tableFilterState.periodFilter}` } ? {
value: tableFilterState.periodFilter,
label: `Periode ${tableFilterState.periodFilter}`,
}
: null : null
} }
onChange={(selected) => { onChange={(selected) => {
const selectedValue = selected as OptionType | null; const selectedValue = selected as OptionType | null;
updateFilter('periodFilter', selectedValue ? selectedValue.value.toString() : ''); updateFilter(
'periodFilter',
selectedValue ? selectedValue.value.toString() : ''
);
setPage(1); setPage(1);
}} }}
className={{ wrapper: 'w-full' }} className={{ wrapper: 'w-full' }}
@@ -396,7 +423,10 @@ const RecordingTable = () => {
setSelectedArea(selectedValue); setSelectedArea(selectedValue);
setSelectedLocation(null); setSelectedLocation(null);
setSelectedKandang(null); setSelectedKandang(null);
updateFilter('areaFilter', selectedValue ? selectedValue.value.toString() : ''); updateFilter(
'areaFilter',
selectedValue ? selectedValue.value.toString() : ''
);
updateFilter('locationFilter', ''); updateFilter('locationFilter', '');
updateFilter('kandangFilter', ''); updateFilter('kandangFilter', '');
setPage(1); setPage(1);
@@ -416,7 +446,10 @@ const RecordingTable = () => {
const selectedValue = selected as OptionType | null; const selectedValue = selected as OptionType | null;
setSelectedLocation(selectedValue); setSelectedLocation(selectedValue);
setSelectedKandang(null); setSelectedKandang(null);
updateFilter('locationFilter', selectedValue ? selectedValue.value.toString() : ''); updateFilter(
'locationFilter',
selectedValue ? selectedValue.value.toString() : ''
);
updateFilter('kandangFilter', ''); updateFilter('kandangFilter', '');
setPage(1); setPage(1);
}} }}
@@ -435,7 +468,10 @@ const RecordingTable = () => {
onChange={(selected) => { onChange={(selected) => {
const selectedValue = selected as OptionType | null; const selectedValue = selected as OptionType | null;
setSelectedKandang(selectedValue); setSelectedKandang(selectedValue);
updateFilter('kandangFilter', selectedValue ? selectedValue.value.toString() : ''); updateFilter(
'kandangFilter',
selectedValue ? selectedValue.value.toString() : ''
);
setPage(1); setPage(1);
}} }}
className={{ wrapper: 'w-full' }} className={{ wrapper: 'w-full' }}
@@ -455,12 +491,18 @@ const RecordingTable = () => {
]} ]}
value={ value={
tableFilterState.periodFilter tableFilterState.periodFilter
? { value: tableFilterState.periodFilter, label: `Periode ${tableFilterState.periodFilter}` } ? {
value: tableFilterState.periodFilter,
label: `Periode ${tableFilterState.periodFilter}`,
}
: null : null
} }
onChange={(selected) => { onChange={(selected) => {
const selectedValue = selected as OptionType | null; const selectedValue = selected as OptionType | null;
updateFilter('periodFilter', selectedValue ? selectedValue.value.toString() : ''); updateFilter(
'periodFilter',
selectedValue ? selectedValue.value.toString() : ''
);
setPage(1); setPage(1);
}} }}
className={{ wrapper: 'w-full' }} className={{ wrapper: 'w-full' }}
@@ -562,11 +604,15 @@ const RecordingTable = () => {
}, },
{ {
header: '#', header: '#',
cell: (props) => tableFilterState.pageSize * (tableFilterState.page - 1) + props.row.index + 1, cell: (props) =>
tableFilterState.pageSize * (tableFilterState.page - 1) +
props.row.index +
1,
}, },
{ {
header: 'Nama Project', header: 'Nama Project',
cell: (props) => `Project ${props.row.original.project_flock_kandang_id}`, cell: (props) =>
`Project ${props.row.original.project_flock_kandangs_id}`,
}, },
{ {
header: 'Umur (hari)', header: 'Umur (hari)',
@@ -576,19 +622,22 @@ const RecordingTable = () => {
accessorKey: 'record_date', accessorKey: 'record_date',
header: 'Waktu Recording', header: 'Waktu Recording',
cell: (props) => cell: (props) =>
new Date(props.row.original.record_date).toLocaleDateString(), new Date(props.row.original.record_datetime).toLocaleDateString(),
}, },
{ {
header: 'Populasi Awal', header: 'Populasi Awal',
cell: (props) => props.row.original.total_chick?.toLocaleString() || '-', cell: (props) =>
props.row.original.total_chick_qty?.toLocaleString() || '-',
}, },
{ {
header: 'BW', header: 'BW',
cell: (props) => props.row.original.avg_daily_gain?.toFixed(2) || '-', cell: (props) =>
props.row.original.avg_daily_gain?.toFixed(2) || '-',
}, },
{ {
header: 'Pakan', header: 'Pakan',
cell: (props) => props.row.original.cum_intake?.toLocaleString() || '-', cell: (props) =>
props.row.original.cum_intake?.toLocaleString() || '-',
}, },
{ {
header: 'FCR', header: 'FCR',
@@ -597,19 +646,20 @@ const RecordingTable = () => {
{ {
accessorKey: 'total_depletion', accessorKey: 'total_depletion',
header: 'Total Deplesi', header: 'Total Deplesi',
cell: (props) => props.row.original.total_depletion, cell: (props) => props.row.original.total_depletion_qty,
}, },
{ {
header: 'Deplesi (%)', header: 'Deplesi (%)',
cell: (props) => props.row.original.daily_depletion_rate?.toFixed(2) || '-', cell: (props) =>
props.row.original.daily_depletion_rate?.toFixed(2) || '-',
}, },
{ {
header: 'Populasi Akhir', header: 'Populasi Akhir',
cell: (props) => (props.row.original.total_chick - props.row.original.total_depletion)?.toLocaleString() || '-', cell: (props) =>
}, (
{ props.row.original.total_chick_qty -
header: 'Ketepatan Waktu', props.row.original.total_depletion_qty
cell: (props) => props.row.original.ontime ? 'Tepat Waktu' : 'Terlambat', )?.toLocaleString() || '-',
}, },
{ {
header: 'Tanggal Submit', header: 'Tanggal Submit',
@@ -660,8 +710,14 @@ const RecordingTable = () => {
}, },
]} ]}
pageSize={tableFilterState.pageSize} pageSize={tableFilterState.pageSize}
page={recordings?.status === 'success' ? recordings.meta?.page : tableFilterState.page} page={
totalItems={recordings?.status === 'success' ? recordings.meta?.total_results : 0} recordings?.status === 'success'
? recordings.meta?.page
: tableFilterState.page
}
totalItems={
recordings?.status === 'success' ? recordings.meta?.total_results : 0
}
onPageChange={setPage} onPageChange={setPage}
isLoading={isLoading} isLoading={isLoading}
sorting={sorting} sorting={sorting}
@@ -43,7 +43,6 @@ import toast from 'react-hot-toast';
import Card from '@/components/Card'; import Card from '@/components/Card';
import Badge from '@/components/Badge'; import Badge from '@/components/Badge';
import Steps from '@/components/steps/Steps';
import StepItem from '@/components/steps/StepItem'; import StepItem from '@/components/steps/StepItem';
import { Kandang } from '@/types/api/master-data/kandang'; import { Kandang } from '@/types/api/master-data/kandang';
@@ -1038,17 +1037,6 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
{/* Project Flock Info Card */} {/* Project Flock Info Card */}
{projectFlockKandangLookup && ( {projectFlockKandangLookup && (
<div className='flex items-center gap-2 mb-4'> <div className='flex items-center gap-2 mb-4'>
<Badge
variant='soft'
color='info'
size='md'
className={{
badge: 'whitespace-nowrap font-semibold text-xs px-2',
}}
>
{projectFlockKandangLookup.project_flock.category}
</Badge>
{/* Form Steps for LAYING Category */} {/* Form Steps for LAYING Category */}
{formSteps && ( {formSteps && (
<div className='flex-1 mt-4'> <div className='flex-1 mt-4'>
@@ -1089,7 +1077,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
type='button' type='button'
color='primary' color='primary'
onClick={() => { onClick={() => {
router.push(`/production/recording/grading/add?recording_id=${initialValues?.id}`); router.push(
`/production/recording/grading/add?recording_id=${initialValues?.id}`
);
}} }}
> >
Lanjut ke Grading Lanjut ke Grading
@@ -2203,7 +2193,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
); );
// Redirect ke grading form setelah submit berhasil // Redirect ke grading form setelah submit berhasil
setTimeout(() => { setTimeout(() => {
router.push('/production/recording/grading/add?recording_id=new'); router.push(
'/production/recording/grading/add?recording_id=new'
);
}, 1000); }, 1000);
} }
}} }}