Merge pull request 'feat(month): add monthy selection' (#54) from lavoce into main

Reviewed-on: #54
This commit is contained in:
2026-06-22 07:38:47 +00:00
2 changed files with 170 additions and 1 deletions

View File

@@ -172,6 +172,19 @@ const DetailDevice = (props) => {
} }
}; };
const [period, setPeriod] = useState({
period: undefined,
start_date: null,
end_date: null,
});
const handleMonthly = (field, value) => {
setPeriod((prev) => ({
...prev,
[field]: value,
}));
};
useEffect(() => { useEffect(() => {
if (props.showModal && (props.actionMode === 'add' || props.actionMode === 'edit')) { if (props.showModal && (props.actionMode === 'add' || props.actionMode === 'edit')) {
fetchBrands(); fetchBrands();
@@ -381,7 +394,7 @@ const DetailDevice = (props) => {
</div> </div>
</div> </div>
<div style={{ marginBottom: 12 }}> <div style={{ marginBottom: 12 }}>
<Text strong>Reminder At</Text> <Text strong>Reminder At(Yearly)</Text>
<div style={{ display: 'flex', gap: 8, alignItems: 'center' }}> <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
<DatePicker <DatePicker
value={ value={
@@ -413,6 +426,84 @@ const DetailDevice = (props) => {
</Button> </Button>
</div> </div>
</div> </div>
<div style={{ marginBottom: 12 }}>
<Text strong>Period</Text>
<Text style={{ color: 'red' }}> *</Text>
<Select
value={period.period}
onChange={(value) => handleMonthly('period', value)}
placeholder="Select Period"
style={{ width: '100%' }}
>
<Select.Option value="1">1 Monthly</Select.Option>
<Select.Option value="3">3 Monthly</Select.Option>
<Select.Option value="6">6 Monthly</Select.Option>
<Select.Option value="custom">Custom</Select.Option>
</Select>
</div>
{period.period === 'custom' && (
<div style={{ display: 'flex', gap: 8, marginBottom: 12 }}>
<DatePicker
placeholder="Start Date"
value={period.start_date ? dayjs(period.start_date) : null}
onChange={(date) =>
setPeriod((prev) => ({
...prev,
start_date: date ? date.toISOString() : null,
}))
}
style={{ flex: 1 }}
/>
<DatePicker
placeholder="End Date"
value={period.end_date ? dayjs(period.end_date) : null}
onChange={(date) =>
setPeriod((prev) => ({
...prev,
end_date: date ? date.toISOString() : null,
}))
}
style={{ flex: 1 }}
/>
</div>
)}
<div style={{ marginBottom: 12 }}>
<Text strong>Reminder At(Monthly)</Text>
<div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
<DatePicker
disabled={period.period === 'custom'}
value={
formData.reminder_at
? dayjs(formData.reminder_at) // ✅ langsung parse ISO
: null
}
onChange={(date) =>
handleDateChange(
'reminder_at',
date ? date.toISOString() : null
)
}
format="DD-MM-YYYY HH:mm"
showTime={{ format: 'HH:mm' }}
style={{ flex: 1 }}
/>
<Button
disabled={period.period === 'custom'}
danger
onClick={() =>
setFormData((prev) => ({
...prev,
reminder_at: null,
}))
}
>
Clear
</Button>
</div>
</div>
<div style={{ marginBottom: 12 }}> <div style={{ marginBottom: 12 }}>
<Text strong>Device Description</Text> <Text strong>Device Description</Text>
<TextArea <TextArea

View File

@@ -38,6 +38,24 @@ const DetailSparepart = (props) => {
const [previewTitle, setPreviewTitle] = useState(''); const [previewTitle, setPreviewTitle] = useState('');
const [isHovering, setIsHovering] = useState(false); const [isHovering, setIsHovering] = useState(false);
const optionsMonthly = [
{
key: 1,
value: 1,
text: '1 Month',
},
{
key: 3,
value: 3,
text: '3 Month',
},
{
key: 6,
value: 6,
text: '6 Month',
},
];
const optionsYearly = [ const optionsYearly = [
{ {
key: 1, key: 1,
@@ -70,6 +88,10 @@ const DetailSparepart = (props) => {
text: '6 Year', text: '6 Year',
}, },
]; ];
const [checkedListM, setCheckedListM] = useState([]);
const [checkAllM, setCheckAllM] = useState(false);
const [indeterminateM, setIndeterminateM] = useState(false);
const [checkedList, setCheckedList] = useState([]); const [checkedList, setCheckedList] = useState([]);
const [checkAll, setCheckAll] = useState(false); const [checkAll, setCheckAll] = useState(false);
const [indeterminate, setIndeterminate] = useState(false); const [indeterminate, setIndeterminate] = useState(false);
@@ -276,6 +298,7 @@ const DetailSparepart = (props) => {
payload.sparepart_number = formData.sparepart_number; payload.sparepart_number = formData.sparepart_number;
payload.sparepart_yearly = checkedList; payload.sparepart_yearly = checkedList;
payload.sparepart_monthly = checkedListM;
// console.log('Sending payload:', payload); // console.log('Sending payload:', payload);
@@ -323,6 +346,21 @@ const DetailSparepart = (props) => {
setFormData({ ...formData, [name]: value }); setFormData({ ...formData, [name]: value });
}; };
const onChangeCheckboxM = (list) => {
setCheckedListM(list);
setIndeterminateM(!!list.length && list.length < optionsMonthly.length);
setCheckAllM(list.length === optionsMonthly.length);
};
const onCheckAllChangeM = (e) => {
const checked = e.target.checked;
setCheckedListM(checked ? optionsMonthly.map((item) => item.value) : []);
setIndeterminateM(false);
setCheckAllM(checked);
};
const onChangeCheckbox = (list) => { const onChangeCheckbox = (list) => {
setCheckedList(list); setCheckedList(list);
@@ -374,10 +412,16 @@ const DetailSparepart = (props) => {
} else { } else {
setFileList([]); setFileList([]);
} }
setCheckedListM(JSON.parse(props.selectedData.sparepart_monthly));
setCheckedList(JSON.parse(props.selectedData.sparepart_yearly)); setCheckedList(JSON.parse(props.selectedData.sparepart_yearly));
} else { } else {
setFormData(defaultData); setFormData(defaultData);
setFileList([]); setFileList([]);
setIndeterminateM(false);
setCheckedListM([]);
setCheckAllM(false);
setIndeterminate(false); setIndeterminate(false);
setCheckedList([]); setCheckedList([]);
setCheckAll(false); setCheckAll(false);
@@ -639,6 +683,8 @@ const DetailSparepart = (props) => {
}, },
}} }}
> >
{/* Yearly */}
<Row style={{ marginTop: 16 }}> <Row style={{ marginTop: 16 }}>
<Col> <Col>
<Checkbox <Checkbox
@@ -669,6 +715,38 @@ const DetailSparepart = (props) => {
</Checkbox.Group> </Checkbox.Group>
</Col> </Col>
</Row> </Row>
{/* Monthly */}
<Row style={{ marginTop: 16 }}>
<Col>
<Checkbox
indeterminate={indeterminateM}
onChange={onCheckAllChangeM}
checked={checkAllM}
>
{checkAllM ? 'Unselect All Months' : 'Select All Months'}
</Checkbox>
</Col>
</Row>
<Row style={{ marginTop: 10 }}>
<Col span={24}>
<Checkbox.Group
value={checkedListM}
onChange={onChangeCheckboxM}
style={{
width: '100%',
display: 'flex',
justifyContent: 'space-between',
}}
>
{optionsMonthly.map((item) => (
<Checkbox key={item.key} value={item.value}>
{item.text}
</Checkbox>
))}
</Checkbox.Group>
</Col>
</Row>
</ConfigProvider> </ConfigProvider>
<Row gutter={[16, 16]} style={{ marginTop: 16 }}> <Row gutter={[16, 16]} style={{ marginTop: 16 }}>
<Col span={24}> <Col span={24}>