feat: enhance DetailSparepart component with image upload and preview functionality
This commit is contained in:
@@ -12,7 +12,7 @@ import {
|
||||
Col,
|
||||
Image,
|
||||
} from 'antd';
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { PlusOutlined, EyeOutlined, DeleteOutlined } from '@ant-design/icons';
|
||||
import { NotifAlert, NotifOk } from '../../../../components/Global/ToastNotif';
|
||||
import { createSparepart, updateSparepart } from '../../../../api/sparepart';
|
||||
import { uploadFile } from '../../../../api/file-uploads';
|
||||
@@ -35,13 +35,14 @@ const DetailSparepart = (props) => {
|
||||
const [previewOpen, setPreviewOpen] = useState(false);
|
||||
const [previewImage, setPreviewImage] = useState('');
|
||||
const [previewTitle, setPreviewTitle] = useState('');
|
||||
const [isHovering, setIsHovering] = useState(false);
|
||||
|
||||
const defaultData = {
|
||||
sparepart_id: '',
|
||||
sparepart_name: '',
|
||||
sparepart_description: '',
|
||||
sparepart_model: '',
|
||||
sparepart_item_type: '',
|
||||
sparepart_item_type: null,
|
||||
sparepart_unit: '',
|
||||
sparepart_merk: '',
|
||||
sparepart_stok: '0',
|
||||
@@ -69,6 +70,10 @@ const DetailSparepart = (props) => {
|
||||
|
||||
const handleChange = ({ fileList: newFileList }) => setFileList(newFileList);
|
||||
|
||||
const handleRemove = () => {
|
||||
setFileList([]);
|
||||
};
|
||||
|
||||
const handleSave = async () => {
|
||||
setConfirmLoading(true);
|
||||
|
||||
@@ -364,85 +369,158 @@ const DetailSparepart = (props) => {
|
||||
{formData && (
|
||||
<div>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={12}>
|
||||
<Text strong>Sparepart Name</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
<Input
|
||||
name="sparepart_name"
|
||||
value={formData.sparepart_name}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Sparepart Name"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Text strong>Item Type</Text>
|
||||
<Select
|
||||
name="sparepart_item_type"
|
||||
value={formData.sparepart_item_type}
|
||||
onChange={(value) =>
|
||||
handleSelectChange('sparepart_item_type', value)
|
||||
}
|
||||
placeholder="Select Item Type"
|
||||
disabled={props.readOnly}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
<Select.Option value="Air Dryer">Air Dryer</Select.Option>
|
||||
<Select.Option value="Compressor">Compressor</Select.Option>
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={12}>
|
||||
<Text strong>Stock</Text>
|
||||
<Input
|
||||
name="sparepart_stok"
|
||||
value={formData.sparepart_stok}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Initial stock quantity"
|
||||
readOnly={props.readOnly}
|
||||
type="number"
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Text strong>Unit</Text>
|
||||
<Input
|
||||
name="sparepart_unit"
|
||||
value={formData.sparepart_unit}
|
||||
onChange={handleInputChange}
|
||||
placeholder="e.g., pcs, box, roll"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
{/* Kolom untuk foto */}
|
||||
<Col span={10} style={{ display: 'flex', flexDirection: 'column' }}>
|
||||
<Text strong>Foto</Text>
|
||||
<Upload
|
||||
listType="picture-card"
|
||||
fileList={fileList}
|
||||
onPreview={handlePreview}
|
||||
onChange={handleChange}
|
||||
beforeUpload={() => false}
|
||||
maxCount={1}
|
||||
disabled={props.readOnly}
|
||||
<div
|
||||
style={{
|
||||
flexGrow: 1,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
width: '100%',
|
||||
}}
|
||||
>
|
||||
{fileList.length >= 1 ? null : uploadButton}
|
||||
</Upload>
|
||||
<Modal
|
||||
open={previewOpen}
|
||||
title={previewTitle}
|
||||
footer={null}
|
||||
onCancel={handlePreviewCancel}
|
||||
>
|
||||
<img alt="preview" style={{ width: '100%' }} src={previewImage} />
|
||||
</Modal>
|
||||
{fileList.length > 0 ? (
|
||||
<div
|
||||
onMouseEnter={() => setIsHovering(true)}
|
||||
onMouseLeave={() => setIsHovering(false)}
|
||||
style={{
|
||||
position: 'relative',
|
||||
width: '180px', // Fixed width for square
|
||||
height: '180px', // Fixed height
|
||||
border: '1px solid #d9d9d9',
|
||||
borderRadius: '8px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
src={fileList[0].url || fileList[0].thumbUrl}
|
||||
alt="preview"
|
||||
style={{
|
||||
maxWidth: '100%',
|
||||
maxHeight: '100%',
|
||||
objectFit: 'contain',
|
||||
}}
|
||||
preview={false} // Disable default preview
|
||||
/>
|
||||
{isHovering && !props.readOnly && (
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
background: 'rgba(0, 0, 0, 0.5)',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
color: 'white',
|
||||
gap: '16px',
|
||||
fontSize: '20px',
|
||||
borderRadius: '8px',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
>
|
||||
<EyeOutlined
|
||||
onClick={() => handlePreview(fileList[0])}
|
||||
/>
|
||||
<DeleteOutlined onClick={handleRemove} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<Upload
|
||||
name="file"
|
||||
multiple={false}
|
||||
fileList={fileList}
|
||||
onChange={handleChange}
|
||||
beforeUpload={() => false}
|
||||
maxCount={1}
|
||||
disabled={props.readOnly}
|
||||
showUploadList={false}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: '180px', // Fixed width for square
|
||||
height: '180px',
|
||||
border: '1px dashed #d9d9d9',
|
||||
borderRadius: '8px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
cursor: 'pointer',
|
||||
gap: '8px',
|
||||
}}
|
||||
>
|
||||
<PlusOutlined />
|
||||
<div>Upload</div>
|
||||
</div>
|
||||
</Upload>
|
||||
)}
|
||||
</div>
|
||||
</Col>
|
||||
|
||||
{/* Kolom untuk field lainnya */}
|
||||
<Col span={14}>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
<Text strong>Sparepart Name</Text>
|
||||
<Text style={{ color: 'red' }}> *</Text>
|
||||
<Input
|
||||
name="sparepart_name"
|
||||
value={formData.sparepart_name}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Enter Sparepart Name"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Text strong>Item Type</Text>
|
||||
<Select
|
||||
name="sparepart_item_type"
|
||||
value={formData.sparepart_item_type}
|
||||
onChange={(value) =>
|
||||
handleSelectChange('sparepart_item_type', value)
|
||||
}
|
||||
placeholder="Enter Item Type"
|
||||
disabled={props.readOnly}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
<Select.Option value="Air Dryer">Air Dryer</Select.Option>
|
||||
<Select.Option value="Compressor">Compressor</Select.Option>
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Text strong>Stock</Text>
|
||||
<Input
|
||||
name="sparepart_stok"
|
||||
value={formData.sparepart_stok}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Initial stock"
|
||||
readOnly={props.readOnly}
|
||||
type="number"
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Text strong>Unit</Text>
|
||||
<Input
|
||||
name="sparepart_unit"
|
||||
value={formData.sparepart_unit}
|
||||
onChange={handleInputChange}
|
||||
placeholder="e.g., pcs"
|
||||
readOnly={props.readOnly}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={[16, 16]}>
|
||||
<Row gutter={[16, 16]} style={{ marginTop: 16 }}>
|
||||
<Col span={12}>
|
||||
<Text strong>Brand</Text>
|
||||
<Input
|
||||
@@ -465,7 +543,7 @@ const DetailSparepart = (props) => {
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={[16, 16]}>
|
||||
<Row gutter={[16, 16]} style={{ marginTop: 16 }}>
|
||||
<Col span={24}>
|
||||
<Text strong>Description</Text>
|
||||
<TextArea
|
||||
@@ -480,6 +558,9 @@ const DetailSparepart = (props) => {
|
||||
</Row>
|
||||
</div>
|
||||
)}
|
||||
<Modal open={previewOpen} title={previewTitle} footer={null} onCancel={handlePreviewCancel}>
|
||||
<img alt="preview" style={{ width: '100%' }} src={previewImage} />
|
||||
</Modal>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user