- Adjusted width of Stock Transfers modal for better UI consistency. - Enhanced New Stock Transfer form with default transfer name generation and improved validation handling. - Added Product Categories to Management Sidebar and updated routing for better navigation. - Implemented delete functionality in Host Info component. - Improved User Info layout for mobile responsiveness and added ObjectProperty component for better data display. - Updated FileUpload and FileList components to support minimal display mode. - Enhanced ObjectTable with subscription filtering and improved rendering logic. - Added new properties and filters to Stock Transfer and Product models for better data management.
216 lines
5.8 KiB
JavaScript
216 lines
5.8 KiB
JavaScript
import { Upload, Button, Flex, Typography, Space, Progress, Card } from 'antd'
|
|
import PropTypes from 'prop-types'
|
|
import { ApiServerContext } from '../context/ApiServerContext'
|
|
import UploadIcon from '../../Icons/UploadIcon'
|
|
import {
|
|
useCallback,
|
|
useContext,
|
|
useEffect,
|
|
useMemo,
|
|
useRef,
|
|
useState
|
|
} from 'react'
|
|
import ObjectSelect from './ObjectSelect'
|
|
import FileList from './FileList'
|
|
import PlusIcon from '../../Icons/PlusIcon'
|
|
import { LoadingOutlined } from '@ant-design/icons'
|
|
import FileIcon from '../../Icons/FileIcon'
|
|
|
|
const { Text } = Typography
|
|
|
|
const getFileIdentity = (value, multiple) => {
|
|
if (multiple) {
|
|
return Array.isArray(value)
|
|
? value.map((file) => file?._id || file).join(',')
|
|
: ''
|
|
}
|
|
|
|
return value?._id || value || ''
|
|
}
|
|
|
|
const FileUpload = ({
|
|
value,
|
|
onChange,
|
|
minimal = false,
|
|
multiple = true,
|
|
defaultPreviewOpen = false,
|
|
showPreview = true,
|
|
showInfo
|
|
}) => {
|
|
const { uploadFile } = useContext(ApiServerContext)
|
|
const [uploading, setUploading] = useState(false)
|
|
const [uploadProgress, setUploadProgress] = useState(0)
|
|
const onChangeRef = useRef(onChange)
|
|
|
|
useEffect(() => {
|
|
onChangeRef.current = onChange
|
|
}, [onChange])
|
|
|
|
// Track current files using useState
|
|
const [currentFiles, setCurrentFiles] = useState(() => {
|
|
if (multiple) {
|
|
return Array.isArray(value) ? value : []
|
|
} else {
|
|
return value || null
|
|
}
|
|
})
|
|
|
|
// Update currentFiles when value prop changes
|
|
useEffect(() => {
|
|
setCurrentFiles((prev) => {
|
|
if (
|
|
getFileIdentity(prev, multiple) === getFileIdentity(value, multiple)
|
|
) {
|
|
return prev
|
|
}
|
|
|
|
return multiple ? (Array.isArray(value) ? value : []) : value || null
|
|
})
|
|
}, [value, multiple])
|
|
|
|
// Track the selected file from ObjectSelect
|
|
const [selectedFile, setSelectedFile] = useState(null)
|
|
|
|
const hasNoItems = useMemo(
|
|
() =>
|
|
multiple
|
|
? !currentFiles ||
|
|
!Array.isArray(currentFiles) ||
|
|
currentFiles.length === 0
|
|
: !currentFiles,
|
|
[currentFiles, multiple]
|
|
)
|
|
|
|
const updateCurrentFiles = useCallback((nextFiles) => {
|
|
setCurrentFiles(nextFiles)
|
|
onChangeRef.current?.(nextFiles)
|
|
}, [])
|
|
|
|
const handleFileUpload = async (file) => {
|
|
try {
|
|
setUploading(true)
|
|
const uploadedFile = await uploadFile(file, {}, (progress) => {
|
|
setUploadProgress(progress)
|
|
})
|
|
setUploading(false)
|
|
if (uploadedFile) {
|
|
if (multiple) {
|
|
// For multiple files, add to existing array
|
|
const newFiles = [...currentFiles, uploadedFile]
|
|
updateCurrentFiles(newFiles)
|
|
} else {
|
|
// For single file, replace the value
|
|
updateCurrentFiles(uploadedFile)
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('File upload failed:', error)
|
|
}
|
|
return false // Prevent default upload behavior
|
|
}
|
|
|
|
// Handle adding selected file to the list
|
|
const handleAddSelectedFile = () => {
|
|
if (selectedFile) {
|
|
if (multiple) {
|
|
// For multiple files, add to existing array
|
|
const newFiles = [...currentFiles, selectedFile]
|
|
updateCurrentFiles(newFiles)
|
|
} else {
|
|
// For single file, replace the value
|
|
updateCurrentFiles(selectedFile)
|
|
}
|
|
// Clear the selection
|
|
setSelectedFile(null)
|
|
}
|
|
}
|
|
|
|
if (minimal == true) {
|
|
return (
|
|
<Flex gap={'small'} vertical>
|
|
<FileIcon file={currentFiles[0]} style={{ fontSize: '24px' }} />
|
|
<Text>{currentFiles[0]?.name}</Text>
|
|
</Flex>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<Flex gap={'small'} vertical>
|
|
{hasNoItems && uploading == false ? (
|
|
<Flex gap={'small'} align='center' wrap>
|
|
<Space.Compact style={{ flexGrow: 1 }}>
|
|
<ObjectSelect
|
|
type={'file'}
|
|
value={selectedFile}
|
|
onChange={setSelectedFile}
|
|
/>
|
|
<Button
|
|
icon={<PlusIcon />}
|
|
onClick={handleAddSelectedFile}
|
|
disabled={!selectedFile}
|
|
/>
|
|
</Space.Compact>
|
|
<Text style={{ whiteSpace: 'nowrap' }} type='secondary'>
|
|
or
|
|
</Text>
|
|
<Upload
|
|
beforeUpload={handleFileUpload}
|
|
showUploadList={false}
|
|
multiple={multiple}
|
|
>
|
|
<Button style={{ width: '100%' }} icon={<UploadIcon />}>
|
|
Upload
|
|
</Button>
|
|
</Upload>
|
|
</Flex>
|
|
) : null}
|
|
{uploading == true ? (
|
|
<Card styles={{ body: { padding: '10px 15px' } }}>
|
|
<Flex gap={'small'} align='center'>
|
|
<Text>Uploading...</Text>
|
|
{uploadProgress > 0 ? (
|
|
<>
|
|
{uploadProgress >= 0 && uploadProgress < 100 ? (
|
|
<>
|
|
<Progress
|
|
percent={uploadProgress}
|
|
showInfo={false}
|
|
style={{ width: '100px', flexGrow: 1 }}
|
|
status='active'
|
|
/>
|
|
<Text>{uploadProgress}%</Text>
|
|
</>
|
|
) : null}
|
|
{uploadProgress == 100 ? <LoadingOutlined /> : null}
|
|
</>
|
|
) : null}
|
|
</Flex>
|
|
</Card>
|
|
) : null}
|
|
<FileList
|
|
files={currentFiles}
|
|
multiple={multiple}
|
|
editing={true}
|
|
showInfo={showInfo || false}
|
|
showPreview={showPreview}
|
|
defaultPreviewOpen={defaultPreviewOpen}
|
|
onChange={(updatedFiles) => {
|
|
updateCurrentFiles(updatedFiles)
|
|
}}
|
|
/>
|
|
</Flex>
|
|
)
|
|
}
|
|
|
|
FileUpload.propTypes = {
|
|
value: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
|
onChange: PropTypes.func,
|
|
multiple: PropTypes.bool,
|
|
showPreview: PropTypes.bool,
|
|
showInfo: PropTypes.bool,
|
|
defaultPreviewOpen: PropTypes.bool,
|
|
minimal: PropTypes.bool
|
|
}
|
|
|
|
export default FileUpload
|