feat: enhance error code management with table display and action buttons

This commit is contained in:
2025-11-24 13:05:33 +07:00
parent 899695f548
commit 908788f41d
3 changed files with 239 additions and 128 deletions

View File

@@ -1,6 +1,19 @@
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Divider, Typography, Button, Steps, Form, Row, Col, Card, ConfigProvider } from 'antd';
import {
Divider,
Typography,
Button,
Steps,
Form,
Row,
Col,
Card,
ConfigProvider,
Table,
Tag,
Space,
} from 'antd';
import { NotifAlert, NotifOk } from '../../../components/Global/ToastNotif';
import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb';
import { createBrand } from '../../../api/master-brand';
@@ -11,6 +24,7 @@ import FormActions from './component/FormActions';
import SolutionForm from './component/SolutionForm';
import { useSolutionLogic } from './hooks/solution';
import { uploadFile, getFolderFromFileType } from '../../../api/file-uploads';
import { EditOutlined, DeleteOutlined, EyeOutlined } from '@ant-design/icons';
const { Title } = Typography;
const { Step } = Steps;
@@ -39,7 +53,6 @@ const AddBrandDevice = () => {
const [formData, setFormData] = useState(defaultData);
const [errorCodes, setErrorCodes] = useState([]);
const [errorCodeIcon, setErrorCodeIcon] = useState(null);
const [showErrorCodeModal, setShowErrorCodeModal] = useState(false);
const {
solutionFields,
@@ -57,7 +70,6 @@ const AddBrandDevice = () => {
setSolutionsForExistingRecord,
} = useSolutionLogic(solutionForm);
useEffect(() => {
setBreadcrumbItems([
{ title: <span style={{ fontSize: '14px', fontWeight: 'bold' }}> Master</span> },
@@ -427,7 +439,7 @@ const AddBrandDevice = () => {
<>
<Row gutter={16} style={{ marginBottom: 24 }}>
{/* Error Code Form Column */}
<Col span={12}>
<Col span={6}>
<Card size="small" title="Error Code">
<Form
form={errorCodeForm}
@@ -449,7 +461,7 @@ const AddBrandDevice = () => {
</Col>
{/* Solution Form Column */}
<Col span={12}>
<Col span={8}>
<Card size="small" title="Solutions">
<Form
form={solutionForm}
@@ -479,49 +491,106 @@ const AddBrandDevice = () => {
</Form>
</Card>
</Col>
</Row>
{/* Error Codes List Button */}
<Row justify="center">
<Col>
<ConfigProvider
theme={{
token: { colorBgContainer: '#23a55ade' },
components: {
Button: {
defaultBg: '#23a55a',
defaultColor: '#FFFFFF',
defaultBorderColor: '#23a55a',
defaultHoverBg: '#209652',
defaultHoverColor: '#FFFFFF',
defaultHoverBorderColor: '#23a55a',
{/* Error Codes Table Column */}
<Col span={10}>
<Card size="small" title={`Error Codes (${errorCodes.length})`}>
<Table
dataSource={errorCodes}
columns={[
{
title: 'Error Code',
dataIndex: 'error_code',
key: 'error_code',
width: '25%',
},
},
}}
{
title: 'Sol',
key: 'Sol',
width: '10%',
align: 'center',
render: (_, record) => {
const solutionCount = record.solution
? record.solution.length
: 0;
return (
<Tag
color={solutionCount > 0 ? 'green' : 'red'}
>
{solutionCount} Sol
</Tag>
);
},
},
{
title: 'Status',
dataIndex: 'status',
key: 'status',
width: '20%',
align: 'center',
render: (_, { status }) => (
<Tag color={status ? 'green' : 'red'}>
{status ? 'Active' : 'Inactive'}
</Tag>
),
},
{
title: 'Action',
key: 'action',
align: 'center',
width: '15%',
render: (_, record) => (
<Space>
<Button
type="primary"
size="large"
onClick={() => setShowErrorCodeModal(true)}
style={{ minWidth: '200px' }}
>
View All Error Codes ({errorCodes.length})
</Button>
</ConfigProvider>
type="text"
style={{ borderColor: '#1890ff' }}
size="small"
icon={
<EyeOutlined
style={{ color: '#1890ff' }}
/>
}
onClick={() =>
handlePreviewErrorCode(record)
}
/>
<Button
type="text"
style={{ borderColor: '#faad14' }}
size="small"
icon={
<EditOutlined
style={{ color: '#faad14' }}
/>
}
onClick={() => handleEditErrorCode(record)}
/>
<Button
type="text"
danger
style={{ borderColor: 'red' }}
size="small"
icon={<DeleteOutlined />}
onClick={() =>
handleDeleteErrorCode(record.key)
}
/>
</Space>
),
},
]}
rowKey="key"
pagination={{
pageSize: 10,
showSizeChanger: false,
hideOnSinglePage: true,
}}
size="small"
scroll={{ y: 300 }}
/>
</Card>
</Col>
</Row>
{/* Error Codes List Modal */}
<ErrorCodeListModal
visible={showErrorCodeModal}
onClose={() => setShowErrorCodeModal(false)}
errorCodes={errorCodes}
loading={loading}
onPreview={handlePreviewErrorCode}
onEdit={handleEditErrorCode}
onDelete={handleDeleteErrorCode}
onAddNew={handleCreateNewErrorCode}
/>
</>
);
}

View File

@@ -12,6 +12,9 @@ import {
Spin,
Modal,
ConfigProvider,
Table,
Tag,
Space,
} from 'antd';
import { NotifAlert, NotifOk } from '../../../components/Global/ToastNotif';
import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb';
@@ -24,6 +27,7 @@ import ErrorCodeListModal from './component/ErrorCodeListModal';
import FormActions from './component/FormActions';
import { useErrorCodeLogic } from './hooks/errorCode';
import { useSolutionLogic } from './hooks/solution';
import { EditOutlined, DeleteOutlined, EyeOutlined } from '@ant-design/icons';
const { Title } = Typography;
const { Step } = Steps;
@@ -53,7 +57,6 @@ const EditBrandDevice = () => {
const [formData, setFormData] = useState(defaultData);
const [errorCodes, setErrorCodes] = useState([]);
const [errorCodeIcon, setErrorCodeIcon] = useState(null);
const [showErrorCodeModal, setShowErrorCodeModal] = useState(false);
const [solutionForm] = Form.useForm();
const { errorCodeFields, addErrorCode, removeErrorCode, editErrorCode } = useErrorCodeLogic(
@@ -493,7 +496,7 @@ const EditBrandDevice = () => {
return (
<>
<Row gutter={24}>
<Col span={12}>
<Col span={6}>
<Card
title={
<Title level={5} style={{ margin: 0 }}>
@@ -503,7 +506,7 @@ const EditBrandDevice = () => {
: 'Error Code Form'
: editingErrorCodeKey
? 'Edit Error Code'
: 'Tambah Error Code'}
: 'Error Code'}
</Title>
}
size="small"
@@ -526,7 +529,7 @@ const EditBrandDevice = () => {
</Form>
</Card>
</Col>
<Col span={12}>
<Col span={8}>
<Card
title={
<Title level={5} style={{ margin: 0 }}>
@@ -559,49 +562,104 @@ const EditBrandDevice = () => {
</Form>
</Card>
</Col>
</Row>
{/* Error Codes List Button */}
<Row justify="center">
<Col>
<ConfigProvider
theme={{
token: { colorBgContainer: '#23a55ade' },
components: {
Button: {
defaultBg: '#23a55a',
defaultColor: '#FFFFFF',
defaultBorderColor: '#23a55a',
defaultHoverBg: '#209652',
defaultHoverColor: '#FFFFFF',
defaultHoverBorderColor: '#23a55a',
<Col span={10}>
<Card size="small" title={`Error Codes (${errorCodes.length})`}>
<Table
dataSource={errorCodes}
columns={[
{
title: 'Error Code',
dataIndex: 'error_code',
key: 'error_code',
width: '25%',
},
},
}}
{
title: 'Sol',
key: 'Sol',
width: '10%',
align: 'center',
render: (_, record) => {
const solutionCount = record.solution
? record.solution.length
: 0;
return (
<Tag
color={solutionCount > 0 ? 'green' : 'red'}
>
{solutionCount} Sol
</Tag>
);
},
},
{
title: 'Status',
dataIndex: 'status',
key: 'status',
width: '20%',
align: 'center',
render: (_, { status }) => (
<Tag color={status ? 'green' : 'red'}>
{status ? 'Active' : 'Inactive'}
</Tag>
),
},
{
title: 'Action',
key: 'action',
align: 'center',
width: '15%',
render: (_, record) => (
<Space>
<Button
type="primary"
size="large"
onClick={() => setShowErrorCodeModal(true)}
style={{ minWidth: '200px' }}
>
View All Error Codes ({errorCodes.length})
</Button>
</ConfigProvider>
type="text"
style={{ borderColor: '#1890ff' }}
size="small"
icon={
<EyeOutlined
style={{ color: '#1890ff' }}
/>
}
onClick={() =>
handlePreviewErrorCode(record)
}
/>
<Button
type="text"
style={{ borderColor: '#faad14' }}
size="small"
icon={
<EditOutlined
style={{ color: '#faad14' }}
/>
}
onClick={() => handleEditErrorCode(record)}
/>
<Button
type="text"
danger
style={{ borderColor: 'red' }}
size="small"
icon={<DeleteOutlined />}
onClick={() =>
handleDeleteErrorCode(record.key)
}
/>
</Space>
),
},
]}
rowKey="key"
pagination={{
pageSize: 10,
showSizeChanger: false,
hideOnSinglePage: true,
}}
size="small"
scroll={{ y: 300 }}
/>
</Card>
</Col>
</Row>
{/* Error Codes List Modal */}
<ErrorCodeListModal
visible={showErrorCodeModal}
onClose={() => setShowErrorCodeModal(false)}
errorCodes={errorCodes}
loading={loading}
onPreview={handlePreviewErrorCode}
onEdit={handleEditErrorCode}
onDelete={handleDeleteErrorCode}
onAddNew={handleCreateNewErrorCode}
/>
</>
);
}

View File

@@ -1,13 +1,4 @@
import {
Form,
Input,
Switch,
Upload,
Button,
Typography,
message,
ConfigProvider,
} from 'antd';
import { Form, Input, Switch, Upload, Button, Typography, message, ConfigProvider } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import { uploadFile } from '../../../../api/file-uploads';
@@ -47,7 +38,8 @@ const ErrorCodeSimpleForm = ({
const folder = 'images';
const uploadResponse = await uploadFile(file, folder);
const iconPath = uploadResponse.data?.path_icon || uploadResponse.data?.path_solution || '';
const iconPath =
uploadResponse.data?.path_icon || uploadResponse.data?.path_solution || '';
if (iconPath) {
onErrorCodeIconUpload({
@@ -82,9 +74,7 @@ const ErrorCodeSimpleForm = ({
style={{ backgroundColor: statusValue ? '#23A55A' : '#bfbfbf' }}
/>
</Form.Item>
<Text style={{ marginLeft: 8 }}>
{statusValue ? 'Active' : 'Inactive'}
</Text>
<Text style={{ marginLeft: 8 }}>{statusValue ? 'Active' : 'Inactive'}</Text>
</div>
</Form.Item>
@@ -94,10 +84,7 @@ const ErrorCodeSimpleForm = ({
name="error_code"
rules={[{ required: true, message: 'Error code wajib diisi!' }]}
>
<Input
placeholder="Enter error code"
disabled={isErrorCodeFormReadOnly}
/>
<Input placeholder="Enter error code" disabled={isErrorCodeFormReadOnly} />
</Form.Item>
{/* Error Name */}
@@ -106,17 +93,11 @@ const ErrorCodeSimpleForm = ({
name="error_code_name"
rules={[{ required: true, message: 'Error name wajib diisi!' }]}
>
<Input
placeholder="Enter error name"
disabled={isErrorCodeFormReadOnly}
/>
<Input placeholder="Enter error name" disabled={isErrorCodeFormReadOnly} />
</Form.Item>
{/* Error Description */}
<Form.Item
label="Description"
name="error_code_description"
>
<Form.Item label="Description" name="error_code_description">
<Input.TextArea
placeholder="Enter error description"
rows={3}
@@ -127,14 +108,16 @@ const ErrorCodeSimpleForm = ({
{/* Color and Icon in same row */}
<Form.Item label="Color & Icon">
<Input.Group compact>
<Form.Item
name="error_code_color"
noStyle
>
<Form.Item name="error_code_color" noStyle>
<input
type="color"
disabled={isErrorCodeFormReadOnly}
style={{ width: '30%', height: '40px', border: '1px solid #d9d9d9', borderRadius: 4 }}
style={{
width: '30%',
height: '40px',
border: '1px solid #d9d9d9',
borderRadius: 4,
}}
defaultValue="#000000"
/>
</Form.Item>
@@ -152,7 +135,13 @@ const ErrorCodeSimpleForm = ({
</Button>
</Upload>
) : (
<div style={{ padding: '8px 12px', border: '1px solid #d9d9d9', borderRadius: 4 }}>
<div
style={{
padding: '8px 12px',
border: '1px solid #d9d9d9',
borderRadius: 4,
}}
>
<Text type="secondary">No upload allowed</Text>
</div>
)}
@@ -181,12 +170,7 @@ const ErrorCodeSimpleForm = ({
</Text>
</div>
{!isErrorCodeFormReadOnly && (
<Button
type="text"
danger
size="small"
onClick={handleIconRemove}
>
<Button type="text" danger size="small" onClick={handleIconRemove}>
Remove
</Button>
)}
@@ -221,7 +205,7 @@ const ErrorCodeSimpleForm = ({
}}
style={{ width: '100%' }}
>
+ Add Error Code
Simpan Error Code
</Button>
</ConfigProvider>
</Form.Item>