repair: sparepart select brand-device
This commit is contained in:
@@ -46,6 +46,11 @@ const CustomSparepartCard = ({
|
||||
}
|
||||
};
|
||||
|
||||
const truncateText = (text, maxLength = 15) => {
|
||||
if (!text) return 'Unnamed';
|
||||
return text.length > maxLength ? `${text.substring(0, maxLength)}...` : text;
|
||||
};
|
||||
|
||||
const handleCardClick = () => {
|
||||
if (!isReadOnly && onCardClick) {
|
||||
onCardClick(sparepart);
|
||||
@@ -125,210 +130,88 @@ const CustomSparepartCard = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card
|
||||
hoverable={!!onCardClick && !isReadOnly}
|
||||
style={getCardStyle()}
|
||||
styles={{
|
||||
body: {
|
||||
padding: 0,
|
||||
height: 'calc(100% - 48px)',
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
}
|
||||
<div
|
||||
style={{
|
||||
border: '1px solid #f0f0f0',
|
||||
borderRadius: '6px',
|
||||
padding: '12px 16px',
|
||||
marginBottom: '8px',
|
||||
backgroundColor: 'white',
|
||||
cursor: onCardClick && !isReadOnly ? 'pointer' : 'default',
|
||||
transition: 'all 0.2s ease',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between'
|
||||
}}
|
||||
actions={getCardActions()}
|
||||
onClick={handleCardClick}
|
||||
>
|
||||
<div style={{ display: 'flex', height: '100%' }}>
|
||||
|
||||
<div style={{
|
||||
width: size === 'small' ? '90px' : '110px',
|
||||
flexShrink: 0,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
padding: size === 'small' ? '12px' : '16px',
|
||||
backgroundColor: '#fafafa',
|
||||
borderRight: '1px solid #f0f0f0',
|
||||
position: 'relative'
|
||||
}}>
|
||||
{sparepart.sparepart_item_type && (
|
||||
<Tag
|
||||
color="blue"
|
||||
style={{
|
||||
marginBottom: '8px',
|
||||
fontSize: '10px',
|
||||
fontWeight: 500
|
||||
}}
|
||||
>
|
||||
{sparepart.sparepart_item_type}
|
||||
</Tag>
|
||||
)}
|
||||
<div
|
||||
<div style={{ flex: 1, minWidth: 0 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', marginBottom: '4px' }}>
|
||||
<Text
|
||||
strong
|
||||
style={{
|
||||
width: size === 'small' ? '65px' : '75px',
|
||||
height: size === 'small' ? '65px' : '75px',
|
||||
backgroundColor: '#f0f0f0',
|
||||
borderRadius: '8px',
|
||||
overflow: 'hidden',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
border: '1px solid #e8e8e8'
|
||||
fontSize: '14px',
|
||||
color: '#262626',
|
||||
marginRight: '12px'
|
||||
}}
|
||||
title={sparepart.sparepart_name || sparepart.name || 'Unnamed'}
|
||||
>
|
||||
<img
|
||||
src={getImageSrc()}
|
||||
alt={sparepart.sparepart_name || 'Sparepart'}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
objectFit: 'cover'
|
||||
}}
|
||||
onError={(e) => {
|
||||
e.target.src = 'https://via.placeholder.com/75';
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
{isSelected && (
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '8px',
|
||||
right: '8px',
|
||||
backgroundColor: '#52c41a',
|
||||
borderRadius: '50%',
|
||||
width: '18px',
|
||||
height: '18px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
boxShadow: '0 2px 4px rgba(0,0,0,0.15)',
|
||||
zIndex: 2
|
||||
}}
|
||||
>
|
||||
<CheckOutlined style={{ color: 'white', fontSize: '10px' }} />
|
||||
</div>
|
||||
)}
|
||||
{truncateText(sparepart.sparepart_name || sparepart.name || 'Unnamed')}
|
||||
</Text>
|
||||
<Tag
|
||||
color={sparepart.sparepart_stok === 'Available' ? 'green' : 'red'}
|
||||
style={{ fontSize: '11px', margin: 0 }}
|
||||
>
|
||||
{sparepart.sparepart_stok || 'Not Available'}
|
||||
</Tag>
|
||||
</div>
|
||||
|
||||
|
||||
<div style={{
|
||||
flex: 1,
|
||||
padding: size === 'small' ? '12px' : '16px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'space-between',
|
||||
overflow: 'hidden'
|
||||
}}>
|
||||
<div style={{ flex: 1, overflow: 'hidden' }}>
|
||||
<Title
|
||||
level={size === 'small' ? 5 : 4}
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<Text style={{ fontSize: '12px', color: '#666', marginRight: '4px' }}>
|
||||
qty:
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
margin: `0 0 ${size === 'small' ? '6px' : '8px'} 0`,
|
||||
fontSize: size === 'small' ? '12px' : '14px',
|
||||
fontSize: '12px',
|
||||
fontWeight: 600,
|
||||
lineHeight: '1.4',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
display: '-webkit-box',
|
||||
WebkitLineClamp: size === 'small' ? 2 : 3,
|
||||
WebkitBoxOrient: 'vertical'
|
||||
color: '#262626'
|
||||
}}
|
||||
>
|
||||
{sparepart.sparepart_name || sparepart.name || 'Unnamed'}
|
||||
</Title>
|
||||
|
||||
|
||||
<div style={{ marginBottom: size === 'small' ? '6px' : '8px' }}>
|
||||
|
||||
<div style={{ marginBottom: '4px' }}>
|
||||
<Tag
|
||||
color={sparepart.sparepart_stok === 'Available' ? 'green' : 'red'}
|
||||
style={{
|
||||
fontSize: size === 'small' ? '9px' : '10px',
|
||||
padding: '0 4px',
|
||||
margin: 0,
|
||||
height: 'auto'
|
||||
}}
|
||||
>
|
||||
{sparepart.sparepart_stok || 'Not Available'}
|
||||
</Tag>
|
||||
</div>
|
||||
|
||||
|
||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: size === 'small' ? '10px' : '11px',
|
||||
fontWeight: 500,
|
||||
color: '#262626',
|
||||
marginRight: '4px'
|
||||
}}
|
||||
>
|
||||
qty:
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: size === 'small' ? '10px' : '11px',
|
||||
color: sparepart.sparepart_qty > 0 ? '#52c41a' : '#ff4d4f',
|
||||
fontWeight: 600
|
||||
}}
|
||||
>
|
||||
{sparepart.sparepart_qty || 0}
|
||||
{sparepart.sparepart_unit ? ` ${sparepart.sparepart_unit}` : ''}
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: size === 'small' ? '4px' : '6px' }}>
|
||||
<Text
|
||||
code
|
||||
style={{
|
||||
fontSize: size === 'small' ? '10px' : '11px',
|
||||
backgroundColor: '#f5f5f5',
|
||||
padding: '2px 6px',
|
||||
borderRadius: '3px'
|
||||
}}
|
||||
>
|
||||
{sparepart.sparepart_code || 'No code'}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
{(sparepart.sparepart_merk || sparepart.sparepart_model) && (
|
||||
<div style={{
|
||||
fontSize: size === 'small' ? '9px' : '10px',
|
||||
color: '#666',
|
||||
lineHeight: '1.4',
|
||||
marginBottom: '4px'
|
||||
}}>
|
||||
{sparepart.sparepart_merk && (
|
||||
<div>Brand: {sparepart.sparepart_merk}</div>
|
||||
)}
|
||||
{sparepart.sparepart_model && (
|
||||
<div>Model: {sparepart.sparepart_model}</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{sparepart.sparepart_qty || 0}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<Text
|
||||
type="secondary"
|
||||
style={{
|
||||
fontSize: size === 'small' ? '9px' : '10px',
|
||||
marginTop: 'auto',
|
||||
paddingTop: '4px',
|
||||
borderTop: '1px solid #f0f0f0'
|
||||
}}
|
||||
>
|
||||
{sparepart.updated_at && dayjs(sparepart.updated_at).format('DD MMM YYYY')}
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Space size="small">
|
||||
{showPreview && (
|
||||
<Button
|
||||
type="text"
|
||||
icon={<EyeOutlined />}
|
||||
size="small"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handlePreview();
|
||||
}}
|
||||
title="Preview"
|
||||
/>
|
||||
)}
|
||||
{showDelete && !isReadOnly && (
|
||||
<Button
|
||||
type="text"
|
||||
icon={<DeleteOutlined />}
|
||||
size="small"
|
||||
danger
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onDelete?.(sparepart);
|
||||
}}
|
||||
title="Remove"
|
||||
/>
|
||||
)}
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
|
||||
<Modal
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Select, Typography, Tag, Spin, Empty, Button, Row, Col } from 'antd';
|
||||
import { Select, Typography, Tag, Spin, Empty, Button } from 'antd';
|
||||
import { PlusOutlined, DeleteOutlined, CheckOutlined, EyeOutlined, InfoCircleOutlined } from '@ant-design/icons';
|
||||
import { getAllSparepart } from '../../../../api/sparepart';
|
||||
import CustomSparepartCard from './CustomSparepartCard';
|
||||
@@ -96,20 +96,16 @@ const SparepartSelect = ({
|
||||
const isAlreadySelected = selectedSpareparts.some(sp => sp.sparepart_id === sparepart.sparepart_id);
|
||||
|
||||
return (
|
||||
<Col xs={24} sm={24} md={12} lg={12} key={sparepart.sparepart_id}>
|
||||
<CustomSparepartCard
|
||||
sparepart={sparepart}
|
||||
isSelected={isSelected}
|
||||
isReadOnly={isReadOnly}
|
||||
showPreview={true}
|
||||
showDelete={isAlreadySelected && !isReadOnly}
|
||||
onCardClick={!isAlreadySelected && !isReadOnly ? () => handleSparepartSelect(sparepart.sparepart_id) : undefined}
|
||||
onDelete={() => handleRemoveSparepart(sparepart.sparepart_id)}
|
||||
style={{
|
||||
border: isAlreadySelected ? '2px solid #52c41a' : undefined,
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
<CustomSparepartCard
|
||||
key={sparepart.sparepart_id}
|
||||
sparepart={sparepart}
|
||||
isSelected={isSelected}
|
||||
isReadOnly={isReadOnly}
|
||||
showPreview={true}
|
||||
showDelete={isAlreadySelected && !isReadOnly}
|
||||
onCardClick={!isAlreadySelected && !isReadOnly ? () => handleSparepartSelect(sparepart.sparepart_id) : undefined}
|
||||
onDelete={() => handleRemoveSparepart(sparepart.sparepart_id)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -163,9 +159,9 @@ const SparepartSelect = ({
|
||||
<Title level={5} style={{ marginBottom: 16 }}>
|
||||
Selected Spareparts ({selectedSpareparts.length})
|
||||
</Title>
|
||||
<Row gutter={[16, 16]}>
|
||||
<div>
|
||||
{selectedSpareparts.map(sparepart => renderSparepartCard(sparepart, true))}
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<Empty
|
||||
|
||||
Reference in New Issue
Block a user