2025-06-01 00:18:15 +01:00

155 lines
4.2 KiB
JavaScript

// PrinterSelect.js
import PropTypes from 'prop-types'
import { TreeSelect, message, Tag } from 'antd'
import React, { useEffect, useState, useContext } from 'react'
import axios from 'axios'
import PrinterState from './PrinterState'
import { AuthContext } from '../../Auth/AuthContext'
import config from '../../../config'
const PrinterSelect = ({ onChange, disabled, checkable, value = [] }) => {
const [printersTreeData, setPrintersTreeData] = useState([])
const [printersData, setPrintersData] = useState([])
const [loading, setLoading] = useState(true)
const [messageApi] = message.useMessage()
const [defaultValue, setDefaultValue] = useState(value)
const { authenticated } = useContext(AuthContext)
const fetchPrintersTreeData = async () => {
if (!authenticated) {
return
}
setLoading(true)
try {
const response = await axios.get(`${config.backendUrl}/printers`, {
headers: {
Accept: 'application/json'
},
withCredentials: true // Important for including cookies
})
setLoading(false)
return response.data
} catch (error) {
if (error.response) {
// For other errors, show a message
messageApi.error('Error fetching printers data:', error.response.status)
} else {
messageApi.error(
'An unexpected error occurred. Please try again later.'
)
}
}
}
const generatePrinterItems = async () => {
const printerData = await fetchPrintersTreeData()
setPrintersData(printerData)
// Create a map to store tags and their printers
const tagMap = new Map()
// Add printers to their respective tag groups
printerData.forEach((printer) => {
if (printer.tags && printer.tags.length > 0) {
printer.tags.forEach((tag) => {
if (!tagMap.has(tag)) {
tagMap.set(tag, [])
}
tagMap.get(tag).push(printer)
})
} else {
// If no tags, add to "Untagged" group
if (!tagMap.has('Untagged')) {
tagMap.set('Untagged', [])
}
tagMap.get('Untagged').push(printer)
}
})
// Convert the map to tree data structure
Array.from(tagMap.entries()).map(([tag, printers]) => {
const newNode = {
title: tag === 'Untagged' ? tag : <Tag color='blue'>{tag}</Tag>,
value: `tag-${tag}`,
key: `tag-${tag}`,
children: printers.map((printer) => ({
title: (
<PrinterState
printer={printer}
showProgress={false}
showControls={false}
/>
),
value: printer._id,
key: printer._id
}))
}
setPrintersTreeData((prev) => {
const filtered = prev.filter((node) => node.key !== newNode.key)
return [...filtered, newNode]
})
})
}
const handleOnChange = (value, selectedOptions) => {
if (checkable) {
// Multiple selection mode
const newValue = printersData.filter((printer) =>
value.includes(printer._id)
)
setDefaultValue(newValue)
onChange(newValue, selectedOptions)
} else {
// Single selection mode
const selectedPrinter = printersData.find(
(printer) => printer._id === value
)
setDefaultValue(selectedPrinter ? [selectedPrinter] : [])
onChange(selectedPrinter, selectedOptions)
}
}
useEffect(() => {
if (value) {
if (Array.isArray(value)) {
setDefaultValue(value)
} else {
setDefaultValue([value])
}
}
}, [value])
useEffect(() => {
generatePrinterItems()
}, [])
return (
<TreeSelect
treeData={printersTreeData}
onChange={handleOnChange}
loading={loading}
disabled={disabled}
treeDefaultExpandAll
treeCheckable={checkable}
treeNodeFilterProp='title'
placeholder='Select printer'
style={{ width: '100%' }}
value={
checkable ? defaultValue.map((item) => item._id) : defaultValue[0]?._id
}
/>
)
}
PrinterSelect.propTypes = {
onChange: PropTypes.func.isRequired,
disabled: PropTypes.bool.isRequired,
checkable: PropTypes.bool,
value: PropTypes.oneOfType([PropTypes.object, PropTypes.array])
}
export default PrinterSelect