import React, { useState, useEffect, useContext } from 'react' import { useLocation } from 'react-router-dom' import axios from 'axios' import { Descriptions, Spin, Space, Button, message, Progress, Typography, Collapse, Flex, Dropdown, Popover, Checkbox, Card } from 'antd' import { LoadingOutlined, CaretLeftOutlined } from '@ant-design/icons' import TimeDisplay from '../../common/TimeDisplay' import JobState from '../../common/JobState' import IdText from '../../common/IdText' import SubJobsTree from '../../common/SubJobsTree' import { SocketContext } from '../../context/SocketContext' import GCodeFileIcon from '../../../Icons/GCodeFileIcon' import ReloadIcon from '../../../Icons/ReloadIcon' import useCollapseState from '../../hooks/useCollapseState' import config from '../../../../config' import AuditLogTable from '../../common/AuditLogTable' import DashboardNotes from '../../common/DashboardNotes' import InfoCircleIcon from '../../../Icons/InfoCircleIcon' import JobIcon from '../../../Icons/JobIcon' import AuditLogIcon from '../../../Icons/AuditLogIcon' import NoteIcon from '../../../Icons/NoteIcon' const { Title, Text } = Typography const JobInfo = () => { const [jobData, setJobData] = useState(null) const [fetchLoading, setFetchLoading] = useState(true) const [error, setError] = useState(null) const location = useLocation() const [messageApi] = message.useMessage() const jobId = new URLSearchParams(location.search).get('jobId') const { socket } = useContext(SocketContext) const [collapseState, updateCollapseState] = useCollapseState('JobInfo', { info: true, subJobs: true, notes: true, auditLogs: true }) useEffect(() => { if (jobId) { fetchJobDetails() } }, [jobId]) useEffect(() => { if (socket && jobId) { socket.on('notify_job_update', (updateData) => { if (updateData._id === jobId) { setJobData((prevData) => { if (!prevData) return prevData return { ...prevData, state: updateData.state, ...updateData } }) } }) } return () => { if (socket) { socket.off('notify_job_update') } } }, [socket, jobId]) const fetchJobDetails = async () => { try { setFetchLoading(true) const response = await axios.get(`${config.backendUrl}/jobs/${jobId}`, { headers: { Accept: 'application/json' }, withCredentials: true // Important for including cookies }) setJobData(response.data) setError(null) } catch (err) { setError('Failed to fetch print job details') messageApi.error('Failed to fetch print job details') } finally { setFetchLoading(false) } } const getViewDropdownItems = () => { const sections = [ { key: 'info', label: 'Job Information' }, { key: 'subJobs', label: 'Sub Jobs' }, { key: 'notes', label: 'Notes' }, { key: 'auditLogs', label: 'Audit Logs' } ] return ( {sections.map((section) => ( { updateCollapseState(section.key, e.target.checked) }} > {section.label} ))} ) } const actionItems = { items: [ { label: 'Reload Job', key: 'reload', icon: } ], onClick: ({ key }) => { if (key === 'edit') { // TODO: Implement edit functionality messageApi.info('Edit functionality coming soon') } else if (key === 'reload') { fetchJobDetails() } } } return ( <> Actions View {error ? ( {error || 'Print job not found'} } onClick={fetchJobDetails}> Retry ) : ( updateCollapseState('info', keys.length > 0) } expandIcon={({ isActive }) => ( )} className='no-h-padding-collapse no-t-padding-collapse' > Job Information } key='info' > }> {jobData?._id ? ( ) : ( n/a )} {jobData?.state ? ( ) : ( n/a )} {jobData?.gcodeFile ? ( {jobData.gcodeFile.name || 'Not specified'} ) : ( n/a )} {jobData?.gcodeFile?._id ? ( ) : ( n/a )} {jobData?.quantity ? ( {jobData.quantity} ) : ( n/a )} {jobData?.createdAt ? ( ) : ( n/a )} {jobData?.startedAt ? ( ) : ( n/a )} {jobData?.state?.type === 'printing' && ( )} {jobData?.printers ? ( {jobData.printers.length} printers assigned ) : ( n/a )} updateCollapseState('subJobs', keys.length > 0) } expandIcon={({ isActive }) => ( )} className='no-h-padding-collapse' > Sub Job Information } key='2' > updateCollapseState('notes', keys.length > 0) } expandIcon={({ isActive }) => ( )} className='no-h-padding-collapse' > Notes } key='notes' > updateCollapseState('auditLogs', keys.length > 0) } expandIcon={({ isActive }) => ( )} className='no-h-padding-collapse' > Audit Logs } key='auditLogs' > )} > ) } export default JobInfo
{error || 'Print job not found'}