209 lines
5.1 KiB
JavaScript
209 lines
5.1 KiB
JavaScript
import { Transfer, Tree, Badge, Spin } from 'antd'
|
|
import { useEffect, useState, useContext, useRef } from 'react'
|
|
import PropTypes from 'prop-types'
|
|
import axios from 'axios'
|
|
import { AuthContext } from '../../Auth/AuthContext'
|
|
//
|
|
const propertyOrder = ['products']
|
|
|
|
const PartTransfer = ({
|
|
onChange,
|
|
filter,
|
|
useFilter,
|
|
selectedKeys: initialSelectedKeys
|
|
}) => {
|
|
const [partsTreeData, setPartsTreeData] = useState([])
|
|
const [targetKeys, setTargetKeys] = useState(initialSelectedKeys || [])
|
|
const { token } = useContext(AuthContext)
|
|
const tokenRef = useRef(token)
|
|
const [loading, setLoading] = useState(true)
|
|
|
|
const fetchPartsData = async (property, filter) => {
|
|
setLoading(true)
|
|
try {
|
|
const response = await axios.get(`${config.backendUrl}/parts', {
|
|
params: {
|
|
...filter,
|
|
property
|
|
},
|
|
headers: {
|
|
Authorization: `Bearer ${tokenRef.current}`
|
|
}
|
|
})
|
|
setLoading(false)
|
|
return response.data
|
|
} catch (err) {
|
|
console.error(err)
|
|
console.error(err)
|
|
setLoading(false)
|
|
return []
|
|
}
|
|
}
|
|
|
|
const getFilter = (node) => {
|
|
let filter = {}
|
|
let currentId = node.id
|
|
while (currentId !== 0) {
|
|
const currentNode = partsTreeData.find(
|
|
(treeData) => treeData.id === currentId
|
|
)
|
|
if (currentNode) {
|
|
filter[propertyOrder[currentNode.propertyId]] =
|
|
currentNode.value.split('-')[0]
|
|
currentId = currentNode.pId
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
return filter
|
|
}
|
|
|
|
const generatePartTreeNodes = async (node = null, filter = null) => {
|
|
if (!node) return
|
|
|
|
const actualFilter = filter === null ? getFilter(node) : filter
|
|
const partData = await fetchPartsData(null, actualFilter)
|
|
|
|
const newNodeList = partData.map((part) => ({
|
|
id: part._id,
|
|
pId: node.id,
|
|
value: part._id,
|
|
key: part._id,
|
|
title: <Badge color={part.color} text={part.name} />,
|
|
isLeaf: true
|
|
}))
|
|
|
|
setPartsTreeData((prev) => [...prev, ...newNodeList])
|
|
}
|
|
|
|
const generatePartCategoryTreeNodes = async (node = null) => {
|
|
let filter = {}
|
|
let propertyId = 0
|
|
|
|
if (node) {
|
|
filter = getFilter(node)
|
|
propertyId = node.propertyId + 1
|
|
}
|
|
|
|
const propertyName = propertyOrder[propertyId]
|
|
const propertyData = await fetchPartsData(propertyName, filter)
|
|
|
|
const newNodeList = propertyData.map((data) => {
|
|
const property = data[propertyName]
|
|
const random = Math.random().toString(36).substring(2, 6)
|
|
return {
|
|
id: random,
|
|
pId: node ? node.id : '0',
|
|
value: `${property}-${random}`,
|
|
key: `${property}-${random}`,
|
|
propertyId: propertyId,
|
|
title: property,
|
|
isLeaf: false,
|
|
selectable: false
|
|
}
|
|
})
|
|
|
|
setPartsTreeData((prev) => [...prev, ...newNodeList])
|
|
}
|
|
|
|
const handleTreeLoad = async (node) => {
|
|
if (node) {
|
|
if (node.propertyId !== propertyOrder.length - 1) {
|
|
await generatePartCategoryTreeNodes(node)
|
|
} else {
|
|
await generatePartTreeNodes(node)
|
|
}
|
|
} else {
|
|
await generatePartCategoryTreeNodes(null)
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
setPartsTreeData([])
|
|
}, [token, filter, useFilter])
|
|
|
|
useEffect(() => {
|
|
if (partsTreeData.length === 0) {
|
|
if (useFilter) {
|
|
generatePartTreeNodes({ id: '0' }, filter)
|
|
} else {
|
|
handleTreeLoad(null)
|
|
}
|
|
}
|
|
}, [partsTreeData.length])
|
|
|
|
const transferDataSource = partsTreeData.filter((node) => node.isLeaf)
|
|
|
|
const renderTransferItem = (item) => item.title
|
|
|
|
const handleTransferChange = (newTargetKeys) => {
|
|
setTargetKeys(newTargetKeys)
|
|
onChange(newTargetKeys)
|
|
}
|
|
|
|
const renderSourceList = ({ onItemSelect }) => {
|
|
const treeData = partsTreeData
|
|
.map((node) => ({
|
|
...node,
|
|
children: partsTreeData
|
|
.filter((child) => child.pId === node.id)
|
|
.map((child) => ({
|
|
...child,
|
|
children: partsTreeData.filter(
|
|
(grandChild) => grandChild.pId === child.id
|
|
)
|
|
}))
|
|
}))
|
|
.filter((node) => !node.pId)
|
|
|
|
return (
|
|
<Tree
|
|
loadData={(node) => handleTreeLoad(node)}
|
|
treeData={treeData}
|
|
onSelect={(selectedKeys, { node }) => {
|
|
if (node.isLeaf) {
|
|
onItemSelect(node.key, !selectedKeys.includes(node.key))
|
|
}
|
|
}}
|
|
/>
|
|
)
|
|
}
|
|
|
|
if (loading && partsTreeData.length === 0) {
|
|
return <Spin />
|
|
}
|
|
|
|
return (
|
|
<Transfer
|
|
dataSource={transferDataSource}
|
|
targetKeys={targetKeys}
|
|
onChange={handleTransferChange}
|
|
render={renderTransferItem}
|
|
showSelectAll={true}
|
|
oneWay={false}
|
|
pagination
|
|
listStyle={{
|
|
width: 300,
|
|
height: 400
|
|
}}
|
|
>
|
|
{renderSourceList}
|
|
</Transfer>
|
|
)
|
|
}
|
|
|
|
PartTransfer.propTypes = {
|
|
onChange: PropTypes.func.isRequired,
|
|
filter: PropTypes.object,
|
|
useFilter: PropTypes.bool,
|
|
selectedKeys: PropTypes.arrayOf(PropTypes.string)
|
|
}
|
|
|
|
PartTransfer.defaultProps = {
|
|
filter: {},
|
|
useFilter: false,
|
|
selectedKeys: []
|
|
}
|
|
|
|
export default PartTransfer
|