refactor(FE): Refactor date input components for consistency and layout

This commit is contained in:
rstubryan
2026-02-27 13:34:51 +07:00
parent 396a5ab5ba
commit 64843a36ab
3 changed files with 149 additions and 143 deletions
@@ -121,37 +121,40 @@ const ExpensesFilterModal = ({
{/* Modal Body */} {/* Modal Body */}
<div className='p-4 flex flex-col gap-1.5'> <div className='p-4 flex flex-col gap-1.5'>
<DateInput <div className='flex flex-col'>
label='Tanggal Transaksi' <span className='py-2 text-xs font-semibold'>Tanggal</span>
name='transaction_date' <div className='flex flex-row items-center gap-1.5'>
placeholder='Masukkan tanggal transaksi' <DateInput
value={formik.values.transaction_date || ''} name='transaction_date'
onChange={formik.handleChange} placeholder='Tanggal Transaksi'
onBlur={formik.handleBlur} value={formik.values.transaction_date || ''}
isError={ onChange={formik.handleChange}
formik.touched.transaction_date && onBlur={formik.handleBlur}
!!formik.errors.transaction_date isError={
} formik.touched.transaction_date &&
/> !!formik.errors.transaction_date
}
<DateInput />
label='Tanggal Realisasi' <hr className='w-full max-w-3 h-px border-base-content/10' />
name='realization_date' <DateInput
placeholder='Masukkan tanggal realisasi' name='realization_date'
value={formik.values.realization_date || ''} placeholder='Tanggal Realisasi'
onChange={formik.handleChange} value={formik.values.realization_date || ''}
onBlur={formik.handleBlur} onChange={formik.handleChange}
isError={ onBlur={formik.handleBlur}
formik.touched.realization_date && isError={
!!formik.errors.realization_date formik.touched.realization_date &&
} !!formik.errors.realization_date
/> }
{formik.touched.realization_date && />
formik.errors.realization_date && ( </div>
<span className='text-xs text-error'> {formik.touched.realization_date &&
{formik.errors.realization_date} formik.errors.realization_date && (
</span> <span className='text-xs text-error'>
)} {formik.errors.realization_date}
</span>
)}
</div>
<SelectInput <SelectInput
label='Lokasi' label='Lokasi'
+30 -23
View File
@@ -765,6 +765,36 @@ const FinanceTable = () => {
onReset={filterFormik.handleReset} onReset={filterFormik.handleReset}
> >
<div className='p-4 flex flex-col gap-1.5'> <div className='p-4 flex flex-col gap-1.5'>
<div className='flex flex-col'>
<span className='py-2 text-xs font-semibold'>Tanggal</span>
<div className='flex flex-row items-center gap-1.5'>
<DateInput
name='start_date'
placeholder='Periode Tanggal Awal'
value={filterFormik.values.start_date}
errorMessage={filterFormik.errors.start_date}
onChange={startDateChangeHandler}
isError={
filterFormik.touched.start_date &&
Boolean(filterFormik.errors.start_date)
}
/>
<hr className='w-full max-w-3 h-px border-base-content/10' />
<DateInput
name='end_date'
placeholder='Periode Tanggal Akhir'
value={filterFormik.values.end_date}
errorMessage={filterFormik.errors.end_date}
onChange={endDateChangeHandler}
isError={
(filterFormik.touched.end_date &&
Boolean(filterFormik.errors.end_date)) ||
hasDateError
}
/>
</div>
</div>
<SelectInput <SelectInput
options={FINANCE_TRANSACTION_TYPE_OPTIONS} options={FINANCE_TRANSACTION_TYPE_OPTIONS}
label='Jenis Transaksi' label='Jenis Transaksi'
@@ -827,29 +857,6 @@ const FinanceTable = () => {
isClearable isClearable
className={{ wrapper: 'w-full' }} className={{ wrapper: 'w-full' }}
/> />
<DateInput
name='start_date'
label='Periode Tanggal (Mulai)'
value={filterFormik.values.start_date}
errorMessage={filterFormik.errors.start_date}
onChange={startDateChangeHandler}
isError={
filterFormik.touched.start_date &&
Boolean(filterFormik.errors.start_date)
}
/>
<DateInput
name='end_date'
label='Periode Tanggal (Akhir)'
value={filterFormik.values.end_date}
errorMessage={filterFormik.errors.end_date}
onChange={endDateChangeHandler}
isError={
(filterFormik.touched.end_date &&
Boolean(filterFormik.errors.end_date)) ||
hasDateError
}
/>
</div> </div>
{/* Modal Footer */} {/* Modal Footer */}
@@ -36,7 +36,6 @@ import {
} from '@/components/pages/report/marketing/filter/DailyMarketingFilter'; } from '@/components/pages/report/marketing/filter/DailyMarketingFilter';
import SelectInput from '@/components/input/SelectInput'; import SelectInput from '@/components/input/SelectInput';
import Modal, { useModal } from '@/components/Modal'; import Modal, { useModal } from '@/components/Modal';
import { cn } from '@/lib/helper';
import { useTabActionsStore } from '@/stores/tab-actions/tab-actions.store'; import { useTabActionsStore } from '@/stores/tab-actions/tab-actions.store';
import DailyMarketingReportSkeleton from '@/components/pages/report/marketing/skeleton/DailyMarketingSkeleton'; import DailyMarketingReportSkeleton from '@/components/pages/report/marketing/skeleton/DailyMarketingSkeleton';
import { useEffect as useEffectHook } from 'react'; import { useEffect as useEffectHook } from 'react';
@@ -46,8 +45,8 @@ import {
MARKETING_DATE_FILTER_TYPE_OPTIONS, MARKETING_DATE_FILTER_TYPE_OPTIONS,
MARKETING_TYPE_OPTIONS, MARKETING_TYPE_OPTIONS,
} from '@/config/constant'; } from '@/config/constant';
import Badge from '@/components/Badge';
import ButtonFilter from '@/components/helper/ButtonFilter'; import ButtonFilter from '@/components/helper/ButtonFilter';
import SelectInputRadio from '@/components/input/SelectInputRadio';
interface DailyMarketingTabProps { interface DailyMarketingTabProps {
tabId: string; tabId: string;
@@ -733,6 +732,88 @@ const DailyMarketingTab = ({ tabId }: DailyMarketingTabProps) => {
</div> </div>
<form onSubmit={formik.handleSubmit} onReset={formik.handleReset}> <form onSubmit={formik.handleSubmit} onReset={formik.handleReset}>
<div className='p-4 flex flex-col gap-3'> <div className='p-4 flex flex-col gap-3'>
{/* Date Range Filter */}
<div className='flex flex-col'>
<span className='py-2 text-xs font-semibold'>Tanggal</span>
<div className='flex flex-row items-center gap-1.5'>
<DateInput
name='start_date'
placeholder='Tanggal Awal'
value={formik.values.start_date || ''}
onChange={(e) => {
const value = e.target.value;
formik.setFieldValue('start_date', value || null);
if (value && formik.values.end_date) {
const startDate = new Date(value);
const endDateObj = new Date(formik.values.end_date);
if (endDateObj < startDate) {
setHasDateError(true);
if (!dateErrorShown) {
toast.error('Tanggal akhir tidak boleh masa lampau', {
duration: Infinity,
});
setDateErrorShown(true);
}
} else {
setHasDateError(false);
if (dateErrorShown) {
toast.dismiss();
setDateErrorShown(false);
}
}
} else {
setHasDateError(false);
}
}}
className={{ wrapper: 'w-full' }}
errorMessage={formik.errors.start_date}
isError={
!!formik.errors.start_date && formik.touched.start_date
}
/>
<hr className='w-full max-w-3 h-px border-base-content/10' />
<DateInput
name='end_date'
placeholder='Tanggal Akhir'
value={formik.values.end_date || ''}
onChange={(e) => {
const value = e.target.value;
formik.setFieldValue('end_date', value || null);
if (value && formik.values.start_date) {
const startDateObj = new Date(formik.values.start_date);
const endDate = new Date(value);
if (endDate < startDateObj) {
setHasDateError(true);
if (!dateErrorShown) {
toast.error('Tanggal akhir tidak boleh masa lampau', {
duration: Infinity,
});
setDateErrorShown(true);
}
return;
}
}
setHasDateError(false);
if (dateErrorShown) {
toast.dismiss();
setDateErrorShown(false);
}
}}
className={{ wrapper: 'w-full' }}
errorMessage={formik.errors.end_date}
isError={
(formik.errors.end_date && formik.touched.end_date) ||
hasDateError
}
/>
</div>
</div>
{/* Area Filter */} {/* Area Filter */}
<SelectInput <SelectInput
label='Area' label='Area'
@@ -801,93 +882,8 @@ const DailyMarketingTab = ({ tabId }: DailyMarketingTabProps) => {
className={{ wrapper: 'w-full' }} className={{ wrapper: 'w-full' }}
/> />
{/* Date Range Filter */}
<div>
<label className='block text-xs font-semibold text-base-content py-2'>
Rentang Tanggal
</label>
<div className='flex flex-col gap-2'>
<DateInput
name='start_date'
label='Tanggal Awal'
placeholder='Pilih Tanggal Awal'
value={formik.values.start_date || ''}
onChange={(e) => {
const value = e.target.value;
formik.setFieldValue('start_date', value || null);
if (value && formik.values.end_date) {
const startDate = new Date(value);
const endDateObj = new Date(formik.values.end_date);
if (endDateObj < startDate) {
setHasDateError(true);
if (!dateErrorShown) {
toast.error('Tanggal akhir tidak boleh masa lampau', {
duration: Infinity,
});
setDateErrorShown(true);
}
} else {
setHasDateError(false);
if (dateErrorShown) {
toast.dismiss();
setDateErrorShown(false);
}
}
} else {
setHasDateError(false);
}
}}
className={{ wrapper: 'w-full' }}
errorMessage={formik.errors.start_date}
isError={
!!formik.errors.start_date && formik.touched.start_date
}
/>
<DateInput
name='end_date'
label='Tanggal Akhir'
placeholder='Pilih Tanggal Akhir'
value={formik.values.end_date || ''}
onChange={(e) => {
const value = e.target.value;
formik.setFieldValue('end_date', value || null);
if (value && formik.values.start_date) {
const startDateObj = new Date(formik.values.start_date);
const endDate = new Date(value);
if (endDate < startDateObj) {
setHasDateError(true);
if (!dateErrorShown) {
toast.error('Tanggal akhir tidak boleh masa lampau', {
duration: Infinity,
});
setDateErrorShown(true);
}
return;
}
}
setHasDateError(false);
if (dateErrorShown) {
toast.dismiss();
setDateErrorShown(false);
}
}}
className={{ wrapper: 'w-full' }}
errorMessage={formik.errors.end_date}
isError={
(formik.errors.end_date && formik.touched.end_date) ||
hasDateError
}
/>
</div>
</div>
{/* Filter By Date Type */} {/* Filter By Date Type */}
<SelectInput <SelectInputRadio
label='Filter Tanggal' label='Filter Tanggal'
placeholder='Pilih Filter Tanggal' placeholder='Pilih Filter Tanggal'
options={MARKETING_DATE_FILTER_TYPE_OPTIONS} options={MARKETING_DATE_FILTER_TYPE_OPTIONS}
@@ -903,7 +899,7 @@ const DailyMarketingTab = ({ tabId }: DailyMarketingTabProps) => {
/> />
{/* Marketing Type Filter */} {/* Marketing Type Filter */}
<SelectInput <SelectInputRadio
label='Tipe Marketing' label='Tipe Marketing'
placeholder='Pilih Tipe Marketing' placeholder='Pilih Tipe Marketing'
options={MARKETING_TYPE_OPTIONS} options={MARKETING_TYPE_OPTIONS}