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