repair: sollution field, handle clear form
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useState, useCallback, useMemo } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useNavigate, useParams, useSearchParams, useLocation } from 'react-router-dom';
|
import { useNavigate, useParams, useSearchParams, useLocation } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
Divider,
|
Divider,
|
||||||
@@ -13,7 +13,10 @@ import {
|
|||||||
Space,
|
Space,
|
||||||
ConfigProvider,
|
ConfigProvider,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { EyeOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
|
import {
|
||||||
|
EditOutlined,
|
||||||
|
DeleteOutlined
|
||||||
|
} from '@ant-design/icons';
|
||||||
import { NotifAlert, NotifOk, NotifConfirmDialog } from '../../../components/Global/ToastNotif';
|
import { NotifAlert, NotifOk, NotifConfirmDialog } from '../../../components/Global/ToastNotif';
|
||||||
import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb';
|
import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb';
|
||||||
import { getBrandById, createBrand, createErrorCode, getErrorCodesByBrandId, updateErrorCode, deleteErrorCode, deleteBrand } from '../../../api/master-brand';
|
import { getBrandById, createBrand, createErrorCode, getErrorCodesByBrandId, updateErrorCode, deleteErrorCode, deleteBrand } from '../../../api/master-brand';
|
||||||
@@ -55,8 +58,6 @@ const AddBrandDevice = () => {
|
|||||||
const [solutionStatuses, setSolutionStatuses] = useState({ 0: true });
|
const [solutionStatuses, setSolutionStatuses] = useState({ 0: true });
|
||||||
const [currentSolutionData, setCurrentSolutionData] = useState([]);
|
const [currentSolutionData, setCurrentSolutionData] = useState([]);
|
||||||
const [confirmLoading, setConfirmLoading] = useState(false);
|
const [confirmLoading, setConfirmLoading] = useState(false);
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
|
||||||
const [pageSize, setPageSize] = useState(10);
|
|
||||||
const [temporaryBrandId, setTemporaryBrandId] = useState(null);
|
const [temporaryBrandId, setTemporaryBrandId] = useState(null);
|
||||||
const [isTemporaryBrand, setIsTemporaryBrand] = useState(false);
|
const [isTemporaryBrand, setIsTemporaryBrand] = useState(false);
|
||||||
const [isAddingNewErrorCode, setIsAddingNewErrorCode] = useState(false);
|
const [isAddingNewErrorCode, setIsAddingNewErrorCode] = useState(false);
|
||||||
@@ -65,17 +66,36 @@ const AddBrandDevice = () => {
|
|||||||
if (!solutionForm) return [];
|
if (!solutionForm) return [];
|
||||||
try {
|
try {
|
||||||
const values = solutionForm.getFieldsValue(true);
|
const values = solutionForm.getFieldsValue(true);
|
||||||
|
const solutions = [];
|
||||||
|
|
||||||
let solutions = [];
|
solutionFields.forEach(fieldKey => {
|
||||||
|
let solution = null;
|
||||||
|
|
||||||
if (values.solution_items) {
|
if (values.solution_items && values.solution_items[fieldKey]) {
|
||||||
if (Array.isArray(values.solution_items)) {
|
solution = values.solution_items[fieldKey];
|
||||||
solutions = values.solution_items.filter(Boolean);
|
|
||||||
} else if (typeof values.solution_items === 'object') {
|
|
||||||
solutions = Object.values(values.solution_items).filter(Boolean);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!solution || !solution.name || solution.name.trim() === '') {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const solutionType = solutionTypes[fieldKey] || solution.type || 'text';
|
||||||
|
let isValid = true;
|
||||||
|
|
||||||
|
if (solutionType === 'text') {
|
||||||
|
isValid = solution.text && solution.text.trim() !== '';
|
||||||
|
} else if (solutionType === 'file') {
|
||||||
|
const hasPathSolution = solution.path_solution && solution.path_solution.trim() !== '';
|
||||||
|
const hasFileUpload = (solution.fileUpload && typeof solution.fileUpload === 'object' && Object.keys(solution.fileUpload).length > 0);
|
||||||
|
const hasFile = (solution.file && typeof solution.file === 'object' && Object.keys(solution.file).length > 0);
|
||||||
|
isValid = hasPathSolution || hasFileUpload || hasFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isValid) {
|
||||||
|
solutions.push(solution);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return solutions;
|
return solutions;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return [];
|
return [];
|
||||||
@@ -83,8 +103,13 @@ const AddBrandDevice = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const resetSolutionFields = () => {
|
const resetSolutionFields = () => {
|
||||||
|
setSolutionFields([0]);
|
||||||
|
setSolutionTypes({ 0: 'text' });
|
||||||
|
setSolutionStatuses({ 0: true });
|
||||||
|
|
||||||
if (solutionForm && solutionForm.resetFields) {
|
if (solutionForm && solutionForm.resetFields) {
|
||||||
solutionForm.resetFields();
|
solutionForm.resetFields();
|
||||||
|
setTimeout(() => {
|
||||||
solutionForm.setFieldsValue({
|
solutionForm.setFieldsValue({
|
||||||
solution_items: {
|
solution_items: {
|
||||||
0: {
|
0: {
|
||||||
@@ -92,17 +117,13 @@ const AddBrandDevice = () => {
|
|||||||
type: 'text',
|
type: 'text',
|
||||||
text: '',
|
text: '',
|
||||||
status: true,
|
status: true,
|
||||||
fileUpload: null,
|
|
||||||
file: null,
|
file: null,
|
||||||
path_solution: null,
|
fileUpload: null
|
||||||
fileName: null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}, 100);
|
||||||
}
|
}
|
||||||
setSolutionFields([0]);
|
|
||||||
setSolutionTypes({ 0: 'text' });
|
|
||||||
setSolutionStatuses({ 0: true });
|
|
||||||
setCurrentSolutionData([]);
|
setCurrentSolutionData([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -300,7 +321,8 @@ const AddBrandDevice = () => {
|
|||||||
|
|
||||||
const loadErrorCodeData = (record) => {
|
const loadErrorCodeData = (record) => {
|
||||||
setIsErrorCodeFormReadOnly(false);
|
setIsErrorCodeFormReadOnly(false);
|
||||||
setEditingErrorCodeKey(record.error_code_id);
|
const editingKey = record.tempId || `existing_${record.error_code_id}`;
|
||||||
|
setEditingErrorCodeKey(editingKey);
|
||||||
|
|
||||||
errorCodeForm.setFieldsValue({
|
errorCodeForm.setFieldsValue({
|
||||||
error_code: record.error_code,
|
error_code: record.error_code,
|
||||||
@@ -327,49 +349,6 @@ const AddBrandDevice = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEditErrorCode = (record) => {
|
|
||||||
loadErrorCodeData(record);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDeleteErrorCode = (record) => {
|
|
||||||
NotifConfirmDialog({
|
|
||||||
icon: 'question',
|
|
||||||
title: 'Konfirmasi Hapus',
|
|
||||||
message: `Apakah Anda yakin ingin menghapus error code "${record.error_code}"?`,
|
|
||||||
onConfirm: async () => {
|
|
||||||
try {
|
|
||||||
const errorCodeToDelete = record.error_code_id;
|
|
||||||
const response = await deleteErrorCode(brandInfo.brand_id || id, errorCodeToDelete);
|
|
||||||
|
|
||||||
if (response && (response.statusCode === 200 || response.statusCode === 201)) {
|
|
||||||
NotifOk({
|
|
||||||
icon: 'success',
|
|
||||||
title: 'Berhasil',
|
|
||||||
message: 'Error code berhasil dihapus!',
|
|
||||||
});
|
|
||||||
setTrigerFilter(prev => !prev);
|
|
||||||
} else {
|
|
||||||
NotifAlert({
|
|
||||||
icon: 'error',
|
|
||||||
title: 'Gagal',
|
|
||||||
message: response?.message || 'Gagal menghapus error code',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
NotifAlert({
|
|
||||||
icon: 'error',
|
|
||||||
title: 'Gagal',
|
|
||||||
message: error.message || 'Gagal menghapus error code',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onCancel: () => { }
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handlePreviewErrorCode = (record) => {
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSearch = () => {
|
const handleSearch = () => {
|
||||||
setSearchText(searchValue);
|
setSearchText(searchValue);
|
||||||
setTrigerFilter((prev) => !prev);
|
setTrigerFilter((prev) => !prev);
|
||||||
@@ -381,154 +360,7 @@ const AddBrandDevice = () => {
|
|||||||
setTrigerFilter((prev) => !prev);
|
setTrigerFilter((prev) => !prev);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleBrandFormValuesChange = useCallback((changedValues, allValues) => {
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const getErrorCodesData = async (params) => {
|
|
||||||
try {
|
|
||||||
const search = params.get('search') || '';
|
|
||||||
const page = parseInt(params.get('page')) || currentPage;
|
|
||||||
const limit = parseInt(params.get('limit')) || pageSize;
|
|
||||||
|
|
||||||
let allErrorCodes = [];
|
|
||||||
let paginationData = {
|
|
||||||
current_page: page,
|
|
||||||
current_limit: limit,
|
|
||||||
total_limit: 0,
|
|
||||||
total_page: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (brandInfo.brand_id) {
|
|
||||||
const queryParams = new URLSearchParams({
|
|
||||||
page: page.toString(),
|
|
||||||
limit: limit.toString(),
|
|
||||||
...(search && { search })
|
|
||||||
});
|
|
||||||
|
|
||||||
const response = await getErrorCodesByBrandId(brandInfo.brand_id, queryParams);
|
|
||||||
if (response && response.statusCode === 200) {
|
|
||||||
const apiErrorData = response.data || [];
|
|
||||||
allErrorCodes = apiErrorData.map(ec => ({
|
|
||||||
...ec,
|
|
||||||
tempId: `existing_${ec.error_code_id}`,
|
|
||||||
status: 'existing'
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (response.paging) {
|
|
||||||
paginationData = {
|
|
||||||
current_page: response.paging.current_page || page,
|
|
||||||
current_limit: response.paging.current_limit || limit,
|
|
||||||
total_limit: response.paging.total_limit || 0,
|
|
||||||
total_page: response.paging.total_page || 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
allErrorCodes = [...allErrorCodes, ...tempErrorCodes.filter(ec => ec.status !== 'deleted')];
|
|
||||||
|
|
||||||
if (searchText) {
|
|
||||||
allErrorCodes = allErrorCodes.filter(ec =>
|
|
||||||
ec.error_code.toLowerCase().includes(searchText.toLowerCase()) ||
|
|
||||||
ec.error_code_name.toLowerCase().includes(searchText.toLowerCase())
|
|
||||||
);
|
|
||||||
paginationData.total_limit = allErrorCodes.length;
|
|
||||||
paginationData.total_page = Math.ceil(allErrorCodes.length / limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
data: allErrorCodes,
|
|
||||||
paging: paginationData
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
return {
|
|
||||||
data: [],
|
|
||||||
paging: {
|
|
||||||
current_page: 1,
|
|
||||||
current_limit: pageSize,
|
|
||||||
total_limit: 0,
|
|
||||||
total_page: 0,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const errorCodeColumns = (showPreviewModal, showEditModal, showDeleteDialog) => [
|
|
||||||
{
|
|
||||||
title: 'No',
|
|
||||||
key: 'no',
|
|
||||||
width: '5%',
|
|
||||||
align: 'center',
|
|
||||||
render: (_, __, index) => index + 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Error Code',
|
|
||||||
dataIndex: 'error_code',
|
|
||||||
key: 'error_code',
|
|
||||||
width: '20%',
|
|
||||||
render: (text, record) => (
|
|
||||||
<Space>
|
|
||||||
{text}
|
|
||||||
</Space>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Error Name',
|
|
||||||
dataIndex: 'error_code_name',
|
|
||||||
key: 'error_code_name',
|
|
||||||
width: '25%',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Description',
|
|
||||||
dataIndex: 'error_code_description',
|
|
||||||
key: 'error_code_description',
|
|
||||||
width: '30%',
|
|
||||||
ellipsis: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Actions',
|
|
||||||
key: 'actions',
|
|
||||||
width: '20%',
|
|
||||||
render: (_, record) => (
|
|
||||||
<Space>
|
|
||||||
<Button
|
|
||||||
type="text"
|
|
||||||
icon={<EyeOutlined />}
|
|
||||||
onClick={() => showPreviewModal(record)}
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
type="text"
|
|
||||||
icon={<EditOutlined />}
|
|
||||||
onClick={() => showEditModal(record)}
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
type="text"
|
|
||||||
danger
|
|
||||||
icon={<DeleteOutlined />}
|
|
||||||
onClick={() => showDeleteDialog(record)}
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
</Space>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const queryParams = useMemo(() => {
|
|
||||||
const params = new URLSearchParams();
|
|
||||||
params.set('page', currentPage.toString());
|
|
||||||
params.set('limit', pageSize.toString());
|
|
||||||
if (searchValue) {
|
|
||||||
params.set('search', searchValue);
|
|
||||||
}
|
|
||||||
return params;
|
|
||||||
}, [searchValue, currentPage, pageSize]);
|
|
||||||
|
|
||||||
const handlePaginationChange = (page, size) => {
|
|
||||||
setCurrentPage(page);
|
|
||||||
setPageSize(size);
|
|
||||||
};
|
|
||||||
|
|
||||||
const resetErrorCodeForm = () => {
|
const resetErrorCodeForm = () => {
|
||||||
errorCodeForm.resetFields();
|
errorCodeForm.resetFields();
|
||||||
@@ -763,7 +595,6 @@ const AddBrandDevice = () => {
|
|||||||
)}
|
)}
|
||||||
<BrandForm
|
<BrandForm
|
||||||
form={brandForm}
|
form={brandForm}
|
||||||
onValuesChange={handleBrandFormValuesChange}
|
|
||||||
isEdit={false}
|
isEdit={false}
|
||||||
brandInfo={brandInfo}
|
brandInfo={brandInfo}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useState, useCallback, useMemo } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useNavigate, useParams, useSearchParams, useLocation } from 'react-router-dom';
|
import { useNavigate, useParams, useSearchParams, useLocation } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
Divider,
|
Divider,
|
||||||
@@ -15,10 +15,9 @@ import {
|
|||||||
Input,
|
Input,
|
||||||
ConfigProvider
|
ConfigProvider
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { EyeOutlined, EditOutlined, DeleteOutlined, PlusOutlined, SearchOutlined } from '@ant-design/icons';
|
|
||||||
import { NotifAlert, NotifOk, NotifConfirmDialog } from '../../../components/Global/ToastNotif';
|
import { NotifAlert, NotifOk, NotifConfirmDialog } from '../../../components/Global/ToastNotif';
|
||||||
import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb';
|
import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb';
|
||||||
import { getBrandById, updateBrand, getErrorCodesByBrandId, getErrorCodeById, deleteErrorCode, updateErrorCode as updateErrorCodeAPI, createErrorCode as createErrorCodeAPI } from '../../../api/master-brand';
|
import { getBrandById, updateBrand, getErrorCodesByBrandId, deleteErrorCode, updateErrorCode as updateErrorCodeAPI, createErrorCode as createErrorCodeAPI } from '../../../api/master-brand';
|
||||||
import { getFileUrl } from '../../../api/file-uploads';
|
import { getFileUrl } from '../../../api/file-uploads';
|
||||||
import { SendRequest } from '../../../components/Global/ApiRequest';
|
import { SendRequest } from '../../../components/Global/ApiRequest';
|
||||||
import BrandForm from './component/BrandForm';
|
import BrandForm from './component/BrandForm';
|
||||||
@@ -63,17 +62,36 @@ const EditBrandDevice = () => {
|
|||||||
if (!solutionForm) return [];
|
if (!solutionForm) return [];
|
||||||
try {
|
try {
|
||||||
const values = solutionForm.getFieldsValue(true);
|
const values = solutionForm.getFieldsValue(true);
|
||||||
|
const solutions = [];
|
||||||
|
|
||||||
let solutions = [];
|
solutionFields.forEach(fieldKey => {
|
||||||
|
let solution = null;
|
||||||
|
|
||||||
if (values.solution_items) {
|
if (values.solution_items && values.solution_items[fieldKey]) {
|
||||||
if (Array.isArray(values.solution_items)) {
|
solution = values.solution_items[fieldKey];
|
||||||
solutions = values.solution_items.filter(Boolean);
|
|
||||||
} else if (typeof values.solution_items === 'object') {
|
|
||||||
solutions = Object.values(values.solution_items).filter(Boolean);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!solution || !solution.name || solution.name.trim() === '') {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const solutionType = solutionTypes[fieldKey] || solution.type || 'text';
|
||||||
|
let isValid = true;
|
||||||
|
|
||||||
|
if (solutionType === 'text') {
|
||||||
|
isValid = solution.text && solution.text.trim() !== '';
|
||||||
|
} else if (solutionType === 'file') {
|
||||||
|
const hasPathSolution = solution.path_solution && solution.path_solution.trim() !== '';
|
||||||
|
const hasFileUpload = (solution.fileUpload && typeof solution.fileUpload === 'object' && Object.keys(solution.fileUpload).length > 0);
|
||||||
|
const hasFile = (solution.file && typeof solution.file === 'object' && Object.keys(solution.file).length > 0);
|
||||||
|
isValid = hasPathSolution || hasFileUpload || hasFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isValid) {
|
||||||
|
solutions.push(solution);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return solutions;
|
return solutions;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return [];
|
return [];
|
||||||
@@ -81,18 +99,26 @@ const EditBrandDevice = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const resetSolutionFields = () => {
|
const resetSolutionFields = () => {
|
||||||
|
setSolutionFields([0]);
|
||||||
|
setSolutionTypes({ 0: 'text' });
|
||||||
|
setSolutionStatuses({ 0: true });
|
||||||
|
|
||||||
if (solutionForm && solutionForm.resetFields) {
|
if (solutionForm && solutionForm.resetFields) {
|
||||||
solutionForm.resetFields();
|
solutionForm.resetFields();
|
||||||
|
setTimeout(() => {
|
||||||
solutionForm.setFieldsValue({
|
solutionForm.setFieldsValue({
|
||||||
solution_items: {
|
solution_items: {
|
||||||
0: {
|
0: {
|
||||||
name: '',
|
name: '',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
text: '',
|
text: '',
|
||||||
status: true
|
status: true,
|
||||||
|
file: null,
|
||||||
|
fileUpload: null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}, 100);
|
||||||
}
|
}
|
||||||
setCurrentSolutionData([]);
|
setCurrentSolutionData([]);
|
||||||
};
|
};
|
||||||
@@ -344,47 +370,9 @@ const EditBrandDevice = () => {
|
|||||||
}
|
}
|
||||||
}, [location, navigate]);
|
}, [location, navigate]);
|
||||||
|
|
||||||
const addErrorCode = (newErrorCode) => {
|
|
||||||
|
|
||||||
const uniqueId = `temp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
||||||
const errorCodeWithId = {
|
|
||||||
...newErrorCode,
|
|
||||||
tempId: uniqueId,
|
|
||||||
status: 'new'
|
|
||||||
};
|
|
||||||
setTempErrorCodes(prev => [...prev, errorCodeWithId]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateErrorCode = (tempId, updatedData) => {
|
|
||||||
setTempErrorCodes(prev =>
|
|
||||||
prev.map(ec => ec.tempId === tempId ? { ...ec, ...updatedData, status: 'modified' } : ec)
|
|
||||||
);
|
|
||||||
setExistingErrorCodes(prev =>
|
|
||||||
prev.map(ec => ec.tempId === tempId ? { ...ec, ...updatedData, status: 'modified' } : ec)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteLocalErrorCode = (tempId, permanent = false) => {
|
|
||||||
if (permanent) {
|
|
||||||
setTempErrorCodes(prev => prev.filter(ec => ec.tempId !== tempId));
|
|
||||||
setExistingErrorCodes(prev => prev.filter(ec => ec.tempId !== tempId));
|
|
||||||
} else {
|
|
||||||
setTempErrorCodes(prev =>
|
|
||||||
prev.map(ec => ec.tempId === tempId ? { ...ec, status: 'deleted' } : ec)
|
|
||||||
);
|
|
||||||
setExistingErrorCodes(prev =>
|
|
||||||
prev.map(ec => ec.tempId === tempId ? { ...ec, status: 'deleted' } : ec)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getErrorCodeById = (tempId) => {
|
|
||||||
const inTemp = tempErrorCodes.find(ec => ec.tempId === tempId);
|
|
||||||
if (inTemp) return inTemp;
|
|
||||||
|
|
||||||
const inExisting = existingErrorCodes.find(ec => ec.tempId === tempId);
|
|
||||||
return inExisting;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleNextStep = async () => {
|
const handleNextStep = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -454,6 +442,7 @@ const EditBrandDevice = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleErrorCodeIconUpload = (iconData) => {
|
const handleErrorCodeIconUpload = (iconData) => {
|
||||||
setErrorCodeIcon(iconData);
|
setErrorCodeIcon(iconData);
|
||||||
};
|
};
|
||||||
@@ -474,11 +463,6 @@ const EditBrandDevice = () => {
|
|||||||
setSelectedSparepartIds([]);
|
setSelectedSparepartIds([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCreateNewErrorCode = () => {
|
|
||||||
resetErrorCodeForm();
|
|
||||||
setCurrentSolutionData([]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSaveErrorCode = async () => {
|
const handleSaveErrorCode = async () => {
|
||||||
try {
|
try {
|
||||||
setConfirmLoading(true);
|
setConfirmLoading(true);
|
||||||
@@ -566,16 +550,6 @@ const EditBrandDevice = () => {
|
|||||||
message: editingErrorCodeKey ? 'Error code berhasil diupdate!' : 'Error code berhasil ditambahkan!',
|
message: editingErrorCodeKey ? 'Error code berhasil diupdate!' : 'Error code berhasil ditambahkan!',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
setTempErrorCodes(prev => prev.filter(ec => {
|
|
||||||
|
|
||||||
if (ec.status === 'existing' || ec.tempId.startsWith('existing_')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ec.tempId !== editingErrorCodeKey;
|
|
||||||
}));
|
|
||||||
|
|
||||||
setTrigerFilter(prev => !prev);
|
setTrigerFilter(prev => !prev);
|
||||||
resetErrorCodeForm();
|
resetErrorCodeForm();
|
||||||
} else {
|
} else {
|
||||||
@@ -627,157 +601,6 @@ const EditBrandDevice = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePreviewErrorCode = (record) => {
|
|
||||||
const errorCode = getErrorCodeById(record.tempId || record.error_code_id);
|
|
||||||
loadErrorCodeData(errorCode, true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleEditErrorCode = (record) => {
|
|
||||||
const errorCode = getErrorCodeById(record.tempId || record.error_code_id);
|
|
||||||
loadErrorCodeData(errorCode, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const handleDeleteErrorCode = async (record) => {
|
|
||||||
NotifConfirmDialog({
|
|
||||||
icon: 'question',
|
|
||||||
title: 'Konfirmasi Hapus',
|
|
||||||
message: `Apakah Anda yakin ingin menghapus error code "${record.error_code}"?`,
|
|
||||||
onConfirm: async () => {
|
|
||||||
try {
|
|
||||||
if (record.status === 'existing' && record.error_code_id) {
|
|
||||||
const response = await deleteErrorCode(id, record.error_code_id);
|
|
||||||
if (response && response.statusCode === 200) {
|
|
||||||
NotifOk({
|
|
||||||
icon: 'success',
|
|
||||||
title: 'Berhasil',
|
|
||||||
message: 'Error code berhasil dihapus!',
|
|
||||||
});
|
|
||||||
setTrigerFilter(prev => !prev);
|
|
||||||
} else {
|
|
||||||
NotifAlert({
|
|
||||||
icon: 'error',
|
|
||||||
title: 'Error',
|
|
||||||
message: response?.message || 'Failed to delete error code',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const tempId = record.tempId;
|
|
||||||
deleteLocalErrorCode(tempId, true);
|
|
||||||
NotifOk({
|
|
||||||
icon: 'success',
|
|
||||||
title: 'Berhasil',
|
|
||||||
message: 'Error code berhasil dihapus!',
|
|
||||||
});
|
|
||||||
setTrigerFilter(prev => !prev);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
NotifAlert({
|
|
||||||
icon: 'error',
|
|
||||||
title: 'Error',
|
|
||||||
message: error.message || 'Failed to delete error code',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onCancel: () => { }
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const mergedErrorCodes = useMemo(() => {
|
|
||||||
const allErrorCodes = [
|
|
||||||
...existingErrorCodes.map(ec => ({ ...ec, status: 'existing' })),
|
|
||||||
...tempErrorCodes
|
|
||||||
];
|
|
||||||
|
|
||||||
const activeErrorCodes = allErrorCodes.filter(ec => ec.status !== 'deleted');
|
|
||||||
|
|
||||||
if (searchText) {
|
|
||||||
return activeErrorCodes.filter(ec =>
|
|
||||||
ec.error_code.toLowerCase().includes(searchText.toLowerCase()) ||
|
|
||||||
ec.error_code_name.toLowerCase().includes(searchText.toLowerCase())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return activeErrorCodes;
|
|
||||||
}, [existingErrorCodes, tempErrorCodes, searchText]);
|
|
||||||
|
|
||||||
const errorCodeColumns = (showPreviewModal, showEditModal, showDeleteDialog) => [
|
|
||||||
{
|
|
||||||
title: 'No',
|
|
||||||
key: 'no',
|
|
||||||
width: '5%',
|
|
||||||
align: 'center',
|
|
||||||
render: (_, __, index) => index + 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Error Code',
|
|
||||||
dataIndex: 'error_code',
|
|
||||||
key: 'error_code',
|
|
||||||
width: '20%',
|
|
||||||
render: (text, record) => (
|
|
||||||
<Space>
|
|
||||||
{text}
|
|
||||||
</Space>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Error Name',
|
|
||||||
dataIndex: 'error_code_name',
|
|
||||||
key: 'error_code_name',
|
|
||||||
width: '25%',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Status',
|
|
||||||
dataIndex: 'is_active',
|
|
||||||
key: 'is_active',
|
|
||||||
width: '10%',
|
|
||||||
align: 'center',
|
|
||||||
render: (_, { is_active }) => (
|
|
||||||
<Tag color={is_active ? 'green' : 'red'}>
|
|
||||||
{is_active ? 'Active' : 'Inactive'}
|
|
||||||
</Tag>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Action',
|
|
||||||
key: 'action',
|
|
||||||
align: 'center',
|
|
||||||
width: '15%',
|
|
||||||
render: (_, record) => (
|
|
||||||
<Space>
|
|
||||||
<Button
|
|
||||||
icon={<EyeOutlined />}
|
|
||||||
onClick={() => showPreviewModal(record)}
|
|
||||||
style={{
|
|
||||||
color: '#1890ff',
|
|
||||||
borderColor: '#1890ff',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
icon={<EditOutlined />}
|
|
||||||
onClick={() => showEditModal(record)}
|
|
||||||
style={{
|
|
||||||
color: '#faad14',
|
|
||||||
borderColor: '#faad14',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
danger
|
|
||||||
icon={<DeleteOutlined />}
|
|
||||||
onClick={() => showDeleteDialog(record)}
|
|
||||||
style={{
|
|
||||||
borderColor: '#ff4d4f',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Space>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const handleBrandFormValuesChange = useCallback((changedValues, allValues) => {
|
|
||||||
setBrandInfo(allValues);
|
|
||||||
}, [setBrandInfo]);
|
|
||||||
|
|
||||||
const handleSearch = () => {
|
const handleSearch = () => {
|
||||||
setTrigerFilter((prev) => !prev);
|
setTrigerFilter((prev) => !prev);
|
||||||
};
|
};
|
||||||
@@ -787,113 +610,6 @@ const EditBrandDevice = () => {
|
|||||||
setTrigerFilter((prev) => !prev);
|
setTrigerFilter((prev) => !prev);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getErrorCodesData = async (params) => {
|
|
||||||
try {
|
|
||||||
const criteria = params.get('criteria') || '';
|
|
||||||
const page = parseInt(params.get('page')) || 1;
|
|
||||||
const limit = parseInt(params.get('limit')) || 10;
|
|
||||||
const currentBrandId = id;
|
|
||||||
|
|
||||||
if (!currentBrandId) {
|
|
||||||
return {
|
|
||||||
data: [],
|
|
||||||
pagination: {
|
|
||||||
current_page: page,
|
|
||||||
current_limit: limit,
|
|
||||||
total_limit: 0,
|
|
||||||
total_page: 0,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const queryParams = new URLSearchParams({
|
|
||||||
page: page.toString(),
|
|
||||||
limit: limit.toString(),
|
|
||||||
...(criteria && { criteria })
|
|
||||||
});
|
|
||||||
|
|
||||||
const response = await getErrorCodesByBrandId(currentBrandId, queryParams);
|
|
||||||
|
|
||||||
if (response && response.statusCode === 200) {
|
|
||||||
const apiData = response.data || [];
|
|
||||||
|
|
||||||
const contextExistingMap = new Map();
|
|
||||||
existingErrorCodes.forEach(ec => {
|
|
||||||
if (ec.status === 'modified' || ec.status === 'deleted') {
|
|
||||||
contextExistingMap.set(ec.error_code_id, ec);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const existingCodes = apiData.map(ec => {
|
|
||||||
const contextModified = contextExistingMap.get(ec.error_code_id);
|
|
||||||
if (contextModified) {
|
|
||||||
return {
|
|
||||||
...contextModified,
|
|
||||||
tempId: `existing_${ec.error_code_id}`,
|
|
||||||
solution: contextModified.solution || ec.solution || [],
|
|
||||||
spareparts: contextModified.spareparts || ec.spareparts || []
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
...ec,
|
|
||||||
tempId: `existing_${ec.error_code_id}`,
|
|
||||||
status: 'existing',
|
|
||||||
solution: ec.solution || [],
|
|
||||||
spareparts: ec.spareparts || []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const activeExistingCodes = existingCodes.filter(ec => ec.status !== 'deleted');
|
|
||||||
|
|
||||||
const allErrorCodes = [...activeExistingCodes, ...tempErrorCodes.filter(ec => ec.status !== 'deleted')];
|
|
||||||
|
|
||||||
let filteredData = allErrorCodes;
|
|
||||||
|
|
||||||
if (search) {
|
|
||||||
filteredData = allErrorCodes.filter(ec =>
|
|
||||||
ec.error_code.toLowerCase().includes(search.toLowerCase()) ||
|
|
||||||
ec.error_code_name.toLowerCase().includes(search.toLowerCase())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const startIndex = 0;
|
|
||||||
const endIndex = startIndex + limit;
|
|
||||||
const paginatedData = filteredData.slice(startIndex, endIndex);
|
|
||||||
|
|
||||||
return {
|
|
||||||
data: paginatedData,
|
|
||||||
pagination: {
|
|
||||||
current_page: page,
|
|
||||||
current_limit: limit,
|
|
||||||
total_limit: filteredData.length,
|
|
||||||
total_page: Math.ceil(filteredData.length / limit),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
data: [],
|
|
||||||
pagination: {
|
|
||||||
current_page: page,
|
|
||||||
current_limit: limit,
|
|
||||||
total_limit: 0,
|
|
||||||
total_page: 0,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
return {
|
|
||||||
data: [],
|
|
||||||
pagination: {
|
|
||||||
current_page: 1,
|
|
||||||
current_limit: 10,
|
|
||||||
total_limit: 0,
|
|
||||||
total_page: 0,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderStepContent = () => {
|
const renderStepContent = () => {
|
||||||
if (currentStep === 0) {
|
if (currentStep === 0) {
|
||||||
return (
|
return (
|
||||||
@@ -919,7 +635,6 @@ const EditBrandDevice = () => {
|
|||||||
)}
|
)}
|
||||||
<BrandForm
|
<BrandForm
|
||||||
form={brandForm}
|
form={brandForm}
|
||||||
onValuesChange={handleBrandFormValuesChange}
|
|
||||||
isEdit={true}
|
isEdit={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -1186,7 +901,10 @@ const EditBrandDevice = () => {
|
|||||||
{editingErrorCodeKey && (
|
{editingErrorCodeKey && (
|
||||||
<Button
|
<Button
|
||||||
size="large"
|
size="large"
|
||||||
onClick={handleCreateNewErrorCode}
|
onClick={() => {
|
||||||
|
resetErrorCodeForm();
|
||||||
|
resetSolutionFields();
|
||||||
|
}}
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: '#fff',
|
backgroundColor: '#fff',
|
||||||
borderColor: '#d9d9d9',
|
borderColor: '#d9d9d9',
|
||||||
|
|||||||
Reference in New Issue
Block a user