retrieved return events working but bug with return to be fixed
This commit is contained in:
@ -1,8 +1,8 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { Box, Typography, Button, Alert } from '@mui/material';
|
||||
import styled from 'styled-components';
|
||||
import styled, { keyframes, css } from 'styled-components';
|
||||
import LocalGasStationIcon from '@mui/icons-material/LocalGasStation';
|
||||
import LocationOnIcon from '@mui/icons-material/LocationOn'; // New import for location indication
|
||||
import LocationOnIcon from '@mui/icons-material/LocationOn';
|
||||
import CountdownTimer from './CountdownTimer';
|
||||
|
||||
export interface SlotData {
|
||||
@ -15,7 +15,9 @@ export interface SlotData {
|
||||
dewar_name?: string;
|
||||
needs_refill?: boolean;
|
||||
time_until_refill?: number;
|
||||
at_beamline?: boolean; // New property to indicate the dewar is at the beamline
|
||||
beamlineLocation?: string;
|
||||
retrieved?: boolean; // Indicates if the dewar is retrieved
|
||||
retrievedTimestamp?: string; // Timestamp of the retrieval event
|
||||
}
|
||||
|
||||
interface SlotProps {
|
||||
@ -26,19 +28,35 @@ interface SlotProps {
|
||||
reloadSlots: () => Promise<void>;
|
||||
}
|
||||
|
||||
interface StyledSlotProps {
|
||||
isSelected: boolean;
|
||||
isOccupied: boolean;
|
||||
atBeamline: boolean;
|
||||
}
|
||||
const pulse = keyframes`
|
||||
0% {
|
||||
box-shadow: 0 0 5px 5px rgba(255, 0, 0, 0.6);
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 0 5px 15px rgba(255, 0, 0, 0.2);
|
||||
}
|
||||
100% {
|
||||
box-shadow: 0 0 5px 5px rgba(255, 0, 0, 0.6);
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledSlot = styled(Box)<StyledSlotProps>`
|
||||
const StyledSlot = styled(Box)<{ isSelected: boolean; isOccupied: boolean; atBeamline: boolean; isRetrieved: boolean; needsRefillSoon: boolean }>`
|
||||
padding: 16px;
|
||||
margin: 8px;
|
||||
width: 150px;
|
||||
height: 260px;
|
||||
background-color: ${({ isSelected, isOccupied, atBeamline }) =>
|
||||
atBeamline ? '#ff9800' : isSelected ? '#3f51b5' : isOccupied ? '#f44336' : '#4caf50'};
|
||||
background-color: ${({ isSelected, isOccupied, atBeamline, isRetrieved }) => {
|
||||
if (isSelected) {
|
||||
return '#3f51b5';
|
||||
}
|
||||
if (isRetrieved && !atBeamline) {
|
||||
return '#9e9e9e'; // Grey color for retrieved but not at beamline
|
||||
}
|
||||
if (atBeamline) {
|
||||
return '#ff9800';
|
||||
}
|
||||
return isOccupied ? '#f44336' : '#4caf50';
|
||||
}};
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
@ -48,6 +66,11 @@ const StyledSlot = styled(Box)<StyledSlotProps>`
|
||||
border-radius: 8px;
|
||||
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.1);
|
||||
transition: transform 0.2s;
|
||||
${({ isOccupied, needsRefillSoon }) =>
|
||||
isOccupied && needsRefillSoon &&
|
||||
css`
|
||||
animation: ${pulse} 1.5s infinite;
|
||||
`}
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.05);
|
||||
@ -62,27 +85,32 @@ const BottleIcon: React.FC<{ fillHeight: number }> = ({ fillHeight }) => {
|
||||
<svg height="100px" width="50px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 276.777 276.777">
|
||||
<defs>
|
||||
<clipPath id="bottle-clip">
|
||||
<path d="M190.886,82.273c-3.23-2.586-7.525-7.643-7.525-21.639V43h8.027V0h-106v43h8.027v17.635
|
||||
c0,11.66-1.891,17.93-6.524,21.639c-21.813,17.459-31.121,36.748-31.121,64.5v100.088c0,16.496,13.42,29.916,29.916,29.916
|
||||
h105.405c16.496,0,29.916-13.42,29.916-29.916V146.773C221.007,121.103,210.029,97.594,190.886,82.273z"/>
|
||||
<path
|
||||
d="M190.886,82.273c-3.23-2.586-7.525-7.643-7.525-21.639V43h8.027V0h-106v43h8.027v17.635
|
||||
c0,11.66-1.891,17.93-6.524,21.639c-21.813,17.459-31.121,36.748-31.121,64.5v100.088c0,16.496,13.42,29.916,29.916,29.916
|
||||
h105.405c16.496,0,29.916-13.42,29.916-29.916V146.773C221.007,121.103,210.029,97.594,190.886,82.273z"
|
||||
/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<path fill="lightgray" d="M190.886,82.273c-3.23-2.586-7.525-7.643-7.525-21.639V43h8.027V0h-106v43h8.027v17.635
|
||||
c0,11.66-1.891,17.93-6.524,21.639c-21.813,17.459-31.121,36.748-31.121,64.5v100.088c0,16.496,13.42,29.916,29.916,29.916
|
||||
h105.405c16.496,0,29.916-13.42,29.916-29.916V146.773C221.007,121.103,210.029,97.594,190.886,82.273z"/>
|
||||
<path
|
||||
fill="lightgray"
|
||||
d="M190.886,82.273c-3.23-2.586-7.525-7.643-7.525-21.639V43h8.027V0h-106v43h8.027v17.635
|
||||
c0,11.66-1.891,17.93-6.524,21.639c-21.813,17.459-31.121,36.748-31.121,64.5v100.088c0,16.496,13.42,29.916,29.916,29.916
|
||||
h105.405c16.496,0,29.916-13.42,29.916-29.916V146.773C221.007,121.103,210.029,97.594,190.886,82.273z"
|
||||
/>
|
||||
<rect x="0" y={yPosition} width="100%" height={pixelHeight} fill="#00bfff" clipPath="url(#bottle-clip)" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
const Slot: React.FC<SlotProps> = ({ data, isSelected, onSelect, onRefillDewar, reloadSlots }) => {
|
||||
const { id, qr_code, label, qr_base, occupied, needs_refill, time_until_refill, dewar_unique_id, dewar_name, at_beamline } = data;
|
||||
const { id, qr_code, label, qr_base, occupied, needs_refill, time_until_refill, dewar_unique_id, dewar_name, beamlineLocation, retrieved, retrievedTimestamp } = data;
|
||||
|
||||
const calculateFillHeight = (timeUntilRefill?: number) => {
|
||||
if (timeUntilRefill === undefined || timeUntilRefill <= 0) {
|
||||
return 0;
|
||||
}
|
||||
const maxTime = 3600;
|
||||
const maxTime = 3600; // Example maximum time for calculating fill height
|
||||
return Math.min((timeUntilRefill / maxTime) * 100, 100);
|
||||
};
|
||||
|
||||
@ -101,13 +129,30 @@ const Slot: React.FC<SlotProps> = ({ data, isSelected, onSelect, onRefillDewar,
|
||||
}
|
||||
};
|
||||
|
||||
const isSpecificBeamline = beamlineLocation === 'X10SA' || beamlineLocation === 'X06SA' || beamlineLocation === 'X06DA';
|
||||
const isRetrieved = retrieved === true && !isSpecificBeamline;
|
||||
|
||||
// Consider slot needs a refill soon if it's occupied and time_until_refill is less than 3 hours (or 0)
|
||||
const needsRefillSoon = occupied && (time_until_refill !== undefined && time_until_refill <= 10800);
|
||||
|
||||
return (
|
||||
<StyledSlot isSelected={isSelected} isOccupied={occupied} atBeamline={!!at_beamline} onClick={() => onSelect(data)}>
|
||||
<StyledSlot
|
||||
isSelected={isSelected}
|
||||
isOccupied={occupied}
|
||||
atBeamline={isSpecificBeamline}
|
||||
isRetrieved={isRetrieved} // prop to control slot color for retrieved
|
||||
needsRefillSoon={needsRefillSoon} // prop to control pulsing animation
|
||||
onClick={() => onSelect(data)}
|
||||
>
|
||||
<Typography variant="h6">{label}</Typography>
|
||||
{dewar_name && <Typography variant="body2">{`${dewar_name}`}</Typography>} {/* Ensure correct dewar_name */}
|
||||
{dewar_name && <Typography variant="body2">{`${dewar_name}`}</Typography>}
|
||||
{needs_refill && <LocalGasStationIcon />}
|
||||
{dewar_unique_id && <BottleIcon fillHeight={fillHeight} />}
|
||||
{at_beamline && <Typography style={{fontSize: 12}}><LocationOnIcon /> At Beamline</Typography>} {/* Indicate at beamline */}
|
||||
{isSpecificBeamline && (
|
||||
<Typography style={{ fontSize: 12 }}>
|
||||
<LocationOnIcon /> {beamlineLocation}
|
||||
</Typography>
|
||||
)}
|
||||
{(dewar_unique_id && time_until_refill !== undefined && time_until_refill !== -1) ? (
|
||||
<CountdownTimer key={dewar_unique_id} totalSeconds={time_until_refill} />
|
||||
) : null}
|
||||
@ -121,6 +166,6 @@ const Slot: React.FC<SlotProps> = ({ data, isSelected, onSelect, onRefillDewar,
|
||||
)}
|
||||
</StyledSlot>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Slot;
|
Reference in New Issue
Block a user