feat: implement sparepart management with CRUD operations and UI components
This commit is contained in:
289
src/pages/master/sparepart/component/DetailSparepart.jsx
Normal file
289
src/pages/master/sparepart/component/DetailSparepart.jsx
Normal file
@@ -0,0 +1,289 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Modal, Input, Divider, Typography, Switch, Button, ConfigProvider, message } from 'antd';
|
||||
import { NotifAlert, NotifOk } from '../../../../components/Global/ToastNotif';
|
||||
import { createSparepart, updateSparepart } from '../../../../api/sparepart';
|
||||
import { validateRun } from '../../../../Utils/validate';
|
||||
|
||||
const { Text } = Typography;
|
||||
const { TextArea } = Input;
|
||||
|
||||
const DetailSparepart = (props) => {
|
||||
const [confirmLoading, setConfirmLoading] = useState(false);
|
||||
|
||||
const defaultData = {
|
||||
sparepart_id: '',
|
||||
sparepart_name: '',
|
||||
sparepart_description: '',
|
||||
sparepart_model: '',
|
||||
sparepart_item_type: '',
|
||||
sparepart_unit: '',
|
||||
sparepart_merk: '',
|
||||
sparepart_stok: '',
|
||||
};
|
||||
|
||||
const [formData, setFormData] = useState(defaultData);
|
||||
|
||||
const handleCancel = () => {
|
||||
props.setSelectedData(null);
|
||||
props.setActionMode('list');
|
||||
};
|
||||
|
||||
const handleSave = async () => {
|
||||
setConfirmLoading(true);
|
||||
|
||||
// Daftar aturan validasi
|
||||
const validationRules = [
|
||||
{ field: 'sparepart_name', label: 'Sparepart Name', required: true },
|
||||
{ field: 'sparepart_model', label: 'Sparepart Model', required: true },
|
||||
{ field: 'sparepart_unit', label: 'Sparepart Unit', required: true },
|
||||
{ field: 'sparepart_merk', label: 'Sparepart Merk', required: true },
|
||||
{ field: 'sparepart_stok', label: 'Sparepart Stok', required: true },
|
||||
];
|
||||
|
||||
if (
|
||||
validateRun(formData, validationRules, (errorMessages) => {
|
||||
NotifOk({
|
||||
icon: 'warning',
|
||||
title: 'Peringatan',
|
||||
message: errorMessages,
|
||||
});
|
||||
setConfirmLoading(false);
|
||||
})
|
||||
)
|
||||
return;
|
||||
|
||||
try {
|
||||
const payload = {
|
||||
sparepart_name: formData.sparepart_name,
|
||||
sparepart_description: formData.sparepart_description,
|
||||
sparepart_model: formData.sparepart_model,
|
||||
sparepart_item_type: formData.sparepart_item_type,
|
||||
sparepart_unit: formData.sparepart_unit,
|
||||
sparepart_merk: formData.sparepart_merk,
|
||||
sparepart_stok: formData.sparepart_stok,
|
||||
};
|
||||
|
||||
const response = formData.sparepart_id
|
||||
? await updateSparepart(formData.sparepart_id, payload)
|
||||
: await createSparepart(payload);
|
||||
|
||||
// Check if response is successful
|
||||
if (response && (response.statusCode === 200 || response.statusCode === 201)) {
|
||||
const sparepartName = response.data?.sparepart_name || formData.sparepart_name;
|
||||
|
||||
NotifOk({
|
||||
icon: 'success',
|
||||
title: 'Berhasil',
|
||||
message: `Data Sparepart "${sparepartName}" berhasil ${
|
||||
formData.sparepart_id ? 'diubah' : 'ditambahkan'
|
||||
}.`,
|
||||
});
|
||||
|
||||
props.setActionMode('list');
|
||||
} else {
|
||||
NotifAlert({
|
||||
icon: 'error',
|
||||
title: 'Gagal',
|
||||
message: response?.message || 'Terjadi kesalahan saat menyimpan data.',
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Save Sparepart Error:', error);
|
||||
NotifAlert({
|
||||
icon: 'error',
|
||||
title: 'Error',
|
||||
message: error.message || 'Terjadi kesalahan pada server. Coba lagi nanti.',
|
||||
});
|
||||
}
|
||||
|
||||
setConfirmLoading(false);
|
||||
};
|
||||
|
||||
const handleInputChange = (e) => {
|
||||
const { name, value } = e.target;
|
||||
setFormData({
|
||||
...formData,
|
||||
[name]: value,
|
||||
});
|
||||
};
|
||||
|
||||
const handleFieldChange = (name, value) => {
|
||||
setFormData({
|
||||
...formData,
|
||||
[name]: value,
|
||||
});
|
||||
};
|
||||
|
||||
const handleStatusToggle = (event) => {
|
||||
const isChecked = event;
|
||||
setFormData({
|
||||
...formData,
|
||||
is_active: isChecked ? true : false,
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (props.selectedData) {
|
||||
setFormData(props.selectedData);
|
||||
} else {
|
||||
setFormData(defaultData);
|
||||
}
|
||||
}, [props.showModal, props.selectedData, props.actionMode]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={`${
|
||||
props.actionMode === 'add'
|
||||
? 'Tambah'
|
||||
: props.actionMode === 'preview'
|
||||
? 'Preview'
|
||||
: 'Edit'
|
||||
} Sparepart`}
|
||||
open={props.showModal}
|
||||
onCancel={handleCancel}
|
||||
footer={[
|
||||
<React.Fragment key="modal-footer">
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
token: { colorBgContainer: '#E9F6EF' },
|
||||
components: {
|
||||
Button: {
|
||||
defaultBg: 'white',
|
||||
defaultColor: '#23A55A',
|
||||
defaultBorderColor: '#23A55A',
|
||||
defaultHoverColor: '#23A55A',
|
||||
defaultHoverBorderColor: '#23A55A',
|
||||
defaultHoverColor: '#23A55A',
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Button onClick={handleCancel}>Batal</Button>
|
||||
</ConfigProvider>
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
token: {
|
||||
colorBgContainer: '#209652',
|
||||
},
|
||||
components: {
|
||||
Button: {
|
||||
defaultBg: '#23a55a',
|
||||
defaultColor: '#FFFFFF',
|
||||
defaultBorderColor: '#23a55a',
|
||||
defaultHoverColor: '#FFFFFF',
|
||||
defaultHoverBorderColor: '#23a55a',
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{!props.readOnly && (
|
||||
<Button loading={confirmLoading} onClick={handleSave}>
|
||||
Simpan
|
||||
</Button>
|
||||
)}
|
||||
</ConfigProvider>
|
||||
</React.Fragment>,
|
||||
]}
|
||||
>
|
||||
{formData && (
|
||||
<div>
|
||||
<div hidden>
|
||||
<Text strong>Sparepart ID</Text>
|
||||
<Input
|
||||
name="sparepart_id"
|
||||
value={formData.sparepart_id}
|
||||
onChange={handleInputChange}
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Sparepart Name</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
<Input
|
||||
name="sparepart_name"
|
||||
value={formData.sparepart_name}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Sparepart Name"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Sparepart Description</Text>
|
||||
<TextArea
|
||||
name="sparepart_description"
|
||||
value={formData.sparepart_description}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Sparepart Description (Optional)"
|
||||
readOnly={props.readOnly}
|
||||
rows={4}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Sparepart Model</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
<Input
|
||||
name="sparepart_model"
|
||||
value={formData.sparepart_model}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Sparepart Model"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Sparepart Item Type</Text>
|
||||
<Input
|
||||
name="sparepart_item_type"
|
||||
value={formData.sparepart_item_type}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Sparepart Item Type"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Sparepart Unit</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
<Input
|
||||
name="sparepart_unit"
|
||||
value={formData.sparepart_unit}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Sparepart Unit"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Sparepart Merk</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
<Input
|
||||
name="sparepart_merk"
|
||||
value={formData.sparepart_merk}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Sparepart Merk"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Sparepart Stok</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
<Input
|
||||
name="sparepart_stok"
|
||||
value={formData.sparepart_stok}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Sparepart Stok"
|
||||
readOnly={props.readOnly}
|
||||
type="number"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default DetailSparepart;
|
||||
Reference in New Issue
Block a user