feat: integrate sparepart management into AddBrandDevice and EditBrandDevice components
This commit is contained in:
152
src/pages/master/brandDevice/component/SparepartField.jsx
Normal file
152
src/pages/master/brandDevice/component/SparepartField.jsx
Normal file
@@ -0,0 +1,152 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Form, Select, Button, Switch, Typography, Space, Input, message } from 'antd';
|
||||
import { DeleteOutlined } from '@ant-design/icons';
|
||||
import { getAllSparepart } from '../../../../api/sparepart';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
const SparepartField = ({
|
||||
fieldKey,
|
||||
fieldName,
|
||||
index,
|
||||
sparepartType,
|
||||
sparepartStatus,
|
||||
isReadOnly = false,
|
||||
canRemove = true,
|
||||
onRemove,
|
||||
spareparts = [],
|
||||
onSparepartChange
|
||||
}) => {
|
||||
const [currentStatus, setCurrentStatus] = useState(sparepartStatus ?? true);
|
||||
const [sparepartList, setSparepartList] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setCurrentStatus(sparepartStatus ?? true);
|
||||
loadSpareparts();
|
||||
}, [sparepartStatus]);
|
||||
|
||||
const loadSpareparts = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
// Get all spareparts from the API
|
||||
const params = new URLSearchParams();
|
||||
params.set('limit', '100'); // Get all spareparts
|
||||
|
||||
const response = await getAllSparepart(params);
|
||||
// Response structure should have { data: [...], statusCode: 200 }
|
||||
if (response && (response.statusCode === 200 || response.data)) {
|
||||
// If response has data array directly
|
||||
const sparepartData = response.data?.data || response.data || [];
|
||||
setSparepartList(sparepartData);
|
||||
if (onSparepartChange) {
|
||||
onSparepartChange(sparepartData);
|
||||
}
|
||||
} else {
|
||||
// For demo purposes, use mock data if API fails
|
||||
setSparepartList([
|
||||
{ brand_sparepart_id: 1, sparepart_name: 'Compressor Oil Filter', brand_sparepart_description: 'Oil filter for compressor' },
|
||||
{ brand_sparepart_id: 2, sparepart_name: 'Air Intake Filter', brand_sparepart_description: 'Air intake filter' },
|
||||
{ brand_sparepart_id: 3, sparepart_name: 'Cooling Fan Motor', brand_sparepart_description: 'Motor for cooling fan' },
|
||||
]);
|
||||
if (onSparepartChange) {
|
||||
onSparepartChange([
|
||||
{ brand_sparepart_id: 1, sparepart_name: 'Compressor Oil Filter', brand_sparepart_description: 'Oil filter for compressor' },
|
||||
{ brand_sparepart_id: 2, sparepart_name: 'Air Intake Filter', brand_sparepart_description: 'Air intake filter' },
|
||||
{ brand_sparepart_id: 3, sparepart_name: 'Cooling Fan Motor', brand_sparepart_description: 'Motor for cooling fan' },
|
||||
]);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading spareparts:', error);
|
||||
// Default mock data
|
||||
const mockSpareparts = [
|
||||
{ brand_sparepart_id: 1, sparepart_name: 'Compressor Oil Filter', brand_sparepart_description: 'Oil filter for compressor' },
|
||||
{ brand_sparepart_id: 2, sparepart_name: 'Air Intake Filter', brand_sparepart_description: 'Air intake filter' },
|
||||
{ brand_sparepart_id: 3, sparepart_name: 'Cooling Fan Motor', brand_sparepart_description: 'Motor for cooling fan' },
|
||||
];
|
||||
setSparepartList(mockSpareparts);
|
||||
if (onSparepartChange) {
|
||||
onSparepartChange(mockSpareparts);
|
||||
}
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const sparepartOptions = sparepartList.map(sparepart => ({
|
||||
label: sparepart.sparepart_name || sparepart.sparepart_name || `Sparepart ${sparepart.sparepart_id || sparepart.brand_sparepart_id}`,
|
||||
value: sparepart.sparepart_id || sparepart.brand_sparepart_id,
|
||||
description: sparepart.sparepart_description
|
||||
}));
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
border: '1px solid #d9d9d9',
|
||||
borderRadius: 8,
|
||||
padding: 16,
|
||||
marginBottom: 16,
|
||||
backgroundColor: isReadOnly ? '#f5f5f5' : 'white'
|
||||
}}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
|
||||
<Text strong>Sparepart #{index + 1}</Text>
|
||||
<Space>
|
||||
<Form.Item
|
||||
name={[fieldName, 'sparepart_id']}
|
||||
rules={[{ required: false, message: 'Sparepart wajib dipilih!' }]} /* Making it optional since sparepart is optional */
|
||||
style={{ margin: 0, width: 200 }}
|
||||
>
|
||||
<Select
|
||||
placeholder="Pilih sparepart"
|
||||
loading={loading}
|
||||
disabled={isReadOnly}
|
||||
options={sparepartOptions}
|
||||
showSearch
|
||||
optionFilterProp="label"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
|
||||
<Form.Item name={[fieldName, 'status']} valuePropName="checked" noStyle>
|
||||
<Switch
|
||||
disabled={isReadOnly}
|
||||
onChange={(checked) => {
|
||||
setCurrentStatus(checked);
|
||||
}}
|
||||
style={{
|
||||
backgroundColor: currentStatus ? '#23A55A' : '#bfbfbf'
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Text style={{ fontSize: 12, color: '#666' }}>
|
||||
{currentStatus ? 'Active' : 'Inactive'}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
{canRemove && !isReadOnly && (
|
||||
<Button
|
||||
type="text"
|
||||
danger
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={onRemove}
|
||||
/>
|
||||
)}
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
{/* Sparepart Description */}
|
||||
<Form.Item
|
||||
name={[fieldName, 'description']}
|
||||
label="Deskripsi"
|
||||
>
|
||||
<Input.TextArea
|
||||
placeholder="Deskripsi sparepart"
|
||||
rows={2}
|
||||
disabled={isReadOnly}
|
||||
/>
|
||||
</Form.Item>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SparepartField;
|
||||
Reference in New Issue
Block a user