Implement polling for tracking sample updates in real-time

Added a 1-second polling interval to fetch the latest sample data, ensuring the UI remains updated with real-time progress. Cleaned up code formatting for readability and consistency. Improved `getSampleStatus` logic to better distinguish sample states.
This commit is contained in:
GotthardG 2025-01-10 15:07:51 +01:00
parent 19ef20e6b0
commit 4a2d9bd1fc

View File

@ -26,26 +26,37 @@ interface Puck {
const SampleTracker: React.FC = () => { const SampleTracker: React.FC = () => {
const [pucks, setPucks] = useState<Puck[]>([]); const [pucks, setPucks] = useState<Puck[]>([]);
const [hoveredSample, setHoveredSample] = useState<{name: string, status: string} | null>(null); const [hoveredSample, setHoveredSample] = useState<{ name: string; status: string } | null>(null);
// Fetch latest sample data
const fetchPucks = async () => {
try {
const data: Puck[] = await SamplesService.getAllPucksWithSamplesAndEventsSamplesPucksSamplesGet();
setPucks(data);
} catch (error) {
console.error('Error fetching pucks', error);
}
};
// Polling logic using a 1-second interval
useEffect(() => { useEffect(() => {
const fetchPucks = async () => { // Fetch data immediately on component mount
try {
const data: Puck[] = await SamplesService.getAllPucksWithSamplesAndEventsSamplesPucksSamplesGet();
console.log(data);
setPucks(data);
} catch (error) {
console.error("Error fetching pucks", error);
}
};
fetchPucks(); fetchPucks();
// Set up polling every 1 second
const interval = setInterval(() => {
fetchPucks();
}, 1000);
// Clear interval on component unmount
return () => clearInterval(interval);
}, []); }, []);
const getSampleColor = (events: Event[] = []) => { const getSampleColor = (events: Event[] = []) => {
const hasMounted = events.some(e => e.event_type === 'Mounted'); const hasMounted = events.some((e) => e.event_type === 'Mounted');
const hasUnmounted = events.some(e => e.event_type === 'Unmounted'); const hasUnmounted = events.some((e) => e.event_type === 'Unmounted');
const hasLost = events.some(e => e.event_type === 'Lost'); const hasLost = events.some((e) => e.event_type === 'Lost');
const hasFailed = events.some(e => e.event_type === 'Failed'); const hasFailed = events.some((e) => e.event_type === 'Failed');
if (hasFailed) return 'red'; if (hasFailed) return 'red';
if (hasLost) return 'orange'; if (hasLost) return 'orange';
@ -55,66 +66,72 @@ const SampleTracker: React.FC = () => {
}; };
const getSampleStatus = (events: Event[] = []) => { const getSampleStatus = (events: Event[] = []) => {
const hasMounted = events.some(e => e.event_type === 'Mounted'); const hasMounted = events.some((e) => e.event_type === 'Mounted');
const hasUnmounted = events.some(e => e.event_type === 'Unmounted'); const hasUnmounted = events.some((e) => e.event_type === 'Unmounted');
const hasLost = events.some(e => e.event_type === 'Lost'); const hasLost = events.some((e) => e.event_type === 'Lost');
const hasFailed = events.some(e => e.event_type === 'Failed'); const hasFailed = events.some((e) => e.event_type === 'Failed');
if (hasFailed) return 'Failed'; if (hasFailed) return 'Failed';
if (hasLost) return 'Lost'; if (hasLost) return 'Lost';
if (hasMounted && !hasUnmounted) return 'In Progress';
if (hasMounted && hasUnmounted) return 'Completed'; if (hasMounted && hasUnmounted) return 'Completed';
if (hasMounted) return 'In Progress';
return 'Pending'; return 'Pending';
}; };
return ( return (
<div className="sample-tracker-container"> <div className="sample-tracker-container">
<div className="sample-tracker"> <div className="sample-tracker">
<div className="header-band"> <div className="header-band">
<h2>Sample Tracker</h2> <h2>Sample Tracker</h2>
</div>
<div className="pucks-container">
{pucks.map((puck) => (
<div key={puck.id} className="puck-column">
<div className="puck-label" style={{fontSize: '6px'}}>
{puck.puck_name.split('').map((char, i) => (
<span key={i} style={{fontSize: '10px'}}>{char}</span>
))}
</div>
<div className="samples">
{Array.from({length: 16}).map((_, index) => {
const sample = puck.samples.find(s => s.position === index + 1);
const status = sample ? getSampleStatus(sample.events) : '';
return (
<div
key={index}
className="sample-dot"
style={{
backgroundColor: sample
? getSampleColor(sample.events)
: 'transparent',
border: sample && sample.events.some(e => e.event_type === 'Lost')
? '1px solid red'
: '1px solid lightgray',
}}
onMouseEnter={() => sample && setHoveredSample({name: sample.sample_name, status})}
onMouseLeave={() => setHoveredSample(null)}
></div>
);
})}
</div>
</div>
))}
</div>
{hoveredSample && (
<div className="tooltip">
<p><strong>Name:</strong> {hoveredSample.name}</p>
<p><strong>Status:</strong> {hoveredSample.status}</p>
</div> </div>
)} <div className="pucks-container">
{pucks.map((puck) => (
<div key={puck.id} className="puck-column">
<div className="puck-label" style={{ fontSize: '6px' }}>
{puck.puck_name.split('').map((char, i) => (
<span key={i} style={{ fontSize: '10px' }}>
{char}
</span>
))}
</div>
<div className="samples">
{Array.from({ length: 16 }).map((_, index) => {
const sample = puck.samples.find((s) => s.position === index + 1);
const status = sample ? getSampleStatus(sample.events) : '';
return (
<div
key={index}
className="sample-dot"
style={{
backgroundColor: sample ? getSampleColor(sample.events) : 'transparent',
border: sample && sample.events.some((e) => e.event_type === 'Lost')
? '1px solid red'
: '1px solid lightgray',
}}
onMouseEnter={() =>
sample && setHoveredSample({ name: sample.sample_name, status })
}
onMouseLeave={() => setHoveredSample(null)}
></div>
);
})}
</div>
</div>
))}
</div>
{hoveredSample && (
<div className="tooltip">
<p>
<strong>Name:</strong> {hoveredSample.name}
</p>
<p>
<strong>Status:</strong> {hoveredSample.status}
</p>
</div>
)}
</div>
</div> </div>
</div>
); );
}; };