diff --git a/frontend/src/App.css b/frontend/src/App.css index 6cd936f..0459cce 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -38,14 +38,29 @@ } .sample-tracker-container { + position: relative; /* Ensure tooltip positions correctly within the container */ padding: 10px; border: 1px solid #ddd; border-radius: 5px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); - max-width: 80%; /* Reduce this percentage to fit your needs */ - width: auto; /* Auto width for responsiveness */ - margin: 0 auto; /* Center the tracker horizontally */ - overflow-x: auto; /* Allow horizontal scrolling if necessary */ + max-width: 80%; + width: auto; + margin: 0 auto; + overflow-x: auto; +} + +.tooltip { + position: absolute; + background-color: #f9f9f9; + border: 1px solid #ccc; + border-radius: 5px; + padding: 8px; + box-shadow: 0 0 10px rgba(0,0,0,0.1); + top: 50px; /* Adjust positioning */ + left: 50%; /* Center horizontally relative to the container */ + transform: translateX(-50%); + z-index: 1000; + pointer-events: none; /* Prevents tooltip from interfering with other elements */ } .sample-tracker { diff --git a/frontend/src/components/SampleTracker.tsx b/frontend/src/components/SampleTracker.tsx index 75a9b2d..714d875 100644 --- a/frontend/src/components/SampleTracker.tsx +++ b/frontend/src/components/SampleTracker.tsx @@ -21,75 +21,99 @@ interface Puck { puck_type: string; puck_location_in_dewar: number; dewar_id: number; - samples: Sample[]; // Check that the API returns this attribute + samples: Sample[]; } const SampleTracker: React.FC = () => { - const [pucks, setPucks] = useState([]); + const [pucks, setPucks] = useState([]); + const [hoveredSample, setHoveredSample] = useState<{name: string, status: string} | null>(null); - - useEffect(() => { - const fetchPucks = async () => { - try { - const data: Puck[] = await SamplesService.getAllPucksWithSamplesAndEventsSamplesPucksSamplesGet(); - console.log(data); // Log the data to inspect it - setPucks(data); - } catch (error) { - console.error('Error fetching pucks', error); - } - }; - fetchPucks(); - }, []); - - const getSampleColor = (events: Event[] = []) => { - const hasMounted = events.some(e => e.event_type === 'Mounted'); - const hasUnmounted = events.some(e => e.event_type === 'Unmounted'); - const hasLost = events.some(e => e.event_type === 'Lost'); - const hasFailed = events.some(e => e.event_type === 'Failed'); - - if (hasFailed) return 'red'; - if (hasLost) return 'orange'; - if (hasMounted && hasUnmounted) return 'green'; - - return 'gray'; + useEffect(() => { + const fetchPucks = async () => { + try { + const data: Puck[] = await SamplesService.getAllPucksWithSamplesAndEventsSamplesPucksSamplesGet(); + console.log(data); // Log the data to inspect it + setPucks(data); + } catch (error) { + console.error("Error fetching pucks", error); + } }; + fetchPucks(); + }, []); - return ( -
-
-

All Pucks and Samples

-
- {pucks.map((puck) => ( -
-
- {puck.puck_name.split('').map((char, i) => ( - {char} - ))} -
-
- {Array.from({length: 16}).map((_, index) => { - const sample = puck.samples.find(s => s.position === index + 1); - return ( -
e.event_type === 'Lost') - ? '1px solid red' : '1px solid lightgray', - }} - >
- ); - })} -
-
- ))} -
+ const getSampleColor = (events: Event[] = []) => { + const hasMounted = events.some(e => e.event_type === 'Mounted'); + const hasUnmounted = events.some(e => e.event_type === 'Unmounted'); + const hasLost = events.some(e => e.event_type === 'Lost'); + const hasFailed = events.some(e => e.event_type === 'Failed'); + + if (hasFailed) return 'red'; + if (hasLost) return 'orange'; + if (hasMounted && hasUnmounted) return 'green'; + + return 'gray'; + }; + + const getSampleStatus = (events: Event[] = []) => { + const hasMounted = events.some(e => e.event_type === 'Mounted'); + const hasUnmounted = events.some(e => e.event_type === 'Unmounted'); + const hasLost = events.some(e => e.event_type === 'Lost'); + const hasFailed = events.some(e => e.event_type === 'Failed'); + + if (hasFailed) return 'Failed'; + if (hasLost) return 'Lost'; + if (hasMounted && hasUnmounted) return 'Completed'; + if (hasMounted) return 'In Progress'; + + return 'Pending'; + }; + + return ( +
+
+

All Pucks and Samples

+
+ {pucks.map((puck) => ( +
+
+ {puck.puck_name.split('').map((char, i) => ( + {char} + ))} +
+
+ {Array.from({ length: 16 }).map((_, index) => { + const sample = puck.samples.find(s => s.position === index + 1); + const status = sample ? getSampleStatus(sample.events) : ''; + return ( +
e.event_type === 'Lost') + ? '1px solid red' + : '1px solid lightgray', + }} + onMouseEnter={() => sample && setHoveredSample({name: sample.sample_name, status})} + onMouseLeave={() => setHoveredSample(null)} + >
+ ); + })} +
+ ))}
- ); + {hoveredSample && ( +
+

Name: {hoveredSample.name}

+

Status: {hoveredSample.status}

+
+ )} +
+
+ ); }; export default SampleTracker; \ No newline at end of file