repair: delete error code
This commit is contained in:
@@ -53,13 +53,6 @@ const AddBrandDevice = () => {
|
|||||||
const {
|
const {
|
||||||
solutionFields,
|
solutionFields,
|
||||||
solutionTypes,
|
solutionTypes,
|
||||||
solutionStatuses,
|
|
||||||
solutionsToDelete,
|
|
||||||
firstSolutionValid,
|
|
||||||
handleAddSolutionField,
|
|
||||||
handleRemoveSolutionField,
|
|
||||||
handleSolutionTypeChange,
|
|
||||||
handleSolutionStatusChange,
|
|
||||||
resetSolutionFields,
|
resetSolutionFields,
|
||||||
getSolutionData,
|
getSolutionData,
|
||||||
setSolutionsForExistingRecord,
|
setSolutionsForExistingRecord,
|
||||||
@@ -72,7 +65,6 @@ const AddBrandDevice = () => {
|
|||||||
const brandValues = await brandForm.validateFields();
|
const brandValues = await brandForm.validateFields();
|
||||||
const userId = JSON.parse(localStorage.getItem('user') || '{}').user_id || 1;
|
const userId = JSON.parse(localStorage.getItem('user') || '{}').user_id || 1;
|
||||||
|
|
||||||
// Prepare brand data for API
|
|
||||||
const brandApiData = {
|
const brandApiData = {
|
||||||
brand_name: brandValues.brand_name,
|
brand_name: brandValues.brand_name,
|
||||||
brand_type: brandValues.brand_type || '',
|
brand_type: brandValues.brand_type || '',
|
||||||
@@ -97,7 +89,6 @@ const AddBrandDevice = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
setCurrentStep(1);
|
setCurrentStep(1);
|
||||||
// Trigger refresh untuk error codes table di fase 2
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setTrigerFilter(prev => !prev);
|
setTrigerFilter(prev => !prev);
|
||||||
}, 100);
|
}, 100);
|
||||||
@@ -239,7 +230,6 @@ const AddBrandDevice = () => {
|
|||||||
|
|
||||||
let allErrorCodes = [];
|
let allErrorCodes = [];
|
||||||
|
|
||||||
// Get error codes from API if brand is created
|
|
||||||
if (createdBrandId) {
|
if (createdBrandId) {
|
||||||
const queryParams = new URLSearchParams({
|
const queryParams = new URLSearchParams({
|
||||||
page: page.toString(),
|
page: page.toString(),
|
||||||
@@ -258,10 +248,8 @@ const AddBrandDevice = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add temp error codes
|
|
||||||
allErrorCodes = [...allErrorCodes, ...tempErrorCodes.filter(ec => ec.status !== 'deleted')];
|
allErrorCodes = [...allErrorCodes, ...tempErrorCodes.filter(ec => ec.status !== 'deleted')];
|
||||||
|
|
||||||
// Filter by search text if needed
|
|
||||||
if (searchText) {
|
if (searchText) {
|
||||||
allErrorCodes = allErrorCodes.filter(ec =>
|
allErrorCodes = allErrorCodes.filter(ec =>
|
||||||
ec.error_code.toLowerCase().includes(searchText.toLowerCase()) ||
|
ec.error_code.toLowerCase().includes(searchText.toLowerCase()) ||
|
||||||
@@ -313,7 +301,6 @@ const AddBrandDevice = () => {
|
|||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<Space>
|
<Space>
|
||||||
{text}
|
{text}
|
||||||
{record.status === 'new' && <Tag color="green">New</Tag>}
|
|
||||||
</Space>
|
</Space>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@@ -360,7 +347,6 @@ const AddBrandDevice = () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// Query params for table
|
|
||||||
const queryParams = useMemo(() => {
|
const queryParams = useMemo(() => {
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
params.set('page', '1');
|
params.set('page', '1');
|
||||||
@@ -424,8 +410,6 @@ const AddBrandDevice = () => {
|
|||||||
solution: solutionData || [],
|
solution: solutionData || [],
|
||||||
spareparts: selectedSparepartIds || []
|
spareparts: selectedSparepartIds || []
|
||||||
};
|
};
|
||||||
|
|
||||||
// For create, include error_code field (required)
|
|
||||||
if (isAddingNewErrorCode) {
|
if (isAddingNewErrorCode) {
|
||||||
payload.error_code = errorCodeValues.error_code;
|
payload.error_code = errorCodeValues.error_code;
|
||||||
}
|
}
|
||||||
@@ -473,7 +457,6 @@ const AddBrandDevice = () => {
|
|||||||
const handleFinish = async () => {
|
const handleFinish = async () => {
|
||||||
setConfirmLoading(true);
|
setConfirmLoading(true);
|
||||||
try {
|
try {
|
||||||
// Fase 2 completion - brand sudah dibuat di fase 1
|
|
||||||
NotifOk({
|
NotifOk({
|
||||||
icon: 'success',
|
icon: 'success',
|
||||||
title: 'Brand Device Tersimpan',
|
title: 'Brand Device Tersimpan',
|
||||||
|
|||||||
@@ -62,7 +62,11 @@ const AddEditErrorCode = () => {
|
|||||||
const isEditMode = errorCodeId && errorCodeId !== 'add';
|
const isEditMode = errorCodeId && errorCodeId !== 'add';
|
||||||
setIsEdit(isEditMode);
|
setIsEdit(isEditMode);
|
||||||
|
|
||||||
|
// Initialize solution form with proper structure
|
||||||
|
if (!isEditMode) {
|
||||||
|
resetSolutionFields();
|
||||||
|
}
|
||||||
|
|
||||||
setBreadcrumbItems([
|
setBreadcrumbItems([
|
||||||
{
|
{
|
||||||
title: <span style={{ fontSize: '14px', fontWeight: 'bold' }}>• Master</span>
|
title: <span style={{ fontSize: '14px', fontWeight: 'bold' }}>• Master</span>
|
||||||
@@ -158,7 +162,6 @@ const AddEditErrorCode = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to load error code:', error);
|
|
||||||
NotifAlert({
|
NotifAlert({
|
||||||
icon: 'error',
|
icon: 'error',
|
||||||
title: 'Error',
|
title: 'Error',
|
||||||
@@ -173,23 +176,10 @@ const AddEditErrorCode = () => {
|
|||||||
try {
|
try {
|
||||||
await errorCodeForm.validateFields();
|
await errorCodeForm.validateFields();
|
||||||
|
|
||||||
const solutionValues = solutionForm.getFieldsValue();
|
const solutionData = getSolutionData();
|
||||||
|
|
||||||
const commaPath = `solution_items,${solutionFields[0]?.key || 0}`;
|
// Validate that at least one solution exists and is valid
|
||||||
const dotPath = `solution_items.${solutionFields[0]?.key || 0}`;
|
if (!solutionData || solutionData.length === 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({
|
NotifAlert({
|
||||||
icon: 'warning',
|
icon: 'warning',
|
||||||
title: 'Perhatian',
|
title: 'Perhatian',
|
||||||
@@ -198,9 +188,29 @@ const AddEditErrorCode = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const errorCodeValues = errorCodeForm.getFieldsValue();
|
// Validate solutions based on their type
|
||||||
|
const invalidSolutions = solutionData.filter(solution => {
|
||||||
|
if (solution.type_solution === 'text') {
|
||||||
|
return !solution.text_solution || solution.text_solution.trim() === '';
|
||||||
|
} else if (solution.type_solution === 'file') {
|
||||||
|
return !solution.path_solution || solution.path_solution.trim() === '';
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
const solutionData = getSolutionData();
|
if (invalidSolutions.length > 0) {
|
||||||
|
const invalidNames = invalidSolutions.map(s => s.solution_name).join(', ');
|
||||||
|
NotifAlert({
|
||||||
|
icon: 'warning',
|
||||||
|
title: 'Perhatian',
|
||||||
|
message: `Harap lengkapi solution berikut:\n${invalidSolutions.map(s =>
|
||||||
|
`- ${s.solution_name}: ${s.type_solution === 'text' ? 'Text solution wajib diisi' : 'File wajib diupload'}`
|
||||||
|
).join('\n')}`,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const errorCodeValues = errorCodeForm.getFieldsValue();
|
||||||
|
|
||||||
setConfirmLoading(true);
|
setConfirmLoading(true);
|
||||||
|
|
||||||
@@ -222,17 +232,9 @@ const AddEditErrorCode = () => {
|
|||||||
let response;
|
let response;
|
||||||
|
|
||||||
if (isEdit && errorCodeId) {
|
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);
|
response = await updateErrorCode(currentBrandId, errorCodeId, payload);
|
||||||
console.log('Full API response:', response);
|
|
||||||
} else {
|
} else {
|
||||||
console.log('Creating new error code');
|
|
||||||
console.log('Create payload:', JSON.stringify(payload, null, 2));
|
|
||||||
response = await createErrorCode(currentBrandId, payload);
|
response = await createErrorCode(currentBrandId, payload);
|
||||||
console.log('Full API response:', response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response && (response.statusCode === 200 || response.statusCode === 201)) {
|
if (response && (response.statusCode === 200 || response.statusCode === 201)) {
|
||||||
@@ -248,7 +250,6 @@ const AddEditErrorCode = () => {
|
|||||||
navigate(`/master/brand-device/edit/${currentBrandId}?tab=error-codes`);
|
navigate(`/master/brand-device/edit/${currentBrandId}?tab=error-codes`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('Error response:', response);
|
|
||||||
NotifAlert({
|
NotifAlert({
|
||||||
icon: 'error',
|
icon: 'error',
|
||||||
title: 'Gagal',
|
title: 'Gagal',
|
||||||
@@ -256,12 +257,6 @@ const AddEditErrorCode = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} 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({
|
NotifAlert({
|
||||||
icon: 'error',
|
icon: 'error',
|
||||||
title: 'Gagal',
|
title: 'Gagal',
|
||||||
@@ -272,12 +267,6 @@ const AddEditErrorCode = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} 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({
|
NotifAlert({
|
||||||
icon: 'error',
|
icon: 'error',
|
||||||
title: 'Error',
|
title: 'Error',
|
||||||
@@ -295,10 +284,7 @@ const AddEditErrorCode = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleErrorCodeIconUpload = (iconData) => {
|
const handleErrorCodeIconUpload = (iconData) => {
|
||||||
console.log('handleErrorCodeIconUpload received:', iconData);
|
|
||||||
|
|
||||||
if (!iconData || !iconData.uploadPath) {
|
if (!iconData || !iconData.uploadPath) {
|
||||||
console.error('❌ Invalid icon data received:', iconData);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,24 +295,17 @@ const AddEditErrorCode = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
setErrorCodeIcon(formattedIconData);
|
setErrorCodeIcon(formattedIconData);
|
||||||
console.log('Icon data stored from upload (no second upload):', formattedIconData);
|
|
||||||
return formattedIconData;
|
return formattedIconData;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleErrorCodeIconRemove = () => {
|
const handleErrorCodeIconRemove = () => {
|
||||||
console.log('🗑️ Removing error code icon');
|
|
||||||
setErrorCodeIcon(null);
|
setErrorCodeIcon(null);
|
||||||
console.log('✅ Error code icon removed');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSolutionFileUpload = (fileObject) => {
|
const handleSolutionFileUpload = (fileObject) => {
|
||||||
console.log('Solution file uploaded:', fileObject);
|
// Handle solution file upload if needed
|
||||||
console.log('File object path_solution:', fileObject?.path_solution);
|
|
||||||
console.log('File object uploadPath:', fileObject?.uploadPath);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
errorCodeForm.resetFields();
|
errorCodeForm.resetFields();
|
||||||
errorCodeForm.setFieldsValue({
|
errorCodeForm.setFieldsValue({
|
||||||
@@ -416,12 +395,7 @@ const AddEditErrorCode = () => {
|
|||||||
<Form
|
<Form
|
||||||
form={solutionForm}
|
form={solutionForm}
|
||||||
layout="vertical"
|
layout="vertical"
|
||||||
initialValues={{
|
initialValues={{}}
|
||||||
solution_items: [{
|
|
||||||
status: true,
|
|
||||||
type: 'text',
|
|
||||||
}]
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<SolutionForm
|
<SolutionForm
|
||||||
solutionForm={solutionForm}
|
solutionForm={solutionForm}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import TableList from '../../../components/Global/TableList';
|
|||||||
import { ConfigProvider } from 'antd';
|
import { ConfigProvider } from 'antd';
|
||||||
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, getErrorCodesByBrandId } from '../../../api/master-brand';
|
import { getBrandById, getErrorCodesByBrandId, deleteErrorCode } from '../../../api/master-brand';
|
||||||
import { getFileUrl } from '../../../api/file-uploads';
|
import { getFileUrl } from '../../../api/file-uploads';
|
||||||
import BrandForm from './component/BrandForm';
|
import BrandForm from './component/BrandForm';
|
||||||
import ErrorCodeSimpleForm from './component/ErrorCodeSimpleForm';
|
import ErrorCodeSimpleForm from './component/ErrorCodeSimpleForm';
|
||||||
@@ -43,9 +43,6 @@ const EditBrandDevice = () => {
|
|||||||
const [errorCodeIcon, setErrorCodeIcon] = useState(null);
|
const [errorCodeIcon, setErrorCodeIcon] = useState(null);
|
||||||
const [selectedSparepartIds, setSelectedSparepartIds] = useState([]);
|
const [selectedSparepartIds, setSelectedSparepartIds] = useState([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
// Context integration
|
|
||||||
// Use step from query parameter
|
|
||||||
const tab = searchParams.get('tab');
|
const tab = searchParams.get('tab');
|
||||||
const [currentStep, setCurrentStep] = useState(tab === 'error-codes' ? 1 : 0);
|
const [currentStep, setCurrentStep] = useState(tab === 'error-codes' ? 1 : 0);
|
||||||
const [editingErrorCodeKey, setEditingErrorCodeKey] = useState(null);
|
const [editingErrorCodeKey, setEditingErrorCodeKey] = useState(null);
|
||||||
@@ -59,16 +56,6 @@ const EditBrandDevice = () => {
|
|||||||
const [existingErrorCodes, setExistingErrorCodes] = useState([]);
|
const [existingErrorCodes, setExistingErrorCodes] = useState([]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
solutionFields,
|
|
||||||
solutionTypes,
|
|
||||||
solutionStatuses,
|
|
||||||
solutionsToDelete,
|
|
||||||
firstSolutionValid,
|
|
||||||
checkFirstSolutionValid,
|
|
||||||
handleAddSolutionField,
|
|
||||||
handleRemoveSolutionField,
|
|
||||||
handleSolutionTypeChange,
|
|
||||||
handleSolutionStatusChange,
|
|
||||||
resetSolutionFields,
|
resetSolutionFields,
|
||||||
getSolutionData,
|
getSolutionData,
|
||||||
setSolutionsForExistingRecord,
|
setSolutionsForExistingRecord,
|
||||||
@@ -199,7 +186,7 @@ const EditBrandDevice = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteErrorCode = (tempId, permanent = false) => {
|
const deleteLocalErrorCode = (tempId, permanent = false) => {
|
||||||
if (permanent) {
|
if (permanent) {
|
||||||
setTempErrorCodes(prev => prev.filter(ec => ec.tempId !== tempId));
|
setTempErrorCodes(prev => prev.filter(ec => ec.tempId !== tempId));
|
||||||
setExistingErrorCodes(prev => prev.filter(ec => ec.tempId !== tempId));
|
setExistingErrorCodes(prev => prev.filter(ec => ec.tempId !== tempId));
|
||||||
@@ -390,21 +377,46 @@ const EditBrandDevice = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteErrorCode = (record) => {
|
const handleDeleteErrorCode = async (record) => {
|
||||||
NotifConfirmDialog({
|
NotifConfirmDialog({
|
||||||
icon: 'question',
|
icon: 'question',
|
||||||
title: 'Konfirmasi Hapus',
|
title: 'Konfirmasi Hapus',
|
||||||
message: `Apakah Anda yakin ingin menghapus error code "${record.error_code}"?`,
|
message: `Apakah Anda yakin ingin menghapus error code "${record.error_code}"?`,
|
||||||
onConfirm: () => {
|
onConfirm: async () => {
|
||||||
// Use soft delete (mark as deleted) instead of permanent delete
|
try {
|
||||||
const tempId = record.tempId || `existing_${record.error_code_id}`;
|
if (record.status === 'existing' && record.error_code_id) {
|
||||||
deleteErrorCode(tempId, false); // false = soft delete
|
const response = await deleteErrorCode(id, record.error_code_id);
|
||||||
NotifOk({
|
if (response && response.statusCode === 200) {
|
||||||
icon: 'success',
|
NotifOk({
|
||||||
title: 'Berhasil',
|
icon: 'success',
|
||||||
message: 'Error code berhasil dihapus!',
|
title: 'Berhasil',
|
||||||
});
|
message: 'Error code berhasil dihapus!',
|
||||||
setTrigerFilter(prev => !prev);
|
});
|
||||||
|
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: () => {}
|
onCancel: () => {}
|
||||||
});
|
});
|
||||||
@@ -416,14 +428,16 @@ const EditBrandDevice = () => {
|
|||||||
...tempErrorCodes
|
...tempErrorCodes
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const activeErrorCodes = allErrorCodes.filter(ec => ec.status !== 'deleted');
|
||||||
|
|
||||||
if (searchText) {
|
if (searchText) {
|
||||||
return allErrorCodes.filter(ec =>
|
return activeErrorCodes.filter(ec =>
|
||||||
ec.error_code.toLowerCase().includes(searchText.toLowerCase()) ||
|
ec.error_code.toLowerCase().includes(searchText.toLowerCase()) ||
|
||||||
ec.error_code_name.toLowerCase().includes(searchText.toLowerCase())
|
ec.error_code_name.toLowerCase().includes(searchText.toLowerCase())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return allErrorCodes;
|
return activeErrorCodes;
|
||||||
}, [existingErrorCodes, tempErrorCodes, searchText]);
|
}, [existingErrorCodes, tempErrorCodes, searchText]);
|
||||||
|
|
||||||
const errorCodeColumns = (showPreviewModal, showEditModal, showDeleteDialog) => [
|
const errorCodeColumns = (showPreviewModal, showEditModal, showDeleteDialog) => [
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
export const useSolutionLogic = (solutionForm) => {
|
export const useSolutionLogic = (solutionForm) => {
|
||||||
const [solutionFields, setSolutionFields] = useState([0]);
|
const [solutionFields, setSolutionFields] = useState([0]);
|
||||||
@@ -6,19 +6,68 @@ export const useSolutionLogic = (solutionForm) => {
|
|||||||
const [solutionStatuses, setSolutionStatuses] = useState({ 0: true });
|
const [solutionStatuses, setSolutionStatuses] = useState({ 0: true });
|
||||||
const [solutionsToDelete, setSolutionsToDelete] = useState([]);
|
const [solutionsToDelete, setSolutionsToDelete] = useState([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (solutionForm) {
|
||||||
|
solutionForm.setFieldsValue({
|
||||||
|
solution_items: {
|
||||||
|
0: {
|
||||||
|
name: 'Solution 1',
|
||||||
|
status: true,
|
||||||
|
type: 'text',
|
||||||
|
text: 'Deskripsi untuk Solution 1',
|
||||||
|
file: null,
|
||||||
|
fileUpload: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
}, [solutionForm]);
|
||||||
|
|
||||||
const handleAddSolutionField = () => {
|
const handleAddSolutionField = () => {
|
||||||
const newKey = Date.now();
|
const newKey = Date.now();
|
||||||
|
|
||||||
setSolutionFields(prev => [...prev, newKey]);
|
setSolutionFields(prev => [...prev, newKey]);
|
||||||
setSolutionTypes(prev => ({ ...prev, [newKey]: 'text' }));
|
setSolutionTypes(prev => ({ ...prev, [newKey]: 'text' }));
|
||||||
setSolutionStatuses(prev => ({ ...prev, [newKey]: true }));
|
setSolutionStatuses(prev => ({ ...prev, [newKey]: true }));
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
solutionForm.setFieldValue(['solution_items', newKey, 'name'], '');
|
const currentFormValues = solutionForm.getFieldsValue(true);
|
||||||
|
const existingNames = [];
|
||||||
|
|
||||||
|
Object.keys(currentFormValues).forEach(key => {
|
||||||
|
if (key.startsWith('solution_items,') || key.startsWith('solution_items.')) {
|
||||||
|
const solutionData = currentFormValues[key];
|
||||||
|
if (solutionData && solutionData.name) {
|
||||||
|
existingNames.push(solutionData.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (currentFormValues.solution_items) {
|
||||||
|
Object.values(currentFormValues.solution_items).forEach(solution => {
|
||||||
|
if (solution && solution.name) {
|
||||||
|
existingNames.push(solution.name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let solutionNumber = solutionFields.length + 1;
|
||||||
|
let defaultName = `Solution ${solutionNumber}`;
|
||||||
|
|
||||||
|
while (existingNames.includes(defaultName)) {
|
||||||
|
solutionNumber++;
|
||||||
|
defaultName = `Solution ${solutionNumber}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
solutionForm.setFieldValue(['solution_items', newKey, 'name'], defaultName);
|
||||||
solutionForm.setFieldValue(['solution_items', newKey, 'type'], 'text');
|
solutionForm.setFieldValue(['solution_items', newKey, 'type'], 'text');
|
||||||
solutionForm.setFieldValue(['solution_items', newKey, 'text'], '');
|
solutionForm.setFieldValue(['solution_items', newKey, 'text'], `Deskripsi untuk ${defaultName}`);
|
||||||
solutionForm.setFieldValue(['solution_items', newKey, 'status'], true);
|
solutionForm.setFieldValue(['solution_items', newKey, 'status'], true);
|
||||||
}, 0);
|
solutionForm.setFieldValue(['solution_items', newKey, 'file'], null);
|
||||||
|
solutionForm.setFieldValue(['solution_items', newKey, 'fileUpload'], null);
|
||||||
|
}, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRemoveSolutionField = (key) => {
|
const handleRemoveSolutionField = (key) => {
|
||||||
@@ -28,7 +77,6 @@ export const useSolutionLogic = (solutionForm) => {
|
|||||||
|
|
||||||
setSolutionFields(prev => prev.filter(field => field !== key));
|
setSolutionFields(prev => prev.filter(field => field !== key));
|
||||||
|
|
||||||
// Clean up type and status
|
|
||||||
const newTypes = { ...solutionTypes };
|
const newTypes = { ...solutionTypes };
|
||||||
const newStatuses = { ...solutionStatuses };
|
const newStatuses = { ...solutionStatuses };
|
||||||
delete newTypes[key];
|
delete newTypes[key];
|
||||||
@@ -36,30 +84,52 @@ export const useSolutionLogic = (solutionForm) => {
|
|||||||
|
|
||||||
setSolutionTypes(newTypes);
|
setSolutionTypes(newTypes);
|
||||||
setSolutionStatuses(newStatuses);
|
setSolutionStatuses(newStatuses);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
try {
|
||||||
|
solutionForm.setFieldValue(['solution_items', key], undefined);
|
||||||
|
solutionForm.setFieldValue(['solution_items', key, 'name'], undefined);
|
||||||
|
solutionForm.setFieldValue(['solution_items', key, 'type'], undefined);
|
||||||
|
solutionForm.setFieldValue(['solution_items', key, 'text'], undefined);
|
||||||
|
solutionForm.setFieldValue(['solution_items', key, 'status'], undefined);
|
||||||
|
solutionForm.setFieldValue(['solution_items', key, 'file'], undefined);
|
||||||
|
solutionForm.setFieldValue(['solution_items', key, 'fileUpload'], undefined);
|
||||||
|
} catch (error) {
|
||||||
|
}
|
||||||
|
}, 50);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSolutionTypeChange = (key, value) => {
|
const handleSolutionTypeChange = (key, value) => {
|
||||||
setSolutionTypes(prev => ({ ...prev, [key]: value }));
|
setSolutionTypes(prev => ({ ...prev, [key]: value }));
|
||||||
|
|
||||||
if (value === 'text') {
|
setTimeout(() => {
|
||||||
setTimeout(() => {
|
const fieldName = ['solution_items', key];
|
||||||
const fieldName = ['solution_items', key];
|
const currentSolutionData = solutionForm.getFieldsValue([fieldName]) || {};
|
||||||
const currentSolutionData = solutionForm.getFieldsValue([fieldName]) || {};
|
const solutionData = currentSolutionData[`solution_items,${key}`] || currentSolutionData[`solution_items.${key}`] || {};
|
||||||
const solutionData = currentSolutionData[`solution_items,${key}`] || currentSolutionData[`solution_items.${key}`] || {};
|
|
||||||
|
|
||||||
|
if (value === 'text') {
|
||||||
const updatedSolutionData = {
|
const updatedSolutionData = {
|
||||||
...solutionData,
|
...solutionData,
|
||||||
fileUpload: null,
|
fileUpload: null,
|
||||||
file: null
|
file: null,
|
||||||
|
text: solutionData.text || `Deskripsi untuk ${solutionData.name || 'Solution'}`
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update form with cleared file data
|
|
||||||
const commaPath = fieldName.join(',');
|
|
||||||
solutionForm.setFieldValue(commaPath, updatedSolutionData);
|
|
||||||
solutionForm.setFieldValue([...fieldName, 'fileUpload'], null);
|
solutionForm.setFieldValue([...fieldName, 'fileUpload'], null);
|
||||||
solutionForm.setFieldValue([...fieldName, 'file'], null);
|
solutionForm.setFieldValue([...fieldName, 'file'], null);
|
||||||
}, 0);
|
solutionForm.setFieldValue([...fieldName, 'text'], updatedSolutionData.text);
|
||||||
}
|
} else if (value === 'file') {
|
||||||
|
const updatedSolutionData = {
|
||||||
|
...solutionData,
|
||||||
|
text: '',
|
||||||
|
fileUpload: null,
|
||||||
|
file: null
|
||||||
|
};
|
||||||
|
solutionForm.setFieldValue([...fieldName, 'text'], '');
|
||||||
|
solutionForm.setFieldValue([...fieldName, 'fileUpload'], null);
|
||||||
|
solutionForm.setFieldValue([...fieldName, 'file'], null);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSolutionStatusChange = (key, value) => {
|
const handleSolutionStatusChange = (key, value) => {
|
||||||
@@ -71,14 +141,31 @@ export const useSolutionLogic = (solutionForm) => {
|
|||||||
setSolutionTypes({ 0: 'text' });
|
setSolutionTypes({ 0: 'text' });
|
||||||
setSolutionStatuses({ 0: true });
|
setSolutionStatuses({ 0: true });
|
||||||
|
|
||||||
// Reset form values
|
|
||||||
solutionForm.resetFields();
|
solutionForm.resetFields();
|
||||||
solutionForm.setFieldsValue({
|
setTimeout(() => {
|
||||||
solution_items: [{
|
solutionForm.setFieldsValue({
|
||||||
status: true,
|
solution_items: {
|
||||||
type: 'text',
|
0: {
|
||||||
}]
|
name: 'Solution 1',
|
||||||
});
|
status: true,
|
||||||
|
type: 'text',
|
||||||
|
text: '',
|
||||||
|
file: null,
|
||||||
|
fileUpload: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
solutionForm.setFieldValue(['solution_items', 0, 'name'], 'Solution 1');
|
||||||
|
solutionForm.setFieldValue(['solution_items', 0, 'type'], 'text');
|
||||||
|
solutionForm.setFieldValue(['solution_items', 0, 'text'], 'Deskripsi untuk Solution 1');
|
||||||
|
solutionForm.setFieldValue(['solution_items', 0, 'status'], true);
|
||||||
|
solutionForm.setFieldValue(['solution_items', 0, 'file'], null);
|
||||||
|
solutionForm.setFieldValue(['solution_items', 0, 'fileUpload'], null);
|
||||||
|
|
||||||
|
console.log('✅ Reset solution fields with proper structure');
|
||||||
|
console.log('Form values after reset:', solutionForm.getFieldsValue(true));
|
||||||
|
}, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkFirstSolutionValid = () => {
|
const checkFirstSolutionValid = () => {
|
||||||
@@ -107,76 +194,121 @@ export const useSolutionLogic = (solutionForm) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getSolutionData = () => {
|
const getSolutionData = () => {
|
||||||
const values = solutionForm.getFieldsValue(true);
|
try {
|
||||||
|
const values = solutionForm.getFieldsValue(true);
|
||||||
|
const result = [];
|
||||||
|
|
||||||
const result = solutionFields.map(key => {
|
solutionFields.forEach(key => {
|
||||||
let solution = null;
|
let solution = null;
|
||||||
|
|
||||||
// Try nested format first (preferred)
|
try {
|
||||||
if (values.solution_items && values.solution_items[key]) {
|
solution = solutionForm.getFieldValue(['solution_items', key]);
|
||||||
solution = values.solution_items[key];
|
} catch (error) {
|
||||||
}
|
// Silently handle errors
|
||||||
|
|
||||||
// Fallback to comma notation
|
|
||||||
if (!solution) {
|
|
||||||
const commaKey = `solution_items,${key}`;
|
|
||||||
solution = values[commaKey];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to dot notation
|
|
||||||
if (!solution) {
|
|
||||||
const dotKey = `solution_items.${key}`;
|
|
||||||
solution = values[dotKey];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!solution) {
|
|
||||||
// Last resort: search in all keys
|
|
||||||
const allKeys = Object.keys(values);
|
|
||||||
const foundKey = allKeys.find(k => k.includes(key.toString()) && k.includes('solution_items'));
|
|
||||||
if (foundKey) {
|
|
||||||
solution = values[foundKey];
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!solution) return null;
|
if (!solution && values.solution_items && values.solution_items[key]) {
|
||||||
|
solution = values.solution_items[key];
|
||||||
const validSolution = solution.name && solution.name.trim() !== '';
|
|
||||||
|
|
||||||
if (!validSolution) return null;
|
|
||||||
|
|
||||||
let pathSolution = '';
|
|
||||||
let fileObject = null;
|
|
||||||
|
|
||||||
if (solution.fileUpload && typeof solution.fileUpload === 'object' && Object.keys(solution.fileUpload).length > 0) {
|
|
||||||
pathSolution = solution.fileUpload.path_solution || solution.fileUpload.uploadPath || '';
|
|
||||||
fileObject = solution.fileUpload;
|
|
||||||
} else if (solution.file && typeof solution.file === 'object' && Object.keys(solution.file).length > 0) {
|
|
||||||
pathSolution = solution.file.path_solution || solution.file.uploadPath || '';
|
|
||||||
fileObject = solution.file;
|
|
||||||
} else if (solution.file && typeof solution.file === 'string' && solution.file.trim() !== '') {
|
|
||||||
pathSolution = solution.file;
|
|
||||||
}
|
|
||||||
|
|
||||||
let typeSolution = solutionTypes[key] || solution.type || 'text';
|
|
||||||
|
|
||||||
if (typeSolution === 'file') {
|
|
||||||
if (fileObject && fileObject.type_solution) {
|
|
||||||
typeSolution = fileObject.type_solution;
|
|
||||||
} else {
|
|
||||||
typeSolution = 'image';
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
if (!solution) {
|
||||||
solution_name: solution.name,
|
const commaKey = `solution_items,${key}`;
|
||||||
type_solution: typeSolution,
|
solution = values[commaKey];
|
||||||
text_solution: solution.text || '',
|
}
|
||||||
path_solution: pathSolution,
|
|
||||||
is_active: solution.status !== false && solution.status !== undefined ? solution.status : (solutionStatuses[key] !== false),
|
|
||||||
};
|
|
||||||
}).filter(Boolean);
|
|
||||||
|
|
||||||
return result;
|
if (!solution) {
|
||||||
|
const dotKey = `solution_items.${key}`;
|
||||||
|
solution = values[dotKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!solution) {
|
||||||
|
const allKeys = Object.keys(values);
|
||||||
|
const foundKey = allKeys.find(k =>
|
||||||
|
k.includes(key.toString()) &&
|
||||||
|
k.includes('solution_items')
|
||||||
|
);
|
||||||
|
if (foundKey) {
|
||||||
|
solution = values[foundKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!solution) {
|
||||||
|
// Try to find the solution in the raw form structure
|
||||||
|
const rawValues = solutionForm.getFieldsValue();
|
||||||
|
|
||||||
|
if (rawValues.solution_items && rawValues.solution_items[key]) {
|
||||||
|
solution = rawValues.solution_items[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!solution) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const hasName = solution.name && solution.name.trim() !== '';
|
||||||
|
|
||||||
|
if (!hasName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const solutionType = solutionTypes[key] || solution.type || 'text';
|
||||||
|
let isValidType = true;
|
||||||
|
|
||||||
|
if (solutionType === 'text') {
|
||||||
|
isValidType = solution.text && solution.text.trim() !== '';
|
||||||
|
if (!isValidType) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} 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);
|
||||||
|
|
||||||
|
isValidType = hasPathSolution || hasFileUpload || hasFile;
|
||||||
|
if (!isValidType) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let pathSolution = '';
|
||||||
|
let fileObject = null;
|
||||||
|
|
||||||
|
if (solution.fileUpload && typeof solution.fileUpload === 'object' && Object.keys(solution.fileUpload).length > 0) {
|
||||||
|
pathSolution = solution.fileUpload.path_solution || solution.fileUpload.uploadPath || '';
|
||||||
|
fileObject = solution.fileUpload;
|
||||||
|
} else if (solution.file && typeof solution.file === 'object' && Object.keys(solution.file).length > 0) {
|
||||||
|
pathSolution = solution.file.path_solution || solution.file.uploadPath || '';
|
||||||
|
fileObject = solution.file;
|
||||||
|
} else if (solution.file && typeof solution.file === 'string' && solution.file.trim() !== '') {
|
||||||
|
pathSolution = solution.file;
|
||||||
|
}
|
||||||
|
|
||||||
|
let typeSolution = solutionTypes[key] || solution.type || 'text';
|
||||||
|
|
||||||
|
if (typeSolution === 'file') {
|
||||||
|
if (fileObject && fileObject.type_solution) {
|
||||||
|
typeSolution = fileObject.type_solution;
|
||||||
|
} else {
|
||||||
|
typeSolution = 'image';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const finalSolution = {
|
||||||
|
solution_name: solution.name,
|
||||||
|
type_solution: typeSolution,
|
||||||
|
text_solution: solution.text || '',
|
||||||
|
path_solution: pathSolution,
|
||||||
|
is_active: solution.status !== false && solution.status !== undefined ? solution.status : (solutionStatuses[key] !== false),
|
||||||
|
};
|
||||||
|
|
||||||
|
result.push(finalSolution);
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const setSolutionsForExistingRecord = (solutions, form) => {
|
const setSolutionsForExistingRecord = (solutions, form) => {
|
||||||
@@ -193,8 +325,6 @@ export const useSolutionLogic = (solutionForm) => {
|
|||||||
solutions.forEach((solution, index) => {
|
solutions.forEach((solution, index) => {
|
||||||
const key = solution.id || index;
|
const key = solution.id || index;
|
||||||
|
|
||||||
console.log(`🔧 Processing solution ${key}:`, solution);
|
|
||||||
|
|
||||||
let fileObject = null;
|
let fileObject = null;
|
||||||
if (solution.path_solution && solution.path_solution.trim() !== '') {
|
if (solution.path_solution && solution.path_solution.trim() !== '') {
|
||||||
const fileName = solution.file_upload_name || solution.path_solution.split('/').pop() || `file_${index}`;
|
const fileName = solution.file_upload_name || solution.path_solution.split('/').pop() || `file_${index}`;
|
||||||
@@ -207,10 +337,8 @@ export const useSolutionLogic = (solutionForm) => {
|
|||||||
isExisting: true,
|
isExisting: true,
|
||||||
size: 0,
|
size: 0,
|
||||||
type: solution.type_solution === 'pdf' ? 'application/pdf' : 'image/jpeg',
|
type: solution.type_solution === 'pdf' ? 'application/pdf' : 'image/jpeg',
|
||||||
fileExtension: solution.type_solution === 'pdf' ? 'pdf' :
|
fileExtension: solution.type_solution === 'pdf' ? 'pdf' : (fileName.split('.').pop().toLowerCase() || 'jpg')
|
||||||
(fileName.split('.').pop().toLowerCase() || 'jpg')
|
|
||||||
};
|
};
|
||||||
console.log(`✅ Created file object for ${key}:`, fileObject);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const isFileType = solution.type_solution && solution.type_solution !== 'text' && fileObject;
|
const isFileType = solution.type_solution && solution.type_solution !== 'text' && fileObject;
|
||||||
@@ -227,13 +355,13 @@ export const useSolutionLogic = (solutionForm) => {
|
|||||||
newStatuses[key] = solution.is_active !== false;
|
newStatuses[key] = solution.is_active !== false;
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('🔧 Final solutions values:', solutionsValues);
|
const nestedFormValues = {
|
||||||
console.log('🔧 Final solution types:', newTypes);
|
solution_items: {}
|
||||||
|
};
|
||||||
|
|
||||||
const formValues = {};
|
|
||||||
Object.keys(solutionsValues).forEach(key => {
|
Object.keys(solutionsValues).forEach(key => {
|
||||||
const solution = solutionsValues[key];
|
const solution = solutionsValues[key];
|
||||||
formValues[`solution_items,${key}`] = {
|
nestedFormValues.solution_items[key] = {
|
||||||
name: solution.name,
|
name: solution.name,
|
||||||
type: solution.type,
|
type: solution.type,
|
||||||
text: solution.text,
|
text: solution.text,
|
||||||
@@ -243,8 +371,40 @@ export const useSolutionLogic = (solutionForm) => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('🔧 Setting form values:', formValues);
|
form.setFieldsValue(nestedFormValues);
|
||||||
form.setFieldsValue(formValues);
|
|
||||||
|
const fallbackFormValues = {};
|
||||||
|
Object.keys(solutionsValues).forEach(key => {
|
||||||
|
const solution = solutionsValues[key];
|
||||||
|
fallbackFormValues[`solution_items,${key}`] = {
|
||||||
|
name: solution.name,
|
||||||
|
type: solution.type,
|
||||||
|
text: solution.text,
|
||||||
|
file: solution.file,
|
||||||
|
fileUpload: solution.fileUpload,
|
||||||
|
status: solution.status
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
form.setFieldsValue(fallbackFormValues);
|
||||||
|
|
||||||
|
Object.keys(solutionsValues).forEach(key => {
|
||||||
|
const solution = solutionsValues[key];
|
||||||
|
form.setFieldValue([`solution_items,${key}`, 'name'], solution.name);
|
||||||
|
form.setFieldValue([`solution_items,${key}`, 'type'], solution.type);
|
||||||
|
form.setFieldValue([`solution_items,${key}`, 'text'], solution.text);
|
||||||
|
form.setFieldValue([`solution_items,${key}`, 'file'], solution.file);
|
||||||
|
form.setFieldValue([`solution_items,${key}`, 'fileUpload'], solution.fileUpload);
|
||||||
|
form.setFieldValue([`solution_items,${key}`, 'status'], solution.status);
|
||||||
|
|
||||||
|
form.setFieldValue(['solution_items', key, 'name'], solution.name);
|
||||||
|
form.setFieldValue(['solution_items', key, 'type'], solution.type);
|
||||||
|
form.setFieldValue(['solution_items', key, 'text'], solution.text);
|
||||||
|
form.setFieldValue(['solution_items', key, 'file'], solution.file);
|
||||||
|
form.setFieldValue(['solution_items', key, 'fileUpload'], solution.fileUpload);
|
||||||
|
form.setFieldValue(['solution_items', key, 'status'], solution.status);
|
||||||
|
});
|
||||||
|
|
||||||
setSolutionTypes(newTypes);
|
setSolutionTypes(newTypes);
|
||||||
setSolutionStatuses(newStatuses);
|
setSolutionStatuses(newStatuses);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user