mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
feat(FE-170,174): clean up RecordingForm and RecordingTable components for improved readability and maintainability
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user