refactor: streamline brand device management components and add error master view

This commit is contained in:
2025-10-10 14:14:10 +07:00
parent 3ce9b3772d
commit bf03891142
4 changed files with 689 additions and 348 deletions

View File

@@ -1,18 +1,174 @@
import React from 'react';
import { Modal, Form, Input, ConfigProvider, Button, Typography } from 'antd';
import { useEffect, useState } from 'react';
import { Modal, Input, Typography, Button, ConfigProvider, Select } from 'antd';
import { NotifAlert, NotifOk } from '../../../../components/Global/ToastNotif';
const { Text } = Typography;
const DetailBrandDevice = ({ visible, onCancel, onOk, form, editingKey, readOnly }) => {
const modalTitle = readOnly ? 'Preview Brand' : (editingKey ? 'Edit Brand' : 'Tambah Brand');
const DetailBrandDevice = (props) => {
const [confirmLoading, setConfirmLoading] = useState(false);
const defaultData = {
brand_id: '',
brandName: '',
brandType: '',
manufacturer: '',
model: '',
status: 'Active',
};
const [FormData, setFormData] = useState(defaultData);
const handleCancel = () => {
props.setSelectedData(null);
props.setActionMode('list');
};
const handleSave = async () => {
setConfirmLoading(true);
// Validasi required fields
if (!FormData.brandName) {
NotifOk({
icon: 'warning',
title: 'Peringatan',
message: 'Kolom Brand Name Tidak Boleh Kosong',
});
setConfirmLoading(false);
return;
}
if (!FormData.brandType) {
NotifOk({
icon: 'warning',
title: 'Peringatan',
message: 'Kolom Type Tidak Boleh Kosong',
});
setConfirmLoading(false);
return;
}
if (!FormData.manufacturer) {
NotifOk({
icon: 'warning',
title: 'Peringatan',
message: 'Kolom Manufacturer Tidak Boleh Kosong',
});
setConfirmLoading(false);
return;
}
if (!FormData.model) {
NotifOk({
icon: 'warning',
title: 'Peringatan',
message: 'Kolom Model Tidak Boleh Kosong',
});
setConfirmLoading(false);
return;
}
if (!FormData.status) {
NotifOk({
icon: 'warning',
title: 'Peringatan',
message: 'Kolom Status Tidak Boleh Kosong',
});
setConfirmLoading(false);
return;
}
const payload = {
brandName: FormData.brandName,
brandType: FormData.brandType,
manufacturer: FormData.manufacturer,
model: FormData.model,
status: FormData.status,
};
try {
// Simulate API call
await new Promise((resolve) => setTimeout(resolve, 500));
const response = {
statusCode: FormData.brand_id ? 200 : 201,
data: {
brandName: FormData.brandName,
},
};
console.log('Save Brand Device Response:', response);
// Check if response is successful
if (response && (response.statusCode === 200 || response.statusCode === 201)) {
NotifOk({
icon: 'success',
title: 'Berhasil',
message: `Data Brand Device "${
response.data?.brandName || FormData.brandName
}" berhasil ${FormData.brand_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 Brand Device 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 handleSelectChange = (name, value) => {
setFormData({
...FormData,
[name]: value,
});
};
useEffect(() => {
const token = localStorage.getItem('token');
if (token) {
if (props.selectedData != null) {
setFormData(props.selectedData);
} else {
setFormData(defaultData);
}
} else {
// navigate('/signin'); // Uncomment if useNavigate is imported
}
}, [props.showModal]);
return (
<Modal
title={modalTitle}
visible={visible}
onCancel={onCancel}
title={`${
props.actionMode === 'add'
? 'Tambah'
: props.actionMode === 'preview'
? 'Preview'
: 'Edit'
} Brand Device`}
open={props.showModal}
onCancel={handleCancel}
footer={[
<React.Fragment key="modal-footer">
<>
<ConfigProvider
theme={{
token: { colorBgContainer: '#E9F6EF' },
@@ -27,7 +183,7 @@ const DetailBrandDevice = ({ visible, onCancel, onOk, form, editingKey, readOnly
},
}}
>
<Button onClick={onCancel}>Batal</Button>
<Button onClick={handleCancel}>Batal</Button>
</ConfigProvider>
<ConfigProvider
theme={{
@@ -45,73 +201,89 @@ const DetailBrandDevice = ({ visible, onCancel, onOk, form, editingKey, readOnly
},
}}
>
{!readOnly && (
<Button onClick={onOk}>
{!props.readOnly && (
<Button loading={confirmLoading} onClick={handleSave}>
Simpan
</Button>
)}
</ConfigProvider>
</React.Fragment>,
</>,
]}
destroyOnClose
>
<Form form={form} layout="vertical" name="form_in_modal">
<div style={{ marginBottom: 12 }}>
<Text strong>Kode Brand</Text>
<Text style={{ color: 'red' }}> *</Text>
<Form.Item
name="brandCode"
rules={[{ required: true, message: 'Please input the brand code!' }]}
style={{ marginBottom: 0 }}
>
<Input readOnly={readOnly} placeholder="Enter Brand Code" />
</Form.Item>
{FormData && (
<div>
<div hidden>
<Text strong>Brand ID</Text>
<Input
name="brand_id"
value={FormData.brand_id}
onChange={handleInputChange}
disabled
/>
</div>
<div style={{ marginBottom: 12 }}>
<Text strong>Brand Name</Text>
<Text style={{ color: 'red' }}> *</Text>
<Input
name="brandName"
value={FormData.brandName}
onChange={handleInputChange}
placeholder="Enter Brand Name"
readOnly={props.readOnly}
/>
</div>
<div style={{ marginBottom: 12 }}>
<Text strong>Type</Text>
<Text style={{ color: 'red' }}> *</Text>
<Input
name="brandType"
value={FormData.brandType}
onChange={handleInputChange}
placeholder="Enter Type (e.g., PLC)"
readOnly={props.readOnly}
/>
</div>
<div style={{ marginBottom: 12 }}>
<Text strong>Manufacturer</Text>
<Text style={{ color: 'red' }}> *</Text>
<Input
name="manufacturer"
value={FormData.manufacturer}
onChange={handleInputChange}
placeholder="Enter Manufacturer"
readOnly={props.readOnly}
/>
</div>
<div style={{ marginBottom: 12 }}>
<Text strong>Model</Text>
<Text style={{ color: 'red' }}> *</Text>
<Input
name="model"
value={FormData.model}
onChange={handleInputChange}
placeholder="Enter Model"
readOnly={props.readOnly}
/>
</div>
<div style={{ marginBottom: 12 }}>
<Text strong>Status</Text>
<Text style={{ color: 'red' }}> *</Text>
<Select
value={FormData.status}
onChange={(value) => handleSelectChange('status', value)}
disabled={props.readOnly}
style={{ width: '100%' }}
placeholder="Select Status"
options={[
{ value: 'Active', label: 'Active' },
{ value: 'Inactive', label: 'Inactive' },
]}
/>
</div>
</div>
<div style={{ marginBottom: 12 }}>
<Text strong>Brand Name</Text>
<Text style={{ color: 'red' }}> *</Text>
<Form.Item
name="brandName"
rules={[{ required: true, message: 'Please input the brand name!' }]}
style={{ marginBottom: 0 }}
>
<Input readOnly={readOnly} placeholder="Enter Brand Name" />
</Form.Item>
</div>
<div style={{ marginBottom: 12 }}>
<Text strong>Brand Type</Text>
<Text style={{ color: 'red' }}> *</Text>
<Form.Item
name="brandType"
rules={[{ required: true, message: 'Please input the brand type!' }]}
style={{ marginBottom: 0 }}
>
<Input readOnly={readOnly} placeholder="Enter Brand Type" />
</Form.Item>
</div>
<div style={{ marginBottom: 12 }}>
<Text strong>Device Name</Text>
<Text style={{ color: 'red' }}> *</Text>
<Form.Item
name="deviceName"
rules={[{ required: true, message: 'Please input the device name!' }]}
style={{ marginBottom: 0 }}
>
<Input readOnly={readOnly} placeholder="Enter Device Name" />
</Form.Item>
</div>
<div style={{ marginBottom: 12 }}>
<Text strong>Description</Text>
<Form.Item
name="description"
style={{ marginBottom: 0 }}
>
<Input.TextArea readOnly={readOnly} placeholder="Enter Description (Optional)" rows={4} />
</Form.Item>
</div>
</Form>
)}
</Modal>
);
};
export default DetailBrandDevice;
export default DetailBrandDevice;