-
- {currentStep === 1 && (
-
- )}
+
+
+ {currentStep === 1 && (
+
+ )}
+
+
+ {currentStep === 0 && (
+
+ )}
+ {currentStep === 1 && (
+
+ )}
+
-
- {currentStep === 0 && (
-
- )}
- {currentStep === 1 && (
-
- )}
-
-
);
diff --git a/src/pages/master/brandDevice/ViewBrandDevice.jsx b/src/pages/master/brandDevice/ViewBrandDevice.jsx
index f0a7940..997af93 100644
--- a/src/pages/master/brandDevice/ViewBrandDevice.jsx
+++ b/src/pages/master/brandDevice/ViewBrandDevice.jsx
@@ -1,414 +1,765 @@
-import React, { useEffect, useState } from 'react';
+import React, { useEffect, useState, useCallback, useMemo } from 'react';
import { useNavigate, useParams, useLocation } from 'react-router-dom';
-import { Typography, Card, Row, Col, Tag, Button, Space, Descriptions, Divider, Steps, Collapse, Switch, Spin, Modal, Empty } from 'antd';
-import { ArrowLeftOutlined, FileTextOutlined, FilePdfOutlined, EyeOutlined } from '@ant-design/icons';
+import {
+ Divider,
+ Typography,
+ Button,
+ Steps,
+ Form,
+ Row,
+ Col,
+ Card,
+ Spin,
+ Tag,
+ Space,
+ ConfigProvider,
+ Empty
+} from 'antd';
+import { ArrowLeftOutlined } from '@ant-design/icons';
import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb';
-import { NotifOk, NotifAlert } from '../../../components/Global/ToastNotif';
-import { getBrandById } from '../../../api/master-brand';
+import { NotifAlert } from '../../../components/Global/ToastNotif';
+import { getBrandById, getErrorCodesByBrandId } from '../../../api/master-brand';
+import { getFileUrl, getFolderFromFileType } from '../../../api/file-uploads';
+import { SendRequest } from '../../../components/Global/ApiRequest';
+import ListErrorCode from './component/ListErrorCode';
+import BrandForm from './component/BrandForm';
+import ErrorCodeForm from './component/ErrorCodeForm';
+import SolutionForm from './component/SolutionForm';
+import SparepartSelect from './component/SparepartSelect';
const { Title, Text } = Typography;
const { Step } = Steps;
-const { Panel } = Collapse;
const ViewBrandDevice = () => {
const navigate = useNavigate();
const { id } = useParams();
const location = useLocation();
const { setBreadcrumbItems } = useBreadcrumb();
+ const [brandForm] = Form.useForm();
+ const [errorCodeForm] = Form.useForm();
+ const [solutionForm] = Form.useForm();
+
const [brandData, setBrandData] = useState(null);
+ const [errorCodes, setErrorCodes] = useState([]);
const [loading, setLoading] = useState(true);
const [currentStep, setCurrentStep] = useState(0);
- const [activeErrorKeys, setActiveErrorKeys] = useState([]);
+ const [selectedErrorCode, setSelectedErrorCode] = useState(null);
+ const [selectedSparepartIds, setSelectedSparepartIds] = useState([]);
+ const [errorCodeIcon, setErrorCodeIcon] = useState(null);
+ const [trigerFilter, setTrigerFilter] = useState(false);
+ const [searchText, setSearchText] = useState('');
+
+
+ const [solutionFields, setSolutionFields] = useState([0]);
+ const [solutionTypes, setSolutionTypes] = useState({ 0: 'text' });
+ const [solutionStatuses, setSolutionStatuses] = useState({ 0: true });
+ const [currentSolutionData, setCurrentSolutionData] = useState([]);
+
+
+ const [brandInfo, setBrandInfo] = useState({});
+
+ const resetSolutionFields = () => {
+ if (solutionForm && solutionForm.resetFields) {
+ solutionForm.resetFields();
+ solutionForm.setFieldsValue({
+ solution_items: {
+ 0: {
+ name: '',
+ type: 'text',
+ text: '',
+ status: true
+ }
+ }
+ });
+ }
+ setCurrentSolutionData([]);
+ };
+
+ const getSolutionData = () => {
+ if (!solutionForm) return [];
+ try {
+ const values = solutionForm.getFieldsValue(true);
+
+ let solutions = [];
+
+ if (values.solution_items) {
+ if (Array.isArray(values.solution_items)) {
+ solutions = values.solution_items.filter(Boolean);
+ } else if (typeof values.solution_items === 'object') {
+ solutions = Object.values(values.solution_items).filter(Boolean);
+ }
+ }
+
+ return solutions;
+ } catch (error) {
+ return [];
+ }
+ };
+
+
+ useEffect(() => {
+ const savedPhase = location.state?.phase || localStorage.getItem(`brand_device_${id}_last_phase`);
+ if (savedPhase) {
+ setCurrentStep(parseInt(savedPhase));
+ localStorage.removeItem(`brand_device_${id}_last_phase`);
+ }
+ }, [location.state, id]);
+
+
+ useEffect(() => {
+ setBreadcrumbItems([
+ {
+ title:
• Master
+ },
+ {
+ title: (
+
navigate('/master/brand-device')}
+ >
+ Brand Device
+
+ ),
+ },
+ {
+ title: (
+
+ View Brand Device
+
+ ),
+ },
+ ]);
+ }, [setBreadcrumbItems, navigate]);
useEffect(() => {
const fetchBrandData = async () => {
const token = localStorage.getItem('token');
- if (token) {
- const savedPhase = location.state?.phase || localStorage.getItem(`brand_device_${id}_last_phase`);
- if (savedPhase) {
- setCurrentStep(parseInt(savedPhase));
- localStorage.removeItem(`brand_device_${id}_last_phase`);
- }
+ if (!token) {
+ navigate('/signin');
+ return;
+ }
- setBreadcrumbItems([
- { title:
• Master },
- {
- title:
navigate('/master/brand-device')}>Brand Device
- },
- { title:
View Brand Device }
- ]);
+ try {
+ setLoading(true);
+ const response = await getBrandById(id);
- try {
- setLoading(true);
- const response = await getBrandById(id);
+ if (response && response.statusCode === 200) {
+ const brandData = response.data;
- if (response && response.statusCode === 200) {
- setBrandData(response.data);
- } else {
- NotifAlert({
- icon: 'error',
- title: 'Error',
- message: response?.message || 'Failed to fetch brand device data',
- });
+ const brandInfoData = {
+ brand_code: brandData.brand_code,
+ brand_name: brandData.brand_name,
+ brand_type: brandData.brand_type || '',
+ brand_manufacture: brandData.brand_manufacture || '',
+ brand_model: brandData.brand_model || '',
+ is_active: brandData.is_active
+ };
+
+ setBrandInfo(brandInfoData);
+ setBrandData(brandData);
+ brandForm.setFieldsValue(brandInfoData);
+
+ if (brandData.brand_id) {
+ try {
+ const errorCodesResponse = await getErrorCodesByBrandId(id || brandData.brand_id);
+ if (errorCodesResponse && errorCodesResponse.statusCode === 200) {
+ const apiErrorData = errorCodesResponse.data || [];
+ const existingCodes = apiErrorData.map(ec => ({
+ ...ec,
+ tempId: `existing_${ec.error_code_id}`,
+ status: 'existing',
+ solution: ec.solution || [],
+ spareparts: ec.spareparts || []
+ }));
+ setErrorCodes(existingCodes);
+ }
+ } catch (error) {
+ }
}
- } catch (error) {
+ } else {
NotifAlert({
icon: 'error',
title: 'Error',
- message: error.message || 'Failed to fetch brand device data',
+ message: response?.message || 'Failed to fetch brand device data',
});
- } finally {
- setLoading(false);
}
- } else {
- navigate('/signin');
+ } catch (error) {
+ NotifAlert({
+ icon: 'error',
+ title: 'Error',
+ message: error.message || 'Failed to fetch brand device data',
+ });
+ } finally {
+ setLoading(false);
}
};
fetchBrandData();
- }, [id, setBreadcrumbItems, navigate, location.state]);
+ }, [id, navigate, brandForm]);
- const handleFileView = (fileName, fileType) => {
- localStorage.setItem(`brand_device_${id}_last_phase`, currentStep.toString());
+ useEffect(() => {
+ if (currentStep === 1 && id) {
+ setTrigerFilter(prev => !prev);
+ }
+ }, [currentStep, id]);
- let actualFileName = fileName;
- if (fileName && fileName.includes('/')) {
- const parts = fileName.split('/');
- actualFileName = parts[parts.length - 1];
+
+ useEffect(() => {
+ if (currentStep === 1 && errorCodes.length > 0 && !selectedErrorCode) {
+ handleErrorCodeSelect(errorCodes[0]);
+ }
+ }, [currentStep, errorCodes]);
+
+ const setSolutionsForExistingRecord = (solutions, targetForm) => {
+
+ if (!targetForm || !solutions || solutions.length === 0) {
+ return;
}
- const encodedFileName = encodeURIComponent(actualFileName);
- const fileTypeParam = fileType === 'image' ? 'image' : 'pdf';
- const navigationPath = `/master/brand-device/view/${id}/files/${fileTypeParam}/${encodedFileName}`;
- navigate(navigationPath);
+ targetForm.resetFields();
+
+ const solutionItems = {};
+ const newSolutionFields = [];
+ const newSolutionTypes = {};
+ const newSolutionStatuses = {};
+
+ solutions.forEach((solution, index) => {
+ const fieldKey = index;
+ newSolutionFields.push(fieldKey);
+
+ const isFileType = solution.type_solution && solution.type_solution !== 'text';
+ newSolutionTypes[fieldKey] = isFileType ? 'file' : 'text';
+ newSolutionStatuses[fieldKey] = solution.is_active;
+
+ let fileObject = null;
+ if (isFileType && (solution.path_solution || solution.path_document)) {
+ fileObject = {
+ uploadPath: solution.path_solution || solution.path_document,
+ path_solution: solution.path_solution || solution.path_document,
+ name: solution.file_upload_name || (solution.path_solution || solution.path_document).split('/').pop() || 'File',
+ type_solution: solution.type_solution,
+ isExisting: true,
+ size: 0,
+ url: solution.path_solution || solution.path_document
+ };
+ }
+
+ solutionItems[fieldKey] = {
+ brand_code_solution_id: solution.brand_code_solution_id,
+ name: solution.solution_name || '',
+ type: isFileType ? 'file' : 'text',
+ text: solution.text_solution || '',
+ status: solution.is_active,
+ file: fileObject,
+ fileUpload: fileObject,
+ path_solution: solution.path_solution || solution.path_document || null,
+ fileName: solution.file_upload_name || null
+ };
+ });
+
+ setSolutionFields(newSolutionFields);
+ setSolutionTypes(newSolutionTypes);
+ setSolutionStatuses(newSolutionStatuses);
+
+ targetForm.resetFields();
+
+ setTimeout(() => {
+ targetForm.setFieldsValue({
+ solution_items: solutionItems
+ });
+
+ setTimeout(() => {
+ Object.keys(solutionItems).forEach(key => {
+ const solution = solutionItems[key];
+ targetForm.setFieldValue(['solution_items', key, 'name'], solution.name);
+ targetForm.setFieldValue(['solution_items', key, 'type'], solution.type);
+ targetForm.setFieldValue(['solution_items', key, 'text'], solution.text);
+ targetForm.setFieldValue(['solution_items', key, 'file'], solution.file);
+ targetForm.setFieldValue(['solution_items', key, 'fileUpload'], solution.fileUpload);
+ targetForm.setFieldValue(['solution_items', key, 'status'], solution.status);
+ targetForm.setFieldValue(['solution_items', key, 'path_solution'], solution.path_solution);
+ targetForm.setFieldValue(['solution_items', key, 'fileName'], solution.fileName);
+ });
+
+ const finalValues = targetForm.getFieldsValue();
+ }, 100);
+ }, 100);
+ };
+
+ const handleErrorCodeSelect = async (errorCode) => {
+
+ setSelectedErrorCode(errorCode);
+
+ try {
+
+ const directResponse = await SendRequest({
+ method: 'get',
+ prefix: `error-code/${errorCode.error_code_id}`,
+ });
+
+ const apiResponse = directResponse.data;
+
+ if (apiResponse && apiResponse.statusCode === 200 && apiResponse.data) {
+ const fullErrorCodeData = {
+ ...apiResponse.data,
+ tempId: `existing_${apiResponse.data.error_code_id}`
+ };
+
+ const formValues = {
+ error_code: fullErrorCodeData.error_code,
+ error_code_name: fullErrorCodeData.error_code_name,
+ error_code_description: fullErrorCodeData.error_code_description || '',
+ error_code_color: fullErrorCodeData.error_code_color && fullErrorCodeData.error_code_color !== '' ? fullErrorCodeData.error_code_color : '#000000',
+ status: fullErrorCodeData.is_active,
+ };
+
+ errorCodeForm.setFieldsValue(formValues);
+
+ if (fullErrorCodeData.path_icon && fullErrorCodeData.path_icon !== '') {
+ const iconData = {
+ name: fullErrorCodeData.path_icon.split('/').pop(),
+ uploadPath: fullErrorCodeData.path_icon,
+ };
+ setErrorCodeIcon(iconData);
+ } else {
+ setErrorCodeIcon(null);
+ }
+
+ if (apiResponse.data.solution && apiResponse.data.solution.length > 0) {
+ setCurrentSolutionData(apiResponse.data.solution);
+ setSolutionsForExistingRecord(apiResponse.data.solution, solutionForm);
+ }
+
+ if (apiResponse.data.spareparts && apiResponse.data.spareparts.length > 0) {
+ setSelectedSparepartIds(apiResponse.data.spareparts.map(sp => sp.sparepart_id));
+ } else {
+ setSelectedSparepartIds([]);
+ }
+ } else {
+ const basicErrorCodeData = {
+ ...errorCode,
+ tempId: `existing_${errorCode.error_code_id}`
+ };
+
+ const formValues = {
+ error_code: basicErrorCodeData.error_code,
+ error_code_name: basicErrorCodeData.error_code_name,
+ error_code_description: basicErrorCodeData.error_code_description || '',
+ error_code_color: basicErrorCodeData.error_code_color && basicErrorCodeData.error_code_color !== '' ? basicErrorCodeData.error_code_color : '#000000',
+ status: basicErrorCodeData.is_active,
+ };
+
+ errorCodeForm.setFieldsValue(formValues);
+
+ if (basicErrorCodeData.path_icon && basicErrorCodeData.path_icon !== '') {
+ const iconData = {
+ name: basicErrorCodeData.path_icon.split('/').pop(),
+ uploadPath: basicErrorCodeData.path_icon,
+ };
+ setErrorCodeIcon(iconData);
+ } else {
+ setErrorCodeIcon(null);
+ }
+
+ resetSolutionFields();
+ setSelectedSparepartIds([]);
+ }
+ } catch (error) {
+ const basicErrorCodeData = {
+ ...errorCode,
+ tempId: `existing_${errorCode.error_code_id}`
+ };
+
+ const formValues = {
+ error_code: basicErrorCodeData.error_code,
+ error_code_name: basicErrorCodeData.error_code_name,
+ error_code_description: basicErrorCodeData.error_code_description || '',
+ error_code_color: basicErrorCodeData.error_code_color && basicErrorCodeData.error_code_color !== '' ? basicErrorCodeData.error_code_color : '#000000',
+ status: basicErrorCodeData.is_active,
+ };
+
+ errorCodeForm.setFieldsValue(formValues);
+
+ if (basicErrorCodeData.path_icon && basicErrorCodeData.path_icon !== '') {
+ const iconData = {
+ name: basicErrorCodeData.path_icon.split('/').pop(),
+ uploadPath: basicErrorCodeData.path_icon,
+ };
+ setErrorCodeIcon(iconData);
+ } else {
+ setErrorCodeIcon(null);
+ }
+
+ resetSolutionFields();
+ setSelectedSparepartIds([]);
+ }
+ };
+
+ const handleBrandFormValuesChange = useCallback((changedValues, allValues) => {
+ setBrandInfo(allValues);
+ }, [setBrandInfo]);
+
+ const handleSearch = () => {
+ setTrigerFilter((prev) => !prev);
+ };
+
+ const handleSearchClear = () => {
+ setSearchText('');
+ setTrigerFilter((prev) => !prev);
+ };
+
+ const handleFileView = (fileName) => {
+ try {
+ let fileUrl = '';
+ let actualFileName = '';
+
+ const filePath = fileName || '';
+ if (filePath) {
+ actualFileName = filePath.split('/').pop();
+ }
+
+ if (actualFileName) {
+ const fileExtension = actualFileName.split('.').pop()?.toLowerCase();
+ const folder = getFolderFromFileType(fileExtension);
+ fileUrl = getFileUrl(folder, actualFileName);
+ }
+
+ if (!fileUrl && filePath) {
+ fileUrl = filePath.startsWith('http') ? filePath : `${import.meta.env.VITE_API_SERVER}/${filePath}`;
+ }
+
+ if (fileUrl && actualFileName) {
+ const fileExtension = actualFileName.split('.').pop()?.toLowerCase();
+ const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
+ const pdfExtensions = ['pdf'];
+
+ if (imageExtensions.includes(fileExtension) || pdfExtensions.includes(fileExtension)) {
+ const viewerUrl = `/image-viewer/${encodeURIComponent(actualFileName)}`;
+ window.open(viewerUrl, '_blank', 'noopener,noreferrer');
+ } else {
+ window.open(fileUrl, '_blank', 'noopener,noreferrer');
+ }
+ } else {
+ NotifAlert({
+ icon: 'error',
+ title: 'Error',
+ message: 'File URL not found'
+ });
+ }
+ } catch (error) {
+ NotifAlert({
+ icon: 'error',
+ title: 'Error',
+ message: 'Failed to open file preview'
+ });
+ }
+ };
+
+ const handleNextStep = () => {
+ setCurrentStep(1);
};
const renderStepContent = () => {
if (currentStep === 0) {
return (
-
-
- Status
-
-
-
-
+ {loading && (
+
+ top: 0,
+ left: 0,
+ right: 0,
+ bottom: 0,
+ backgroundColor: 'rgba(255, 255, 255, 0.7)',
+ display: 'flex',
+ justifyContent: 'center',
+ alignItems: 'center',
+ zIndex: 10,
+ borderRadius: '8px',
+ }}
+ >
+
-
{(brandData || {}).is_active ? 'Running' : 'Offline'}
-
-
-
- Brand Code
-
-
-
- {brandData?.brand_code || (loading ? 'Loading...' : '-')}
-
-
-
-
-
-
- Brand Name
-
-
-
- {brandData?.brand_name || (loading ? 'Loading...' : '-')}
-
-
-
-
-
- Manufacture
-
-
-
- {brandData?.brand_manufacture || (loading ? 'Loading...' : '-')}
-
-
-
-
-
-
-
-
- Brand Type
-
-
-
- {brandData?.brand_type || (loading ? 'Loading...' : '-')}
-
-
-
-
-
- Model
-
-
-
- {brandData?.brand_model || (loading ? 'Loading...' : '-')}
-
-
-
-
+ )}
+
);
}
if (currentStep === 1) {
- const errorCodes = brandData?.error_code || [];
-
return (
-
-
- Error Codes ({errorCodes.length})
-
-
- {errorCodes.length > 0 ? (
-
- {errorCodes.map((errorCode, index) => (
-
-
- {errorCode.error_code}
-
- - {errorCode.error_code_name}
-
-
-
-
- {errorCode.is_active ? 'Active' : 'Inactive'}
-
-
- {errorCode.solution?.length || 0} solution(s)
-
-
-
- }
- >
-
-
-
Description:
-
- {errorCode.error_code_description || 'No description'}
-
-
-
-
-
Solutions:
- {errorCode.solution && errorCode.solution.length > 0 ? (
-
- {errorCode.solution.map((solution) => (
-
-
-
-
- {solution.type_solution === 'pdf' ? (
-
- ) : solution.type_solution === 'image' ? (
-
- ) : (
-
- )}
- {solution.solution_name}
-
-
-
-
- {solution.type_solution ? solution.type_solution.toUpperCase() : 'TEXT'}
-
-
-
-
-
- {solution.type_solution === 'text' ? (
-
- {solution.text_solution}
-
- ) : (
-
-
- File: {solution.path_document || solution.path_solution || 'Document'}
-
- {(solution.path_document || solution.path_solution) && (
-
- )}
-
- )}
-
-
- ))}
-
- ) : (
-
- No solutions available
-
- )}
-
-
-
- ))}
-
- ) : (
- !loading && (
-
No error codes available
+
+
+ {
+ setSearchText(value);
+ if (value === '') {
+ setTrigerFilter((prev) => !prev);
}
- />
- )
- )}
-
+ }}
+ onSearch={handleSearch}
+ onSearchClear={handleSearchClear}
+ isReadOnly={true}
+ />
+
+
+
+
+ {selectedErrorCode ? (
+
+
+ Error Code Form
+
+ }
+ style={{
+ width: '100%',
+ boxShadow: '0 2px 8px rgba(0,0,0,0.06)',
+ borderRadius: '12px'
+ }}
+ styles={{
+ body: { padding: '16px 24px 12px 24px' },
+ header: {
+ padding: '16px 24px',
+ borderBottom: '1px solid #f0f0f0',
+ backgroundColor: '#fafafa'
+ }
+ }}
+ >
+
+
+
+
+
+ Error Code Details
+
+
+
{ }}
+ onErrorCodeIconRemove={() => { }}
+ isEdit={true}
+ />
+
+
+
+
+
+
+
{ }}
+ onRemoveSolutionField={() => { }}
+ onSolutionTypeChange={() => { }}
+ onSolutionStatusChange={() => { }}
+ onSolutionFileUpload={() => { }}
+ onFileView={(fileData) => {
+ if (fileData && (fileData.url || fileData.uploadPath)) {
+ window.open(fileData.url || fileData.uploadPath, '_blank');
+ }
+ }}
+ isReadOnly={true}
+ solutionData={currentSolutionData}
+ />
+
+
+
+
+
+
+
+ Sparepart Selection
+
+
+
+ { }}
+ isReadOnly={true}
+ />
+
+
+
+
+
+
+ ) : (
+
+
+
+ )}
+
+
+
);
}
-
return null;
};
return (
-
+
-
-
- View Brand Device
-
-
-
- }
- onClick={() => navigate('/master/brand-device')}
- >
- Kembali
-
-
-
-
-
-
-
- {loading && (
-
-
-
- )}
-
-
- {renderStepContent()}
+ {renderStepContent()}
+
+
+
+ {currentStep === 1 && (
+
+ )}
+
+
+ {currentStep === 0 && (
+
+ )}
+ {currentStep === 1 && (
+
+ )}
-
-
-
- {currentStep > 0 && (
-
- )}
- {currentStep < 1 && (
-
- )}
-
-
+
);
};
diff --git a/src/pages/master/brandDevice/ViewFilePage.jsx b/src/pages/master/brandDevice/ViewFilePage.jsx
index 16de7a7..b46b56b 100644
--- a/src/pages/master/brandDevice/ViewFilePage.jsx
+++ b/src/pages/master/brandDevice/ViewFilePage.jsx
@@ -6,10 +6,10 @@ import { ArrowLeftOutlined, FilePdfOutlined, FileImageOutlined, DownloadOutlined
import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb';
import { getBrandById } from '../../../api/master-brand';
import {
- downloadFile,
- getFile,
- getFileUrl,
- getFolderFromFileType,
+ downloadFile,
+ getFile,
+ getFileUrl,
+ getFolderFromFileType,
} from '../../../api/file-uploads';
const { Title } = Typography;
@@ -412,7 +412,7 @@ const ViewFilePage = () => {
- {/* File type indicator */}
+
{
- {/* Overlay with blur effect during loading */}
+
{loading && (
{
const isActive = Form.useWatch('is_active', form) ?? true;
@@ -38,6 +39,7 @@ const BrandForm = ({
@@ -61,18 +63,18 @@ const BrandForm = ({
-
+
-
+
@@ -80,12 +82,12 @@ const BrandForm = ({
-
+
-
+
diff --git a/src/pages/master/brandDevice/component/CustomSparepartCard.jsx b/src/pages/master/brandDevice/component/CustomSparepartCard.jsx
index 5327cee..1dea0a5 100644
--- a/src/pages/master/brandDevice/component/CustomSparepartCard.jsx
+++ b/src/pages/master/brandDevice/component/CustomSparepartCard.jsx
@@ -140,7 +140,7 @@ const CustomSparepartCard = ({
onClick={handleCardClick}
>
- {/* Image Section */}
+
- {/* Selection Indicator */}
+
{isSelected && (
- {/* Content Section */}
+
- {/* Stock and Quantity Information */}
+
- {/* Stock Status Tag */}
+
- {/* Quantity */}
+
- {/* Preview Modal */}
+
- {/* Item Type Tag */}
+
{sparepart.sparepart_item_type && (
@@ -383,7 +383,7 @@ const CustomSparepartCard = ({
)}
- {/* Stock Status and Quantity */}
+
- {/* Sparepart Name */}
+
{sparepart.sparepart_name || 'Unnamed'}
- {/* Basic Information */}
+
@@ -480,7 +480,7 @@ const CustomSparepartCard = ({
- {/* Timeline Information */}
+
{sparepart.created_at && (
diff --git a/src/pages/master/brandDevice/component/ErrorCodeForm.jsx b/src/pages/master/brandDevice/component/ErrorCodeForm.jsx
index 2030332..0dbf604 100644
--- a/src/pages/master/brandDevice/component/ErrorCodeForm.jsx
+++ b/src/pages/master/brandDevice/component/ErrorCodeForm.jsx
@@ -232,15 +232,16 @@ const ErrorCodeForm = ({
-
+
@@ -260,7 +261,9 @@ const ErrorCodeForm = ({
height: '40px',
border: '1px solid #d9d9d9',
borderRadius: 4,
+ cursor: isErrorCodeFormReadOnly ? 'not-allowed' : 'pointer',
}}
+ disabled={isErrorCodeFormReadOnly}
/>
diff --git a/src/pages/master/brandDevice/component/FileUploadHandler.jsx b/src/pages/master/brandDevice/component/FileUploadHandler.jsx
index b0aad6c..6e5b0e0 100644
--- a/src/pages/master/brandDevice/component/FileUploadHandler.jsx
+++ b/src/pages/master/brandDevice/component/FileUploadHandler.jsx
@@ -147,7 +147,7 @@ const FileUploadHandler = ({
}
}
-
+
if (actualPath) {
let fileObject;
@@ -394,9 +394,7 @@ const FileUploadHandler = ({
)}
- {/* renderExistingFile() is disabled because SolutionField.jsx already handles file card rendering */}
- {/* This prevents duplicate card rendering */}
- {/* {renderExistingFile()} */}
+
{showPreview && (
handleDelete(param.brand_id, param.brand_name),
- onCancel: () => {},
+ onCancel: () => { },
});
};
@@ -156,7 +156,7 @@ const ListBrandDevice = memo(function ListBrandDevice(props) {
title: 'Berhasil',
message: `Brand ${brand_name} deleted successfully.`,
});
- doFilter(); // Refresh data
+ doFilter();
} else {
NotifAlert({
icon: 'error',
diff --git a/src/pages/master/brandDevice/component/ListErrorCode.jsx b/src/pages/master/brandDevice/component/ListErrorCode.jsx
index a1f1d01..85fe86c 100644
--- a/src/pages/master/brandDevice/component/ListErrorCode.jsx
+++ b/src/pages/master/brandDevice/component/ListErrorCode.jsx
@@ -14,7 +14,9 @@ const ListErrorCode = ({
searchText,
onSearchChange,
onSearch,
- onSearchClear
+ onSearchClear,
+ isReadOnly = false,
+ errorCodes: propErrorCodes = null
}) => {
const [errorCodes, setErrorCodes] = useState([]);
const [loading, setLoading] = useState(false);
@@ -25,7 +27,7 @@ const ListErrorCode = ({
total_page: 0,
});
const [currentPage, setCurrentPage] = useState(1);
- const pageSize = 15; // Fixed limit 15 items per page
+ const pageSize = 15;
const queryParams = useMemo(() => {
const params = new URLSearchParams();
@@ -79,8 +81,15 @@ const ListErrorCode = ({
};
useEffect(() => {
- fetchErrorCodes();
- }, [brandId, queryParams, tempErrorCodes, trigerFilter]);
+ if (isReadOnly && propErrorCodes) {
+
+ setErrorCodes(propErrorCodes);
+ setLoading(false);
+ } else {
+
+ fetchErrorCodes();
+ }
+ }, [brandId, queryParams, tempErrorCodes, trigerFilter, isReadOnly, propErrorCodes]);
const handlePrevious = () => {
if (pagination.current_page > 1) {
@@ -117,7 +126,7 @@ const ListErrorCode = ({
title: 'Hapus Error Code',
message: `Apakah Anda yakin ingin menghapus error code ${item.error_code}?`,
onConfirm: () => performDelete(item),
- onCancel: () => {},
+ onCancel: () => { },
confirmButtonText: 'Hapus'
});
}
@@ -125,7 +134,7 @@ const ListErrorCode = ({
const performDelete = async (item) => {
try {
- // Additional validation
+
if (!item.error_code_id || item.error_code_id === 'undefined') {
NotifAlert({
icon: 'error',
@@ -144,7 +153,7 @@ const ListErrorCode = ({
return;
}
- const response = await deleteErrorCode(item.brand_id, item.error_code_id);
+ const response = await deleteErrorCode(item.brand_id, item.error_code_id);
if (response && response.statusCode === 200) {
NotifOk({
diff --git a/src/pages/master/brandDevice/component/SolutionField.jsx b/src/pages/master/brandDevice/component/SolutionField.jsx
index d0746b5..4ce54c1 100644
--- a/src/pages/master/brandDevice/component/SolutionField.jsx
+++ b/src/pages/master/brandDevice/component/SolutionField.jsx
@@ -30,28 +30,15 @@ const SolutionFieldNew = ({
const fileUpload = Form.useWatch(['solution_items', fieldKey, 'fileUpload'], form);
const file = Form.useWatch(['solution_items', fieldKey, 'file'], form);
-
- const getSolutionData = () => {
- try {
- return form.getFieldValue(['solution_items', fieldKey]) || {};
- } catch (error) {
- return {};
- }
- };
-
const nameValue = Form.useWatch(['solution_items', fieldKey, 'name'], form);
- const typeValue = Form.useWatch(['solution_items', fieldKey, 'type'], form);
- const textValue = Form.useWatch(['solution_items', fieldKey, 'text'], form);
const fileNameValue = Form.useWatch(['solution_items', fieldKey, 'fileName'], form);
const statusValue = Form.useWatch(['solution_items', fieldKey, 'status'], form) ?? true;
const pathSolution = Form.useWatch(['solution_items', fieldKey, 'path_solution'], form);
const [deleteCounter, setDeleteCounter] = useState(0);
-
- // Reset internal state when form is reset to initial values
+
React.useEffect(() => {
- // Check if form is in initial/reset state (name is empty)
if (!nameValue || nameValue === '') {
setCurrentFile(null);
setIsDeleted(false);
diff --git a/src/pages/master/brandDevice/component/SparepartSelect.jsx b/src/pages/master/brandDevice/component/SparepartSelect.jsx
index 81c3e78..709dbd4 100644
--- a/src/pages/master/brandDevice/component/SparepartSelect.jsx
+++ b/src/pages/master/brandDevice/component/SparepartSelect.jsx
@@ -115,7 +115,7 @@ const SparepartSelect = ({
return (
<>
- {/* Fixed Search Section */}
+
{!isReadOnly && (
)}
- {/* Scrollable Selected Items Section */}
+
{selectedSpareparts.length > 0 ? (