now with a working countdowntimer for each dewar
This commit is contained in:
@ -9,12 +9,14 @@ const CountdownTimer: React.FC<CountdownTimerProps> = ({ totalSeconds }) => {
|
||||
const [timeLeft, setTimeLeft] = useState(totalSeconds);
|
||||
|
||||
useEffect(() => {
|
||||
setTimeLeft(totalSeconds); // Reset timer on prop change
|
||||
|
||||
const timerId = setInterval(() => {
|
||||
setTimeLeft(prev => Math.max(prev - 1, 0));
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(timerId);
|
||||
}, []);
|
||||
}, [totalSeconds]); // Listen to changes in totalSeconds
|
||||
|
||||
const formatTime = (seconds: number) => {
|
||||
const hrs = Math.floor(seconds / 3600);
|
||||
@ -23,8 +25,10 @@ const CountdownTimer: React.FC<CountdownTimerProps> = ({ totalSeconds }) => {
|
||||
return `${hrs}h ${min}m ${sec}s`;
|
||||
};
|
||||
|
||||
const timeColor = timeLeft < 300 ? 'red' : 'white'; // Red if less than 5 minutes remaining
|
||||
|
||||
return (
|
||||
<Typography variant="body2" style={{ color: timeLeft < 300 ? 'red' : 'white' }} > {/* Warn with red color if less than 5 minutes */}
|
||||
<Typography variant="body2" style={{ color: timeColor }}>
|
||||
{`Time until refill: ${formatTime(timeLeft)}`}
|
||||
</Typography>
|
||||
);
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import { Box, Typography } from '@mui/material';
|
||||
import React, { useEffect } from 'react';
|
||||
import { Box, Typography, Button, Alert } from '@mui/material';
|
||||
import styled from 'styled-components';
|
||||
import LocalGasStationIcon from '@mui/icons-material/LocalGasStation'; // Icon for refilling indicator.
|
||||
import CountdownTimer from './CountdownTimer'; // Import the CountdownTimer component
|
||||
import LocalGasStationIcon from '@mui/icons-material/LocalGasStation';
|
||||
import CountdownTimer from './CountdownTimer';
|
||||
|
||||
export interface SlotData {
|
||||
id: string;
|
||||
@ -10,23 +10,30 @@ export interface SlotData {
|
||||
label: string;
|
||||
qr_base: string;
|
||||
occupied: boolean;
|
||||
dewar_unique_id?: string; // Optional additional information.
|
||||
dewar_name?: string; // Optional dewar information.
|
||||
needs_refill?: boolean; // Indicator for refill requirement.
|
||||
time_until_refill?: number; // Time until refill in seconds, optional field
|
||||
dewar_unique_id?: string;
|
||||
dewar_name?: string;
|
||||
needs_refill?: boolean;
|
||||
time_until_refill?: number;
|
||||
}
|
||||
|
||||
interface SlotProps {
|
||||
data: SlotData;
|
||||
isSelected: boolean;
|
||||
onSelect: (slot: SlotData) => void;
|
||||
onSelect: (data: SlotData) => void;
|
||||
onRefillDewar: (qr_code?: string) => Promise<void>;
|
||||
reloadSlots: () => Promise<void>;
|
||||
}
|
||||
|
||||
const StyledSlot = styled(Box)<{ isSelected: boolean; isOccupied: boolean }>`
|
||||
interface StyledSlotProps {
|
||||
isSelected: boolean;
|
||||
isOccupied: boolean;
|
||||
}
|
||||
|
||||
const StyledSlot = styled(Box)<StyledSlotProps>`
|
||||
padding: 16px;
|
||||
margin: 8px;
|
||||
width: 150px; // Increase the width to accommodate more info.
|
||||
height: 200px; // Increase the height to accommodate more info.
|
||||
width: 150px;
|
||||
height: 220px;
|
||||
background-color: ${({ isSelected, isOccupied }) =>
|
||||
isSelected ? '#3f51b5' : isOccupied ? '#f44336' : '#4caf50'};
|
||||
color: white;
|
||||
@ -44,24 +51,41 @@ const StyledSlot = styled(Box)<{ isSelected: boolean; isOccupied: boolean }>`
|
||||
}
|
||||
`;
|
||||
|
||||
const Slot: React.FC<SlotProps> = ({ data, isSelected, onSelect }) => {
|
||||
const Slot: React.FC<SlotProps> = ({ data, isSelected, onSelect, onRefillDewar, reloadSlots }) => {
|
||||
useEffect(() => {
|
||||
console.log(`Updated time_until_refill: ${data.time_until_refill}`);
|
||||
}, [data.time_until_refill]);
|
||||
|
||||
const handleRefill = async () => {
|
||||
if (data.dewar_unique_id) {
|
||||
await onRefillDewar(data.dewar_unique_id);
|
||||
reloadSlots();
|
||||
}
|
||||
};
|
||||
|
||||
const { id, qr_code, label, qr_base, occupied, needs_refill, time_until_refill, dewar_unique_id, dewar_name, ...rest } = data;
|
||||
|
||||
return (
|
||||
<StyledSlot
|
||||
isSelected={isSelected}
|
||||
isOccupied={data.occupied}
|
||||
isOccupied={occupied}
|
||||
onClick={() => onSelect(data)}
|
||||
{...rest}
|
||||
>
|
||||
<Typography variant="h6">{data.label}</Typography>
|
||||
{data.dewar_name && (
|
||||
<Typography variant="body2">{`Dewar: ${data.dewar_name}`}</Typography>
|
||||
<Typography variant="h6">{label}</Typography>
|
||||
{dewar_name && <Typography variant="body2">{`Dewar: ${dewar_name}`}</Typography>}
|
||||
{dewar_unique_id && <Typography variant="body2">{`ID: ${dewar_unique_id}`}</Typography>}
|
||||
{needs_refill && <LocalGasStationIcon />}
|
||||
{dewar_unique_id && time_until_refill !== undefined && time_until_refill !== -1 && (
|
||||
<CountdownTimer key={dewar_unique_id} totalSeconds={time_until_refill} />
|
||||
)}
|
||||
{data.dewar_unique_id && (
|
||||
<Typography variant="body2">{`ID: ${data.dewar_unique_id}`}</Typography>
|
||||
{needs_refill && (
|
||||
<Button onClick={handleRefill} sx={{ mt: 1, color: 'white' }}>
|
||||
Refill
|
||||
</Button>
|
||||
)}
|
||||
{data.needs_refill && <LocalGasStationIcon />}
|
||||
{/* Display countdown timer only for slots that have an associated dewar */}
|
||||
{data.dewar_unique_id && data.time_until_refill !== undefined && (
|
||||
<CountdownTimer totalSeconds={data.time_until_refill} />
|
||||
{occupied && time_until_refill === -1 && (
|
||||
<Alert severity="warning">This dewar has no recorded refill event. It needs to be refilled.</Alert>
|
||||
)}
|
||||
</StyledSlot>
|
||||
);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Box, Typography } from '@mui/material';
|
||||
import React from 'react';
|
||||
import { Box, Typography, Button } from '@mui/material';
|
||||
import styled from 'styled-components';
|
||||
import Slot, { SlotData } from '../components/Slots';
|
||||
|
||||
@ -28,9 +28,10 @@ interface StorageProps {
|
||||
selectedSlot: string | null;
|
||||
slotsData: SlotData[];
|
||||
onSelectSlot: (slot: SlotData) => void;
|
||||
onRefillDewar: (slot: SlotData) => void; // Adjusted this prop to pass SlotData object
|
||||
}
|
||||
|
||||
const Storage: React.FC<StorageProps> = ({ name, selectedSlot, slotsData, onSelectSlot }) => {
|
||||
const Storage: React.FC<StorageProps> = ({ name, selectedSlot, slotsData, onSelectSlot, onRefillDewar }) => {
|
||||
const handleSlotSelect = (slot: SlotData) => {
|
||||
onSelectSlot(slot);
|
||||
console.log('Selected slot:', slot);
|
||||
@ -46,9 +47,23 @@ const Storage: React.FC<StorageProps> = ({ name, selectedSlot, slotsData, onSele
|
||||
data={slot}
|
||||
onSelect={handleSlotSelect}
|
||||
isSelected={selectedSlot === slot.qr_code}
|
||||
onRefillDewar={onRefillDewar} // Pass the refill handler to Slot component
|
||||
/>
|
||||
))}
|
||||
</StorageWrapper>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
onClick={() => {
|
||||
const selectedSlotData = slotsData.find(slot => slot.qr_code === selectedSlot);
|
||||
if (selectedSlotData) {
|
||||
onRefillDewar(selectedSlotData);
|
||||
} else {
|
||||
alert('Please select a slot to refill its dewar.');
|
||||
}
|
||||
}}>
|
||||
Refill Dewar
|
||||
</Button>
|
||||
</StorageContainer>
|
||||
);
|
||||
};
|
||||
|
Reference in New Issue
Block a user