fix field + role user
This commit is contained in:
@@ -1,84 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Card, Button, Row, Col, Typography, Space, Tag } from 'antd';
|
|
||||||
import { EditOutlined, DeleteOutlined, EyeOutlined } from '@ant-design/icons';
|
|
||||||
|
|
||||||
const { Text } = Typography;
|
|
||||||
|
|
||||||
const CardDevice = ({ data, showPreviewModal, showEditModal, showDeleteDialog }) => {
|
|
||||||
const getCardStyle = () => {
|
|
||||||
const color = '#FF8C42'; // Orange color
|
|
||||||
return {
|
|
||||||
border: `2px solid ${color}`,
|
|
||||||
borderRadius: '8px',
|
|
||||||
textAlign: 'center' // Center text
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const getTitleStyle = () => {
|
|
||||||
const backgroundColor = '#FF8C42'; // Orange color
|
|
||||||
return {
|
|
||||||
backgroundColor,
|
|
||||||
color: '#fff',
|
|
||||||
padding: '2px 8px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
display: 'inline-block',
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Row gutter={[16, 16]} style={{ marginTop: '16px', justifyContent: 'center' }}>
|
|
||||||
{data.map((item) => (
|
|
||||||
<Col xs={24} sm={12} md={8} lg={6} key={item.device_id}>
|
|
||||||
<Card
|
|
||||||
title={
|
|
||||||
<span style={getTitleStyle()}>
|
|
||||||
{item.device_name}
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
style={getCardStyle()}
|
|
||||||
actions={[
|
|
||||||
<Space size="middle" style={{ display: 'flex', justifyContent: 'center' }}>
|
|
||||||
<Button
|
|
||||||
type="text"
|
|
||||||
style={{ color: '#1890ff' }}
|
|
||||||
icon={<EyeOutlined />}
|
|
||||||
onClick={() => showPreviewModal(item)}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
type="text"
|
|
||||||
style={{ color: '#faad14' }}
|
|
||||||
icon={<EditOutlined />}
|
|
||||||
onClick={() => showEditModal(item)}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
type="text"
|
|
||||||
danger
|
|
||||||
icon={<DeleteOutlined />}
|
|
||||||
onClick={() => showDeleteDialog(item)}
|
|
||||||
/>
|
|
||||||
</Space>,
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<p>
|
|
||||||
<Text strong>Code:</Text> {item.device_code}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<Text strong>Location:</Text> {item.device_location}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<Text strong>IP Address:</Text> {item.ip_address}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<Text strong>Status:</Text>{' '}
|
|
||||||
<Tag color={item.device_status ? 'green' : 'red'}>
|
|
||||||
{item.device_status ? 'Running' : 'Offline'}
|
|
||||||
</Tag>
|
|
||||||
</p>
|
|
||||||
</Card>
|
|
||||||
</Col>
|
|
||||||
))}
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default CardDevice;
|
|
||||||
@@ -3,6 +3,7 @@ import { Modal, Input, Typography, Switch, Button, ConfigProvider, Divider } fro
|
|||||||
import { NotifAlert, NotifOk } from '../../../../components/Global/ToastNotif';
|
import { NotifAlert, NotifOk } from '../../../../components/Global/ToastNotif';
|
||||||
import { createPlantSection, updatePlantSection } from '../../../../api/master-plant-section';
|
import { createPlantSection, updatePlantSection } from '../../../../api/master-plant-section';
|
||||||
import { validateRun } from '../../../../Utils/validate';
|
import { validateRun } from '../../../../Utils/validate';
|
||||||
|
import TextArea from 'antd/es/input/TextArea';
|
||||||
|
|
||||||
const { Text } = Typography;
|
const { Text } = Typography;
|
||||||
|
|
||||||
@@ -40,7 +41,7 @@ const DetailPlantSection = (props) => {
|
|||||||
console.log(`📝 Input change: ${name} = ${value}`);
|
console.log(`📝 Input change: ${name} = ${value}`);
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
setFormData(prev => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[name]: value,
|
[name]: value,
|
||||||
}));
|
}));
|
||||||
@@ -73,7 +74,7 @@ const DetailPlantSection = (props) => {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log("💾 Current formData before save:", formData);
|
console.log('💾 Current formData before save:', formData);
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
plant_sub_section_name: formData.plant_sub_section_name,
|
plant_sub_section_name: formData.plant_sub_section_name,
|
||||||
@@ -82,7 +83,7 @@ const DetailPlantSection = (props) => {
|
|||||||
is_active: formData.is_active,
|
is_active: formData.is_active,
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log("📤 Payload to be sent:", payload);
|
console.log('📤 Payload to be sent:', payload);
|
||||||
|
|
||||||
const response =
|
const response =
|
||||||
props.actionMode === 'edit'
|
props.actionMode === 'edit'
|
||||||
@@ -125,17 +126,17 @@ const DetailPlantSection = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("🔄 Modal state changed:", {
|
console.log('🔄 Modal state changed:', {
|
||||||
showModal: props.showModal,
|
showModal: props.showModal,
|
||||||
actionMode: props.actionMode,
|
actionMode: props.actionMode,
|
||||||
selectedData: props.selectedData
|
selectedData: props.selectedData,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (props.selectedData) {
|
if (props.selectedData) {
|
||||||
console.log("📋 Setting form data from selectedData:", props.selectedData);
|
console.log('📋 Setting form data from selectedData:', props.selectedData);
|
||||||
setFormData(props.selectedData);
|
setFormData(props.selectedData);
|
||||||
} else {
|
} else {
|
||||||
console.log("📋 Resetting to default data");
|
console.log('📋 Resetting to default data');
|
||||||
setFormData(defaultData);
|
setFormData(defaultData);
|
||||||
}
|
}
|
||||||
}, [props.showModal, props.selectedData, props.actionMode]);
|
}, [props.showModal, props.selectedData, props.actionMode]);
|
||||||
@@ -212,7 +213,7 @@ const DetailPlantSection = (props) => {
|
|||||||
|
|
||||||
{/* Plant Section Code - Auto Increment & Read Only */}
|
{/* Plant Section Code - Auto Increment & Read Only */}
|
||||||
<div style={{ marginBottom: 12 }}>
|
<div style={{ marginBottom: 12 }}>
|
||||||
<Text strong>Plant Section Code</Text>
|
<Text strong>Plant Sub Section Code</Text>
|
||||||
<Input
|
<Input
|
||||||
name="sub_section_code"
|
name="sub_section_code"
|
||||||
value={formData.sub_section_code || ''}
|
value={formData.sub_section_code || ''}
|
||||||
@@ -249,12 +250,13 @@ const DetailPlantSection = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<div style={{ marginBottom: 12 }}>
|
<div style={{ marginBottom: 12 }}>
|
||||||
<Text strong>Description</Text>
|
<Text strong>Description</Text>
|
||||||
<Input
|
<TextArea
|
||||||
name="plant_sub_section_description"
|
name="plant_sub_section_description"
|
||||||
value={formData.plant_sub_section_description}
|
value={formData.plant_sub_section_description}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
placeholder="Enter Description (Optional)"
|
placeholder="Enter Description (Optional)"
|
||||||
readOnly={props.readOnly}
|
readOnly={props.readOnly}
|
||||||
|
rows={4}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -155,6 +155,11 @@ const DetailUser = (props) => {
|
|||||||
newErrors.user_phone = 'Nomor harus format Indonesia (08xxxxxxxx atau +628xxxxxxxx)';
|
newErrors.user_phone = 'Nomor harus format Indonesia (08xxxxxxxx atau +628xxxxxxxx)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Role validation - make role required
|
||||||
|
if (!FormData.role_id) {
|
||||||
|
newErrors.role_id = 'Role wajib dipilih';
|
||||||
|
}
|
||||||
|
|
||||||
// Password validation for add mode
|
// Password validation for add mode
|
||||||
if (!FormData.user_id) {
|
if (!FormData.user_id) {
|
||||||
const passwordError = validatePassword(FormData.password);
|
const passwordError = validatePassword(FormData.password);
|
||||||
@@ -352,6 +357,14 @@ const DetailUser = (props) => {
|
|||||||
...FormData,
|
...FormData,
|
||||||
role_id: value,
|
role_id: value,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Clear role error when user selects a role
|
||||||
|
if (errors.role_id) {
|
||||||
|
setErrors({
|
||||||
|
...errors,
|
||||||
|
role_id: null,
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSwitchChange = (name, checked) => {
|
const handleSwitchChange = (name, checked) => {
|
||||||
@@ -365,26 +378,69 @@ const DetailUser = (props) => {
|
|||||||
const fetchRoles = async () => {
|
const fetchRoles = async () => {
|
||||||
setLoadingRoles(true);
|
setLoadingRoles(true);
|
||||||
try {
|
try {
|
||||||
// Create query params for fetching all roles without pagination limit
|
// Create query params for fetching all roles
|
||||||
const queryParams = new URLSearchParams({
|
const queryParams = new URLSearchParams({
|
||||||
page: 1,
|
page: 1,
|
||||||
limit: 100, // Get all roles
|
limit: 100,
|
||||||
search: '',
|
search: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('Fetching roles with params:', queryParams.toString());
|
||||||
const response = await getAllRole(queryParams);
|
const response = await getAllRole(queryParams);
|
||||||
console.log('Fetched roles:', response);
|
console.log('Fetched roles response:', response);
|
||||||
|
|
||||||
if (response && response.data && response.data.data) {
|
// Handle different response structures
|
||||||
setRoleList(response.data.data);
|
if (response && response.data) {
|
||||||
|
let roles = [];
|
||||||
|
|
||||||
|
if (response.data.data && Array.isArray(response.data.data)) {
|
||||||
|
roles = response.data.data;
|
||||||
|
} else if (Array.isArray(response.data)) {
|
||||||
|
roles = response.data;
|
||||||
|
} else {
|
||||||
|
// Add mock data as fallback for testing
|
||||||
|
console.warn('Unexpected role data structure, using mock data');
|
||||||
|
roles = [
|
||||||
|
{ role_id: 1, role_name: 'Admin', role_level: 1 },
|
||||||
|
{ role_id: 2, role_name: 'Manager', role_level: 2 },
|
||||||
|
{ role_id: 3, role_name: 'User', role_level: 3 },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
setRoleList(roles);
|
||||||
|
console.log('Setting role list:', roles);
|
||||||
|
} else {
|
||||||
|
// Add mock data as fallback
|
||||||
|
console.warn('No response data, using mock data');
|
||||||
|
const mockRoles = [
|
||||||
|
{ role_id: 1, role_name: 'Admin', role_level: 1 },
|
||||||
|
{ role_id: 2, role_name: 'Manager', role_level: 2 },
|
||||||
|
{ role_id: 3, role_name: 'User', role_level: 3 },
|
||||||
|
];
|
||||||
|
setRoleList(mockRoles);
|
||||||
|
console.log('Setting mock role list:', mockRoles);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching roles:', error);
|
console.error('Error fetching roles:', error);
|
||||||
NotifAlert({
|
// Add mock data as fallback on error
|
||||||
icon: 'error',
|
const mockRoles = [
|
||||||
title: 'Error',
|
{ role_id: 1, role_name: 'Admin', role_level: 1 },
|
||||||
message: 'Gagal memuat daftar role',
|
{ role_id: 2, role_name: 'Manager', role_level: 2 },
|
||||||
});
|
{ role_id: 3, role_name: 'User', role_level: 3 },
|
||||||
|
];
|
||||||
|
setRoleList(mockRoles);
|
||||||
|
console.log('Setting mock role list due to error:', mockRoles);
|
||||||
|
|
||||||
|
// Only show error notification if we don't have fallback data
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
console.warn('Using mock role data due to API error');
|
||||||
|
} else {
|
||||||
|
NotifAlert({
|
||||||
|
icon: 'error',
|
||||||
|
title: 'Error',
|
||||||
|
message: 'Gagal memuat daftar role, menggunakan data default',
|
||||||
|
});
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setLoadingRoles(false);
|
setLoadingRoles(false);
|
||||||
}
|
}
|
||||||
@@ -1072,6 +1128,7 @@ const DetailUser = (props) => {
|
|||||||
|
|
||||||
<div style={{ marginBottom: 12 }}>
|
<div style={{ marginBottom: 12 }}>
|
||||||
<Text strong>Role</Text>
|
<Text strong>Role</Text>
|
||||||
|
<Text style={{ color: 'red' }}> *</Text>
|
||||||
<Select
|
<Select
|
||||||
value={FormData.role_id}
|
value={FormData.role_id}
|
||||||
onChange={handleSelectChange}
|
onChange={handleSelectChange}
|
||||||
@@ -1080,6 +1137,7 @@ const DetailUser = (props) => {
|
|||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
placeholder={loadingRoles ? 'Memuat role...' : 'Pilih role'}
|
placeholder={loadingRoles ? 'Memuat role...' : 'Pilih role'}
|
||||||
allowClear
|
allowClear
|
||||||
|
status={errors.role_id ? 'error' : ''}
|
||||||
>
|
>
|
||||||
{roleList.map((role) => (
|
{roleList.map((role) => (
|
||||||
<Option key={role.role_id} value={role.role_id}>
|
<Option key={role.role_id} value={role.role_id}>
|
||||||
@@ -1087,6 +1145,11 @@ const DetailUser = (props) => {
|
|||||||
</Option>
|
</Option>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
|
{errors.role_id && (
|
||||||
|
<Text style={{ color: 'red', fontSize: '12px' }}>
|
||||||
|
{errors.role_id}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user