feat: add onGetData callback to TableList and enhance DetailSparepart with improved image handling

This commit is contained in:
2025-11-27 13:30:45 +07:00
parent 572042ab53
commit ed4570e8dd
4 changed files with 334 additions and 70 deletions

View File

@@ -1,5 +1,17 @@
import React, { useState, useEffect } from 'react';
import { Modal, Input, Select, Divider, Typography, Button, ConfigProvider, Upload, Row, Col, Image } from 'antd';
import {
Modal,
Input,
Select,
Divider,
Typography,
Button,
ConfigProvider,
Upload,
Row,
Col,
Image,
} from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { NotifAlert, NotifOk } from '../../../../components/Global/ToastNotif';
import { createSparepart, updateSparepart } from '../../../../api/sparepart';
@@ -33,7 +45,7 @@ const DetailSparepart = (props) => {
sparepart_unit: '',
sparepart_merk: '',
sparepart_stok: '0',
image_url: '',
sparepart_foto: '',
};
const [formData, setFormData] = useState(defaultData);
@@ -60,7 +72,9 @@ const DetailSparepart = (props) => {
const handleSave = async () => {
setConfirmLoading(true);
const validationRules = [{ field: 'sparepart_name', label: 'Sparepart Name', required: true }];
const validationRules = [
{ field: 'sparepart_name', label: 'Sparepart Name', required: true },
];
if (
validateRun(formData, validationRules, (errorMessages) => {
@@ -71,40 +85,153 @@ const DetailSparepart = (props) => {
return;
try {
let imageUrl = formData.image_url;
let imageUrl = formData.sparepart_foto;
const newFile = fileList.length > 0 ? fileList[0] : null;
if (newFile && newFile.originFileObj) {
console.log('Uploading file:', newFile.originFileObj);
const uploadResponse = await uploadFile(newFile.originFileObj, 'images');
if (uploadResponse && uploadResponse.file_url) {
imageUrl = uploadResponse.file_url;
// Log untuk debugging
console.log('Upload response:', uploadResponse);
// Cek berbagai kemungkinan struktur respons dari API
let uploadedUrl = null;
// Cek berbagai kemungkinan struktur respons dari API
// Cek langsung properti file_url atau url
if (uploadResponse && typeof uploadResponse === 'object') {
// Cek jika uploadResponse langsung memiliki file_url
if (uploadResponse.file_url) {
uploadedUrl = uploadResponse.file_url;
}
// Cek jika uploadResponse memiliki data yang berisi file_url
else if (uploadResponse.data && uploadResponse.data.file_url) {
uploadedUrl = uploadResponse.data.file_url;
}
// Cek jika uploadResponse memiliki data yang berisi url
else if (uploadResponse.data && uploadResponse.data.url) {
uploadedUrl = uploadResponse.data.url;
}
// Cek jika uploadResponse langsung memiliki url
else if (uploadResponse.url) {
uploadedUrl = uploadResponse.url;
}
// Cek jika uploadResponse.data adalah string URL
else if (uploadResponse.data && typeof uploadResponse.data === 'string') {
uploadedUrl = uploadResponse.data;
}
// Cek jika uploadResponse.data adalah objek yang berisi file URL dalam format berbeda
else if (uploadResponse.data && typeof uploadResponse.data === 'object') {
// Cek kemungkinan nama field lain
if (uploadResponse.data.file) {
uploadedUrl = uploadResponse.data.file;
} else if (uploadResponse.data.filename) {
// Jika hanya nama file dikembalikan, bangun URL
const baseUrl = import.meta.env.VITE_API_SERVER || '';
uploadedUrl = `${baseUrl}/uploads/images/${uploadResponse.data.filename}`;
} else if (uploadResponse.data.path) {
uploadedUrl = uploadResponse.data.path;
} else if (uploadResponse.data.location) {
uploadedUrl = uploadResponse.data.location;
}
// Tambahkan kemungkinan lain berdasarkan struktur respons umum
else if (uploadResponse.data.filePath) {
uploadedUrl = uploadResponse.data.filePath;
} else if (uploadResponse.data.file_path) {
uploadedUrl = uploadResponse.data.file_path;
} else if (uploadResponse.data.publicUrl) {
uploadedUrl = uploadResponse.data.publicUrl;
} else if (uploadResponse.data.public_url) {
uploadedUrl = uploadResponse.data.public_url;
}
// Berdasarkan log yang ditampilkan, API mengembalikan path_document atau path_solution
else if (uploadResponse.data.path_document) {
uploadedUrl = uploadResponse.data.path_document;
} else if (uploadResponse.data.path_solution) {
uploadedUrl = uploadResponse.data.path_solution;
} else if (uploadResponse.data.file_upload_name) {
// Jika hanya nama file dikembalikan, bangun URL
const baseUrl = import.meta.env.VITE_API_SERVER || '';
uploadedUrl = `${baseUrl}/uploads/images/${uploadResponse.data.file_upload_name}`;
}
}
}
// Jika respons adalah string, mungkin itu adalah URL
else if (uploadResponse && typeof uploadResponse === 'string') {
uploadedUrl = uploadResponse;
}
if (uploadedUrl) {
console.log('Successfully extracted image URL:', uploadedUrl);
imageUrl = uploadedUrl;
} else {
throw new Error('Image upload failed or did not return a URL.');
console.error('Upload response structure:', uploadResponse);
console.error('Available properties:', Object.keys(uploadResponse || {}));
console.error('Response type:', typeof uploadResponse);
console.error(
'Is response an object?',
uploadResponse && typeof uploadResponse === 'object'
);
if (uploadResponse && typeof uploadResponse === 'object') {
console.error('Response keys:', Object.keys(uploadResponse));
console.error(
'Response data keys:',
uploadResponse.data
? Object.keys(uploadResponse.data)
: 'No data property'
);
}
// Tampilkan notifikasi bahwa upload gagal tapi lanjutkan penyimpanan
NotifOk({
icon: 'warning',
title: 'Peringatan',
message: 'Upload gambar gagal. Data akan disimpan tanpa gambar.',
});
// Gunakan URL gambar yang sebelumnya jika ada, atau kosongkan
imageUrl = formData.sparepart_foto || '';
}
} else if (fileList.length === 0 && formData.sparepart_id) {
imageUrl = '';
}
// Kirim semua field yang dianggap required oleh API, bahkan jika kosong
const payload = {
sparepart_name: formData.sparepart_name,
sparepart_item_type: formData.sparepart_item_type,
sparepart_stok: formData.sparepart_stok || '0',
image_url: imageUrl,
sparepart_merk: formData.sparepart_merk,
sparepart_model: formData.sparepart_model,
sparepart_description: formData.sparepart_description,
sparepart_unit: formData.sparepart_unit,
sparepart_name: formData.sparepart_name, // Wajib
sparepart_description: formData.sparepart_description || '', // Diperlukan oleh API
sparepart_model: formData.sparepart_model || '', // Diperlukan oleh API
sparepart_item_type: formData.sparepart_item_type || '', // Diperlukan oleh API
sparepart_unit: formData.sparepart_unit || '', // Diperlukan oleh API
sparepart_merk: formData.sparepart_merk || '', // Diperlukan oleh API
};
// Tambahkan field-field yang tidak dianggap required jika ada nilainya
if (formData.sparepart_stok && formData.sparepart_stok.trim() !== '') {
payload.sparepart_stok = formData.sparepart_stok.toString();
} else {
payload.sparepart_stok = '0'; // Set default value jika tidak diisi
}
if (imageUrl && imageUrl.trim() !== '') {
payload.sparepart_foto = imageUrl;
}
console.log('Sending payload:', payload);
const response = formData.sparepart_id
? await updateSparepart(formData.sparepart_id, payload)
: await createSparepart(payload);
console.log('API response:', response);
if (response && (response.statusCode === 200 || response.statusCode === 201)) {
NotifOk({
icon: 'success',
title: 'Berhasil',
message: `Data Sparepart berhasil ${formData.sparepart_id ? 'diubah' : 'ditambahkan'}.`,
message: `Data Sparepart berhasil ${
formData.sparepart_id ? 'diubah' : 'ditambahkan'
}.`,
});
props.setActionMode('list');
setFileList([]);
@@ -139,13 +266,13 @@ const DetailSparepart = (props) => {
useEffect(() => {
if (props.selectedData) {
setFormData(props.selectedData);
if (props.selectedData.image_url) {
if (props.selectedData.sparepart_foto) {
setFileList([
{
uid: '-1',
name: props.selectedData.image_url.split('/').pop(),
name: props.selectedData.sparepart_foto.split('/').pop(),
status: 'done',
url: props.selectedData.image_url,
url: props.selectedData.sparepart_foto,
},
]);
} else {
@@ -167,7 +294,11 @@ const DetailSparepart = (props) => {
return (
<Modal
title={`${
props.actionMode === 'add' ? 'Tambah' : props.actionMode === 'preview' ? 'Preview' : 'Edit'
props.actionMode === 'add'
? 'Tambah'
: props.actionMode === 'preview'
? 'Preview'
: 'Edit'
} Sparepart`}
open={props.showModal}
onCancel={handleCancel}
@@ -231,7 +362,9 @@ const DetailSparepart = (props) => {
<Select
name="sparepart_item_type"
value={formData.sparepart_item_type}
onChange={(value) => handleSelectChange('sparepart_item_type', value)}
onChange={(value) =>
handleSelectChange('sparepart_item_type', value)
}
placeholder="Select Item Type"
disabled={props.readOnly}
style={{ width: '100%' }}
@@ -280,7 +413,12 @@ const DetailSparepart = (props) => {
>
{fileList.length >= 1 ? null : uploadButton}
</Upload>
<Modal open={previewOpen} title={previewTitle} footer={null} onCancel={handlePreviewCancel}>
<Modal
open={previewOpen}
title={previewTitle}
footer={null}
onCancel={handlePreviewCancel}
>
<img alt="preview" style={{ width: '100%' }} src={previewImage} />
</Modal>
</Col>
@@ -328,4 +466,4 @@ const DetailSparepart = (props) => {
);
};
export default DetailSparepart;
export default DetailSparepart;