mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-25 15:55:48 +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 [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);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|||||||
Reference in New Issue
Block a user