refactor(FE): Add validation and error messages to filter modal

This commit is contained in:
rstubryan
2026-01-09 09:30:51 +07:00
parent 4fdfe63dc9
commit 3ce30115f8
@@ -230,6 +230,7 @@ const UniformityTable = () => {
const [filterStartDate, setFilterStartDate] = useState(''); const [filterStartDate, setFilterStartDate] = useState('');
const [filterEndDate, setFilterEndDate] = useState(''); const [filterEndDate, setFilterEndDate] = useState('');
const [projectFlockSearchValue, setProjectFlockSearchValue] = useState(''); const [projectFlockSearchValue, setProjectFlockSearchValue] = useState('');
const [filterErrors, setFilterErrors] = useState<Record<string, string>>({});
const { const {
setInputValue: setFilterLocationInputValue, setInputValue: setFilterLocationInputValue,
@@ -423,9 +424,38 @@ const UniformityTable = () => {
}, []); }, []);
const handleApplyFilters = useCallback(() => { const handleApplyFilters = useCallback(() => {
setIsSubmitted(true); const errors: Record<string, string> = {};
filterModal.closeModal();
}, [filterModal]); if (!filterStartDate) {
errors.start_date = 'Tanggal mulai wajib diisi';
}
if (!filterEndDate) {
errors.end_date = 'Tanggal akhir wajib diisi';
}
if (!filterLocation) {
errors.location = 'Lokasi wajib dipilih';
}
if (!filterProjectFlock) {
errors.project_flock = 'Project Flock wajib dipilih';
}
if (!filterKandang) {
errors.kandang = 'Kandang wajib dipilih';
}
setFilterErrors(errors);
if (Object.keys(errors).length === 0) {
setIsSubmitted(true);
filterModal.closeModal();
}
}, [
filterModal,
filterStartDate,
filterEndDate,
filterLocation,
filterProjectFlock,
filterKandang,
]);
const selectedRowIds = useMemo(() => { const selectedRowIds = useMemo(() => {
return Object.keys(rowSelection) return Object.keys(rowSelection)
@@ -1124,58 +1154,105 @@ const UniformityTable = () => {
</div> </div>
<div className='space-y-4 px-4'> <div className='space-y-4 px-4'>
<div className='grid grid-cols-1 sm:grid-cols-2 sm:gap-4'> <div className='grid grid-cols-1 sm:grid-cols-2 sm:gap-4'>
<DateInput <div>
label='Tanggal' <DateInput
name='start_date' label='Tanggal'
value={filterStartDate} name='start_date'
onChange={(e) => setFilterStartDate(e.target.value)} value={filterStartDate}
className={{ wrapper: 'w-full' }} onChange={(e) => {
/> setFilterStartDate(e.target.value);
setFilterErrors((prev) => ({ ...prev, start_date: '' }));
}}
className={{ wrapper: 'w-full' }}
/>
{filterErrors.start_date && (
<p className='text-red-500 text-sm mt-1'>
{filterErrors.start_date}
</p>
)}
</div>
<DateInput <div>
label=' ' <DateInput
name='end_date' label=' '
value={filterEndDate} name='end_date'
onChange={(e) => setFilterEndDate(e.target.value)} value={filterEndDate}
className={{ wrapper: 'w-full' }} onChange={(e) => {
/> setFilterEndDate(e.target.value);
setFilterErrors((prev) => ({ ...prev, end_date: '' }));
}}
className={{ wrapper: 'w-full' }}
/>
{filterErrors.end_date && (
<p className='text-red-500 text-sm mt-1'>
{filterErrors.end_date}
</p>
)}
</div>
</div> </div>
<SelectInput <div>
label='Lokasi' <SelectInput
placeholder='Pilih Lokasi...' label='Lokasi'
value={filterLocation} placeholder='Pilih Lokasi...'
onChange={handleFilterLocationChange} value={filterLocation}
options={filterLocationOptions} onChange={(value) => {
onInputChange={setFilterLocationInputValue} handleFilterLocationChange(value);
isLoading={isLoadingFilterLocations} setFilterErrors((prev) => ({ ...prev, location: '' }));
isClearable }}
className={{ wrapper: 'w-full' }} options={filterLocationOptions}
/> onInputChange={setFilterLocationInputValue}
isLoading={isLoadingFilterLocations}
className={{ wrapper: 'w-full' }}
/>
{filterErrors.location && (
<p className='text-red-500 text-sm mt-1'>
{filterErrors.location}
</p>
)}
</div>
<SelectInput <div>
label='Project Flock' <SelectInput
placeholder='Pilih Project Flock...' label='Project Flock'
value={filterProjectFlock} placeholder='Pilih Project Flock...'
onChange={handleFilterProjectFlockChange} value={filterProjectFlock}
options={filterProjectFlockOptions} onChange={(value) => {
onInputChange={setProjectFlockSearchValue} handleFilterProjectFlockChange(value);
isLoading={isLoadingFilterProjectFlocks} setFilterErrors((prev) => ({ ...prev, project_flock: '' }));
isDisabled={!filterLocation} }}
isClearable options={filterProjectFlockOptions}
className={{ wrapper: 'w-full' }} onInputChange={setProjectFlockSearchValue}
/> isLoading={isLoadingFilterProjectFlocks}
isDisabled={!filterLocation}
className={{ wrapper: 'w-full' }}
/>
{filterErrors.project_flock && (
<p className='text-red-500 text-sm mt-1'>
{filterErrors.project_flock}
</p>
)}
</div>
<SelectInput <div>
label='Kandang' <SelectInput
placeholder='Pilih Kandang...' label='Kandang'
value={filterKandang} placeholder='Pilih Kandang...'
onChange={handleFilterKandangChange} value={filterKandang}
options={filterKandangOptions} onChange={(value) => {
isDisabled={!filterProjectFlock} handleFilterKandangChange(value);
isClearable setFilterErrors((prev) => ({ ...prev, kandang: '' }));
className={{ wrapper: 'w-full' }} }}
/> options={filterKandangOptions}
isDisabled={!filterProjectFlock}
className={{ wrapper: 'w-full' }}
/>
{filterErrors.kandang && (
<p className='text-red-500 text-sm mt-1'>
{filterErrors.kandang}
</p>
)}
</div>
</div> </div>
{/* Action Buttons */} {/* Action Buttons */}