diff --git a/src/App.jsx b/src/App.jsx
index 4581a26..6314408 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -4,7 +4,6 @@ import SignIn from './pages/auth/SignIn';
import SignUp from './pages/auth/Signup';
import { ProtectedRoute } from './ProtectedRoute';
import NotFound from './pages/blank/NotFound';
-import { BrandFormProvider } from './context/BrandFormContext';
// Dashboard
import Home from './pages/home/Home';
@@ -97,33 +96,26 @@ const App = () => {
} />
} />
- {/* Brand Device Routes with BrandFormProvider */}
-
-
- } />
- } />
- } />
- } />
- }
- />
- }
- />
- }
- />
- } />
- } />
- } />
- } />
-
-
- } />
+ {/* Brand Device Routes */}
+ } />
+ } />
+ } />
+ } />
+ }
+ />
+ }
+ />
+ }
+ />
+ } />
+ } />
+ } />
}>
diff --git a/src/api/master-brand.jsx b/src/api/master-brand.jsx
index 99db0ba..908d8ef 100644
--- a/src/api/master-brand.jsx
+++ b/src/api/master-brand.jsx
@@ -66,4 +66,44 @@ const getErrorCodeById = async (id) => {
return response.data;
};
-export { getAllBrands, getBrandById, createBrand, updateBrand, deleteBrand, getErrorCodesByBrandId, getErrorCodeById };
+const createErrorCode = async (brandId, queryParams) => {
+ const response = await SendRequest({
+ method: 'post',
+ prefix: `error-code/brand/${brandId}`,
+ params: queryParams,
+ });
+
+ return response.data;
+};
+
+const updateErrorCode = async (brandId, errorCodeId, queryParams) => {
+ const response = await SendRequest({
+ method: 'put',
+ prefix: `error-code/brand/${brandId}/${errorCodeId}`,
+ params: queryParams,
+ });
+
+ return response.data;
+};
+
+const deleteErrorCode = async (brandId, errorCode) => {
+ const response = await SendRequest({
+ method: 'delete',
+ prefix: `error-code/brand/${brandId}/${errorCode}`,
+ });
+
+ return response.data;
+};
+
+export {
+ getAllBrands,
+ getBrandById,
+ createBrand,
+ updateBrand,
+ deleteBrand,
+ getErrorCodesByBrandId,
+ getErrorCodeById,
+ createErrorCode,
+ updateErrorCode,
+ deleteErrorCode
+};
diff --git a/src/context/BrandFormContext.jsx b/src/context/BrandFormContext.jsx
deleted file mode 100644
index 66a1765..0000000
--- a/src/context/BrandFormContext.jsx
+++ /dev/null
@@ -1,624 +0,0 @@
-import React, { createContext, useContext, useReducer } from 'react';
-import { NotifAlert } from '../components/Global/ToastNotif';
-
-// Initial state
-const initialState = {
- brandId: null,
- routeBrandId: null,
- errorCodeId: null,
- currentStep: 1,
- brandInfo: {
- brand_name: '',
- brand_type: '',
- brand_manufacture: '',
- brand_model: '',
- is_active: true
- },
- tempErrorCodes: [],
- existingErrorCodes: [],
- currentErrorCode: null,
- isLoading: false,
- error: null,
- lastSaved: null
-};
-
-// Action types
-const SET_BRAND_INFO = 'SET_BRAND_INFO';
-const SET_BRAND_ID = 'SET_BRAND_ID';
-const SET_ROUTE_BRAND_ID = 'SET_ROUTE_BRAND_ID';
-const SET_ERROR_CODE_ID = 'SET_ERROR_CODE_ID';
-const SET_CURRENT_STEP = 'SET_CURRENT_STEP';
-const UPDATE_BRAND_FIELD = 'UPDATE_BRAND_FIELD';
-const ADD_ERROR_CODE = 'ADD_ERROR_CODE';
-const UPDATE_ERROR_CODE = 'UPDATE_ERROR_CODE';
-const DELETE_ERROR_CODE = 'DELETE_ERROR_CODE';
-const MARK_AS_DELETED = 'MARK_AS_DELETED';
-const SET_TEMP_ERROR_CODES = 'SET_TEMP_ERROR_CODES';
-const SET_EXISTING_ERROR_CODES = 'SET_EXISTING_ERROR_CODES';
-const MERGE_ERROR_CODES = 'MERGE_ERROR_CODES';
-const SET_CURRENT_ERROR_CODE = 'SET_CURRENT_ERROR_CODE';
-const SET_LOADING = 'SET_LOADING';
-const SET_ERROR = 'SET_ERROR';
-const RESET_FORM = 'RESET_FORM';
-const SET_LAST_SAVED = 'SET_LAST_SAVED';
-
-// Reducer function
-const brandFormReducer = (state, action) => {
- switch (action.type) {
- case SET_BRAND_INFO:
- return {
- ...state,
- brandInfo: action.payload
- };
-
- case SET_BRAND_ID:
- return {
- ...state,
- brandId: action.payload
- };
-
- case SET_ROUTE_BRAND_ID:
- return {
- ...state,
- routeBrandId: action.payload
- };
-
- case SET_ERROR_CODE_ID:
- return {
- ...state,
- errorCodeId: action.payload
- };
-
- case SET_CURRENT_STEP:
- return {
- ...state,
- currentStep: action.payload
- };
-
- case UPDATE_BRAND_FIELD:
- return {
- ...state,
- brandInfo: {
- ...state.brandInfo,
- [action.payload.field]: action.payload.value
- }
- };
-
- case ADD_ERROR_CODE:
- const newErrorCode = {
- tempId: Date.now(),
- error_code: '',
- error_code_name: '',
- error_code_description: '',
- error_code_color: '#000000ff',
- path_icon: '',
- is_active: true,
- solutions: [],
- spareparts: [],
- status: 'new',
- created_at: new Date().toISOString()
- };
- return {
- ...state,
- tempErrorCodes: [...state.tempErrorCodes, newErrorCode]
- };
-
- case UPDATE_ERROR_CODE:
- const { tempId, data } = action.payload;
-
- if (tempId.startsWith('existing_')) {
- return {
- ...state,
- existingErrorCodes: state.existingErrorCodes.map(ec =>
- `existing_${ec.error_code_id}` === tempId
- ? {
- ...ec,
- ...data,
- status: 'modified',
- updated_at: new Date().toISOString()
- }
- : ec
- )
- };
- } else {
- // Update in tempErrorCodes
- return {
- ...state,
- tempErrorCodes: state.tempErrorCodes.map(ec =>
- ec.tempId === tempId
- ? {
- ...ec,
- ...data,
- status: ec.status === 'new' ? 'new' : 'modified',
- updated_at: new Date().toISOString()
- }
- : ec
- )
- };
- }
-
- case DELETE_ERROR_CODE:
- return {
- ...state,
- tempErrorCodes: state.tempErrorCodes.filter(ec => ec.tempId !== action.payload)
- };
-
- case MARK_AS_DELETED:
- const deleteTempId = action.payload;
-
- // Check if it's an existing error code (format: existing_${error_code_id})
- if (deleteTempId.startsWith('existing_')) {
- return {
- ...state,
- existingErrorCodes: state.existingErrorCodes.map(ec =>
- `existing_${ec.error_code_id}` === deleteTempId
- ? {
- ...ec,
- status: 'deleted',
- is_active: false,
- deleted_at: new Date().toISOString()
- }
- : ec
- )
- };
- } else {
- return {
- ...state,
- tempErrorCodes: state.tempErrorCodes.map(ec =>
- ec.tempId === deleteTempId
- ? {
- ...ec,
- status: 'deleted',
- is_active: false,
- deleted_at: new Date().toISOString()
- }
- : ec
- )
- };
- }
-
- case SET_TEMP_ERROR_CODES:
- return {
- ...state,
- tempErrorCodes: action.payload
- };
-
- case SET_EXISTING_ERROR_CODES:
- return {
- ...state,
- existingErrorCodes: action.payload
- };
-
- case MERGE_ERROR_CODES:
- return {
- ...state,
- existingErrorCodes: action.payload.existing || [],
- tempErrorCodes: action.payload.temporary || []
- };
-
- case SET_LOADING:
- return {
- ...state,
- isLoading: action.payload
- };
-
- case SET_ERROR:
- return {
- ...state,
- error: action.payload
- };
-
- case RESET_FORM:
- return { ...initialState, lastSaved: state.lastSaved };
-
- case SET_CURRENT_ERROR_CODE:
- return {
- ...state,
- currentErrorCode: action.payload
- };
-
- case SET_LAST_SAVED:
- return {
- ...state,
- lastSaved: action.payload
- };
-
- default:
- return state;
- }
-};
-
-// Create context
-const BrandFormContext = createContext();
-
-export const BrandFormProvider = ({ children }) => {
- const [state, dispatch] = useReducer(brandFormReducer, initialState);
-
- // Actions
- const actions = {
- setBrandId: (brandId) => {
- dispatch({ type: SET_BRAND_ID, payload: brandId });
- },
-
- setRouteBrandId: (routeBrandId) => {
- dispatch({ type: SET_ROUTE_BRAND_ID, payload: routeBrandId });
- },
-
- setErrorCodeId: (errorCodeId) => {
- dispatch({ type: SET_ERROR_CODE_ID, payload: errorCodeId });
- },
-
- setCurrentStep: (step) => {
- dispatch({ type: SET_CURRENT_STEP, payload: step });
- },
-
- getCurrentBrandId: () => {
- return state.brandId || state.routeBrandId;
- },
-
- setBrandInfo: (brandInfo) => {
- dispatch({ type: SET_BRAND_INFO, payload: brandInfo });
- },
-
- updateBrandField: (field, value) => {
- dispatch({ type: UPDATE_BRAND_FIELD, payload: { field, value } });
- },
-
- addErrorCode: (errorCodeData = {}) => {
- const defaultErrorCode = {
- tempId: Date.now(),
- error_code: '',
- error_code_name: '',
- error_code_description: '',
- error_code_color: '#000000ff',
- path_icon: '',
- is_active: true,
- solutions: [],
- spareparts: [],
- status: 'new',
- created_at: new Date().toISOString()
- };
- const newErrorCode = { ...defaultErrorCode, ...errorCodeData };
- dispatch({ type: ADD_ERROR_CODE, payload: newErrorCode });
- },
-
- updateErrorCode: (tempId, data) => {
- dispatch({ type: UPDATE_ERROR_CODE, payload: { tempId, data } });
- },
-
- deleteErrorCode: (tempId, isPermanent = false) => {
- if (isPermanent) {
- dispatch({ type: DELETE_ERROR_CODE, payload: tempId });
- } else {
- dispatch({ type: MARK_AS_DELETED, payload: tempId });
- }
- },
-
- markAsDeleted: (tempId) => {
- dispatch({ type: MARK_AS_DELETED, payload: tempId });
- },
-
- setTempErrorCodes: (errorCodes) => {
- dispatch({ type: SET_TEMP_ERROR_CODES, payload: errorCodes });
- },
-
- setExistingErrorCodes: (errorCodes) => {
- dispatch({ type: SET_EXISTING_ERROR_CODES, payload: errorCodes });
- },
-
- mergeErrorCodes: (existing, temporary) => {
- dispatch({ type: MERGE_ERROR_CODES, payload: { existing, temporary } });
- },
-
- setLoading: (isLoading) => {
- dispatch({ type: SET_LOADING, payload: isLoading });
- },
-
- setError: (error) => {
- dispatch({ type: SET_ERROR, payload: error });
- },
-
- resetForm: () => {
- dispatch({ type: RESET_FORM });
- },
-
- setLastSaved: (timestamp) => {
- dispatch({ type: SET_LAST_SAVED, payload: timestamp });
- },
-
- setCurrentErrorCode: (errorCode) => {
- dispatch({ type: SET_CURRENT_ERROR_CODE, payload: errorCode });
- },
-
- // Initialize context with route parameters
- initializeFromRoute: (routeBrandId, errorCodeId = null) => {
- dispatch({ type: SET_ROUTE_BRAND_ID, payload: routeBrandId });
- if (errorCodeId) {
- dispatch({ type: SET_ERROR_CODE_ID, payload: errorCodeId });
- }
- },
-
- // Navigate to specific step with parameter handling
- navigateToStep: (step, brandId = null, errorCodeId = null) => {
- dispatch({ type: SET_CURRENT_STEP, payload: step });
- if (brandId) {
- dispatch({ type: SET_BRAND_ID, payload: brandId });
- }
- if (errorCodeId) {
- dispatch({ type: SET_ERROR_CODE_ID, payload: errorCodeId });
- }
- },
-
- // Utility functions
- getErrorCodeByTempId: (tempId) => {
- return state.tempErrorCodes.find(ec => ec.tempId === tempId);
- },
-
- getActiveErrorCodes: () => {
- return state.tempErrorCodes.filter(ec => ec.status !== 'deleted');
- },
-
- getModifiedErrorCodes: () => {
- return state.tempErrorCodes.filter(ec =>
- ec.status === 'new' || ec.status === 'modified' || ec.status === 'deleted'
- );
- },
-
- hasChanges: () => {
- return state.tempErrorCodes.some(ec =>
- ec.status === 'new' || ec.status === 'modified' || ec.status === 'deleted'
- );
- },
-
- validateForm: () => {
- const errors = {};
-
- // Validate brand info
- if (!state.brandInfo.brand_name?.trim()) {
- errors.brand = 'Brand name is required';
- NotifAlert({
- icon: 'warning',
- title: 'Validasi Gagal',
- message: 'Brand name wajib diisi!',
- });
- return { isValid: false, errors };
- }
-
- if (!state.brandInfo.brand_manufacture?.trim()) {
- errors.brand_manufacture = 'Brand manufacture is required';
- NotifAlert({
- icon: 'warning',
- title: 'Validasi Gagal',
- message: 'Brand manufacture wajib diisi!',
- });
- return { isValid: false, errors };
- }
-
- const allActiveErrorCodes = [
- ...state.existingErrorCodes,
- ...state.tempErrorCodes.filter(ec => ec.status !== 'deleted')
- ];
-
- if (allActiveErrorCodes.length === 0) {
- errors.errorCodes = 'At least one error code is required';
- NotifAlert({
- icon: 'warning',
- title: 'Validasi Gagal',
- message: 'Brand harus memiliki minimal 1 error code!',
- });
- return { isValid: false, errors };
- }
-
- // Validate each error code
- allActiveErrorCodes.forEach((ec, index) => {
- if (!ec.error_code?.trim()) {
- errors[`errorCode_${ec.tempId || ec.error_code_id}`] = 'Error code is required';
- }
- if (!ec.error_code_name?.trim()) {
- errors[`errorCodeName_${ec.tempId || ec.error_code_id}`] = 'Error code name is required';
- }
-
- let solutionsToCheck = [];
- if (ec.solution && Array.isArray(ec.solution)) {
- solutionsToCheck = ec.solution;
- } else if (ec.solutions && Array.isArray(ec.solutions)) {
- solutionsToCheck = ec.solutions;
- }
-
- if (solutionsToCheck.length > 0) {
- const activeSolutions = solutionsToCheck.filter(sol => sol.status !== 'deleted');
- if (activeSolutions.length === 0) {
- errors[`solutions_${ec.tempId || ec.error_code_id}`] = 'Setiap error code harus memiliki minimal 1 solution';
- }
- } else {
- errors[`solutions_${ec.tempId || ec.error_code_id}`] = 'Setiap error code harus memiliki minimal 1 solution';
- }
-
- if (ec.spareparts && Array.isArray(ec.spareparts)) {
- ec.spareparts.forEach((sp, spIndex) => {
- if (sp === undefined || sp === null || sp === '') {
- console.error(`❌ Error Code ${index}, Sparepart ${spIndex}: sparepart_id is undefined, null, or empty`);
- }
- });
- }
- });
-
- if (Object.keys(errors).length > 0) {
- NotifAlert({
- icon: 'warning',
- title: 'Validasi Gagal',
- message: 'Perbaiki error yang ada sebelum melanjutkan!',
- });
- }
-
- return { isValid: Object.keys(errors).length === 0, errors };
- },
-
- prepareSubmissionData: (userId) => {
- const allErrorCodes = [
- ...state.existingErrorCodes.map(ec => ({
- ...ec,
- tempId: `existing_${ec.error_code_id}`,
- status: 'existing'
- })),
- ...state.tempErrorCodes
- ];
-
- const finalErrorCodes = allErrorCodes
- .filter(ec => ec.status !== 'deleted')
- .map(ec => {
- const cleanedCode = {
- error_code: ec.error_code || '',
- error_code_name: ec.error_code_name || '',
- error_code_description: ec.error_code_description || '',
- error_code_color: ec.error_code_color || '#000000',
- path_icon: ec.path_icon || '',
- is_active: ec.is_active === true ? 1 : 0,
- solution: [],
- spareparts: []
- };
-
- if (ec.error_code_id && ec.status === 'existing') {
- cleanedCode.error_code_id = parseInt(ec.error_code_id);
- }
-
- // Handle both solution and solutions fields for compatibility
- let solutions = [];
- if (ec.solution && Array.isArray(ec.solution)) {
- solutions = ec.solution;
- } else if (ec.solutions && Array.isArray(ec.solutions)) {
- solutions = ec.solutions;
- }
-
- if (solutions.length > 0) {
- cleanedCode.solution = solutions
- .filter(sol => sol && sol.solution_name)
- .map(sol => ({
- solution_name: sol.solution_name || '',
- type_solution: sol.type_solution || 'text',
- text_solution: sol.text_solution || '',
- path_solution: sol.path_solution || '',
- is_active: sol.is_active === true ? 1 : 0
- }));
- }
-
- if (ec.spareparts && Array.isArray(ec.spareparts)) {
- cleanedCode.spareparts = ec.spareparts
- .filter(sp => sp !== undefined && sp !== null && sp !== '' && sp !== 0)
- .map(sp => {
- let sparepartId = 0;
- if (typeof sp === 'object' && sp !== null) {
- sparepartId = sp.sparepart_id || sp.id || sp.sparepartId || 0;
- } else if (typeof sp === 'string' || typeof sp === 'number') {
- sparepartId = parseInt(sp) || 0;
- }
- return parseInt(sparepartId) || 0;
- })
- .filter(id => id > 0);
- }
-
- return cleanedCode;
- });
-
- const submissionData = {
- brand_name: state.brandInfo.brand_name || '',
- brand_type: state.brandInfo.brand_type || '',
- brand_manufacture: state.brandInfo.brand_manufacture || '',
- brand_model: state.brandInfo.brand_model || '',
- is_active: state.brandInfo.is_active === true ? 1 : 0,
- error_code: finalErrorCodes,
- updated_by: parseInt(userId) || 1
- };
-
- // console.log(' Prepared flat submission data:', JSON.stringify(submissionData, null, 2));
-
- return submissionData;
- },
-
- getAllErrorCodes: () => {
- return [
- ...state.existingErrorCodes.map(ec => ({
- ...ec,
- tempId: `existing_${ec.error_code_id}`,
- status: 'existing'
- })),
- ...state.tempErrorCodes
- ];
- },
-
- getErrorCodeById: (id) => {
- const existingCode = state.existingErrorCodes.find(ec => ec.error_code_id == id);
- if (existingCode) {
- return {
- ...existingCode,
- tempId: `existing_${existingCode.error_code_id}`,
- status: 'existing'
- };
- }
-
- return state.tempErrorCodes.find(ec => ec.tempId == id);
- },
-
- // Enhanced error code management
- loadErrorCodesForBrand: async (brandId) => {
- dispatch({ type: SET_LOADING, payload: true });
- try {
- const { getErrorCodesByBrandId } = await import('../api/master-brand');
- const response = await getErrorCodesByBrandId(brandId);
-
- if (response && response.data) {
- dispatch({ type: SET_EXISTING_ERROR_CODES, payload: response.data });
- }
- return response;
- } catch (error) {
- dispatch({ type: SET_ERROR, payload: error.message });
- throw error;
- } finally {
- dispatch({ type: SET_LOADING, payload: false });
- }
- },
-
- // Smart navigation helper
- navigateToErrorCodes: (brandId) => {
- const currentId = brandId || state.brandId || state.routeBrandId;
- if (currentId) {
- dispatch({ type: SET_BRAND_ID, payload: currentId });
- dispatch({ type: SET_CURRENT_STEP, payload: 2 });
- return currentId;
- }
- return null;
- },
-
- editErrorCode: (errorCodeId, brandId) => {
- const currentBrandId = brandId || state.brandId || state.routeBrandId;
- if (currentBrandId && errorCodeId) {
- dispatch({ type: SET_BRAND_ID, payload: currentBrandId });
- dispatch({ type: SET_ERROR_CODE_ID, payload: errorCodeId });
- dispatch({ type: SET_CURRENT_STEP, payload: 3 });
- return { brandId: currentBrandId, errorCodeId };
- }
- return null;
- }
- };
-
- const value = {
- ...state,
- ...actions
- };
-
- return (
-
- {children}
-
- );
-};
-
-export const useBrandForm = () => {
- const context = useContext(BrandFormContext);
- if (!context) {
- throw new Error('useBrandForm must be used within a BrandFormProvider');
- }
- return context;
-};
-
-export default BrandFormContext;
\ No newline at end of file
diff --git a/src/pages/master/brandDevice/AddBrandDevice.jsx b/src/pages/master/brandDevice/AddBrandDevice.jsx
index 00d1ddc..88310a8 100644
--- a/src/pages/master/brandDevice/AddBrandDevice.jsx
+++ b/src/pages/master/brandDevice/AddBrandDevice.jsx
@@ -19,10 +19,9 @@ import TableList from '../../../components/Global/TableList';
import { ConfigProvider } from 'antd';
import { NotifAlert, NotifOk, NotifConfirmDialog } from '../../../components/Global/ToastNotif';
import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb';
-import { createBrand } from '../../../api/master-brand';
+import { createBrand, createErrorCode, getErrorCodesByBrandId, updateErrorCode, deleteErrorCode } from '../../../api/master-brand';
import BrandForm from './component/BrandForm';
import { useSolutionLogic } from './hooks/solution';
-import { useBrandForm } from '../../../context/BrandFormContext';
const { Title } = Typography;
const { Step } = Steps;
@@ -32,32 +31,24 @@ const AddBrandDevice = () => {
const [searchParams] = useSearchParams();
const { setBreadcrumbItems } = useBreadcrumb();
const [brandForm] = Form.useForm();
- const [solutionForm] = Form.useForm();
- const [errorCodeIcon, setErrorCodeIcon] = useState(null);
- const [selectedSparepartIds, setSelectedSparepartIds] = useState([]);
const [loading, setLoading] = useState(false);
const [confirmLoading, setConfirmLoading] = useState(false);
const [searchValue, setSearchValue] = useState('');
const [searchText, setSearchText] = useState('');
const [trigerFilter, setTrigerFilter] = useState(false);
+ const [currentStep, setCurrentStep] = useState(0);
+ const [createdBrandId, setCreatedBrandId] = useState(null);
+ const [brandData, setBrandData] = useState({});
+ const [tempErrorCodes, setTempErrorCodes] = useState([]);
- // Context integration
- const {
- brandId,
- brandInfo,
- setBrandInfo,
- tempErrorCodes,
- addErrorCode,
- updateErrorCode,
- deleteErrorCode,
- prepareSubmissionData,
- validateForm,
- resetForm,
- } = useBrandForm();
-
- // Use step from query parameter or context
- const tab = searchParams.get('tab');
- const [currentStep, setCurrentStep] = useState(tab === 'error-codes' ? 1 : 0);
+ // Error code management states
+ const [errorCodeForm] = Form.useForm();
+ const [solutionForm] = Form.useForm();
+ const [errorCodeIcon, setErrorCodeIcon] = useState(null);
+ const [selectedSparepartIds, setSelectedSparepartIds] = useState([]);
+ const [editingErrorCodeKey, setEditingErrorCodeKey] = useState(null);
+ const [isErrorCodeFormReadOnly, setIsErrorCodeFormReadOnly] = useState(false);
+ const [isAddingNewErrorCode, setIsAddingNewErrorCode] = useState(false);
const {
solutionFields,
@@ -77,14 +68,54 @@ const AddBrandDevice = () => {
// Navigation functions
const handleNextStep = async () => {
try {
- await brandForm.validateFields();
- setCurrentStep(1);
+ setConfirmLoading(true);
+ const brandValues = await brandForm.validateFields();
+ const userId = JSON.parse(localStorage.getItem('user') || '{}').user_id || 1;
+
+ // Prepare brand data for API
+ const brandApiData = {
+ brand_name: brandValues.brand_name,
+ brand_type: brandValues.brand_type || '',
+ brand_manufacture: brandValues.brand_manufacture || '',
+ brand_model: brandValues.brand_model || '',
+ is_active: brandValues.is_active !== undefined ? brandValues.is_active : true
+ };
+
+ // Create brand via API
+ const response = await createBrand(brandApiData);
+
+ if (response && (response.statusCode === 200 || response.statusCode === 201)) {
+ const createdBrand = response.data;
+ setCreatedBrandId(createdBrand.brand_id);
+ setBrandData(createdBrand);
+
+
+ NotifOk({
+ icon: 'success',
+ title: 'Berhasil',
+ message: 'Brand device berhasil dibuat. Silakan tambahkan error codes.',
+ });
+
+ setCurrentStep(1);
+ // Trigger refresh untuk error codes table di fase 2
+ setTimeout(() => {
+ setTrigerFilter(prev => !prev);
+ }, 100);
+ } else {
+ NotifAlert({
+ icon: 'error',
+ title: 'Gagal',
+ message: response?.message || 'Gagal membuat brand device',
+ });
+ }
} catch (error) {
NotifAlert({
- icon: 'warning',
- title: 'Perhatian',
- message: 'Harap isi semua kolom wajib untuk brand device!',
+ icon: 'error',
+ title: 'Gagal',
+ message: error.message || 'Gagal membuat brand device',
});
+ } finally {
+ setConfirmLoading(false);
}
};
@@ -97,13 +128,50 @@ const AddBrandDevice = () => {
};
const handleAddErrorCode = () => {
- navigate(`/master/brand-device/add/error-code/add`);
+ if (createdBrandId) {
+ resetErrorCodeForm();
+ setIsAddingNewErrorCode(true);
+ setIsErrorCodeFormReadOnly(false);
+ setEditingErrorCodeKey(null);
+ } else {
+ NotifAlert({
+ icon: 'warning',
+ title: 'Perhatian',
+ message: 'Brand device harus dibuat terlebih dahulu.',
+ });
+ }
};
- const handleEditErrorCodeNavigate = (record) => {
- const errorCodeId = record.status === 'existing' ? record.error_code_id : record.tempId;
- if (errorCodeId) {
- navigate(`/master/brand-device/add/error-code/edit/${errorCodeId}`);
+ const handleEditErrorCode = (record) => {
+ if (createdBrandId) {
+ setIsAddingNewErrorCode(false);
+ setIsErrorCodeFormReadOnly(false);
+ setEditingErrorCodeKey(record.error_code_id);
+
+ // Load error code data into form
+ errorCodeForm.setFieldsValue({
+ error_code: record.error_code,
+ error_code_name: record.error_code_name || '',
+ error_code_description: record.error_code_description || '',
+ error_code_color: record.error_code_color || '#000000',
+ status: record.is_active !== false,
+ });
+
+ if (record.path_icon) {
+ setErrorCodeIcon({
+ name: record.path_icon.split('/').pop(),
+ uploadPath: record.path_icon,
+ url: record.path_icon,
+ });
+ }
+
+ if (record.solution && record.solution.length > 0) {
+ setSolutionsForExistingRecord(record.solution, solutionForm);
+ }
+
+ if (record.spareparts && record.spareparts.length > 0) {
+ setSelectedSparepartIds(record.spareparts);
+ }
}
};
@@ -112,15 +180,33 @@ const AddBrandDevice = () => {
icon: 'question',
title: 'Konfirmasi Hapus',
message: `Apakah Anda yakin ingin menghapus error code "${record.error_code}"?`,
- onConfirm: () => {
- const tempId = record.tempId || `existing_${record.error_code_id}`;
- deleteErrorCode(tempId, false); // false = soft delete
- NotifOk({
- icon: 'success',
- title: 'Berhasil',
- message: 'Error code berhasil dihapus!',
- });
- setTrigerFilter(prev => !prev);
+ onConfirm: async () => {
+ try {
+ const errorCodeToDelete = record.error_code_id;
+ const response = await deleteErrorCode(createdBrandId, 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) {
+ console.error('Error deleting error code:', error);
+ NotifAlert({
+ icon: 'error',
+ title: 'Gagal',
+ message: error.message || 'Gagal menghapus error code',
+ });
+ }
},
onCancel: () => {}
});
@@ -142,8 +228,8 @@ const AddBrandDevice = () => {
};
const handleBrandFormValuesChange = useCallback((changedValues, allValues) => {
- setBrandInfo(allValues);
- }, [setBrandInfo]);
+ setBrandData(allValues);
+ }, []);
const getErrorCodesData = async (params) => {
try {
@@ -151,12 +237,33 @@ const AddBrandDevice = () => {
const page = parseInt(params.get('page')) || 1;
const limit = parseInt(params.get('limit')) || 10;
- const allErrorCodes = tempErrorCodes.filter(ec => ec.status !== 'deleted');
+ let allErrorCodes = [];
- let filteredData = allErrorCodes;
+ // Get error codes from API if brand is created
+ if (createdBrandId) {
+ const queryParams = new URLSearchParams({
+ page: page.toString(),
+ limit: limit.toString(),
+ ...(search && { search })
+ });
+ const response = await getErrorCodesByBrandId(createdBrandId, queryParams);
+ if (response && response.statusCode === 200) {
+ const apiErrorData = response.data || [];
+ allErrorCodes = apiErrorData.map(ec => ({
+ ...ec,
+ tempId: `existing_${ec.error_code_id}`,
+ status: 'existing'
+ }));
+ }
+ }
+
+ // Add temp error codes
+ allErrorCodes = [...allErrorCodes, ...tempErrorCodes.filter(ec => ec.status !== 'deleted')];
+
+ // Filter by search text if needed
if (searchText) {
- filteredData = allErrorCodes.filter(ec =>
+ allErrorCodes = allErrorCodes.filter(ec =>
ec.error_code.toLowerCase().includes(searchText.toLowerCase()) ||
ec.error_code_name.toLowerCase().includes(searchText.toLowerCase())
);
@@ -164,15 +271,15 @@ const AddBrandDevice = () => {
const startIndex = 0;
const endIndex = startIndex + limit;
- const paginatedData = filteredData.slice(startIndex, endIndex);
+ const paginatedData = allErrorCodes.slice(startIndex, endIndex);
return {
data: paginatedData,
pagination: {
current_page: page,
current_limit: limit,
- total_limit: filteredData.length,
- total_page: Math.ceil(filteredData.length / limit),
+ total_limit: allErrorCodes.length,
+ total_page: Math.ceil(allErrorCodes.length / limit),
}
};
} catch (error) {
@@ -264,39 +371,120 @@ const AddBrandDevice = () => {
return params;
}, [searchValue]);
- const handleFinish = async () => {
- setConfirmLoading(true);
+ const resetErrorCodeForm = () => {
+ errorCodeForm.resetFields();
+ errorCodeForm.setFieldsValue({
+ status: true,
+ });
+ setErrorCodeIcon(null);
+ resetSolutionFields();
+ setIsErrorCodeFormReadOnly(false);
+ setEditingErrorCodeKey(null);
+ setSelectedSparepartIds([]);
+ setIsAddingNewErrorCode(false);
+ };
+
+ const handleSaveErrorCode = async () => {
try {
- // Validate form using context
- const validation = validateForm();
- if (!validation.isValid) {
+ await errorCodeForm.validateFields();
+
+ const solutionValues = solutionForm.getFieldsValue();
+ const commaPath = `solution_items,${solutionFields[0]?.key || 0}`;
+ const dotPath = `solution_items.${solutionFields[0]?.key || 0}`;
+ const firstSolution = solutionValues[commaPath] || solutionValues[dotPath];
+
+ let isValid = false;
+ if (firstSolution && firstSolution.name && firstSolution.name.trim() !== '') {
+ const firstSolutionType = solutionTypes[solutionFields[0]?.key || 0];
+ if (firstSolutionType === 'text') {
+ isValid = firstSolution.text && firstSolution.text.trim() !== '';
+ } else {
+ isValid = true;
+ }
+ }
+
+ if (!isValid) {
+ NotifAlert({
+ icon: 'warning',
+ title: 'Perhatian',
+ message: 'Harap lengkapi minimal 1 solution',
+ });
return;
}
- const submissionData = prepareSubmissionData(1);
+ const errorCodeValues = errorCodeForm.getFieldsValue();
+ const solutionData = getSolutionData();
- const response = await createBrand(submissionData);
+ const payload = {
+ error_code_name: errorCodeValues.error_code_name,
+ error_code_description: errorCodeValues.error_code_description || '',
+ error_code_color: errorCodeValues.error_code_color || '#000000',
+ path_icon: errorCodeIcon?.uploadPath || '',
+ is_active: errorCodeValues.status !== undefined ? errorCodeValues.status : true,
+ solution: solutionData || [],
+ spareparts: selectedSparepartIds || []
+ };
+
+ // For create, include error_code field (required)
+ if (isAddingNewErrorCode) {
+ payload.error_code = errorCodeValues.error_code;
+ }
+
+ let response;
+
+ if (isAddingNewErrorCode) {
+ response = await createErrorCode(createdBrandId, payload);
+ } else {
+ response = await updateErrorCode(createdBrandId, editingErrorCodeKey, payload);
+ }
if (response && (response.statusCode === 200 || response.statusCode === 201)) {
NotifOk({
icon: 'success',
title: 'Berhasil',
- message: response.message || 'Brand Device berhasil ditambahkan.',
+ message: isAddingNewErrorCode ? 'Error Code berhasil ditambahkan!' : 'Error Code berhasil diupdate!',
});
- resetForm();
- navigate('/master/brand-device');
+
+ resetErrorCodeForm();
+ setTrigerFilter(prev => !prev);
} else {
NotifAlert({
icon: 'error',
title: 'Gagal',
- message: response?.message || 'Gagal menambahkan Brand Device',
+ message: response?.message || 'Gagal menyimpan error code',
});
}
+ } catch (error) {
+ console.error('Error saving error code:', error);
+ NotifAlert({
+ icon: 'error',
+ title: 'Gagal',
+ message: error.message || 'Gagal menyimpan error code. Silakan coba lagi.',
+ });
+ }
+ };
+
+
+ const handleErrorCodeIconRemove = () => {
+ setErrorCodeIcon(null);
+ };
+
+
+ const handleFinish = async () => {
+ setConfirmLoading(true);
+ try {
+ // Fase 2 completion - brand sudah dibuat di fase 1
+ NotifOk({
+ icon: 'success',
+ title: 'Brand Device Tersimpan',
+ message: 'Brand device telah berhasil disimpan dengan error codes yang ditambahkan.',
+ });
+ navigate('/master/brand-device');
} catch (error) {
NotifAlert({
icon: 'error',
title: 'Gagal',
- message: error.message || 'Gagal menyimpan data. Silakan coba lagi.',
+ message: error.message || 'Terjadi kesalahan. Silakan coba lagi.',
});
} finally {
setConfirmLoading(false);
@@ -391,7 +579,7 @@ const AddBrandDevice = () => {
>
}
- onClick={handleAddErrorCode}
+ onClick={() => navigate(`/master/brand-device/${createdBrandId}/error-code/add`)}
size="large"
>
Add Error Code
@@ -407,11 +595,11 @@ const AddBrandDevice = () => {
cardColor={'#42AAFF'}
header={'error_code'}
showPreviewModal={handlePreviewErrorCode}
- showEditModal={handleEditErrorCodeNavigate}
+ showEditModal={(record) => navigate(`/master/brand-device/${createdBrandId}/error-code/edit/${record.error_code_id}`)}
showDeleteDialog={handleDeleteErrorCode}
getData={getErrorCodesData}
queryParams={queryParams}
- columns={errorCodeColumns(handlePreviewErrorCode, handleEditErrorCodeNavigate, handleDeleteErrorCode)}
+ columns={errorCodeColumns(handlePreviewErrorCode, (record) => navigate(`/master/brand-device/${createdBrandId}/error-code/edit/${record.error_code_id}`), handleDeleteErrorCode)}
triger={trigerFilter}
/>
@@ -447,6 +635,12 @@ const AddBrandDevice = () => {
]);
}, [setBreadcrumbItems, navigate]);
+ useEffect(() => {
+ if (createdBrandId && currentStep === 1) {
+ setTrigerFilter(prev => !prev);
+ }
+ }, [createdBrandId, currentStep]);
+
return (
@@ -525,7 +719,7 @@ const AddBrandDevice = () => {
borderColor: '#23A55A',
}}
>
- Save Brand Device
+ Selesai
)}
diff --git a/src/pages/master/brandDevice/AddEditErrorCode.jsx b/src/pages/master/brandDevice/AddEditErrorCode.jsx
index 99af522..fb65629 100644
--- a/src/pages/master/brandDevice/AddEditErrorCode.jsx
+++ b/src/pages/master/brandDevice/AddEditErrorCode.jsx
@@ -1,5 +1,5 @@
import { useEffect, useState } from 'react';
-import { useNavigate, useParams } from 'react-router-dom';
+import { useNavigate, useParams, useLocation } from 'react-router-dom';
import {
Card,
Typography,
@@ -11,10 +11,8 @@ import {
Upload,
} from 'antd';
import { ArrowLeftOutlined, UploadOutlined } from '@ant-design/icons';
-import { getBrandById, getErrorCodeById, updateBrand, getErrorCodesByBrandId } from '../../../api/master-brand';
+import { getBrandById, getErrorCodeById, updateBrand, getErrorCodesByBrandId, createErrorCode, updateErrorCode } from '../../../api/master-brand';
import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb';
-import { useBrandForm } from '../../../context/BrandFormContext';
-import { uploadFile } from '../../../api/file-uploads';
import ErrorCodeSimpleForm from './component/ErrorCodeSimpleForm';
import SolutionForm from './component/SolutionForm';
import { useSolutionLogic } from './hooks/solution';
@@ -27,23 +25,12 @@ const AddEditErrorCode = () => {
const navigate = useNavigate();
const { brandId: routeBrandId, errorCodeId } = useParams();
const { setBreadcrumbItems } = useBreadcrumb();
+ const location = useLocation();
- // Use BrandForm context
- const {
- brandId: contextBrandId,
- routeBrandId: contextRouteBrandId,
- setRouteBrandId,
- setErrorCodeId,
- initializeFromRoute,
- tempErrorCodes,
- existingErrorCodes,
- addErrorCode,
- updateErrorCode,
- setCurrentErrorCode
- } = useBrandForm();
+ const currentBrandId = routeBrandId;
- // Use brandId from context first, fallback to route
- const currentBrandId = contextBrandId || routeBrandId;
+ const isFromAddBrand = location.pathname.includes('/master/brand-device/') && location.pathname.includes('/error-code/') &&
+ (location.pathname.includes('/add') || (location.pathname.includes('/edit/') && !location.pathname.includes('/edit/')));
// Forms
const [errorCodeForm] = Form.useForm();
@@ -75,11 +62,7 @@ const AddEditErrorCode = () => {
const isEditMode = errorCodeId && errorCodeId !== 'add';
setIsEdit(isEditMode);
- // Initialize context with route parameters
- if (routeBrandId) {
- initializeFromRoute(routeBrandId, errorCodeId);
- }
-
+
setBreadcrumbItems([
{
title: • Master
@@ -114,7 +97,6 @@ const AddEditErrorCode = () => {
]);
if (isEditMode && errorCodeId) {
- // For existing error codes, construct the proper tempId format
const tempId = errorCodeId.startsWith('existing_') ? errorCodeId : `existing_${errorCodeId}`;
loadExistingErrorCode(tempId);
}
@@ -124,113 +106,56 @@ const AddEditErrorCode = () => {
try {
setLoading(true);
- // console.log(' Looking for error code with tempId:', tempId);
- // console.log(' Available error codes in context:', tempErrorCodes);
-
- // Find error code in tempErrorCodes first
- let existingErrorCode = tempErrorCodes.find(ec => ec.tempId === tempId);
-
- // If not found, check in existingErrorCodes with format existing_${error_code_id}
- if (!existingErrorCode && tempId.startsWith('existing_')) {
- const errorId = tempId.replace('existing_', '');
- existingErrorCode = existingErrorCodes.find(ec => ec.error_code_id == errorId);
- if (existingErrorCode) {
- existingErrorCode = {
- ...existingErrorCode,
- tempId: tempId
- };
- }
+ let errorIdToUse = tempId;
+ if (tempId.startsWith('existing_')) {
+ errorIdToUse = tempId.replace('existing_', '');
}
- // console.log(' Found error code in context:', existingErrorCode);
+ const errorCodeResponse = await getErrorCodeById(errorIdToUse);
- if (existingErrorCode) {
- errorCodeForm.setFieldsValue({
- error_code: existingErrorCode.error_code,
- error_code_name: existingErrorCode.error_code_name || '',
- error_code_description: existingErrorCode.error_code_description || '',
- error_code_color: existingErrorCode.error_code_color || '#000000',
- status: existingErrorCode.is_active !== false,
- });
+ if (errorCodeResponse && errorCodeResponse.statusCode === 200) {
+ const errorData = errorCodeResponse.data;
- if (existingErrorCode.path_icon) {
- setErrorCodeIcon({
- name: existingErrorCode.path_icon.split('/').pop(),
- uploadPath: existingErrorCode.path_icon,
- url: existingErrorCode.path_icon,
+ if (errorData) {
+ errorCodeForm.setFieldsValue({
+ error_code: errorData.error_code,
+ error_code_name: errorData.error_code_name || '',
+ error_code_description: errorData.error_code_description || '',
+ error_code_color: errorData.error_code_color || '#000000',
+ status: errorData.is_active !== false,
});
- }
- if (existingErrorCode.solution && existingErrorCode.solution.length > 0) {
- // console.log('🔍 Setting solutions from context:', existingErrorCode.solution);
- setSolutionsForExistingRecord(existingErrorCode.solution, solutionForm);
- }
+ if (errorData.path_icon) {
+ setErrorCodeIcon({
+ name: errorData.path_icon.split('/').pop(),
+ uploadPath: errorData.path_icon,
+ url: errorData.path_icon,
+ });
+ }
- if (existingErrorCode.spareparts && existingErrorCode.spareparts.length > 0) {
- // console.log('🔍 Setting spareparts from context:', existingErrorCode.spareparts);
- setSelectedSparepartIds(existingErrorCode.spareparts);
+ if (errorData.solution && errorData.solution.length > 0) {
+ setSolutionsForExistingRecord(errorData.solution, solutionForm);
+ }
+
+ if (errorData.spareparts && errorData.spareparts.length > 0) {
+ const sparepartIds = errorData.spareparts.map(sp => sp.sparepart_id);
+ setSelectedSparepartIds(sparepartIds);
+ }
}
} else {
- // console.log('🔍 Error code not found in context, trying API...');
+ errorCodeForm.setFieldsValue({
+ error_code: '',
+ error_code_name: '',
+ error_code_description: '',
+ error_code_color: '#000000',
+ status: true,
+ });
- let errorIdToUse = tempId;
- // Extract the actual error_code_id from tempId format
- if (tempId.startsWith('existing_')) {
- errorIdToUse = tempId.replace('existing_', '');
- }
-
- const errorCodeResponse = await getErrorCodeById(errorIdToUse);
-
- if (errorCodeResponse && errorCodeResponse.statusCode === 200) {
- const errorData = errorCodeResponse.data;
-
- if (errorData) {
- errorCodeForm.setFieldsValue({
- error_code: errorData.error_code,
- error_code_name: errorData.error_code_name || '',
- error_code_description: errorData.error_code_description || '',
- error_code_color: errorData.error_code_color || '#000000',
- status: errorData.is_active !== false,
- });
-
- if (errorData.path_icon) {
- setErrorCodeIcon({
- name: errorData.path_icon.split('/').pop(),
- uploadPath: errorData.path_icon,
- url: errorData.path_icon,
- });
- }
-
- // Set solutions from API data (include file data)
- if (errorData.solution && errorData.solution.length > 0) {
- setSolutionsForExistingRecord(errorData.solution, solutionForm);
- }
-
- // Set spareparts from API data
- if (errorData.spareparts && errorData.spareparts.length > 0) {
- const sparepartIds = errorData.spareparts.map(sp => sp.sparepart_id);
- setSelectedSparepartIds(sparepartIds);
- }
-
- // Don't add to context - this is existing data from API
- // The context should already have this error code from the brand data loading
- }
- } else {
- // console.log('🔍 API Response error or not found:', errorCodeResponse);
- errorCodeForm.setFieldsValue({
- error_code: '',
- error_code_name: '',
- error_code_description: '',
- error_code_color: '#000000',
- status: true,
- });
-
- NotifAlert({
- icon: 'warning',
- title: 'Peringatan',
- message: 'Error code not found. Creating new error code.',
- });
- }
+ NotifAlert({
+ icon: 'warning',
+ title: 'Peringatan',
+ message: 'Error code not found. Creating new error code.',
+ });
}
} catch (error) {
console.error('Failed to load error code:', error);
@@ -250,8 +175,9 @@ const AddEditErrorCode = () => {
const solutionValues = solutionForm.getFieldsValue();
- const firstSolutionPath = `solution_items,${solutionFields[0]?.key || 0}`;
- const firstSolution = solutionValues[firstSolutionPath];
+ const commaPath = `solution_items,${solutionFields[0]?.key || 0}`;
+ const dotPath = `solution_items.${solutionFields[0]?.key || 0}`;
+ const firstSolution = solutionValues[commaPath] || solutionValues[dotPath];
let isValid = false;
if (firstSolution && firstSolution.name && firstSolution.name.trim() !== '') {
@@ -276,55 +202,82 @@ const AddEditErrorCode = () => {
const solutionData = getSolutionData();
- // Determine the correct tempId for editing
- let updateTempId;
- if (isEdit) {
- // For existing error codes, find the correct tempId
- if (errorCodeId && !errorCodeId.startsWith('pending-')) {
- // Look for existing error code in context
- const existingEc = existingErrorCodes.find(ec => ec.error_code_id == errorCodeId);
- if (existingEc && existingEc.tempId) {
- updateTempId = existingEc.tempId;
+ setConfirmLoading(true);
+
+ try {
+ const payload = {
+ error_code_name: errorCodeValues.error_code_name,
+ error_code_description: errorCodeValues.error_code_description || '',
+ error_code_color: errorCodeValues.error_code_color || '#000000',
+ path_icon: errorCodeIcon?.path_icon || errorCodeIcon?.uploadPath || '',
+ is_active: errorCodeValues.status !== undefined ? errorCodeValues.status : true,
+ solution: solutionData || [],
+ spareparts: selectedSparepartIds || []
+ };
+
+ if (!isEdit) {
+ payload.error_code = errorCodeValues.error_code;
+ }
+
+ let response;
+
+ if (isEdit && errorCodeId) {
+ console.log('Updating error code:', errorCodeId);
+ console.log('Current brand ID:', currentBrandId);
+ console.log('Update payload:', JSON.stringify(payload, null, 2));
+ console.log('API URL:', `error-code/brand/${currentBrandId}/${errorCodeId}`);
+ response = await updateErrorCode(currentBrandId, errorCodeId, payload);
+ console.log('Full API response:', response);
+ } else {
+ console.log('Creating new error code');
+ console.log('Create payload:', JSON.stringify(payload, null, 2));
+ response = await createErrorCode(currentBrandId, payload);
+ console.log('Full API response:', response);
+ }
+
+ if (response && (response.statusCode === 200 || response.statusCode === 201)) {
+ NotifOk({
+ icon: 'success',
+ title: 'Berhasil',
+ message: isEdit ? 'Error Code berhasil diupdate!' : 'Error Code berhasil ditambahkan!',
+ });
+
+ if (isFromAddBrand) {
+ navigate(`/master/brand-device/add`);
} else {
- updateTempId = `existing_${errorCodeId}`;
+ navigate(`/master/brand-device/edit/${currentBrandId}?tab=error-codes`);
}
} else {
- updateTempId = errorCodeId;
+ console.log('Error response:', response);
+ NotifAlert({
+ icon: 'error',
+ title: 'Gagal',
+ message: response?.message || 'Gagal menyimpan error code',
+ });
}
- } else {
- updateTempId = Date.now().toString();
+ } catch (error) {
+ console.error('Error saving error code:', error);
+ console.error('Full error object:', JSON.stringify(error, null, 2));
+ if (error.response) {
+ console.error('Error response data:', error.response.data);
+ console.error('Error response status:', error.response.status);
+ }
+ NotifAlert({
+ icon: 'error',
+ title: 'Gagal',
+ message: error.message || 'Gagal menyimpan error code. Silakan coba lagi.',
+ });
+ } finally {
+ setConfirmLoading(false);
}
- const currentErrorCode = {
- tempId: updateTempId,
- error_code_id: isEdit && errorCodeId && !errorCodeId.startsWith('pending-') ? errorCodeId : null,
- error_code: errorCodeValues.error_code || '',
- error_code_name: errorCodeValues.error_code_name || '',
- error_code_description: errorCodeValues.error_code_description || '',
- error_code_color: errorCodeValues.error_code_color || '#000000',
- path_icon: errorCodeIcon?.uploadPath || '',
- is_active: errorCodeValues.status !== undefined ? errorCodeValues.status : true,
- solution: solutionData || [],
- spareparts: selectedSparepartIds || [],
- errorCodeIcon: errorCodeIcon,
- };
-
- if (isEdit) {
- updateErrorCode(updateTempId, currentErrorCode);
- } else {
- addErrorCode(currentErrorCode);
- }
-
- NotifOk({
- icon: 'success',
- title: 'Berhasil',
- message: isEdit ? 'Error Code berhasil diupdate!' : 'Error Code berhasil ditambahkan!',
- });
-
- navigate(`/master/brand-device/edit/${currentBrandId}?tab=error-codes`);
-
} catch (error) {
console.error('Error saving error code:', error);
+ console.error('Full error object:', JSON.stringify(error, null, 2));
+ if (error.response) {
+ console.error('Error response data:', error.response.data);
+ console.error('Error response status:', error.response.status);
+ }
NotifAlert({
icon: 'error',
title: 'Error',
@@ -334,103 +287,46 @@ const AddEditErrorCode = () => {
};
const handleCancel = () => {
- navigate(`/master/brand-device/edit/${currentBrandId}?tab=error-codes`);
+ if (isFromAddBrand) {
+ navigate(`/master/brand-device/add`);
+ } else {
+ navigate(`/master/brand-device/edit/${currentBrandId}?tab=error-codes`);
+ }
};
- const handleErrorCodeIconUpload = async (file) => {
- if (!file) return null;
+ const handleErrorCodeIconUpload = (iconData) => {
+ console.log('handleErrorCodeIconUpload received:', iconData);
- try {
- const folder = 'images';
- const response = await uploadFile(file, folder);
-
- if (response && response.statusCode === 200) {
- const iconData = {
- name: file.name,
- uploadPath: response.data.path_document,
- url: response.data.path_document,
- };
-
- setErrorCodeIcon(iconData);
- NotifOk({
- icon: 'success',
- title: 'Berhasil',
- message: 'Error code icon uploaded successfully',
- });
- return iconData;
- } else {
- NotifAlert({
- icon: 'error',
- title: 'Gagal',
- message: response?.message || 'Failed to upload error code icon',
- });
- return null;
- }
- } catch (error) {
- console.error('Error uploading icon:', error);
- NotifAlert({
- icon: 'error',
- title: 'Gagal',
- message: 'Failed to upload error code icon',
- });
+ if (!iconData || !iconData.uploadPath) {
+ console.error('❌ Invalid icon data received:', iconData);
return null;
}
+
+ const formattedIconData = {
+ name: iconData.name,
+ uploadPath: iconData.uploadPath,
+ url: iconData.uploadPath,
+ };
+
+ setErrorCodeIcon(formattedIconData);
+ console.log('Icon data stored from upload (no second upload):', formattedIconData);
+ return formattedIconData;
};
const handleErrorCodeIconRemove = () => {
+ console.log('🗑️ Removing error code icon');
setErrorCodeIcon(null);
+ console.log('✅ Error code icon removed');
};
- const handleSolutionFileUpload = async (file, solutionKey) => {
- if (!file) return null;
-
- try {
- // Determine folder based on file type
- const fileExtension = file.name.split('.').pop().toLowerCase();
- const folder = ['pdf'].includes(fileExtension) ? 'pdf' : 'images';
-
- const response = await uploadFile(file, folder);
-
- if (response && response.statusCode === 200) {
- const fileData = {
- name: file.name,
- uploadPath: response.data.path_document,
- url: response.data.path_document,
- size: file.size,
- type: file.type,
- };
-
- NotifOk({
- icon: 'success',
- title: 'Berhasil',
- message: 'Solution file uploaded successfully',
- });
- return fileData;
- } else {
- NotifAlert({
- icon: 'error',
- title: 'Gagal',
- message: response?.message || 'Failed to upload solution file',
- });
- return null;
- }
- } catch (error) {
- console.error('Error uploading solution file:', error);
- NotifAlert({
- icon: 'error',
- title: 'Gagal',
- message: 'Failed to upload solution file',
- });
- return null;
- }
- };
-
- const handleSolutionFileView = (fileData) => {
- if (fileData && fileData.url) {
- window.open(fileData.url, '_blank');
- }
+ const handleSolutionFileUpload = (fileObject) => {
+ console.log('Solution file uploaded:', fileObject);
+ console.log('File object path_solution:', fileObject?.path_solution);
+ console.log('File object uploadPath:', fileObject?.uploadPath);
};
+
+
const resetForm = () => {
errorCodeForm.resetFields();
errorCodeForm.setFieldsValue({
@@ -504,6 +400,7 @@ const AddEditErrorCode = () => {
errorCodeIcon={errorCodeIcon}
onErrorCodeIconUpload={handleErrorCodeIconUpload}
onErrorCodeIconRemove={handleErrorCodeIconRemove}
+ isEdit={isEdit}
/>
@@ -541,8 +438,11 @@ const AddEditErrorCode = () => {
onSolutionTypeChange={handleSolutionTypeChange}
onSolutionStatusChange={handleSolutionStatusChange}
onSolutionFileUpload={handleSolutionFileUpload}
- onFileView={handleSolutionFileView}
- fileList={fileList}
+ onFileView={(fileData) => {
+ if (fileData && fileData.url) {
+ window.open(fileData.url, '_blank');
+ }
+ }}
isReadOnly={false}
/>
@@ -570,6 +470,7 @@ const AddEditErrorCode = () => {
);
diff --git a/src/pages/master/brandDevice/component/SolutionForm.jsx b/src/pages/master/brandDevice/component/SolutionForm.jsx
index f6a7a9f..8dbaa19 100644
--- a/src/pages/master/brandDevice/component/SolutionForm.jsx
+++ b/src/pages/master/brandDevice/component/SolutionForm.jsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { Form, Card, Typography, Divider, Button } from 'antd';
+import { Typography, Divider, Button } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import SolutionFieldNew from './SolutionField';
@@ -21,83 +21,66 @@ const SolutionForm = ({
fileList,
isReadOnly = false,
}) => {
- // Debug props
- console.log('🔍 SolutionForm props:', {
- solutionFields,
- solutionTypes,
- solutionStatuses,
- firstSolutionValid,
- onAddSolutionField: typeof onAddSolutionField,
- onRemoveSolutionField: typeof onRemoveSolutionField,
- checkFirstSolutionValid: typeof checkFirstSolutionValid,
- onSolutionFileUpload: typeof onSolutionFileUpload,
- onFileView: typeof onFileView,
- fileList: fileList ? fileList.length : 0
- });
+ // console.log('SolutionForm props:', {
+ // solutionFields,
+ // solutionTypes,
+ // solutionStatuses,
+ // firstSolutionValid,
+ // onAddSolutionField: typeof onAddSolutionField,
+ // onRemoveSolutionField: typeof onRemoveSolutionField,
+ // checkFirstSolutionValid: typeof checkFirstSolutionValid,
+ // onSolutionFileUpload: typeof onSolutionFileUpload,
+ // onFileView: typeof onFileView,
+ // fileList: fileList ? fileList.length : 0
+ // });
return (