feat: enhance DetailTag and ListTag components with improved device handling and search functionality
This commit is contained in:
@@ -188,6 +188,7 @@ const DetailTag = (props) => {
|
||||
const params = new URLSearchParams({ limit: 1000 });
|
||||
const response = await getAllDevice(params);
|
||||
if (response && response.data && response.data.data) {
|
||||
console.log('Loaded devices:', response.data.data); // Debug
|
||||
setDeviceList(response.data.data);
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -305,82 +306,7 @@ const DetailTag = (props) => {
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Tag Name</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
<Input
|
||||
name="tag_name"
|
||||
value={FormData.tag_name}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Tag Name"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Tag Number</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
<Input
|
||||
name="tag_number"
|
||||
value={FormData.tag_number}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Tag Number"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Data Type</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
<Input
|
||||
name="data_type"
|
||||
value={FormData.data_type}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Data Type"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Unit</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
<Input
|
||||
name="unit"
|
||||
value={FormData.unit}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Unit"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Device Code</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
<Select
|
||||
style={{ width: '100%' }}
|
||||
placeholder="Select Device Code"
|
||||
value={FormData.device_id || undefined}
|
||||
onChange={handleDeviceChange}
|
||||
disabled={props.readOnly}
|
||||
loading={loadingDevices}
|
||||
showSearch
|
||||
filterOption={(input, option) =>
|
||||
(option?.label ?? '').toLowerCase().includes(input.toLowerCase())
|
||||
}
|
||||
options={deviceList.map((device) => ({
|
||||
value: device.device_id,
|
||||
label: device.device_code || '',
|
||||
}))}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Device Name</Text>
|
||||
<Input
|
||||
name="device_name"
|
||||
value={FormData.device_name}
|
||||
placeholder="Auto-filled from selected device code"
|
||||
disabled
|
||||
style={{ backgroundColor: '#f5f5f5' }}
|
||||
/>
|
||||
</div>
|
||||
{/* Device ID hidden - value dari dropdown */}
|
||||
<input type="hidden" name="device_id" value={FormData.device_id || ''} />
|
||||
{/* Status dipindah ke atas Tag Name */}
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<div>
|
||||
<Text strong>Status</Text>
|
||||
@@ -408,6 +334,91 @@ const DetailTag = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Tag Name</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
<Input
|
||||
name="tag_name"
|
||||
value={FormData.tag_name}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Tag Name"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Tag Number</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
<Input
|
||||
name="tag_number"
|
||||
value={FormData.tag_number}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Tag Number"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Data Type</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
<Select
|
||||
style={{ width: '100%' }}
|
||||
placeholder="Select Data Type"
|
||||
value={FormData.data_type || undefined}
|
||||
onChange={(value) => handleSelectChange('data_type', value)}
|
||||
disabled={props.readOnly}
|
||||
>
|
||||
<Select.Option value="Diskrit">Diskrit</Select.Option>
|
||||
<Select.Option value="Analog">Analog</Select.Option>
|
||||
</Select>
|
||||
</div>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Unit</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
<Input
|
||||
name="unit"
|
||||
value={FormData.unit}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Unit"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Device Code</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
<Select
|
||||
style={{ width: '100%' }}
|
||||
placeholder="Search device by code, name, or type..."
|
||||
value={FormData.device_id || undefined}
|
||||
onChange={handleDeviceChange}
|
||||
disabled={props.readOnly}
|
||||
loading={loadingDevices}
|
||||
showSearch
|
||||
allowClear
|
||||
optionFilterProp="children"
|
||||
filterOption={(input, option) => {
|
||||
const text = option.children;
|
||||
if (!text) return false;
|
||||
return text.toLowerCase().includes(input.toLowerCase());
|
||||
}}
|
||||
>
|
||||
{deviceList.map((device) => (
|
||||
<Select.Option key={device.device_id} value={device.device_id}>
|
||||
{device.device_code || ''}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Text strong>Device Name</Text>
|
||||
<Input
|
||||
name="device_name"
|
||||
value={FormData.device_name}
|
||||
placeholder="Auto-filled from selected device code"
|
||||
disabled
|
||||
style={{ backgroundColor: '#f5f5f5' }}
|
||||
/>
|
||||
</div>
|
||||
{/* Device ID hidden - value dari dropdown */}
|
||||
<input type="hidden" name="device_id" value={FormData.device_id || ''} />
|
||||
</div>
|
||||
)}
|
||||
</Modal>
|
||||
|
||||
@@ -115,7 +115,15 @@ const columns = (showPreviewModal, showEditModal, showDeleteDialog) => [
|
||||
const ListTag = memo(function ListTag(props) {
|
||||
const [trigerFilter, setTrigerFilter] = useState(false);
|
||||
|
||||
const defaultFilter = { search: '' };
|
||||
const defaultFilter = {
|
||||
criteria: '', // Global search (OR condition)
|
||||
name: '',
|
||||
code: '',
|
||||
data: '',
|
||||
unit: '',
|
||||
device: '',
|
||||
subsection: '',
|
||||
};
|
||||
const [formDataFilter, setFormDataFilter] = useState(defaultFilter);
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
|
||||
@@ -132,18 +140,19 @@ const ListTag = memo(function ListTag(props) {
|
||||
}
|
||||
}, [props.actionMode]);
|
||||
|
||||
useEffect(() => {
|
||||
// Memicu filter setiap kali formDataFilter berubah
|
||||
doFilter();
|
||||
}, [formDataFilter]);
|
||||
|
||||
const doFilter = () => {
|
||||
setTrigerFilter((prev) => !prev);
|
||||
};
|
||||
|
||||
const handleSearch = (value) => {
|
||||
setSearchValue(value);
|
||||
setFormDataFilter({ search: value });
|
||||
const handleSearch = () => {
|
||||
setFormDataFilter((prev) => ({ ...prev, criteria: searchValue }));
|
||||
doFilter();
|
||||
};
|
||||
|
||||
const handleSearchClear = () => {
|
||||
setSearchValue('');
|
||||
setFormDataFilter((prev) => ({ ...prev, criteria: '' }));
|
||||
doFilter();
|
||||
};
|
||||
const showPreviewModal = (param) => {
|
||||
props.setSelectedData(param);
|
||||
@@ -210,11 +219,16 @@ const ListTag = memo(function ListTag(props) {
|
||||
placeholder="Search tag by code, name, or type..."
|
||||
value={searchValue}
|
||||
onChange={(e) => {
|
||||
const { value } = e.target;
|
||||
const value = e.target.value;
|
||||
setSearchValue(value);
|
||||
// Auto search when clearing by backspace/delete
|
||||
if (value === '') {
|
||||
handleSearchClear();
|
||||
}
|
||||
}}
|
||||
onSearch={handleSearch}
|
||||
allowClear
|
||||
onClear={handleSearchClear}
|
||||
enterButton={
|
||||
<Button
|
||||
type="primary"
|
||||
|
||||
Reference in New Issue
Block a user