https and ssl integration on the backend, frontend and started integration of logistics app as a separate frontend
This commit is contained in:
@ -1,75 +1,64 @@
|
||||
import React from 'react';
|
||||
import { Box } from '@mui/material';
|
||||
import { QrCode, AcUnit, AccessTime } from '@mui/icons-material';
|
||||
import { Box, Typography } from '@mui/material';
|
||||
import styled from 'styled-components';
|
||||
|
||||
interface SlotProps {
|
||||
data: SlotData;
|
||||
onSelect: (slot: SlotData) => void;
|
||||
isSelected: boolean;
|
||||
}
|
||||
import LocalGasStationIcon from '@mui/icons-material/LocalGasStation'; // Icon for refilling indicator.
|
||||
|
||||
export interface SlotData {
|
||||
id: string;
|
||||
qr_code: string;
|
||||
label: string;
|
||||
qr_base: string;
|
||||
occupied: boolean;
|
||||
needsRefill: boolean;
|
||||
timeUntilRefill: string;
|
||||
dewar_unique_id?: string; // Optional additional information.
|
||||
dewar_name?: string; // Optional dewar information.
|
||||
needs_refill?: boolean; // Indicator for refill requirement.
|
||||
}
|
||||
|
||||
const SlotContainer = styled(Box)<{ isOccupied: boolean, isSelected: boolean }>`
|
||||
width: 90px;
|
||||
height: 180px;
|
||||
margin: 10px;
|
||||
background-color: ${({ isOccupied }) => (isOccupied ? '#ffebee' : '#e8f5e9')}; /* occupied = light red, free = light green */
|
||||
border: ${({ isSelected }) => (isSelected ? '3px solid blue' : '2px solid #aaaaaa')};
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||
interface SlotProps {
|
||||
data: SlotData;
|
||||
isSelected: boolean;
|
||||
onSelect: (slot: SlotData) => void;
|
||||
}
|
||||
|
||||
const StyledSlot = styled(Box)<{ isSelected: boolean; isOccupied: boolean }>`
|
||||
padding: 16px;
|
||||
margin: 8px;
|
||||
width: 150px; // Increase the width to accommodate more info.
|
||||
height: 150px; // Increase the height to accommodate more info.
|
||||
background-color: ${({ isSelected, isOccupied }) =>
|
||||
isSelected ? '#3f51b5' : isOccupied ? '#f44336' : '#4caf50'};
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
border-radius: 8px;
|
||||
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.1);
|
||||
transition: transform 0.2s;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
`;
|
||||
|
||||
const SlotNumber = styled.div`
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
`;
|
||||
|
||||
const QrCodeIcon = styled(QrCode)`
|
||||
font-size: 40px;
|
||||
color: #aaaaaa;
|
||||
`;
|
||||
|
||||
const RefillIcon = styled(AcUnit)`
|
||||
font-size: 20px;
|
||||
color: #1e88e5;
|
||||
margin-top: auto;
|
||||
`;
|
||||
|
||||
const ClockIcon = styled(AccessTime)`
|
||||
font-size: 20px;
|
||||
color: #ff6f00;
|
||||
`;
|
||||
|
||||
const Slot: React.FC<SlotProps> = ({ data, onSelect, isSelected }) => {
|
||||
const { id, occupied, needsRefill, timeUntilRefill } = data;
|
||||
|
||||
const Slot: React.FC<SlotProps> = ({ data, isSelected, onSelect }) => {
|
||||
return (
|
||||
<SlotContainer isOccupied={occupied} onClick={() => onSelect(data)} isSelected={isSelected}>
|
||||
<SlotNumber>{id}</SlotNumber>
|
||||
<QrCodeIcon />
|
||||
{occupied && (
|
||||
<>
|
||||
{needsRefill && <RefillIcon titleAccess="Needs Refill" />}
|
||||
<ClockIcon titleAccess={`Time until refill: ${timeUntilRefill}`} />
|
||||
</>
|
||||
<StyledSlot
|
||||
isSelected={isSelected}
|
||||
isOccupied={data.occupied}
|
||||
onClick={() => onSelect(data)}
|
||||
>
|
||||
<Typography variant="h6">{data.label}</Typography>
|
||||
{data.dewar_name && (
|
||||
<Typography variant="body2">{`Dewar: ${data.dewar_name}`}</Typography>
|
||||
)}
|
||||
</SlotContainer>
|
||||
{data.dewar_unique_id && (
|
||||
<Typography variant="body2">{`ID: ${data.dewar_unique_id}`}</Typography>
|
||||
)}
|
||||
{data.needs_refill && <LocalGasStationIcon />}
|
||||
</StyledSlot>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Slot;
|
@ -1,7 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Box, Typography } from '@mui/material';
|
||||
import styled from 'styled-components';
|
||||
import Slot, { SlotData } from './Slots';
|
||||
import Slot, { SlotData } from '../components/Slots';
|
||||
|
||||
const StorageContainer = styled(Box)`
|
||||
display: flex;
|
||||
@ -26,91 +26,41 @@ const StorageWrapper = styled.div`
|
||||
interface StorageProps {
|
||||
name: string;
|
||||
selectedSlot: string | null;
|
||||
slotsData: SlotData[];
|
||||
onSelectSlot: (slot: SlotData) => void;
|
||||
}
|
||||
|
||||
|
||||
const storageSlotsData: { [key: string]: SlotData[] } = {
|
||||
"X06SA-storage": [
|
||||
{ id: "A1-X06SA", occupied: false, needsRefill: false, timeUntilRefill: '' },
|
||||
{ id: "A2-X06SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "A3-X06SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "A4-X06SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "A5-X06SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "B1-X06SA", occupied: false, needsRefill: false, timeUntilRefill: '' },
|
||||
{ id: "B2-X06SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "B3-X06SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "B4-X06SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "B5-X06SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "C1-X06SA", occupied: false, needsRefill: false, timeUntilRefill: '' },
|
||||
{ id: "C2-X06SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "C3-X06SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "C4-X06SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "C5-X06SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "D1-X06SA", occupied: false, needsRefill: false, timeUntilRefill: '' },
|
||||
{ id: "D2-X06SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "D3-X06SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "D4-X06SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "D5-X06SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
],
|
||||
"X10SA-storage": [
|
||||
{ id: "A1-X10SA", occupied: false, needsRefill: false, timeUntilRefill: '' },
|
||||
{ id: "A2-X10SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "A3-X10SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "A4-X10SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "A5-X10SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "B1-X10SA", occupied: false, needsRefill: false, timeUntilRefill: '' },
|
||||
{ id: "B2-X10SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "B3-X10SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "B4-X10SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "B5-X10SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "C1-X10SA", occupied: false, needsRefill: false, timeUntilRefill: '' },
|
||||
{ id: "C2-X10SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "C3-X10SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "C4-X10SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "C5-X10SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "D1-X10SA", occupied: false, needsRefill: false, timeUntilRefill: '' },
|
||||
{ id: "D2-X10SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "D3-X10SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "D4-X10SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
{ id: "D5-X10SA", occupied: true, needsRefill: true, timeUntilRefill: '12h' },
|
||||
],
|
||||
"Novartis-Box": [
|
||||
{ id: "NB1", occupied: true, needsRefill: true, timeUntilRefill: '6h' },
|
||||
{ id: "NB2", occupied: true, needsRefill: true, timeUntilRefill: '6h' },
|
||||
{ id: "NB3", occupied: true, needsRefill: true, timeUntilRefill: '6h' },
|
||||
{ id: "NB4", occupied: true, needsRefill: true, timeUntilRefill: '6h' },
|
||||
{ id: "NB5", occupied: true, needsRefill: true, timeUntilRefill: '6h' },
|
||||
{ id: "NB6", occupied: true, needsRefill: true, timeUntilRefill: '6h' },
|
||||
],
|
||||
};
|
||||
|
||||
const Storage: React.FC<StorageProps> = ({ name, selectedSlot }) => {
|
||||
const Storage: React.FC<StorageProps> = ({ name, selectedSlot, slotsData, onSelectSlot }) => {
|
||||
const [highlightedSlot, setHighlightedSlot] = useState<SlotData | null>(null);
|
||||
|
||||
const handleSlotSelect = (slot: SlotData) => {
|
||||
setHighlightedSlot(slot);
|
||||
onSelectSlot(slot);
|
||||
console.log('Selected slot:', slot);
|
||||
};
|
||||
|
||||
console.log("Rendering Storage Component with name:", name);
|
||||
|
||||
return (
|
||||
<StorageContainer>
|
||||
<Typography variant="h5">{name} Slots</Typography>
|
||||
<StorageWrapper>
|
||||
{storageSlotsData[name].map((slot) => (
|
||||
{slotsData.map((slot: SlotData) => (
|
||||
<Slot
|
||||
key={slot.id}
|
||||
data={slot}
|
||||
onSelect={handleSlotSelect}
|
||||
isSelected={selectedSlot === slot.id}
|
||||
isSelected={selectedSlot === slot.qr_code}
|
||||
/>
|
||||
))}
|
||||
</StorageWrapper>
|
||||
{highlightedSlot && (
|
||||
<Typography variant="subtitle1">
|
||||
Selected Slot: {highlightedSlot.id}
|
||||
Selected Slot: {highlightedSlot.label}
|
||||
</Typography>
|
||||
)}
|
||||
</StorageContainer>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Storage;
|
Reference in New Issue
Block a user